[mkgmap] 01/05: Imported Upstream version 0.0.0+svn3741

Bas Couwenberg sebastic at debian.org
Sat Dec 31 23:34:40 UTC 2016


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

sebastic pushed a commit to branch master
in repository mkgmap.

commit bb420e6e3397e626378451e591fe695b06394a2f
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Sun Jan 1 00:23:10 2017 +0100

    Imported Upstream version 0.0.0+svn3741
---
 .idea/dictionaries/steve.xml                       |   1 +
 .idea/inspectionProfiles/Mapping.xml               | 143 +++++++++--
 .idea/misc.xml                                     |   3 +-
 Makefile                                           |   1 +
 resources/help/en/options                          | 286 +++++++++++----------
 resources/mkgmap-version.properties                |   4 +-
 resources/styles/default/inc/water_lines           |   3 +-
 src/uk/me/parabola/imgfmt/app/Area.java            |   5 +-
 .../parabola/imgfmt/app/BufferedImgFileReader.java |  14 +-
 src/uk/me/parabola/imgfmt/app/ImgFileReader.java   |   2 +-
 .../imgfmt/app/labelenc/CodeFunctions.java         |  10 +-
 src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java     |   6 +-
 .../me/parabola/imgfmt/app/lbl/LBLFileReader.java  |   7 +-
 src/uk/me/parabola/imgfmt/app/map/Map.java         |  22 +-
 src/uk/me/parabola/imgfmt/app/trergn/TREFile.java  |  13 +-
 .../parabola/imgfmt/app/trergn/TREFileReader.java  |  24 +-
 src/uk/me/parabola/imgfmt/mps/Block.java           |  78 ------
 src/uk/me/parabola/imgfmt/mps/MapBlock.java        |   6 +-
 src/uk/me/parabola/imgfmt/mps/MapsetBlock.java     |   4 +-
 src/uk/me/parabola/imgfmt/mps/MpsBlock.java        |  28 ++
 src/uk/me/parabola/imgfmt/mps/MpsFile.java         |  13 +-
 src/uk/me/parabola/imgfmt/mps/MpsFileReader.java   |  36 ++-
 src/uk/me/parabola/imgfmt/mps/ProductBlock.java    |   6 +-
 src/uk/me/parabola/imgfmt/sys/ImgHeader.java       |  44 +++-
 src/uk/me/parabola/io/FileBlock.java               |  80 ++++++
 src/uk/me/parabola/io/StructuredOutputStream.java  |  26 +-
 src/uk/me/parabola/mkgmap/build/MapArea.java       |  15 +-
 src/uk/me/parabola/mkgmap/build/MapBuilder.java    |  18 +-
 src/uk/me/parabola/mkgmap/build/MapSplitter.java   |  28 +-
 src/uk/me/parabola/mkgmap/combiners/Combiner.java  |   3 +
 src/uk/me/parabola/mkgmap/combiners/FileInfo.java  |  24 +-
 .../me/parabola/mkgmap/combiners/GmapiBuilder.java | 283 ++++++++++++++++++++
 .../parabola/mkgmap/combiners/GmapsuppBuilder.java |  25 +-
 .../me/parabola/mkgmap/combiners/MdrBuilder.java   |   4 +
 .../me/parabola/mkgmap/combiners/MdxBuilder.java   |   4 +
 .../parabola/mkgmap/combiners/OverviewBuilder.java |   7 +-
 .../me/parabola/mkgmap/combiners/TdbBuilder.java   |   7 +-
 .../parabola/mkgmap/filters/ShapeMergeFilter.java  |  31 ++-
 src/uk/me/parabola/mkgmap/main/Main.java           |  46 ++--
 .../mkgmap/reader/osm/OsmMapDataSource.java        |  14 +-
 .../mkgmap/reader/osm/o5m/O5mBinHandler.java       |  52 ++--
 src/uk/me/parabola/tdbfmt/Block.java               | 121 ---------
 src/uk/me/parabola/tdbfmt/CopyrightBlock.java      |  22 +-
 src/uk/me/parabola/tdbfmt/CopyrightSegment.java    |   3 +-
 src/uk/me/parabola/tdbfmt/DetailMapBlock.java      |  20 +-
 src/uk/me/parabola/tdbfmt/HeaderBlock.java         |  40 +--
 src/uk/me/parabola/tdbfmt/OverviewMapBlock.java    |  24 +-
 src/uk/me/parabola/tdbfmt/RBlock.java              |  11 +-
 src/uk/me/parabola/tdbfmt/TBlock.java              |  15 +-
 src/uk/me/parabola/tdbfmt/TdbFile.java             | 138 +++++-----
 test/func/ArgsTest.java                            |   6 +
 test/func/SimpleTest.java                          |  19 +-
 test/func/StructureTest.java                       |   5 +-
 test/func/files/GmapsuppTest.java                  | 118 +++------
 test/func/files/TdbTest.java                       |  18 +-
 test/func/route/SimpleRouteTest.java               |  13 +-
 test/func/sources/TestSourceTest.java              |   8 +-
 57 files changed, 1184 insertions(+), 823 deletions(-)

diff --git a/.idea/dictionaries/steve.xml b/.idea/dictionaries/steve.xml
index 09cba22..99612fe 100644
--- a/.idea/dictionaries/steve.xml
+++ b/.idea/dictionaries/steve.xml
@@ -30,6 +30,7 @@
       <w>garmin's</w>
       <w>gawron</w>
       <w>geofabrik</w>
+      <w>gmapi</w>
       <w>gmapsupp</w>
       <w>gpsmapedit</w>
       <w>gtype</w>
diff --git a/.idea/inspectionProfiles/Mapping.xml b/.idea/inspectionProfiles/Mapping.xml
index de1ea77..fbde4d8 100644
--- a/.idea/inspectionProfiles/Mapping.xml
+++ b/.idea/inspectionProfiles/Mapping.xml
@@ -1,7 +1,6 @@
 <component name="InspectionProjectProfileManager">
   <profile version="1.0" is_locked="true">
     <option name="myName" value="Mapping" />
-    <option name="myLocal" value="false" />
     <inspection_tool class="AbsoluteAlignmentInUserInterface" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AbstractBeanReferencesInspection" enabled="true" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AbstractClassExtendsConcreteClass" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -29,20 +28,29 @@
     <inspection_tool class="AndroidDomInspection" enabled="true" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidElementNotAllowed" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintAddJavascriptInterface" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintAllowAllHostnameVerifier" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintAlwaysShowAction" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintAppCompatMethod" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintAuthLeak" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintBadHostnameVerifier" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintBatteryLife" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintCommitPrefEdits" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintCommitTransaction" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintCustomViewStyleable" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintCutPasteId" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintDefaultLocale" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintDrawAllocation" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintEasterEgg" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintExportedContentProvider" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintExportedPreferenceActivity" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintExportedReceiver" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintExportedService" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintFloatMath" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintGetInstance" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintGifUsage" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintGoogleAppIndexingApiWarning" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintGoogleAppIndexingUrlError" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintGoogleAppIndexingWarning" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintGrantAllUris" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintHandlerLeak" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintIconColors" enabled="false" level="WARNING" enabled_by_default="true" />
@@ -61,31 +69,46 @@
     <inspection_tool class="AndroidKLintInconsistentLayout" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintInflateParams" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintInlinedApi" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintInvalidUsesTagAttribute" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintJavascriptInterface" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintLocalSuppress" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintLogConditional" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintLogTagMismatch" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintLongLogTag" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintMergeRootFrame" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintMissingIntentFilterForMediaSearch" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintMissingMediaBrowserServiceIntentFilter" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintMissingOnPlayFromSearch" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintMissingSuperCall" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintNewApi" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintOverdraw" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintOverride" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintOverrideAbstract" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintPackageManagerGetSignatures" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintParcelClassLoader" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintParcelCreator" enabled="false" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintPendingBindings" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintPluralsCandidate" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintPrivateResource" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintRecycle" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintRecyclerView" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintRegistered" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintRequiredSize" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintRtlCompat" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintRtlEnabled" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintRtlHardcoded" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintRtlSymmetry" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintSQLiteString" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintSSLCertificateSocketFactoryCreateSocket" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintSSLCertificateSocketFactoryGetInsecure" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintSdCardPath" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintSecureRandom" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintServiceCast" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintSetJavaScriptEnabled" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintSetTextI18n" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintSetWorldReadable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintSetWorldWritable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintShiftFlags" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintShortAlarm" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintShowToast" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintSimpleDateFormat" enabled="false" level="WARNING" enabled_by_default="true" />
@@ -93,8 +116,17 @@
     <inspection_tool class="AndroidKLintStringFormatCount" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintStringFormatInvalid" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintStringFormatMatches" enabled="false" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintSupportAnnotationUsage" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintSuspiciousImport" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintSwitchIntDef" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintTrustAllX509TrustManager" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintUniqueConstants" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintUnlocalizedSms" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintUnprotectedSMSBroadcastReceiver" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintUnsafeDynamicallyLoadedCode" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintUnsafeNativeCodeLocation" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintUnsafeProtectedBroadcastReceiver" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidKLintUnusedAttribute" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintUnusedIds" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintUnusedResources" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintUseSparseArrays" enabled="false" level="WARNING" enabled_by_default="true" />
@@ -102,6 +134,7 @@
     <inspection_tool class="AndroidKLintValidFragment" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintViewConstructor" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintViewHolder" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidKLintViewTag" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidKLintWorldReadableFiles" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintWorldWriteableFiles" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidKLintWrongCall" enabled="false" level="ERROR" enabled_by_default="true" />
@@ -120,8 +153,10 @@
     <inspection_tool class="AndroidLintAppLinksAutoVerifyError" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="AndroidLintAppLinksAutoVerifyWarning" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidLintAssert" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintAuthLeak" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidLintBackButton" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidLintBadHostnameVerifier" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintBatteryLife" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidLintButtonCase" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidLintButtonOrder" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidLintButtonStyle" enabled="false" level="WARNING" enabled_by_default="true" />
@@ -174,6 +209,7 @@
     <inspection_tool class="AndroidLintHandlerLeak" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidLintHardcodedDebugMode" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidLintHardcodedText" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintHardwareIds" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidLintIconColors" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidLintIconDensities" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidLintIconDipSize" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -215,6 +251,7 @@
     <inspection_tool class="AndroidLintMergeRootFrame" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidLintMipmapIcons" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidLintMissingApplicationIcon" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintMissingConstraints" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="AndroidLintMissingId" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidLintMissingIntentFilterForMediaSearch" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidLintMissingLeanbackLauncher" enabled="false" level="ERROR" enabled_by_default="true" />
@@ -247,6 +284,7 @@
     <inspection_tool class="AndroidLintPackagedPrivateKey" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidLintParcelClassLoader" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidLintParcelCreator" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintPendingBindings" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="AndroidLintPermissionImpliesUnsupportedHardware" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidLintPluralsCandidate" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidLintPrivateResource" enabled="false" level="ERROR" enabled_by_default="false" />
@@ -292,12 +330,14 @@
     <inspection_tool class="AndroidLintSpUsage" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidLintSparseArray" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidLintStateListReachable" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintStaticFieldLeak" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidLintStopShip" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidLintStringFormatCount" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidLintStringFormatInvalid" enabled="true" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidLintStringFormatMatches" enabled="true" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidLintStringShouldBeInt" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidLintStyleCycle" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="AndroidLintSupportAnnotationUsage" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="AndroidLintSuspicious0dp" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidLintSuspiciousImport" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AndroidLintSwitchIntDef" enabled="false" level="WARNING" enabled_by_default="true" />
@@ -337,10 +377,12 @@
     <inspection_tool class="AndroidLintUsingHttp" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidLintValidFragment" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidLintValidRestrictions" enabled="false" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintVectorDrawableCompat" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="AndroidLintVectorRaster" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidLintViewConstructor" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidLintViewHolder" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidLintViewTag" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AndroidLintWearableBindListener" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="AndroidLintWebViewLayout" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="AndroidLintWorldReadableFiles" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AndroidLintWorldWriteableFiles" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -369,6 +411,7 @@
     </inspection_tool>
     <inspection_tool class="AnonymousClassVariableHidesContainingMethodVariable" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AnonymousFunctionJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="AnonymousHasLambdaAlternative" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AnonymousInnerClass" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AnonymousInnerClassMayBeStatic" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AntDuplicateTargetsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
@@ -382,12 +425,13 @@
     <inspection_tool class="ArgNamesErrorsInspection" enabled="true" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="ArgNamesWarningsInspection" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AroundAdviceStyleInspection" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ArrayCreationWithoutNewKeyword" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="ArrayEquality" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="ArrayEquals" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="ArrayHashCode" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="ArrayInDataClass" enabled="false" level="WEAK WARNING" enabled_by_default="true" />
     <inspection_tool class="ArrayLengthInLoopCondition" enabled="false" level="WARNING" enabled_by_default="false" />
-    <inspection_tool class="ArrayObjectsEquals" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ArrayObjectsEquals" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="ArraysAsListWithZeroOrOneArgument" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AssertAsName" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AssertEqualsBetweenInconvertibleTypes" enabled="true" level="WARNING" enabled_by_default="true" />
@@ -397,6 +441,7 @@
     <inspection_tool class="AssertMessageNotString" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AssertStatement" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AssertWithSideEffects" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AssertionCanBeIf" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="AssertsWithoutMessages" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AssertsWithoutMessagesTestNG" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AssignmentResultUsedJS" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -420,8 +465,8 @@
     <inspection_tool class="AssignmentToStaticFieldFromInstanceMethod" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AssignmentToSuperclassField" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="AssignmentUsedAsCondition" enabled="true" level="WARNING" enabled_by_default="true" />
-    <inspection_tool class="AtomicFieldUpdaterIssues" enabled="false" level="WARNING" enabled_by_default="true" />
-    <inspection_tool class="AtomicFieldUpdaterNotStaticFinal" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AtomicFieldUpdaterIssues" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="AtomicFieldUpdaterNotStaticFinal" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="AutoBoxing" enabled="false" level="INFO" enabled_by_default="false">
       <option name="ignoreAddedToCollection" value="false" />
     </inspection_tool>
@@ -463,7 +508,7 @@
     <inspection_tool class="BlockMarkerComments" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="BlockStatementJS" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="BooleanConstructor" enabled="true" level="WARNING" enabled_by_default="true" />
-    <inspection_tool class="BooleanExpressionMayBeConditional" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="BooleanExpressionMayBeConditional" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="BooleanMethodIsAlwaysInverted" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="BooleanMethodNameMustStartWithQuestion" enabled="false" level="WARNING" enabled_by_default="false">
       <option name="ignoreBooleanMethods" value="false" />
@@ -632,7 +677,7 @@
     <inspection_tool class="CloneableImplementsClone" enabled="true" level="WARNING" enabled_by_default="true">
       <option name="m_ignoreCloneableDueToInheritance" value="true" />
     </inspection_tool>
-    <inspection_tool class="CodeBlock2Expr" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CodeBlock2Expr" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="CollectionAddAllCanBeReplacedWithConstructor" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="CollectionAddedToSelf" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="CollectionContainsUrl" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -641,6 +686,7 @@
     <inspection_tool class="CommaExpressionJS" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="CommandLineInspection" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="ComparableImplementedButEqualsNotOverridden" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ComparatorCombinators" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="ComparatorMethodParameterNotUsed" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="ComparatorNotSerializable" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="CompareToUsesNonFinalVariable" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -711,12 +757,13 @@
     <inspection_tool class="ControlFlowStatementWithoutBraces" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="Convert2Diamond" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="Convert2Lambda" enabled="false" level="WARNING" enabled_by_default="false" />
-    <inspection_tool class="Convert2MethodRef" enabled="false" level="WARNING" enabled_by_default="false" />
-    <inspection_tool class="Convert2streamapi" enabled="false" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="Convert2MethodRef" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Convert2streamapi" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
     <inspection_tool class="ConvertAnnotations" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ConvertJavadoc" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ConvertLambdaToReference" enabled="false" level="INFO" enabled_by_default="true" />
     <inspection_tool class="ConvertOldAnnotations" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ConvertSecondaryConstructorToPrimary" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ConvertToStringTemplate" enabled="false" level="INFO" enabled_by_default="true" />
     <inspection_tool class="CovariantCompareTo" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="CovariantEquals" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -762,7 +809,9 @@
     </inspection_tool>
     <inspection_tool class="CssUnknownTarget" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="CssUnknownTargetInspection" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="CssUnresolvedClass" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="CssUnresolvedCustomProperty" enabled="false" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="CssUnresolvedCustomPropertySet" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="CssUnusedSymbol" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="CssUnusedSymbolInspection" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="CucumberExamplesColon" enabled="false" level="ERROR" enabled_by_default="false" />
@@ -801,12 +850,15 @@
     <inspection_tool class="DeprecatedCallableAddReplaceWith" enabled="false" level="INFO" enabled_by_default="true" />
     <inspection_tool class="DeprecatedClassUsageInspection" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="DeprecatedDefenderSyntax" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="DeprecatedIsStillUsed" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="DeprecatedObjectInstanceFieldReference" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="DeprecatedUsageOfStaticField" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="Deprecation" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="DeserializableClassInSecureContext" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="DesignForExtension" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="Destructure" enabled="false" level="INFO" enabled_by_default="false" />
     <inspection_tool class="DialogTitleCapitalization" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="DiamondCanBeReplacedWithExplicitTypeArguments" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="DifferentKotlinGradleVersion" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="DifferentStdlibGradleVersion" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="DisjointPackage" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -865,6 +917,7 @@
     <inspection_tool class="ELSpecValidationInJSP" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="ELValidationInJSP" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="ES6BindWithArrowFunction" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ES6ConvertRequireIntoImport" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="ES6ConvertVarToLetConst" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ES6ModulesDependencies" enabled="false" level="WEAK WARNING" enabled_by_default="true" />
     <inspection_tool class="ES6UnusedImports" enabled="false" level="WARNING" enabled_by_default="true" />
@@ -934,12 +987,13 @@
     </inspection_tool>
     <inspection_tool class="EnumerationCanBeIteration" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="EqualityComparisonWithCoercionJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="EqualityOperatorComparesObjects" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="EqualsAndHashcode" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="EqualsBetweenInconvertibleTypes" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="EqualsCalledOnEnumConstant" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="EqualsHashCodeCalledOnUrl" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="EqualsOrHashCode" enabled="false" level="WARNING" enabled_by_default="true" />
-    <inspection_tool class="EqualsReplaceableByObjectsCall" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="EqualsReplaceableByObjectsCall" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="EqualsUsesNonFinalVariable" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="EqualsWhichDoesntCheckParameterClass" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="EqualsWithItself" enabled="false" level="WARNING" enabled_by_default="true" />
@@ -1022,6 +1076,11 @@
     <inspection_tool class="FlexUnitMixedAPIInspection" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="FlexUnitSuiteWithNoRunnerInspection" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="FloatingPointEquality" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FlowJSConfig" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FlowJSCoverage" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="FlowJSError" enabled="false" level="ERROR" enabled_by_default="false" />
+    <inspection_tool class="FlowJSFlagCommentPlacement" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="FoldInitializerAndIfToElvis" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
     <inspection_tool class="ForCanBeForeach" enabled="true" level="WARNING" enabled_by_default="true">
       <option name="REPORT_INDEXED_LOOP" value="true" />
       <option name="ignoreUntypedCollections" value="false" />
@@ -1068,6 +1127,9 @@
     <inspection_tool class="GrMethodMayBeStatic" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="GrPackage" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="GrReassignedInClosureLocalVar" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="GrUnnecessaryDefModifier" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GrUnnecessaryPublicModifier" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="GrUnnecessarySemicolon" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="GrUnresolvedAccess" enabled="false" level="WEAK WARNING" enabled_by_default="true" />
     <inspection_tool class="GroovyAccessToStaticFieldLockedOnInstance" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="GroovyAccessibility" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -1248,7 +1310,7 @@
     <inspection_tool class="GspInspection" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="GspPropertiesInspection" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="GtkPreferredJComboBoxRenderer" enabled="false" level="WARNING" enabled_by_default="false" />
-    <inspection_tool class="Guava" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Guava" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="GuavaFluentIterable" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="GwtClientClassFromNonInheritedModule" enabled="true" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="GwtCssResourceErrors" enabled="true" level="ERROR" enabled_by_default="true" />
@@ -1327,6 +1389,7 @@
       <option name="ignoredTypesString" value="java.io.ByteArrayOutputStream,java.io.ByteArrayInputStream,java.io.StringBufferInputStream,java.io.CharArrayWriter,java.io.CharArrayReader,java.io.StringWriter,java.io.StringReader" />
       <option name="insideTryAllowed" value="false" />
     </inspection_tool>
+    <inspection_tool class="IfCanBeAssertion" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="IfCanBeSwitch" enabled="true" level="WARNING" enabled_by_default="true">
       <option name="minimumBranches" value="3" />
       <option name="suggestIntSwitches" value="false" />
@@ -1436,7 +1499,7 @@
     <inspection_tool class="IntentionDescriptionNotFoundInspection" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="InterceptionAnnotationWithoutRuntimeRetention" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="InterfaceMayBeAnnotatedFunctional" enabled="false" level="WARNING" enabled_by_default="false" />
-    <inspection_tool class="InterfaceMethodClashesWithObject" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="InterfaceMethodClashesWithObject" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="InterfaceNamingConvention" enabled="false" level="WARNING" enabled_by_default="false">
       <option name="m_regex" value="[A-Z][A-Za-z\d]*" />
       <option name="m_minLength" value="8" />
@@ -1447,6 +1510,7 @@
     </inspection_tool>
     <inspection_tool class="InterfaceWithOnlyOneDirectInheritor" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="IntroduceWhenSubject" enabled="false" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="InvalidComparatorMethodReference" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="InvalidImplementedBy" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="InvalidProvidedBy" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="InvalidRequestParameters" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -1477,6 +1541,7 @@
     <inspection_tool class="JSFieldCanBeLocal" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="JSFieldCanBeLocalInspection" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="JSFileReferences" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="JSFunctionExpressionToArrowFunction" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="JSHint" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="JSImplicitlyInternalDeclaration" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="JSJQueryEfficiency" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -1507,6 +1572,7 @@
     <inspection_tool class="JSPrimitiveTypeWrapperUsage" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="JSReferencingArgumentsOutsideOfFunction" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="JSReferencingMutableVariableFromClosure" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="JSStringConcatenationToES6Template" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="JSSuspiciousNameCombination" enabled="false" level="WARNING" enabled_by_default="false">
       <group names="x,width,left,right" />
       <group names="y,height,top,bottom" />
@@ -1550,7 +1616,10 @@
       <option name="m_maxLength" value="64" />
     </inspection_tool>
     <inspection_tool class="JUnitTestNG" enabled="false" level="WARNING" enabled_by_default="false" />
-    <inspection_tool class="Java8CollectionsApi" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Java8CollectionRemoveIf" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Java8CollectionsApi" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Java8ListSort" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Java8ReplaceMapGet" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
       <option name="TOP_LEVEL_CLASS_OPTIONS">
         <value>
@@ -1626,9 +1695,12 @@
     <inspection_tool class="KotlinUnusedImport" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="LabeledStatement" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="LabeledStatementJS" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="LambdaBodyCanBeCodeBlock" enabled="false" level="INFORMATION" enabled_by_default="false" />
+    <inspection_tool class="LambdaCanBeReplacedWithAnonymous" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="LambdaParameterHidingMemberVariable" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="LambdaParameterNamingConvention" enabled="false" level="WARNING" enabled_by_default="false" />
-    <inspection_tool class="LambdaUnfriendlyMethodOverload" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="LambdaParameterTypeCanBeSpecified" enabled="false" level="INFORMATION" enabled_by_default="false" />
+    <inspection_tool class="LambdaUnfriendlyMethodOverload" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="LanguageMismatch" enabled="true" level="WARNING" enabled_by_default="true">
       <option name="CHECK_NON_ANNOTATED_REFERENCES" value="true" />
     </inspection_tool>
@@ -1684,6 +1756,7 @@
     </inspection_tool>
     <inspection_tool class="LoopStatementThatDoesntLoopJS" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="LoopStatementsThatDontLoop" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="LoopToCallChain" enabled="false" level="INFO" enabled_by_default="false" />
     <inspection_tool class="LoopWithImplicitTerminationCondition" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="LossyEncoding" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="MVCPathVariableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -1694,6 +1767,7 @@
     <inspection_tool class="MakoArgumentListInspection" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="MalformedFormatString" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="MalformedRegex" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MalformedSetUpTearDown" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="MalformedXPath" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="ManagedBeanClassInspection" enabled="true" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="ManualArrayCopy" enabled="true" level="WARNING" enabled_by_default="true" />
@@ -1704,8 +1778,9 @@
     <inspection_tool class="MavenDuplicateDependenciesInspection" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="MavenModelInspection" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="MethodCallInLoopCondition" enabled="false" level="WARNING" enabled_by_default="false" />
-    <inspection_tool class="MethodCanBeVariableArityMethod" enabled="false" level="WARNING" enabled_by_default="false">
+    <inspection_tool class="MethodCanBeVariableArityMethod" enabled="true" level="WARNING" enabled_by_default="true">
       <option name="ignoreByteAndShortArrayParameters" value="true" />
+      <option name="ignoreOverridingMethods" value="true" />
     </inspection_tool>
     <inspection_tool class="MethodCount" enabled="false" level="WARNING" enabled_by_default="false">
       <option name="m_limit" value="20" />
@@ -1735,6 +1810,7 @@
     <inspection_tool class="MethodOverridesPackageLocalMethod" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="MethodOverridesPrivateMethod" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="MethodOverridesStaticMethod" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="MethodRefCanBeReplacedWithLambda" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="MethodReturnAlwaysConstant" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="MethodReturnOfConcreteClass" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="MethodWithMultipleLoops" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -1770,6 +1846,7 @@
     <inspection_tool class="MisspelledEquals" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="MisspelledHashcode" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="MisspelledHeader" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="MisspelledMethodName" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="MisspelledSetUp" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="MisspelledTearDown" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="MisspelledToString" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -1779,6 +1856,7 @@
     <inspection_tool class="ModuleWithTooManyClasses" enabled="false" level="WARNING" enabled_by_default="false">
       <option name="limit" value="100" />
     </inspection_tool>
+    <inspection_tool class="MultiCatchCanBeSplit" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="MultipleBindingAnnotations" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="MultipleDeclaration" enabled="false" level="WARNING" enabled_by_default="false">
       <option name="ignoreForLoopDeclarations" value="true" />
@@ -1928,8 +2006,9 @@
     <inspection_tool class="OneButtonGroup" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="OneWayWebMethod" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="OptionalContainsCollection" enabled="false" level="WARNING" enabled_by_default="false" />
-    <inspection_tool class="OptionalGetWithoutIsPresent" enabled="false" level="WARNING" enabled_by_default="true" />
-    <inspection_tool class="OptionalUsedAsFieldOrParameterType" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="OptionalGetWithoutIsPresent" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="OptionalIsPresent" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="OptionalUsedAsFieldOrParameterType" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="OrredNotEqualExpression" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="OverloadedMethodsWithSameNumberOfParameters" enabled="false" level="WARNING" enabled_by_default="false">
       <option name="ignoreInconvertibleTypes" value="true" />
@@ -1951,6 +2030,7 @@
     <inspection_tool class="OverlyLargePrimitiveArrayInitializer" enabled="false" level="WARNING" enabled_by_default="false">
       <option name="m_limit" value="64" />
     </inspection_tool>
+    <inspection_tool class="OverlyLongLambda" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="OverlyStrongTypeCast" enabled="false" level="WARNING" enabled_by_default="false">
       <option name="ignoreInMatchingInstanceof" value="false" />
     </inspection_tool>
@@ -2137,6 +2217,7 @@
     <inspection_tool class="PyDictDuplicateKeysInspection" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="PyDocstringInspection" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="PyDocstringTypesInspection" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
+    <inspection_tool class="PyDunderSlotsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="PyExceptClausesOrderInspection" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="PyExceptionInheritInspection" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="PyFromFutureImportInspection" enabled="true" level="WARNING" enabled_by_default="true" />
@@ -2222,6 +2303,7 @@
     </inspection_tool>
     <inspection_tool class="RSReferenceInspection" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="RandomDoubleForRandomInteger" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="RawTypeCanBeGeneric" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="RawUseOfParameterizedType" enabled="true" level="WARNING" enabled_by_default="true">
       <option name="ignoreTypeCasts" value="true" />
     </inspection_tool>
@@ -2234,11 +2316,13 @@
     <inspection_tool class="RedundantFieldInitialization" enabled="true" level="WARNING" enabled_by_default="true">
       <option name="onlyWarnOnNull" value="true" />
     </inspection_tool>
+    <inspection_tool class="RedundantIf" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="RedundantImplements" enabled="false" level="WARNING" enabled_by_default="false">
       <option name="ignoreSerializable" value="false" />
       <option name="ignoreCloneable" value="false" />
     </inspection_tool>
     <inspection_tool class="RedundantImport" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RedundantLambdaParameterType" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="RedundantMethodOverride" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="RedundantModalityModifier" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="RedundantSamConstructor" enabled="false" level="WARNING" enabled_by_default="true" />
@@ -2262,14 +2346,18 @@
     </inspection_tool>
     <inspection_tool class="RemoveAtFromAnnotationArgument" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="RemoveCurlyBracesFromTemplate" enabled="false" level="WEAK WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveEmptyClassBody" enabled="false" level="INFO" enabled_by_default="false" />
+    <inspection_tool class="RemoveEmptyParenthesesFromLambdaCall" enabled="false" level="INFO" enabled_by_default="false" />
     <inspection_tool class="RemoveExplicitSuperQualifier" enabled="false" level="WEAK WARNING" enabled_by_default="true" />
     <inspection_tool class="RemoveExplicitTypeArguments" enabled="false" level="WEAK WARNING" enabled_by_default="true" />
     <inspection_tool class="RemoveForLoopIndices" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="RemoveRedundantCallsOfConversionMethods" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="RemoveSetterParameterType" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="RemoveSingleExpressionStringTemplate" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="RemoveToStringInStringTemplate" enabled="false" level="WEAK WARNING" enabled_by_default="true" />
     <inspection_tool class="RemoveUnnecessaryLateinit" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="ReplaceAllDot" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ReplaceArrayEqualityOpWithArraysEquals" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ReplaceAssignmentWithOperatorAssignment" enabled="true" level="WARNING" enabled_by_default="true">
       <option name="ignoreLazyOperators" value="true" />
       <option name="ignoreObscureOperators" value="false" />
@@ -2277,6 +2365,10 @@
     <inspection_tool class="ReplaceAssignmentWithOperatorAssignmentJS" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ReplaceCallWithComparison" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="ReplaceGetOrSet" enabled="false" level="INFO" enabled_by_default="true" />
+    <inspection_tool class="ReplaceInefficientStreamCount" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ReplaceSingleLineLet" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ReplaceSizeCheckWithIsNotEmpty" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ReplaceSizeZeroCheckWithIsEmpty" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ReplaceWithOperatorAssignment" enabled="false" level="WEAK WARNING" enabled_by_default="true" />
     <inspection_tool class="RequiredArtifactTypeInspection" enabled="false" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="RequiredAttributes" enabled="true" level="WARNING" enabled_by_default="true">
@@ -2309,6 +2401,7 @@
     </inspection_tool>
     <inspection_tool class="ReturnOfDateField" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ReturnOfInnerClass" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="ReturnSeparatedFromComputation" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="ReturnThis" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ReuseOfLocalVariable" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ReuseOfLocalVariableJS" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -2316,7 +2409,7 @@
     <inspection_tool class="RuntimeExecWithNonConstantString" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="SSBasedInspection" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="SafeLock" enabled="false" level="WARNING" enabled_by_default="false" />
-    <inspection_tool class="SafeVarargsDetector" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SafeVarargsDetector" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="SamePackageImport" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="SameParameterValue" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="SameReturnValue" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -2390,6 +2483,8 @@
     <inspection_tool class="Since15" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="SingleCharacterStartsWith" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="SingleClassImport" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SingleElementAnnotation" enabled="false" level="INFORMATION" enabled_by_default="false" />
+    <inspection_tool class="SingleStatementInBlock" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="Singleton" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="SingletonInjectsScoped" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="SizeReplaceableByIsEmpty" enabled="true" level="WARNING" enabled_by_default="true" />
@@ -2471,6 +2566,7 @@
     <inspection_tool class="SqlShouldBeInGroupByInspection" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="SqlSignatureInspection" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="SqlTypeInspection" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SqlUnusedVariableInspection" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="StandardVariableNames" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="StatefulEp" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="StatementsPerFunctionJS" enabled="false" level="WARNING" enabled_by_default="false">
@@ -2552,6 +2648,7 @@
     <inspection_tool class="StrutsValidatorFormInspection" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="StrutsValidatorInspection" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="StubBasedPsiElementBaseGetParent" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="Stylelint" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="SubstringZero" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="SubtractionInCompareTo" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="SuperClassHasFrequentlyUsedInheritors" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -2586,7 +2683,7 @@
     <inspection_tool class="SwitchStatementsWithoutDefault" enabled="false" level="WARNING" enabled_by_default="false">
       <option name="m_ignoreFullyCoveredEnums" value="true" />
     </inspection_tool>
-    <inspection_tool class="SynchronizationOnGetClass" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="SynchronizationOnGetClass" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="SynchronizationOnLocalVariableOrMethodParameter" enabled="true" level="WARNING" enabled_by_default="true">
       <option name="reportLocalVariables" value="true" />
       <option name="reportMethodParameters" value="true" />
@@ -2652,6 +2749,7 @@
     <inspection_tool class="ThrowFromFinallyBlock" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="ThrowFromFinallyBlockJS" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="ThrowableInstanceNeverThrown" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ThrowableNotThrown" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ThrowablePrintStackTrace" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ThrowablePrintedToSystemOut" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="ThrowableResultOfMethodCallIgnored" enabled="true" level="WARNING" enabled_by_default="true" />
@@ -2680,6 +2778,7 @@
     <inspection_tool class="TrivialMethodReference" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="TrivialStringConcatenation" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="TryFinallyCanBeTryWithResources" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="TryStatementWithMultipleResources" enabled="false" level="INFORMATION" enabled_by_default="false" />
     <inspection_tool class="TryWithIdenticalCatches" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="TsLint" enabled="false" level="ERROR" enabled_by_default="false" />
     <inspection_tool class="TypeCustomizer" enabled="false" level="WARNING" enabled_by_default="true" />
@@ -2699,6 +2798,7 @@
     </inspection_tool>
     <inspection_tool class="TypeScriptAccessibilityCheck" enabled="false" level="WEAK WARNING" enabled_by_default="true" />
     <inspection_tool class="TypeScriptCheckImport" enabled="false" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="TypeScriptPreferShortImport" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="TypeScriptUnresolvedFunction" enabled="false" level="WEAK WARNING" enabled_by_default="true" />
     <inspection_tool class="TypeScriptUnresolvedVariable" enabled="false" level="WEAK WARNING" enabled_by_default="true" />
     <inspection_tool class="TypeScriptValidateJSTypes" enabled="false" level="WEAK WARNING" enabled_by_default="true" />
@@ -2754,6 +2854,7 @@
     <inspection_tool class="UnnecessaryContinue" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="UnnecessaryContinueJS" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="UnnecessaryDefault" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="UnnecessaryEmptyArrayUsage" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="UnnecessaryEnumModifier" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="UnnecessaryExplicitNumericCast" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="UnnecessaryFinalOnLocalVariable" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -2765,7 +2866,7 @@
       <option name="m_ignoreJavadoc" value="false" />
     </inspection_tool>
     <inspection_tool class="UnnecessaryInheritDoc" enabled="false" level="WARNING" enabled_by_default="false" />
-    <inspection_tool class="UnnecessaryInitCause" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UnnecessaryInitCause" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="UnnecessaryInterfaceModifier" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="UnnecessaryJavaDocLink" enabled="true" level="WARNING" enabled_by_default="true">
       <option name="ignoreInlineLinkToSuper" value="false" />
@@ -2823,6 +2924,7 @@
     <inspection_tool class="UnresolvedMessageChannelWarningInspection" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="UnresolvedPropertyKey" enabled="true" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="UnresolvedReference" enabled="true" level="ERROR" enabled_by_default="true" />
+    <inspection_tool class="UnsafeCastFromDynamic" enabled="false" level="INFO" enabled_by_default="false" />
     <inspection_tool class="UnsafeReturnStatementVisitor" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="UnsafeVfsRecursion" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="UnsecureRandomNumberGeneration" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -2876,6 +2978,7 @@
     <inspection_tool class="UsePrimitiveTypes" enabled="false" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="UsePropertyAccessSyntax" enabled="false" level="WEAK WARNING" enabled_by_default="true" />
     <inspection_tool class="UseVirtualFileEquals" enabled="false" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="UseWithIndex" enabled="false" level="INFO" enabled_by_default="false" />
     <inspection_tool class="UtilSchemaInspection" enabled="true" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="UtilityClass" enabled="false" level="WARNING" enabled_by_default="false">
       <option name="ignorableAnnotations">
@@ -2911,6 +3014,7 @@
     <inspection_tool class="WaitCalledOnCondition" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="WaitNotInLoop" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="WaitNotInSynchronizedContext" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="WaitNotifyNotInSynchronizedContext" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="WaitOrAwaitWithoutTimeout" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="WaitWhileHoldingTwoLocks" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="WaitWithoutCorrespondingNotify" enabled="false" level="WARNING" enabled_by_default="false" />
@@ -2940,6 +3044,7 @@
     <inspection_tool class="XmlUnboundNsPrefix" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="XmlUnusedNamespaceDeclaration" enabled="true" level="WARNING" enabled_by_default="true" />
     <inspection_tool class="XmlWithMistakes" enabled="false" level="INFO" enabled_by_default="false" />
+    <inspection_tool class="XmlWrongFileType" enabled="false" level="WARNING" enabled_by_default="false" />
     <inspection_tool class="XmlWrongRootElement" enabled="true" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="XsltDeclarations" enabled="true" level="ERROR" enabled_by_default="true" />
     <inspection_tool class="XsltTemplateInvocation" enabled="true" level="ERROR" enabled_by_default="true" />
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 94ee379..bf764c5 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,7 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="EntryPointsManager">
-    <entry_points version="2.0" />
     <list size="5">
       <item index="0" class="java.lang.String" itemvalue="org.junit.After" />
       <item index="1" class="java.lang.String" itemvalue="org.junit.AfterClass" />
@@ -73,7 +72,7 @@
   <component name="ProjectResources">
     <default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
   </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="false" project-jdk-name="1.8" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/build/classes" />
   </component>
   <component name="SvnBranchConfigurationManager">
diff --git a/Makefile b/Makefile
index de2ff53..88b57d6 100644
--- a/Makefile
+++ b/Makefile
@@ -61,6 +61,7 @@ clean:
 	rm -f gmapsupp.img 632*.img
 	if [ -d 63240001 ]; then rmdir 6324000?; fi
 	rm -f 11112222.img 11112222.tdb
+	rm -rf *.gmapi *.gmap
 	rm -f osmmap*
 	rm -f ovm_*.img
 	rm -f g?.img
diff --git a/resources/help/en/options b/resources/help/en/options
index 3306ac1..ce7346c 100644
--- a/resources/help/en/options
+++ b/resources/help/en/options
@@ -23,6 +23,10 @@ filename
 	compiled img files, if the input files are not already compiled
 	then they are compiled first and then the gmapsupp is created.
 
+--gmapi
+	Create a directory in the "gmapi" format required by Mac
+	applications.
+
 -c filename
 --read-config=filename
 	The given file is opened and each line is an option setting of
@@ -32,9 +36,9 @@ filename
 	long name instead.
 
 --output-dir=filename
-    The directory in which all output files are written. It defaults
-    to the current working directory, i.e. the directory the command is
-    executed from.
+	The directory in which all output files are written. It defaults
+	to the current working directory, i.e. the directory the command is
+	executed from.
 
 -n name
 --mapname=name
@@ -74,9 +78,9 @@ Label options:
 	This is equivalent to --code-page=65001. Note that only newer devices support Unicode.
 
 --code-page=number
-    This option enables the use of international characters. Only 8 bit
-    character sets are supported and so you have to specify which code page
-    you want to use.
+	This option enables the use of international characters. Only 8 bit
+	character sets are supported and so you have to specify which code page
+	you want to use.
 
 	It is entirely dependent on the device firmware which code pages are
 	supported.
@@ -121,46 +125,46 @@ Address search options:
 	  mkgmap:phone
 	  (mkgmap:is_in - used by location-autofill=is_in)
 
-  If the index is created from previously compiled .img files, then the
-  same code page and sorting options (e.g. --code-page, --latin1) must
-  be used as were used to compile the individual map tiles.
-  
+	If the index is created from previously compiled .img files, then the
+	same code page and sorting options (e.g. --code-page, --latin1) must
+	be used as were used to compile the individual map tiles.
+
 --x-split-name-index
-    A temporary option to enable indexing each part of a street name separately.
-    So for example if the street is "Aleksandra Gryglewskiego" then you will be able to
-    search for it as both "Aleksandra" and "Gryglewskiego".  It will also increase the
-    size of the index.  Useful in countries where searching for the first word in name
-    is not the right thing to do.
+	A temporary option to enable indexing each part of a street name separately.
+	So for example if the street is "Aleksandra Gryglewskiego" then you will be able to
+	search for it as both "Aleksandra" and "Gryglewskiego".  It will also increase the
+	size of the index.  Useful in countries where searching for the first word in name
+	is not the right thing to do.
 
-    Note that this option is still experimental and there may be problems. If you find
-    any let us know!
+	Note that this option is still experimental and there may be problems. If you find
+	any let us know!
 
 --bounds=directory|zipfile
-    A directory or a zip file containing the preprocessed bounds files. 
-    Bounds files in a zip file must be located in the zip file's root directory.
-
-    The preprocessed boundaries are used to add special tags to all elements 
-    (points, lines and polygons) containing the elements location information.
-    The style file can be used to assign the address tags mkgmap:country,
-    mkgmap:region etc. using these values.
-    
-    The following special tags are added:          
-              mkgmap:admin_level2 : Name of the admin_level=2 boundary 
-              mkgmap:admin_level3 : Name of the admin_level=3 boundary
-              ..
-              mkgmap:admin_level11
-              mkgmap:postcode : the postal_code value
-              
-    Preprocessed bounds can be created with the following command:
-       java -cp mkgmap.jar 
-          uk.me.parabola.mkgmap.reader.osm.boundary.BoundaryPreprocessor
-          <inputfile> <boundsdir>
-    
-    The input file must contain the boundaries that should be preprocessed. 
-    It can have OSM, PBF or O5M file format. It is recommended that it 
-    contains the boundary data only to avoid very high memory usage.
-    The boundsdir gives the directory where the processed files are stored.
-    This directory can be used as --bounds parameter with mkgmap.               
+	A directory or a zip file containing the preprocessed bounds files. 
+	Bounds files in a zip file must be located in the zip file's root directory.
+
+	The preprocessed boundaries are used to add special tags to all elements 
+	(points, lines and polygons) containing the elements location information.
+	The style file can be used to assign the address tags mkgmap:country,
+	mkgmap:region etc. using these values.
+
+	The following special tags are added:          
+			  mkgmap:admin_level2 : Name of the admin_level=2 boundary 
+			  mkgmap:admin_level3 : Name of the admin_level=3 boundary
+			  ..
+			  mkgmap:admin_level11
+			  mkgmap:postcode : the postal_code value
+			  
+	Preprocessed bounds can be created with the following command:
+	   java -cp mkgmap.jar 
+		  uk.me.parabola.mkgmap.reader.osm.boundary.BoundaryPreprocessor
+		  <inputfile> <boundsdir>
+
+	The input file must contain the boundaries that should be preprocessed. 
+	It can have OSM, PBF or O5M file format. It is recommended that it 
+	contains the boundary data only to avoid very high memory usage.
+	The boundsdir gives the directory where the processed files are stored.
+	This directory can be used as --bounds parameter with mkgmap.               
     
 --location-autofill=[option1,[option2]]
 	Controls how the address fields for country, region, city and zip info 
@@ -168,39 +172,39 @@ Address search options:
 	mkgmap address tags (e.g. mkgmap:city - see option index).
 	Warning: automatic assignment of address fields is somehow a best guess.
 
-    is_in     The is_in tag is analyzed for country and region information.
+	is_in     The is_in tag is analyzed for country and region information.
               
-    nearest   The city/hamlet points that are closest to the element are used 
+	nearest   The city/hamlet points that are closest to the element are used 
               to assign the missing address fields. Beware that cities located 
               in the same tile are used only. So the results close to a tile 
               border have less quality.  
 
 --housenumbers
-  Enables house number search for OSM input files. 
-  All nodes and polygons having addr:housenumber set are matched 
-  to streets. A match between a house number element and a street is created if
-  the street is located within a radius of 150m and the addr:street tag value of 
-  the house number element equals the mgkmap:street tag value of the street. 
-  The mkgmap:street tag must be added to the street in the style file.
-  For optimal results, the tags mkgmap:city and mkgmap:postal_code should be
-  set for the housenumber element. If a street connects two or more cities
-  this allows to find all addresses along the road, even they have the same
-  number.
-  Example for given street name: 
-     Node -  addr:street=Main Street addr:housenumber=2
-     Way 1 - name=Main Street
-     Way 2 - name=Main Street, mkgmap:street=Main Street
-     Way 3 - mkgmap:street=Mainstreet
-     Way 4 - name=Main Street [A504]
-    The node matches to Way 2. It has mkgmap:street set with a value equal to
-    the addr:street tag value of the house number node.
-  If the street is not given with addr:housenumber, mkgmap uses heuristics
+	Enables house number search for OSM input files. 
+	All nodes and polygons having addr:housenumber set are matched 
+	to streets. A match between a house number element and a street is created if
+	the street is located within a radius of 150m and the addr:street tag value of 
+	the house number element equals the mgkmap:street tag value of the street. 
+	The mkgmap:street tag must be added to the street in the style file.
+	For optimal results, the tags mkgmap:city and mkgmap:postal_code should be
+	set for the housenumber element. If a street connects two or more cities
+	this allows to find all addresses along the road, even they have the same
+	number.
+	Example for given street name: 
+	 Node -  addr:street=Main Street addr:housenumber=2
+	 Way 1 - name=Main Street
+	 Way 2 - name=Main Street, mkgmap:street=Main Street
+	 Way 3 - mkgmap:street=Mainstreet
+	 Way 4 - name=Main Street [A504]
+	The node matches to Way 2. It has mkgmap:street set with a value equal to
+	the addr:street tag value of the house number node.
+	If the street is not given with addr:housenumber, mkgmap uses heuristics
 	to find the best match.
-  
+
 Overview map options:
 --overview-mapname=name
-	If --tdbfile is enabled, this gives the name of the overview
-	.img and .tdb files. The default map name is osmmap.
+If --tdbfile is enabled, this gives the name of the overview
+.img and .tdb files. The default map name is osmmap.
 
 --overview-mapnumber=8 digit number
 	If --tdbfile is enabled, this gives the internal 8 digit
@@ -208,17 +212,17 @@ Overview map options:
 	number is 63240000.
 
 --overview-levels
-  like levels, specifies additional levels that are to be written to the
-  overview map. Counting of the levels should continue. Up to 8 additional 
-  levels may be specified, but the lowest usable resolution with MapSource 
-  seems to be 11. The hard coded default is empty.      
+	like levels, specifies additional levels that are to be written to the
+	overview map. Counting of the levels should continue. Up to 8 additional 
+	levels may be specified, but the lowest usable resolution with MapSource 
+	seems to be 11. The hard coded default is empty.      
 
 --remove-ovm-work-files
-  If overview-levels is used, mkgmap creates one additional file 
-  with the prefix ovm_ for each map (*.img) file. 
-  These files are used to create the overview map.
-  With option --remove-ovm-work-files=true the files are removed 
-  after the overview map was created. The default is to keep the files.  
+	If overview-levels is used, mkgmap creates one additional file 
+	with the prefix ovm_ for each map (*.img) file. 
+	These files are used to create the overview map.
+	With option --remove-ovm-work-files=true the files are removed 
+	after the overview map was created. The default is to keep the files.  
 
 Style options:
 --style-file=file
@@ -241,8 +245,8 @@ Style options:
 
 --style=name
 	Specify a style name. Must be used if --style-file points to a 
-  directory or zip file containing multiple styles. If --style-file 
-  is not used, it selects one of the built-in styles. 
+	directory or zip file containing multiple styles. If --style-file 
+	is not used, it selects one of the built-in styles. 
 
 --list-styles
 	List the available styles. If this option is preceded by a style-file
@@ -250,9 +254,9 @@ Style options:
 
 --check-styles
 	Perform some checks on the available styles. If this option is 
-  preceded by a style-file option then it checks the styles 
-  available within that file. If it is also preceded by the style
-  option it will only check that style.
+	preceded by a style-file option then it checks the styles 
+	available within that file. If it is also preceded by the style
+	option it will only check that style.
 
 --levels=levels code
 	Change the way that the levels on the map correspond to the zoom
@@ -293,9 +297,9 @@ Product description options:
 	drop-down. The default is "OSM map".
 
 --area-name
-  Area name is displayed on Garmin units (or at least on eTrex) as the second 
-  part of the mapname in the list of the individual maps.
-   
+	Area name is displayed on Garmin units (or at least on eTrex) as the second 
+	part of the mapname in the list of the individual maps.
+
 --copyright-message=note
 	Specify a copyright message for files that do not contain one.
 
@@ -306,7 +310,7 @@ Product description options:
 
 --license-file=file
 	Specify a file which content will be added as license. 
-  All entries of all maps will be merged in the overview map.
+	All entries of all maps will be merged in the overview map.
 
 Optimization options:
 
@@ -329,21 +333,21 @@ Optimization options:
   Default is enabled, use --no-merge-lines to disable.
 	
 --min-size-polygon=NUM
-  Removes all polygons smaller than NUM from the map.
-  This reduces map size and speeds up redrawing of maps. 
-  Recommended value is 8 to 15, default is 8.
-  See also polygon-size-limits.
-   
+	Removes all polygons smaller than NUM from the map.
+	This reduces map size and speeds up redrawing of maps. 
+	Recommended value is 8 to 15, default is 8.
+	See also polygon-size-limits.
+
 --polygon-size-limits=limits code
-  Allows to specify different min-size-polygon values for each resolution.
-  Sample:  
-  --polygon-size-limits="24:12, 18:10, 16:8, 14:4, 12:2, 11:0"
-  If a resolution is not given, mkgmap uses the value for the next higher 
-  one. For the given sample, resolutions 19 to 24 will use value 12,
-  resolution 17 and 18 will use 10, and so on.
-  Value 0 means to skip the size filter. 
-  Note that in resolution 24 the filter is not used.  
-   
+	Allows to specify different min-size-polygon values for each resolution.
+	Sample:  
+	--polygon-size-limits="24:12, 18:10, 16:8, 14:4, 12:2, 11:0"
+	If a resolution is not given, mkgmap uses the value for the next higher 
+	one. For the given sample, resolutions 19 to 24 will use value 12,
+	resolution 17 and 18 will use 10, and so on.
+	Value 0 means to skip the size filter. 
+	Note that in resolution 24 the filter is not used.  
+
 Miscellaneous options:
 
 --max-jobs[=number]
@@ -508,21 +512,21 @@ Miscellaneous options:
 	       * the centre point of the biggest area
 
 --pois-to-areas-placement[=taglist]
-    A semicolon separated list of tag=value definitions. A POI is placed at the first
-    node of the polygon tagged with the first tag/value pair. If none of the nodes are
-    tagged with the first tag-value pair the first node tagged with the second tag-value
-    pair is used and so on. If none of the tag-value pairs matches or the taglist is empty 
-    the centre of the polygon is used.
-    It is possible to define wildcards for tag values like entrance=*.
-    Default: entrance=main;entrance=yes;building=entrance
+	A semicolon separated list of tag=value definitions. A POI is placed at the first
+	node of the polygon tagged with the first tag/value pair. If none of the nodes are
+	tagged with the first tag-value pair the first node tagged with the second tag-value
+	pair is used and so on. If none of the tag-value pairs matches or the taglist is empty 
+	the centre of the polygon is used.
+	It is possible to define wildcards for tag values like entrance=*.
+	Default: entrance=main;entrance=yes;building=entrance
 
 --precomp-sea=directory|zipfile
-    Defines the directory or a zip file that contains precompiled sea tiles. 
-    Sea files in a zip file must be located in the zip file's root directory or in 
-    a sub directory sea. When this option is defined all natural=coastline tags 
-    from the input OSM tiles are removed and the precompiled data is used instead. 
-    This option can be combined with the generate-sea options multipolygon, polygons 
-    and land-tag. The coastlinefile option is ignored if precomp-sea is set.      
+	Defines the directory or a zip file that contains precompiled sea tiles. 
+	Sea files in a zip file must be located in the zip file's root directory or in 
+	a sub directory sea. When this option is defined all natural=coastline tags 
+	from the input OSM tiles are removed and the precompiled data is used instead. 
+	This option can be combined with the generate-sea options multipolygon, polygons 
+	and land-tag. The coastlinefile option is ignored if precomp-sea is set.      
 
 --coastlinefile=filename[,filename]
 	Defines a comma separated list of files that contain coastline 
@@ -593,7 +597,7 @@ Miscellaneous options:
 	(NSIS) to create a Windows Mapsource Installer.
 
 --make-all-cycleways
-  Deprecated, use --make-opposite-cycleways instead. Former meaning: 
+	Deprecated, use --make-opposite-cycleways instead. Former meaning: 
 	Turn on all of the options that make cycleways.
 
 --make-opposite-cycleways
@@ -602,7 +606,7 @@ Miscellaneous options:
 	the original that allows bicycle traffic (in both directions).
 
 --make-cycleways
-  Now ignored, former meaning:
+	Now ignored, former meaning:
 	Some streets have a separate cycleway track/lane just for
 	bicycle traffic and this option makes a way with the same
 	points as the original that allows bicycle traffic. Also,
@@ -610,22 +614,22 @@ Miscellaneous options:
 	(unless that way's bicycle access has been defined).
 
 --link-pois-to-ways
-    This option may copy some specific attributes of a POI 
-    to a small part of the way the POI is located on. This can be used
-    to let barriers block a way or to lower the calculated speed
-    around traffic signals.
-    POIs with the tags highway=* (e.g. highway=traffic_signals)  
-    or barrier=* (e.g. barrier=cycle_barrier) are supported.
-    The style developer must add at least one of the access tags
-    (mkgmap:foot, mkgmap:car etc.), mkgmap:road-speed and/or 
-    mkgmap:road-class to the POI. 
-    The access tags are ignored if they have no effect for the way, 
-    else a route restriction is added at the POI so that only 
-    allowed vehicles are routed through it. 
-    The tags mkgmap:road-speed and/or mkgmap:road-class are 
-    applied to a small part of the way around the POI, typically
-    to the next junction or a length of ~25 m. The tags
-    are ignored for pedestrian-only ways.      
+	This option may copy some specific attributes of a POI 
+	to a small part of the way the POI is located on. This can be used
+	to let barriers block a way or to lower the calculated speed
+	around traffic signals.
+	POIs with the tags highway=* (e.g. highway=traffic_signals)  
+	or barrier=* (e.g. barrier=cycle_barrier) are supported.
+	The style developer must add at least one of the access tags
+	(mkgmap:foot, mkgmap:car etc.), mkgmap:road-speed and/or 
+	mkgmap:road-class to the POI. 
+	The access tags are ignored if they have no effect for the way, 
+	else a route restriction is added at the POI so that only 
+	allowed vehicles are routed through it. 
+	The tags mkgmap:road-speed and/or mkgmap:road-class are 
+	applied to a small part of the way around the POI, typically
+	to the next junction or a length of ~25 m. The tags
+	are ignored for pedestrian-only ways.      
 
 --process-destination
 	Splits all motorway_link, trunk_link, primary_link, secondary_link,
@@ -642,20 +646,20 @@ Miscellaneous options:
 	See also --process-exits.
 	
 --process-exits
-    Usual Garmin devices do not tell the name of the exit on motorways 
-    while routing with mkgmap created maps. This option splits each
-    motorway_link, trunk_link, primary_link, secondary_link, and tertiary_link 
+	Usual Garmin devices do not tell the name of the exit on motorways 
+	while routing with mkgmap created maps. This option splits each
+	motorway_link, trunk_link, primary_link, secondary_link, and tertiary_link 
 		way into three parts. 
 		All parts are tagged with the original tags of the link. 
 		Additionally the middle part is tagged with the following tags:
-      mkgmap:exit_hint=true
-      mkgmap:exit_hint_ref=<ref tag value of the exit>
-      mkgmap:exit_hint_name=<name tag value of the exit>
-      mkgmap:exit_hint_exit_to=<exit_to tag value of the exit>
-    Adding a rule checking the mkgmap:exit_hint=true makes it possible
-    to use any routable Garmin type (except 0x08 and 0x09) for the middle 
-    part so that the Garmin device tells the name of this middle part as 
-    hint where to leave the major road.
+	  mkgmap:exit_hint=true
+	  mkgmap:exit_hint_ref=<ref tag value of the exit>
+	  mkgmap:exit_hint_name=<name tag value of the exit>
+	  mkgmap:exit_hint_exit_to=<exit_to tag value of the exit>
+	Adding a rule checking the mkgmap:exit_hint=true makes it possible
+	to use any routable Garmin type (except 0x08 and 0x09) for the middle 
+	part so that the Garmin device tells the name of this middle part as 
+	hint where to leave the major road.
 	The first part must have type 0x08 or 0x09 so that Garmin uses the hint. 
 	
 --delete-tags-file=FILENAME
@@ -686,7 +690,7 @@ Miscellaneous options:
 	things.
 
 --hide-gmapsupp-on-pc
-  Set a bit in the gmapsupp.img that tells PC software that the file is
+	Set a bit in the gmapsupp.img that tells PC software that the file is
 	already installed on the PC and therefore there is no need to read it 
 	from the device.
 
diff --git a/resources/mkgmap-version.properties b/resources/mkgmap-version.properties
index 4d2e788..4a2fc76 100644
--- a/resources/mkgmap-version.properties
+++ b/resources/mkgmap-version.properties
@@ -1,2 +1,2 @@
-svn.version: 3706
-build.timestamp: 2016-11-28T13:14:14+0000
+svn.version: 3741
+build.timestamp: 2016-12-26T11:25:19+0000
diff --git a/resources/styles/default/inc/water_lines b/resources/styles/default/inc/water_lines
index e93ab4e..c89add3 100644
--- a/resources/styles/default/inc/water_lines
+++ b/resources/styles/default/inc/water_lines
@@ -8,7 +8,6 @@ route=ferry {add mkgmap:ferry=1} [0x1b road_class=3 road_speed=0 resolution 19]
 (waterway=stream | waterway=drain) & intermittent=yes [0x10A02 resolution 22]
 
 waterway=canal [0x1f resolution 21]
-waterway=drain [0x1f resolution 22]
 waterway=river [0x1f resolution 18]
 waterway=rapids|waterway=waterfall [0x1f resolution 22]
-waterway=stream [0x18 resolution 22]
+waterway=stream | waterway=drain [0x18 resolution 22]
diff --git a/src/uk/me/parabola/imgfmt/app/Area.java b/src/uk/me/parabola/imgfmt/app/Area.java
index fb775fe..99c4c5b 100644
--- a/src/uk/me/parabola/imgfmt/app/Area.java
+++ b/src/uk/me/parabola/imgfmt/app/Area.java
@@ -163,12 +163,13 @@ public class Area {
 			xstart = xend;
 		}
 
-//		assert areas.length == xsplit * ysplit;
 		if (nAreas == areas.length) // no problem
 			return areas;
 // beware - MapSplitter.splitMaxSize requests split of 1/1 if the original area wasn't too big
 		else if (nAreas == 1) // failed to split in half
-			return null;  
+			return null;
+		else if (areas.length == 1 && areas[0] == null)
+			return null;
 		else
 			throw new MapFailedException("Area split shift align problems");
 	}
diff --git a/src/uk/me/parabola/imgfmt/app/BufferedImgFileReader.java b/src/uk/me/parabola/imgfmt/app/BufferedImgFileReader.java
index 2a9b295..ebec9e5 100644
--- a/src/uk/me/parabola/imgfmt/app/BufferedImgFileReader.java
+++ b/src/uk/me/parabola/imgfmt/app/BufferedImgFileReader.java
@@ -16,6 +16,7 @@
  */
 package uk.me.parabola.imgfmt.app;
 
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 
@@ -172,18 +173,19 @@ public class BufferedImgFileReader implements ImgFileReader {
 	}
 
 	/**
-	 * Read a zero terminated string from the file.
-	 * @return A string
+	 * Read a zero terminated string from the file, still as raw bytes.
+	 *
+	 * @return A byte array containing the encoded representation of the string.
 	 * @throws ReadFailedException For failures.
 	 */
-	public String getZString() throws ReadFailedException {
-		StringBuffer sb = new StringBuffer();
+	public byte[] getZString() throws ReadFailedException {
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
 
 		// Slow but sure implementation.
 		for (byte b = get(); b != 0; b = get()) {
-			sb.append((char) b);
+			out.write(b);
 		}
-		return sb.toString();
+		return out.toByteArray();
 	}
 
 	/**
diff --git a/src/uk/me/parabola/imgfmt/app/ImgFileReader.java b/src/uk/me/parabola/imgfmt/app/ImgFileReader.java
index 6603128..c03dcad 100644
--- a/src/uk/me/parabola/imgfmt/app/ImgFileReader.java
+++ b/src/uk/me/parabola/imgfmt/app/ImgFileReader.java
@@ -96,7 +96,7 @@ public interface ImgFileReader extends Closeable {
 	 * @return A string
 	 * @throws ReadFailedException For failures.
 	 */
-	public String getZString() throws ReadFailedException;
+	public byte[] getZString() throws ReadFailedException;
 
 	/**
 	 * Read in a string of digits in the compressed base 11 format that is used
diff --git a/src/uk/me/parabola/imgfmt/app/labelenc/CodeFunctions.java b/src/uk/me/parabola/imgfmt/app/labelenc/CodeFunctions.java
index 24996ec..189490d 100644
--- a/src/uk/me/parabola/imgfmt/app/labelenc/CodeFunctions.java
+++ b/src/uk/me/parabola/imgfmt/app/labelenc/CodeFunctions.java
@@ -40,7 +40,7 @@ public class CodeFunctions {
 		return encoder;
 	}
 
-	protected void setDecoder(CharacterDecoder decoder) {
+	private void setDecoder(CharacterDecoder decoder) {
 		this.decoder = decoder;
 	}
 
@@ -52,7 +52,7 @@ public class CodeFunctions {
 		return encodingType;
 	}
 
-	protected void setEncodingType(int encodingType) {
+	private void setEncodingType(int encodingType) {
 		this.encodingType = encodingType;
 	}
 
@@ -78,6 +78,12 @@ public class CodeFunctions {
 			funcs.setEncoder(new Format6Encoder());
 			funcs.setDecoder(new Format6Decoder());
 			break;
+		case "cp0":  // This is used for ascii but with the single byte format
+			funcs.setEncodingType(ENCODING_FORMAT9);
+			funcs.setEncoder(new AnyCharsetEncoder("ascii", new TableTransliterator("ascii")));
+			funcs.setDecoder(new AnyCharsetDecoder("ascii"));
+			funcs.setCodepage(0);
+			break;
 		case "cp1252":
 		case "latin1":
 			funcs.setEncodingType(ENCODING_FORMAT9);
diff --git a/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java b/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java
index 22c415a..9e41aaa 100644
--- a/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java
+++ b/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java
@@ -50,7 +50,7 @@ public class LBLFile extends ImgFile {
 
 	private CharacterEncoder textEncoder = CodeFunctions.getDefaultEncoder();
 
-	private final Map<EncodedText, Label> labelCache = new HashMap<EncodedText, Label>();
+	private final Map<EncodedText, Label> labelCache = new HashMap<>();
 
 	private final LBLHeader lblHeader = new LBLHeader();
 
@@ -224,4 +224,8 @@ public class LBLFile extends ImgFile {
 	public int numZips() {
 		return places.numZips();
 	}
+
+	public int getCodePage() {
+		return lblHeader.getCodePage();
+	}
 }
diff --git a/src/uk/me/parabola/imgfmt/app/lbl/LBLFileReader.java b/src/uk/me/parabola/imgfmt/app/lbl/LBLFileReader.java
index fd58cd5..27bdc37 100644
--- a/src/uk/me/parabola/imgfmt/app/lbl/LBLFileReader.java
+++ b/src/uk/me/parabola/imgfmt/app/lbl/LBLFileReader.java
@@ -18,6 +18,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
 import uk.me.parabola.imgfmt.app.BufferedImgFileReader;
 import uk.me.parabola.imgfmt.app.ImgFile;
 import uk.me.parabola.imgfmt.app.ImgFileReader;
@@ -48,11 +49,11 @@ public class LBLFileReader extends ImgFile {
 
 	private final LBLHeader header = new LBLHeader();
 
-	private final Map<Integer, Label> labels = new HashMap<>();
-	private final Map<Integer, POIRecord> pois = new HashMap<>();
+	private final Int2ObjectOpenHashMap<Label> labels = new Int2ObjectOpenHashMap<>();
+	private final Int2ObjectOpenHashMap<POIRecord> pois = new Int2ObjectOpenHashMap<>();
 	private final List<Country> countries = new ArrayList<>();
 	private final List<Region> regions = new ArrayList<>();
-	private final Map<Integer, Zip> zips = new HashMap<>();
+	private final Int2ObjectOpenHashMap<Zip> zips = new Int2ObjectOpenHashMap<>();
 	private final List<City> cities = new ArrayList<>();
 
 	public LBLFileReader(ImgChannel chan) {
diff --git a/src/uk/me/parabola/imgfmt/app/map/Map.java b/src/uk/me/parabola/imgfmt/app/map/Map.java
index 18f94fb..5e5d122 100644
--- a/src/uk/me/parabola/imgfmt/app/map/Map.java
+++ b/src/uk/me/parabola/imgfmt/app/map/Map.java
@@ -23,6 +23,7 @@ import uk.me.parabola.imgfmt.Utils;
 import uk.me.parabola.imgfmt.app.Area;
 import uk.me.parabola.imgfmt.app.ImgFile;
 import uk.me.parabola.imgfmt.app.Label;
+import uk.me.parabola.imgfmt.app.labelenc.CodeFunctions;
 import uk.me.parabola.imgfmt.app.lbl.LBLFile;
 import uk.me.parabola.imgfmt.app.net.NETFile;
 import uk.me.parabola.imgfmt.app.net.NODFile;
@@ -115,8 +116,8 @@ public class Map implements InternalFiles, Configurable {
 	}
 
 	public void config(EnhancedProperties props) {
-		// we don't want routing infos in the overview map (for now)
-		if (OverviewBuilder.isOverviewImg(mapName) == false){
+		// we don't want routing info in the overview map (for now)
+		if (!OverviewBuilder.isOverviewImg(mapName)){
 			try {
 				if (props.containsKey("route")) {
 					addNet();
@@ -131,11 +132,11 @@ public class Map implements InternalFiles, Configurable {
 		treFile.config(props);
 	}
 
-	protected void addNet() throws FileExistsException {
+	private void addNet() throws FileExistsException {
 		netFile = new NETFile(fileSystem.create(mapName + ".NET"));
 	}
 
-	protected void addNod() throws FileExistsException {
+	private void addNod() throws FileExistsException {
 		nodFile = new NODFile(fileSystem.create(mapName + ".NOD"), true);
 	}
 
@@ -159,12 +160,17 @@ public class Map implements InternalFiles, Configurable {
 
 	/**
 	 * There is an area after the TRE header and before its data
-	 * starts that can be used to save any old junk it seems.
+	 * starts that is used to save licence info.
 	 *
-	 * @param info Any string.
+	 * It seems that this must follow the code page of the LBL file.  The format6 encoding is not allowed
+	 * however.
+	 *
+	 * @param msg Any string.
 	 */
-	public void addInfo(String info) {
-		treFile.addInfo(info);
+	public void addInfo(String msg) {
+		int codePage = lblFile.getCodePage();
+		CodeFunctions functions = CodeFunctions.createEncoderForLBL(0, codePage);
+		treFile.addInfo(functions.getEncoder().encodeText(msg));
 	}
 
 	/**
diff --git a/src/uk/me/parabola/imgfmt/app/trergn/TREFile.java b/src/uk/me/parabola/imgfmt/app/trergn/TREFile.java
index 8542279..aa4bfeb 100644
--- a/src/uk/me/parabola/imgfmt/app/trergn/TREFile.java
+++ b/src/uk/me/parabola/imgfmt/app/trergn/TREFile.java
@@ -21,12 +21,12 @@ import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
-import uk.me.parabola.imgfmt.Utils;
 import uk.me.parabola.imgfmt.app.Area;
 import uk.me.parabola.imgfmt.app.BufferedImgFileWriter;
 import uk.me.parabola.imgfmt.app.ImgFile;
 import uk.me.parabola.imgfmt.app.ImgFileWriter;
 import uk.me.parabola.imgfmt.app.Label;
+import uk.me.parabola.imgfmt.app.labelenc.EncodedText;
 import uk.me.parabola.imgfmt.fs.ImgChannel;
 import uk.me.parabola.log.Logger;
 import uk.me.parabola.util.Configurable;
@@ -50,7 +50,7 @@ public class TREFile extends ImgFile implements Configurable {
 	//	private List<Zoom> mapLevels = new ArrayList<Zoom>();
 	private final Zoom[] mapLevels = new Zoom[16];
 
-	private final List<Label> copyrights = new ArrayList<Label>();
+	private final List<Label> copyrights = new ArrayList<>();
 
 	// Information about polylines.  eg roads etc.
 	private final List<PolylineOverview> polylineOverviews = new ArrayList<PolylineOverview>();
@@ -82,15 +82,14 @@ public class TREFile extends ImgFile implements Configurable {
 	 * Add a string to the 'mapinfo' section.  This is a section between the
 	 * header and the start of the data.  Nothing points to it directly.
 	 *
-	 * @param msg A string, usually used to describe the program that generated
-	 * the file.
+	 * @param enc A string in the EncodedText format.
 	 */
-	public void addInfo(String msg) {
-		byte[] val = Utils.toBytes(msg);
+	public void addInfo(EncodedText enc) {
+		byte[] val = enc.getCtext();
 		if (position() != header.getHeaderLength() + header.getMapInfoSize())
 			throw new IllegalStateException("All info must be added before anything else");
 
-		header.setMapInfoSize(header.getMapInfoSize() + (val.length+1));
+		header.setMapInfoSize(header.getMapInfoSize() + enc.getLength() + 1);
 		getWriter().put(val);
 		getWriter().put((byte) 0);
 	}
diff --git a/src/uk/me/parabola/imgfmt/app/trergn/TREFileReader.java b/src/uk/me/parabola/imgfmt/app/trergn/TREFileReader.java
index 11eb272..289fba7 100644
--- a/src/uk/me/parabola/imgfmt/app/trergn/TREFileReader.java
+++ b/src/uk/me/parabola/imgfmt/app/trergn/TREFileReader.java
@@ -21,6 +21,9 @@ import uk.me.parabola.imgfmt.app.ImgFileReader;
 import uk.me.parabola.imgfmt.app.ImgReader;
 import uk.me.parabola.imgfmt.app.Label;
 import uk.me.parabola.imgfmt.app.Section;
+import uk.me.parabola.imgfmt.app.labelenc.CharacterDecoder;
+import uk.me.parabola.imgfmt.app.labelenc.CodeFunctions;
+import uk.me.parabola.imgfmt.app.labelenc.DecodedText;
 import uk.me.parabola.imgfmt.app.lbl.LBLFileReader;
 import uk.me.parabola.imgfmt.fs.ImgChannel;
 import uk.me.parabola.util.EnhancedProperties;
@@ -196,16 +199,25 @@ public class TREFileReader extends ImgReader {
 		header.config(props);
 	}
 
-	public String[] getMapInfo() {
-
-		List<String> msgs = new ArrayList<String>();
+	public String[] getMapInfo(int codePage) {
+		CodeFunctions funcs = CodeFunctions.createEncoderForLBL(0, codePage);
+		CharacterDecoder decoder = funcs.getDecoder();
 
 		// First do the ones in the TRE header gap
 		ImgFileReader reader = getReader();
 		reader.position(header.getHeaderLength());
+		List<String> msgs = new ArrayList<>();
 		while (reader.position() < header.getHeaderLength() + header.getMapInfoSize()) {
-			String m = reader.getZString();
-			msgs.add(m);
+			byte[] m = reader.getZString();
+
+			decoder.reset();
+			for (byte b : m)
+				decoder.addByte(b);
+
+			DecodedText text = decoder.getText();
+			String text1 = text.getText();
+
+			msgs.add(text1);
 		}
 
 
@@ -215,7 +227,7 @@ public class TREFileReader extends ImgReader {
 	public String[] getCopyrights(LBLFileReader lblReader) {
 		Section sect = header.getCopyrightSection();
 		ImgFileReader reader = getReader();
-		List<String> msgs = new ArrayList<String>();
+		List<String> msgs = new ArrayList<>();
 
 		long pos = sect.getPosition();
 		while (pos < sect.getEndPos()) {
diff --git a/src/uk/me/parabola/imgfmt/mps/Block.java b/src/uk/me/parabola/imgfmt/mps/Block.java
deleted file mode 100644
index f089692..0000000
--- a/src/uk/me/parabola/imgfmt/mps/Block.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2007 Steve Ratcliffe
- * 
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- * 
- *  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.
- * 
- * 
- * Author: Steve Ratcliffe
- * Create date: Dec 19, 2007
- */
-package uk.me.parabola.imgfmt.mps;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-import uk.me.parabola.imgfmt.fs.ImgChannel;
-import uk.me.parabola.io.StructuredOutputStream;
-
-/**
- * All the blocks in the file have a type and a length.
- *
- * @author Steve Ratcliffe
- */
-public abstract class Block {
-	private final int type;
-	private final ByteArrayOutputStream output = new ByteArrayOutputStream();
-
-	protected Block(int type) {
-		this.type = type;
-	}
-
-	public void write(ImgChannel chan) throws IOException {
-		// First write the body to the byte buffer so that we know its length.
-		writeBody(new StructuredOutputStream(output));
-
-		ByteBuffer buf = ByteBuffer.allocate(16);
-		buf.order(ByteOrder.LITTLE_ENDIAN);
-		buf.put((byte) type);
-		char len = getLength();
-		buf.putChar(len);
-
-		// write the header.
-		buf.flip();
-		chan.write(buf);
-
-		// write the body.
-		buf = ByteBuffer.allocate(len);
-		buf.put(output.toByteArray());
-		buf.flip();
-		chan.write(buf);
-	}
-
-	/**
-	 * Writes the body to the output stream given.
-	 *
-	 * @param out The stream to write to.
-	 */
-	protected abstract void writeBody(StructuredOutputStream out) throws IOException;
-
-	/**
-	 * This is only valid after everything is written to the block.
-	 *
-	 * @return The length of the block (or the amount written already).
-	 */
-	private char getLength() {
-		int len = output.toByteArray().length;
-		assert len <= 0xffff;
-		return (char) len;
-	}
-}
diff --git a/src/uk/me/parabola/imgfmt/mps/MapBlock.java b/src/uk/me/parabola/imgfmt/mps/MapBlock.java
index 296736d..c46642e 100644
--- a/src/uk/me/parabola/imgfmt/mps/MapBlock.java
+++ b/src/uk/me/parabola/imgfmt/mps/MapBlock.java
@@ -24,7 +24,7 @@ import uk.me.parabola.io.StructuredOutputStream;
  *
  * @author Steve Ratcliffe
  */
-public class MapBlock extends Block {
+public class MapBlock extends MpsBlock {
 	private static final int BLOCK_TYPE = 0x4c;
 
 	private int familyId;
@@ -36,8 +36,8 @@ public class MapBlock extends Block {
 	private String mapDescription;
 	private String areaName;
 
-	public MapBlock() {
-		super(BLOCK_TYPE);
+	public MapBlock(int codePage) {
+		super(BLOCK_TYPE, codePage);
 	}
 
 	protected void writeBody(StructuredOutputStream out) throws IOException {
diff --git a/src/uk/me/parabola/imgfmt/mps/MapsetBlock.java b/src/uk/me/parabola/imgfmt/mps/MapsetBlock.java
index d69736c..a5272fc 100644
--- a/src/uk/me/parabola/imgfmt/mps/MapsetBlock.java
+++ b/src/uk/me/parabola/imgfmt/mps/MapsetBlock.java
@@ -25,13 +25,13 @@ import java.io.IOException;
  *
  * @author Steve Ratcliffe
  */
-public class MapsetBlock extends Block {
+public class MapsetBlock extends MpsBlock {
 	private static final int BLOCK_TYPE = 0x56;
 	
 	private String name = "OSM map set";
 	
 	public MapsetBlock() {
-		super(BLOCK_TYPE);
+		super(BLOCK_TYPE, 0);
 	}
 
 	protected void writeBody(StructuredOutputStream out) throws IOException {
diff --git a/src/uk/me/parabola/imgfmt/mps/MpsBlock.java b/src/uk/me/parabola/imgfmt/mps/MpsBlock.java
new file mode 100644
index 0000000..2d610af
--- /dev/null
+++ b/src/uk/me/parabola/imgfmt/mps/MpsBlock.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+package uk.me.parabola.imgfmt.mps;
+
+import uk.me.parabola.io.FileBlock;
+
+public abstract class MpsBlock extends FileBlock {
+	private final int codePage;
+
+	public MpsBlock(int kind, int codePage) {
+		super(kind);
+		this.codePage = codePage;
+	}
+
+	public int getCodePage() {
+		return codePage;
+	}
+}
diff --git a/src/uk/me/parabola/imgfmt/mps/MpsFile.java b/src/uk/me/parabola/imgfmt/mps/MpsFile.java
index 9b6b9ca..e9f2d53 100644
--- a/src/uk/me/parabola/imgfmt/mps/MpsFile.java
+++ b/src/uk/me/parabola/imgfmt/mps/MpsFile.java
@@ -17,6 +17,8 @@
 package uk.me.parabola.imgfmt.mps;
 
 import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.channels.Channels;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -36,8 +38,8 @@ import uk.me.parabola.imgfmt.fs.ImgChannel;
 public class MpsFile {
 	private String mapsetName = "OSM map set";
 
-	private final Set<ProductBlock> products = new HashSet<ProductBlock>();
-	private final List<MapBlock> maps = new ArrayList<MapBlock>();
+	private final Set<ProductBlock> products = new HashSet<>();
+	private final List<MapBlock> maps = new ArrayList<>();
 
 	private final ImgChannel chan;
 
@@ -46,15 +48,16 @@ public class MpsFile {
 	}
 
 	public void sync() throws IOException {
+		OutputStream os = Channels.newOutputStream(chan);
 		for (MapBlock map : maps)
-			map.write(chan);
+			map.writeTo(os, map.getCodePage());
 
 		for (ProductBlock block : products)
-			block.write(chan);
+			block.writeTo(os, block.getCodePage());
 
 		MapsetBlock mapset = new MapsetBlock();
 		mapset.setName(mapsetName);
-		mapset.write(chan);
+		mapset.writeTo(os, mapset.getCodePage());
 	}
 
 	public void addMap(MapBlock map) {
diff --git a/src/uk/me/parabola/imgfmt/mps/MpsFileReader.java b/src/uk/me/parabola/imgfmt/mps/MpsFileReader.java
index bfc8c8f..00eb2de 100644
--- a/src/uk/me/parabola/imgfmt/mps/MpsFileReader.java
+++ b/src/uk/me/parabola/imgfmt/mps/MpsFileReader.java
@@ -23,6 +23,8 @@ import java.util.List;
 
 import uk.me.parabola.imgfmt.app.BufferedImgFileReader;
 import uk.me.parabola.imgfmt.app.ImgFileReader;
+import uk.me.parabola.imgfmt.app.labelenc.CharacterDecoder;
+import uk.me.parabola.imgfmt.app.labelenc.CodeFunctions;
 import uk.me.parabola.imgfmt.fs.ImgChannel;
 
 /**
@@ -36,16 +38,22 @@ import uk.me.parabola.imgfmt.fs.ImgChannel;
  */
 public class MpsFileReader implements Closeable {
 
-	private final List<MapBlock> maps = new ArrayList<MapBlock>();
-	private final List<ProductBlock> products = new ArrayList<ProductBlock>();
+	private final List<MapBlock> maps = new ArrayList<>();
+	private final List<ProductBlock> products = new ArrayList<>();
 
 	private final ImgChannel chan;
 	private final ImgFileReader reader;
+	private final CharacterDecoder decoder;
+	private final int codePage;
 
-	public MpsFileReader(ImgChannel chan) {
+	public MpsFileReader(ImgChannel chan, int codePage) {
 		this.chan = chan;
 		this.reader = new BufferedImgFileReader(chan);
 
+		this.codePage = codePage;
+		CodeFunctions funcs = CodeFunctions.createEncoderForLBL(0, codePage);
+		decoder = funcs.getDecoder();
+
 		readBlocks();
 	}
 
@@ -70,26 +78,36 @@ public class MpsFileReader implements Closeable {
 	}
 
 	private void readMapBlock() {
-		MapBlock block = new MapBlock();
+		MapBlock block = new MapBlock(codePage);
 		int val = reader.getInt();
 		block.setIds(val >>> 16, val & 0xffff);
 		block.setMapNumber(reader.getInt());
-		block.setSeriesName(reader.getZString());
-		block.setMapDescription(reader.getZString());
-		block.setAreaName(reader.getZString());
+
+		byte[] zString = reader.getZString();
+		block.setSeriesName(decodeToString(zString));
+		block.setMapDescription(decodeToString(reader.getZString()));
+		block.setAreaName(decodeToString(reader.getZString()));
 		block.setHexNumber(reader.getInt());
 		reader.getInt();
 		maps.add(block);
 	}
 
 	private void readProductBlock() {
-		ProductBlock block = new ProductBlock();
+		ProductBlock block = new ProductBlock(codePage);
 		block.setProductId(reader.getChar());
 		block.setFamilyId(reader.getChar());
-		block.setDescription(reader.getZString());
+		block.setDescription(decodeToString(reader.getZString()));
 		products.add(block);
 	}
 
+	private String decodeToString(byte[] zString) {
+		decoder.reset();
+		for (byte b : zString)
+			decoder.addByte(b);
+
+		return decoder.getText().getText();
+	}
+
 	public List<MapBlock> getMaps() {
 		return maps;
 	}
diff --git a/src/uk/me/parabola/imgfmt/mps/ProductBlock.java b/src/uk/me/parabola/imgfmt/mps/ProductBlock.java
index e672f46..ae17968 100644
--- a/src/uk/me/parabola/imgfmt/mps/ProductBlock.java
+++ b/src/uk/me/parabola/imgfmt/mps/ProductBlock.java
@@ -26,15 +26,15 @@ import uk.me.parabola.io.StructuredOutputStream;
  *
  * @author Steve Ratcliffe
  */
-public class ProductBlock extends Block {
+public class ProductBlock extends MpsBlock {
 	private static final int BLOCK_TYPE = 0x46;
 
 	private int familyId;
 	private int productId;
 	private String description = "OSM maps";
 
-	public ProductBlock() {
-		super(BLOCK_TYPE);
+	public ProductBlock(int codePage) {
+		super(BLOCK_TYPE, codePage);
 	}
 
 	protected void writeBody(StructuredOutputStream out) throws IOException {
diff --git a/src/uk/me/parabola/imgfmt/sys/ImgHeader.java b/src/uk/me/parabola/imgfmt/sys/ImgHeader.java
index a5e66df..f764ffa 100644
--- a/src/uk/me/parabola/imgfmt/sys/ImgHeader.java
+++ b/src/uk/me/parabola/imgfmt/sys/ImgHeader.java
@@ -19,11 +19,15 @@ package uk.me.parabola.imgfmt.sys;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
+import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Date;
 
 import uk.me.parabola.imgfmt.FileSystemParam;
 import uk.me.parabola.imgfmt.Utils;
+import uk.me.parabola.imgfmt.app.labelenc.CharacterEncoder;
+import uk.me.parabola.imgfmt.app.labelenc.CodeFunctions;
+import uk.me.parabola.imgfmt.app.labelenc.EncodedText;
 import uk.me.parabola.imgfmt.fs.ImgChannel;
 import uk.me.parabola.log.Logger;
 
@@ -305,30 +309,42 @@ class ImgHeader {
 
 	/**
 	 * Set the description.  It is spread across two areas in the header.
+	 *
+	 * It appears that the description has to be in ascii.
+	 *
 	 * @param desc The description.
 	 */
 	protected void setDescription(String desc) {
-		int len = desc.length();
+		// Force the description to be in ascii.
+		CodeFunctions funcs = CodeFunctions.createEncoderForLBL(0, 0);
+		CharacterEncoder encoder = funcs.getEncoder();
+		EncodedText enc = encoder.encodeText(desc);
+
+		byte[] ctext = enc.getCtext();
+		int len = enc.getLength() - 1;
 		if (len > 50)
 			throw new IllegalArgumentException("Description is too long (max 50)");
-		String part1, part2;
-		if (len > LEN_MAP_DESCRIPTION) {
-			part1 = desc.substring(0, LEN_MAP_DESCRIPTION);
-			part2 = desc.substring(LEN_MAP_DESCRIPTION, len);
-		} else {
-			part1 = desc.substring(0, len);
-			part2 = "";
+
+		byte[] part1 = new byte[LEN_MAP_DESCRIPTION];
+		Arrays.fill(part1, (byte) ' ');
+
+		byte[] part2 = new byte[LEN_MAP_NAME_CONT];
+		Arrays.fill(part2, (byte) ' ');
+
+		if (ctext != null) {
+			if (len > LEN_MAP_DESCRIPTION) {
+				System.arraycopy(ctext, 0, part1, 0, LEN_MAP_DESCRIPTION);
+				System.arraycopy(ctext, LEN_MAP_DESCRIPTION, part2, 0, len - LEN_MAP_DESCRIPTION);
+			} else {
+				System.arraycopy(ctext, 0, part1, 0, len);
+			}
 		}
 
 		header.position(OFF_MAP_DESCRIPTION);
-		header.put(toByte(part1));
-		for (int i = len; i < LEN_MAP_DESCRIPTION; i++)
-			header.put((byte) ' ');
+		header.put(part1);
 
 		header.position(OFF_MAP_NAME_CONT);
-		header.put(toByte(part2));
-		for (int i = Math.max(len - LEN_MAP_DESCRIPTION, 0); i < LEN_MAP_NAME_CONT; i++)
-			header.put((byte) ' ');
+		header.put(part2);
 
 		header.put((byte) 0); // really?
 	}
diff --git a/src/uk/me/parabola/io/FileBlock.java b/src/uk/me/parabola/io/FileBlock.java
new file mode 100644
index 0000000..bb84adb
--- /dev/null
+++ b/src/uk/me/parabola/io/FileBlock.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+package uk.me.parabola.io;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import uk.me.parabola.imgfmt.app.labelenc.CharacterEncoder;
+import uk.me.parabola.imgfmt.app.labelenc.CodeFunctions;
+
+/**
+ * A block forming part of a file.
+ *
+ * Used for TDB and MPS files.  It will be read and written using the structured reader and
+ * writer defined in this package.
+ */
+public abstract class FileBlock {
+	private final byte blockId;
+
+	private final ByteArrayOutputStream output = new ByteArrayOutputStream();
+
+	public FileBlock(int blockId) {
+		this.blockId = (byte) blockId;
+
+		fillHeader();
+	}
+
+	/**
+	 * Write the body of the block.
+	 */
+	protected abstract void writeBody(StructuredOutputStream output) throws IOException;
+
+	private StructuredOutputStream getStructuredOutput(int codePage) {
+		CharacterEncoder enc = CodeFunctions.createEncoderForLBL(0, codePage).getEncoder();
+		return new StructuredOutputStream(output, enc);
+	}
+
+	/**
+	 * Write to an output stream.
+	 *
+	 * This will be to the actual TDB file.
+	 */
+	public void writeTo(OutputStream os, int codePage) throws IOException {
+		StructuredOutputStream output = getStructuredOutput(codePage);
+		writeBody(output);
+
+		byte[] b = this.output.toByteArray();
+
+		// Fill in the actual full block length
+		int blockLength = b.length - 3;
+		b[1] = (byte) (blockLength & 0xff);
+		b[2] = (byte) ((blockLength >> 8) & 0xff);
+		os.write(b);
+	}
+
+	/**
+	 * Write the header to the internal buffer.  The length may not be known yet and so is re-written later.
+	 */
+	private void fillHeader() {
+		try {
+			byte[] b = new byte[3];
+			b[0] = this.blockId;
+
+			output.write(b);
+		} catch (IOException ignore) {
+			// does not throw
+		}
+	}
+}
diff --git a/src/uk/me/parabola/io/StructuredOutputStream.java b/src/uk/me/parabola/io/StructuredOutputStream.java
index 53e36cb..7a535f3 100644
--- a/src/uk/me/parabola/io/StructuredOutputStream.java
+++ b/src/uk/me/parabola/io/StructuredOutputStream.java
@@ -16,9 +16,15 @@
  */
 package uk.me.parabola.io;
 
+import java.io.FilterOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.io.FilterOutputStream;
+
+import uk.me.parabola.imgfmt.ExitException;
+import uk.me.parabola.imgfmt.app.labelenc.CharacterEncoder;
+import uk.me.parabola.imgfmt.app.labelenc.EncodedText;
+
+import static uk.me.parabola.imgfmt.app.labelenc.BaseEncoder.NO_TEXT;
 
 /**
  * An output stream that has methods for writing strings and little endian
@@ -27,9 +33,12 @@ import java.io.FilterOutputStream;
  * @author Steve Ratcliffe
  */
 public class StructuredOutputStream extends FilterOutputStream {
-	
-	public StructuredOutputStream(OutputStream out) {
+
+	private final CharacterEncoder encoder;
+
+	public StructuredOutputStream(OutputStream out, CharacterEncoder encoder) {
 		super(out);
+		this.encoder = encoder;
 	}
 
 	public void write(int b) throws IOException {
@@ -63,10 +72,13 @@ public class StructuredOutputStream extends FilterOutputStream {
 	 * @throws IOException If the write fails.
 	 */
 	public void writeString(String s) throws IOException {
-		for (char c : s.toCharArray()) {
-			out.write((byte) c);
-		}
+		if (encoder == null)
+			throw new ExitException("tdbfile: character encoding is null");
+
+		EncodedText encodedText = encoder.encodeText(s);
+		if (encodedText == NO_TEXT)
+			return;
 
-		out.write('\0');
+		out.write(encodedText.getCtext(), 0, encodedText.getLength());
 	}
 }
diff --git a/src/uk/me/parabola/mkgmap/build/MapArea.java b/src/uk/me/parabola/mkgmap/build/MapArea.java
index 17014f9..94753dd 100644
--- a/src/uk/me/parabola/mkgmap/build/MapArea.java
+++ b/src/uk/me/parabola/mkgmap/build/MapArea.java
@@ -34,6 +34,7 @@ import uk.me.parabola.mkgmap.filters.LineSplitterFilter;
 import uk.me.parabola.mkgmap.filters.MapFilterChain;
 import uk.me.parabola.mkgmap.filters.PolygonSplitterFilter;
 import uk.me.parabola.mkgmap.filters.PolygonSubdivSizeSplitterFilter;
+import uk.me.parabola.mkgmap.filters.ShapeMergeFilter;
 import uk.me.parabola.mkgmap.general.MapDataSource;
 import uk.me.parabola.mkgmap.general.MapElement;
 import uk.me.parabola.mkgmap.general.MapLine;
@@ -623,7 +624,7 @@ public class MapArea implements MapDataSource {
 	 * @param dy30 The size of each division (y direction)
 	 * @return The index to areas where the map element fits.
 	 */
-	private int pickArea(MapArea[] areas, MapElement e,
+	private static int pickArea(MapArea[] areas, MapElement e,
 			int xbase30, int ybase30,
 			int nx, int ny,
 			int dx30, int dy30)
@@ -733,8 +734,18 @@ public class MapArea implements MapDataSource {
 							areasHashMap.put(hashVal, co);
 					}
 				}
+				if (Math.abs(signedAreaSize) < ShapeMergeFilter.SINGLE_POINT_AREA
+						&& areas[areaIndex].areaResolution != 24) {
+					if (log.isInfoEnabled()) {
+						log.info("splitIntoAreas creates single point shape. id", e.getOsmid(),
+								"type", uk.me.parabola.mkgmap.reader.osm.GType.formatType(e.getType()), subSize,
+								"points, at", subShape.get(0).toOSMURL());
+					}
+					continue;
+				}
+
 				if (signedAreaSize == 0) {
-					log.warn("splitIntoAreas flat shape. id", e.getOsmid(),
+					log.warn("splitIntoAreas creates single point shape. id", e.getOsmid(),
 						 "type", uk.me.parabola.mkgmap.reader.osm.GType.formatType(e.getType()), subSize,
 						 "points, at", subShape.get(0).toOSMURL());
 					continue;
diff --git a/src/uk/me/parabola/mkgmap/build/MapBuilder.java b/src/uk/me/parabola/mkgmap/build/MapBuilder.java
index 865c46a..43be0c3 100644
--- a/src/uk/me/parabola/mkgmap/build/MapBuilder.java
+++ b/src/uk/me/parabola/mkgmap/build/MapBuilder.java
@@ -16,8 +16,9 @@ package uk.me.parabola.mkgmap.build;
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileNotFoundException;
-import java.io.FileReader;
 import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -27,8 +28,6 @@ import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Set;
 
-import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
-
 import uk.me.parabola.imgfmt.ExitException;
 import uk.me.parabola.imgfmt.Utils;
 import uk.me.parabola.imgfmt.app.Coord;
@@ -95,6 +94,8 @@ import uk.me.parabola.mkgmap.reader.overview.OverviewMapDataSource;
 import uk.me.parabola.util.Configurable;
 import uk.me.parabola.util.EnhancedProperties;
 
+import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
+
 /**
  * This is the core of the code to translate from the general representation
  * into the garmin representation.
@@ -135,7 +136,7 @@ public class MapBuilder implements Configurable {
 
 	private int minSizePolygon;
 	private String polygonSizeLimitsOpt;
-	private HashMap<Integer,Integer> polygonSizeLimits = null;
+	private HashMap<Integer,Integer> polygonSizeLimits;
 	private double reducePointError;
 	private double reducePointErrorPolygon;
 	private boolean mergeLines;
@@ -821,16 +822,13 @@ public class MapBuilder implements Configurable {
 
 	/**
 	 * Set all the information that appears in the header.
-	 *
-	 * @param map The map to write to.
-	 * @param src The source of map information.
 	 */
-	protected void getMapInfo() {
+	private void getMapInfo() {
 		if (licenseFileName != null) {
 			File file = new File(licenseFileName);
 
 			try {
-				BufferedReader reader = new BufferedReader(new FileReader(file));
+				BufferedReader reader = Files.newBufferedReader(file.toPath(), Charset.forName("utf-8"));
 				String text;
 
 				// repeat until all lines is read
@@ -881,7 +879,7 @@ public class MapBuilder implements Configurable {
 	 * @param map The map to write to.
 	 * @param src The source of map information.
 	 */
-	protected void processInfo(Map map, LoadableMapDataSource src) {
+	private void processInfo(Map map, LoadableMapDataSource src) {
 		// The bounds of the map.
 		map.setBounds(src.getBounds());
 
diff --git a/src/uk/me/parabola/mkgmap/build/MapSplitter.java b/src/uk/me/parabola/mkgmap/build/MapSplitter.java
index 96176fc..c85d448 100644
--- a/src/uk/me/parabola/mkgmap/build/MapSplitter.java
+++ b/src/uk/me/parabola/mkgmap/build/MapSplitter.java
@@ -17,6 +17,7 @@
 package uk.me.parabola.mkgmap.build;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 import uk.me.parabola.imgfmt.app.Area;
@@ -99,13 +100,21 @@ public class MapSplitter {
 		log.debug("orig area", mapSource.getBounds());
 
 		MapArea ma = initialArea(mapSource);
+		MapArea[] origArea = {ma};
 		MapArea[] areas = splitMaxSize(ma, orderByDecreasingArea);
+		if (areas == null) {
+			log.warn("initial split returned null for ",ma);
+			return origArea;
+		}
 
 		// Now step through each area and see if any have too many map features
 		// in them.  For those that do, we further split them.  This is done
 		// recursively until everything fits.
 		List<MapArea> alist = new ArrayList<>();
 		addAreasToList(areas, alist, 0, orderByDecreasingArea);
+		if (alist.isEmpty()) {
+			return origArea;
+		}
 
 		MapArea[] results = new MapArea[alist.size()];
 		return alist.toArray(results);
@@ -137,8 +146,8 @@ public class MapSplitter {
 						 ", lines = " + area.getNumLines() + "/" + sizes[MapArea.LINE_KIND] +
 						 ", shapes = " + area.getNumShapes() + "/" + sizes[MapArea.SHAPE_KIND]);
 			}
-			boolean doSplit = false;
-			
+			boolean wantSplit = false;
+			boolean mustSplit = false;
 			if (area.getNumLines() > MAX_NUM_LINES ||
 				area.getNumPoints() > MAX_NUM_POINTS ||
 				(sizes[MapArea.POINT_KIND] +
@@ -147,7 +156,7 @@ public class MapSplitter {
 				sizes[MapArea.XT_POINT_KIND] > MAX_XT_POINTS_SIZE ||
 				sizes[MapArea.XT_LINE_KIND] > MAX_XT_LINES_SIZE ||
 				sizes[MapArea.XT_SHAPE_KIND] > MAX_XT_SHAPES_SIZE)
-				doSplit = true; // we must split
+				mustSplit = true; // we must split
 			else if (bounds.getMaxDimension() > MIN_DIMENSION) {
 				int sumSize = 0;
 				for (int s : sizes)
@@ -156,11 +165,11 @@ public class MapSplitter {
 					if (area.getLines().size() + area.getShapes().size() >= 2) {
 						// area has more bytes than wanted, and we can split
 						log.debug("splitting area because size is larger than wanted: " + sumSize);
-						doSplit = true;
+						wantSplit = true;
 					}
 				}
 			}
-			if (doSplit){
+			if (wantSplit || mustSplit){
 				if (bounds.getMaxDimension() > MIN_DIMENSION) {
 					if (log.isDebugEnabled())
 						log.debug("splitting area", area);
@@ -170,8 +179,13 @@ public class MapSplitter {
 					else
 						sublist = area.split(1, 2, res, bounds, orderByDecreasingArea);
 					if (sublist == null) {
-						log.warn("SubDivision is single point at this resolution so can't split at " +
-							 area.getBounds().getCenter().toOSMURL() + " (probably harmless)");
+						String msg = "SubDivision is single point at this resolution so can't split at "
+								+ area.getBounds().getCenter().toOSMURL();
+						if (wantSplit) {
+							log.info(msg + " (probably harmless)");
+						} else { 
+							log.error(msg);
+						}
 					} else {
 						addAreasToList(sublist, alist, depth + 1, orderByDecreasingArea);
 						continue;
diff --git a/src/uk/me/parabola/mkgmap/combiners/Combiner.java b/src/uk/me/parabola/mkgmap/combiners/Combiner.java
index 3c5ebb2..e553400 100644
--- a/src/uk/me/parabola/mkgmap/combiners/Combiner.java
+++ b/src/uk/me/parabola/mkgmap/combiners/Combiner.java
@@ -48,4 +48,7 @@ public interface Combiner {
 	 */
 	public void onFinish();
 
+	public default String getFilename() {
+		return null;
+	}
 }
diff --git a/src/uk/me/parabola/mkgmap/combiners/FileInfo.java b/src/uk/me/parabola/mkgmap/combiners/FileInfo.java
index bd3f62c..a538615 100644
--- a/src/uk/me/parabola/mkgmap/combiners/FileInfo.java
+++ b/src/uk/me/parabola/mkgmap/combiners/FileInfo.java
@@ -210,9 +210,8 @@ public class FileInfo {
 	 * @throws FileNotFoundException If the file doesn't exist.
 	 */
 	private static FileInfo imgInfo(String inputName) throws FileNotFoundException {
-		FileSystem imgFs = ImgFS.openFs(inputName);
 
-		try {
+		try (FileSystem imgFs = ImgFS.openFs(inputName)) {
 			FileSystemParam params = imgFs.fsparam();
 			log.info("Desc", params.getMapDescription());
 			log.info("Blocksize", params.getBlockSize());
@@ -237,6 +236,8 @@ public class FileInfo {
 			info.setMapname(name);
 
 			boolean hasTre = false;
+			DirectoryEntry treEnt = null;
+
 			List<DirectoryEntry> entries = imgFs.list();
 			for (DirectoryEntry ent : entries) {
 				if (ent.isSpecial())
@@ -249,8 +250,8 @@ public class FileInfo {
 					info.setTresize(ent.getSize());
 					info.setInnername(ent.getName());
 
-					treInfo(imgFs, ent, info);
 					hasTre = true;
+					treEnt = ent;
 				} else if ("RGN".equals(ext)) {
 					int size = ent.getSize();
 					info.setRgnsize(size);
@@ -273,12 +274,13 @@ public class FileInfo {
 				info.fileSizes.add(ent.getSize());
 			}
 
+			if (hasTre)
+				treInfo(imgFs, treEnt, info);
+
 			if (info.getKind() == UNKNOWN_KIND && hasTre)
 				info.setKind(IMG_KIND);
-			
+
 			return info;
-		} finally {
-			imgFs.close();
 		}
 	}
 
@@ -297,7 +299,7 @@ public class FileInfo {
 
 			info.setBounds(treFile.getBounds());
 
-			info.setLicenceInfo(treFile.getMapInfo());
+			info.setLicenceInfo(treFile.getMapInfo(info.getCodePage()));
 
 			info.setHexname(((TREHeader) treFile.getHeader()).getMapId());
 		} finally {
@@ -399,7 +401,7 @@ public class FileInfo {
 	}
 
 	
-	protected void setLicenceInfo(String[] info) {
+	private void setLicenceInfo(String[] info) {
 		this.licenceInfo = info;
 	}
 
@@ -428,7 +430,7 @@ public class FileInfo {
 	}
 
 	public String getFamilyName() {
-		return args.get("family-name", "family name");
+		return args.get("family-name", "OSM map");
 	}
 
 	public String getSeriesName() {
@@ -490,4 +492,8 @@ public class FileInfo {
 	public boolean hasSortOrder() {
 		return sortOrderId != 0;
 	}
+
+	public String getOverviewName() {
+		return args.get("overview-mapname", "osmmap");
+	}
 }
diff --git a/src/uk/me/parabola/mkgmap/combiners/GmapiBuilder.java b/src/uk/me/parabola/mkgmap/combiners/GmapiBuilder.java
new file mode 100644
index 0000000..6dbcd6b
--- /dev/null
+++ b/src/uk/me/parabola/mkgmap/combiners/GmapiBuilder.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2016.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+package uk.me.parabola.mkgmap.combiners;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Writer;
+import java.nio.ByteBuffer;
+import java.nio.channels.ByteChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+import uk.me.parabola.imgfmt.ExitException;
+import uk.me.parabola.imgfmt.fs.DirectoryEntry;
+import uk.me.parabola.imgfmt.fs.FileSystem;
+import uk.me.parabola.imgfmt.fs.ImgChannel;
+import uk.me.parabola.imgfmt.sys.ImgFS;
+import uk.me.parabola.mkgmap.CommandArgs;
+
+import static java.nio.file.StandardOpenOption.*;
+
+/**
+ * Create a map in the gmapi format.
+ *
+ * This is directory tree containing an XML file describing the contents, and exploded versions of
+ * each .img file.
+ */
+public class GmapiBuilder implements Combiner {
+	private final static String NS = "http://www.garmin.com/xmlschemas/MapProduct/v1";
+
+	private final Map<String, Combiner> combinerMap;
+
+	private Path gmapDir;
+	private final Map<Integer, ProductInfo> productMap = new HashMap<>();
+
+	private String familyName;
+	private int familyId;
+	private short productVersion;
+
+	private String typFile;
+
+	public GmapiBuilder(Map<String, Combiner> combinerMap) {
+		this.combinerMap = combinerMap;
+	}
+
+	/**
+	 * Initialise with the command line arguments.  This is called after all
+	 * the command line arguments have been processed, but before any calls to
+	 * the {@link #onMapEnd} methods.
+	 *
+	 * @param args The command line arguments.
+	 */
+	public void init(CommandArgs args) {
+		familyName = args.get("family-name", "OSM map");
+		familyId = args.get("family-id", CommandArgs.DEFAULT_FAMILYID);
+		productVersion = (short) args.get("product-version", 100);
+
+		gmapDir = Paths.get(args.getOutputDir(), String.format("%s.gmap", familyName));
+	}
+
+	/**
+	 * This is called when an individual map is complete.
+	 *
+	 * @param info An interface to read the map.
+	 */
+	public void onMapEnd(FileInfo info) {
+
+		String fn = info.getFilename();
+		String mapname = info.getMapname();
+
+		int productId = info.getProductId();
+		if (!productMap.containsKey(productId))
+			productMap.put(productId, new ProductInfo(productId, info.getSeriesName(), info.getOverviewName()));
+
+		// Unzip the image into the product tile directory.
+		try {
+			if (info.isImg())
+				unzipImg(fn, mapname, productId);
+			else if (info.getKind() == FileKind.TYP_KIND)
+				typFile = info.getFilename();
+
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * The complete map set has been processed.  Finish off anything that needs
+	 * doing.
+	 */
+	public void onFinish() {
+		try {
+			if (combinerMap.containsKey("mdx")) {
+				File file = new File(getFilenameFor("mdx"));
+				Files.copy(file.toPath(), gmapDir.resolve(file.getName()), StandardCopyOption.REPLACE_EXISTING);
+			}
+			if (combinerMap.containsKey("mdr")) {
+				File file = new File(getFilenameFor("mdr"));
+				unzipImg(file.getCanonicalPath(), gmapDir.resolve(nameWithoutExtension(file)));
+			}
+
+			if (typFile != null) {
+				File file = new File(typFile);
+				Files.copy(file.toPath(), gmapDir.resolve(file.getName()), StandardCopyOption.REPLACE_EXISTING);
+			}
+
+			for (ProductInfo info : productMap.values()) {
+				finishTdbFile(info);
+				unzipImg(getFilenameFor("img"), info.overviewName, info.id);
+			}
+
+			writeXmlFile(gmapDir);
+
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	private String nameWithoutExtension(File file) {
+		String name = file.getName();
+		int len = name.length();
+		if (len < 4)
+			return name;
+		return name.substring(0, len-4);
+	}
+
+	private void finishTdbFile(ProductInfo info) throws IOException {
+		Path tdbPath = Paths.get(getFilenameFor("tdb"));
+
+		Files.copy(tdbPath, gmapDir
+				.resolve(String.format("Product%d", info.id))
+				.resolve(String.format("%s.tdb", info.overviewName)), StandardCopyOption.REPLACE_EXISTING);
+	}
+
+	private void unzipImg(String srcImgName, String mapname, int productId) throws IOException {
+		Path destDir = Paths.get(gmapDir.toString(), "Product" + productId, mapname);
+
+		unzipImg(srcImgName, destDir);
+	}
+
+	private void unzipImg(String srcImgName, Path destDir) throws IOException {
+		FileSystem fs = ImgFS.openFs(srcImgName);
+		for (DirectoryEntry ent : fs.list()) {
+			String fullname = ent.getFullName();
+
+			try (ImgChannel f = fs.open(fullname, "r")) {
+				String name = displayName(fullname);
+				if (Objects.equals(name, "."))
+					continue;
+
+				Files.createDirectories(destDir);
+				copyToFile(f, destDir.resolve(name));
+			}
+		}
+	}
+
+	private void copyToFile(ImgChannel f, Path dest) {
+		ByteBuffer buf = ByteBuffer.allocate(8 * 1024);
+		try (ByteChannel outchan = Files.newByteChannel(dest, CREATE, WRITE, TRUNCATE_EXISTING)) {
+			while (f.read(buf) > 0) {
+				buf.flip();
+				outchan.write(buf);
+				buf.compact();
+			}
+		} catch (IOException e) {
+			throw new ExitException("Cannot write file " + e);
+		}
+	}
+
+	private String getFilenameFor(String kind) {
+		return combinerMap.get(kind).getFilename();
+	}
+
+	private String displayName(String fullname) {
+		return fullname.trim().replace("\000", "");
+	}
+
+	/**
+	 * An xml file contains similar information that is contained in the windows registry.
+	 *
+	 * @param gDir The directory where the Info.xml file will be created.
+	 */
+	private void writeXmlFile(Path gDir) {
+		Path infoFile = gDir.resolve("Info.xml");
+
+		XMLOutputFactory factory = XMLOutputFactory.newFactory();
+
+		try (Writer stream = Files.newBufferedWriter(infoFile)) {
+
+			XMLStreamWriter writer = factory.createXMLStreamWriter(stream);
+
+			writer.writeStartDocument("UTF-8", "1.0");
+			writer.setDefaultNamespace(NS);
+			writer.writeCharacters("\n");
+
+			writer.writeStartElement(NS,"MapProduct");
+			writer.writeDefaultNamespace(NS);
+			writer.writeCharacters("\n");
+
+			xmlElement(writer, "Name", familyName);
+			xmlElement(writer, "DataVersion", String.valueOf(productVersion));
+			xmlElement(writer, "DataFormat", "Original");
+			xmlElement(writer, "ID", String.valueOf(familyId));
+
+			if (combinerMap.containsKey("mdx")) {
+				String mdxFile = getFilenameFor("mdx");
+
+				File file = new File(mdxFile);
+				xmlElement(writer, "IDX", file.getName());
+			}
+
+			if (combinerMap.containsKey("mdr")) {
+				String mdrName = getFilenameFor("mdr");
+				File file = new File(mdrName);
+				xmlElement(writer, "MDR", nameWithoutExtension(file));
+			}
+
+			if (typFile != null) {
+				File file = new File(typFile);
+				xmlElement(writer, "TYP", file.getName());
+			}
+
+			for (ProductInfo prod : productMap.values()) {
+				writer.writeStartElement(NS, "SubProduct");
+				writer.writeCharacters("\n");
+
+				xmlElement(writer, "Name", prod.seriesName);
+				xmlElement(writer, "ID", String.valueOf(prod.id));
+				xmlElement(writer, "BaseMap", prod.overviewName);
+				xmlElement(writer, "TDB", String.format("%s.tdb", prod.overviewName));
+				xmlElement(writer, "Directory", String.format("Product%s", prod.id));
+				writer.writeEndElement();
+				writer.writeCharacters("\n");
+			}
+
+			writer.writeEndElement();
+			writer.writeEndDocument();
+			writer.flush();
+		} catch (XMLStreamException | IOException e) {
+			throw new ExitException("Could not create file " + infoFile + "; " + e);
+		}
+	}
+
+	private void xmlElement(XMLStreamWriter writer, String name, String value) throws XMLStreamException {
+		writer.writeCharacters(" ");
+		writer.writeStartElement(NS, name);
+		writer.writeCharacters(value);
+		writer.writeEndElement();
+		writer.writeCharacters("\n");
+	}
+
+	private static class ProductInfo {
+
+		private final String seriesName;
+		private final String overviewName;
+		private final int id;
+
+		public ProductInfo(int id, String seriesName, String overviewName) {
+			this.id = id;
+			this.seriesName = seriesName;
+			this.overviewName = overviewName;
+		}
+	}
+}
diff --git a/src/uk/me/parabola/mkgmap/combiners/GmapsuppBuilder.java b/src/uk/me/parabola/mkgmap/combiners/GmapsuppBuilder.java
index 5cb9ab1..f392e67 100644
--- a/src/uk/me/parabola/mkgmap/combiners/GmapsuppBuilder.java
+++ b/src/uk/me/parabola/mkgmap/combiners/GmapsuppBuilder.java
@@ -68,7 +68,7 @@ public class GmapsuppBuilder implements Combiner {
 	private static final int ENTRY_SIZE = 240;
 	private static final int DIRECTORY_OFFSET_ENTRY = 2;
 
-	private final Map<String, FileInfo> files = new LinkedHashMap<String, FileInfo>();
+	private final Map<String, FileInfo> files = new LinkedHashMap<>();
 
 	// all these need to be set in the init routine from arguments.
 	private String areaName;
@@ -81,8 +81,8 @@ public class GmapsuppBuilder implements Combiner {
 	private boolean createIndex;	// True if we should create and add an index file
 
 	// There is a separate MDR and SRT file for each family id in the gmapsupp
-	private final Map<Integer, MdrBuilder> mdrBuilderMap = new LinkedHashMap<Integer, MdrBuilder>();
-	private final Map<Integer, Sort> sortMap = new LinkedHashMap<Integer, Sort>();
+	private final Map<Integer, MdrBuilder> mdrBuilderMap = new LinkedHashMap<>();
+	private final Map<Integer, Sort> sortMap = new LinkedHashMap<>();
 	private boolean splitName;
 	private boolean hideGmapsuppOnPC;
 
@@ -231,7 +231,7 @@ public class GmapsuppBuilder implements Combiner {
 	}
 
 	private MapBlock makeMapBlock(FileInfo info) {
-		MapBlock mb = new MapBlock();
+		MapBlock mb = new MapBlock(info.getCodePage());
 		mb.setMapNumber(info.getMapnameAsInt());
 		mb.setHexNumber(info.getHexname());
 		mb.setMapDescription(info.getDescription());
@@ -243,7 +243,7 @@ public class GmapsuppBuilder implements Combiner {
 	}
 
 	private ProductBlock makeProductBlock(FileInfo info) {
-		ProductBlock pb = new ProductBlock();
+		ProductBlock pb = new ProductBlock(info.getCodePage());
 		pb.setFamilyId(info.getFamilyId());
 		pb.setProductId(info.getProductId());
 		pb.setDescription(info.getFamilyName());
@@ -282,7 +282,7 @@ public class GmapsuppBuilder implements Combiner {
 		FileSystem fs = null;
 		try {
 			fs = ImgFS.openFs(name);
-			MpsFileReader mr = new MpsFileReader(fs.open(info.getMpsName(), "r"));
+			MpsFileReader mr = new MpsFileReader(fs.open(info.getMpsName(), "r"), info.getCodePage());
 			for (MapBlock block : mr.getMaps())
 				mpsFile.addMap(block);
 
@@ -356,9 +356,10 @@ public class GmapsuppBuilder implements Combiner {
 		int dot = name.lastIndexOf('.');
 
 		String base = name.substring(0, dot);
-		String ext = name.substring(dot + 1);
 		if (base.length() > 8)
 			base = base.substring(0, 8);
+
+		String ext = name.substring(dot + 1);
 		if (ext.length() > 3)
 			ext = ext.substring(0, 3);
 
@@ -373,13 +374,10 @@ public class GmapsuppBuilder implements Combiner {
 	 */
 	private void addImg(FileSystem outfs, String filename) {
 		try {
-			FileSystem infs = ImgFS.openFs(filename);
-
-			try {
+			try (FileSystem infs = ImgFS.openFs(filename)) {
 				copyAllFiles(infs, outfs);
-			} finally {
-				infs.close();
 			}
+
 		} catch (FileNotFoundException e) {
 			log.error("Could not open file " + filename);
 		}
@@ -417,6 +415,7 @@ public class GmapsuppBuilder implements Combiner {
 	private FileSystem createGmapsupp() throws FileNotWritableException {
 		BlockInfo bi = calcBlockSize();
 		int blockSize = bi.blockSize;
+
 		// Create this file, containing all the sub files
 		FileSystemParam params = new FileSystemParam();
 		params.setBlockSize(blockSize);
@@ -429,7 +428,7 @@ public class GmapsuppBuilder implements Combiner {
 		params.setReservedDirectoryBlocks(reserveBlocks);
 
 		FileSystem outfs = ImgFS.createFs(Utils.joinPath(outputDir, GMAPSUPP), params);
-		
+
 		mpsFile = createMpsFile(outfs);
 		mpsFile.setMapsetName(mapsetName);
 
diff --git a/src/uk/me/parabola/mkgmap/combiners/MdrBuilder.java b/src/uk/me/parabola/mkgmap/combiners/MdrBuilder.java
index 6c5c985..1057341 100644
--- a/src/uk/me/parabola/mkgmap/combiners/MdrBuilder.java
+++ b/src/uk/me/parabola/mkgmap/combiners/MdrBuilder.java
@@ -362,6 +362,10 @@ public class MdrBuilder implements Combiner {
 			Utils.closeFile(file);
 	}
 
+	public String getFilename() {
+		return outputName;
+	}
+
 	public int getSize() {
 		return (int) tmpName.length();
 	}
diff --git a/src/uk/me/parabola/mkgmap/combiners/MdxBuilder.java b/src/uk/me/parabola/mkgmap/combiners/MdxBuilder.java
index d700f52..0ad9563 100644
--- a/src/uk/me/parabola/mkgmap/combiners/MdxBuilder.java
+++ b/src/uk/me/parabola/mkgmap/combiners/MdxBuilder.java
@@ -55,4 +55,8 @@ public class MdxBuilder implements Combiner {
 			throw new ExitException("Could not create MDX file", e);
 		}
 	}
+
+	public String getFilename() {
+		return Utils.joinPath(outputDir, mdxFilename);
+	}
 }
diff --git a/src/uk/me/parabola/mkgmap/combiners/OverviewBuilder.java b/src/uk/me/parabola/mkgmap/combiners/OverviewBuilder.java
index 5fa08ab..f02b71f 100644
--- a/src/uk/me/parabola/mkgmap/combiners/OverviewBuilder.java
+++ b/src/uk/me/parabola/mkgmap/combiners/OverviewBuilder.java
@@ -90,7 +90,12 @@ public class OverviewBuilder implements Combiner {
 		calcLevels();
 		writeOverviewMap();
 	}
-	
+
+	@Override
+	public String getFilename() {
+		return Utils.joinPath(outputDir, overviewMapname, "img");
+	}
+
 	private void calcLevels() {
 		List<MapShape> shapes = overviewSource.getShapes();
 		int maxRes = 16; // we can write a 0x4a polygon for planet in res 16
diff --git a/src/uk/me/parabola/mkgmap/combiners/TdbBuilder.java b/src/uk/me/parabola/mkgmap/combiners/TdbBuilder.java
index 7d2a34c..8138943 100644
--- a/src/uk/me/parabola/mkgmap/combiners/TdbBuilder.java
+++ b/src/uk/me/parabola/mkgmap/combiners/TdbBuilder.java
@@ -47,7 +47,7 @@ public class TdbBuilder implements Combiner {
 	private String overviewMapnumber;
 	private String outputDir;
 	private int tdbVersion;
-	private List<String[]> copyrightMsgs = new ArrayList<String[]>();
+	private final List<String[]> copyrightMsgs = new ArrayList<>();
 
 	public TdbBuilder(OverviewBuilder ovb) {
 		overviewBuilder = ovb;
@@ -60,6 +60,7 @@ public class TdbBuilder implements Combiner {
 	 *
 	 * @param args The command line arguments as they are at the end of the list.
 	 * In other words if the same argument appears more than once, then it will
+	 * have the latest value set.
 	 */
 	public void init(CommandArgs args) {
 		overviewMapname = args.get("overview-mapname", "osmmap");
@@ -182,6 +183,10 @@ public class TdbBuilder implements Combiner {
 		writeTdbFile();
 	}
 
+	public String getFilename() {
+		return Utils.joinPath(outputDir, overviewMapname, "tdb");
+	}
+
 	/**
 	 * Write out the TDB file at the end of processing.
 	 */
diff --git a/src/uk/me/parabola/mkgmap/filters/ShapeMergeFilter.java b/src/uk/me/parabola/mkgmap/filters/ShapeMergeFilter.java
index 74218e3..e77602a 100644
--- a/src/uk/me/parabola/mkgmap/filters/ShapeMergeFilter.java
+++ b/src/uk/me/parabola/mkgmap/filters/ShapeMergeFilter.java
@@ -15,6 +15,7 @@ package uk.me.parabola.mkgmap.filters;
 import it.unimi.dsi.fastutil.ints.IntArrayList;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
@@ -52,8 +53,8 @@ public class ShapeMergeFilter{
 		if (shapes.size() <= 1)
 			return shapes;
 		int count = 0;
-		MultiHashMap<Integer, Map<MapShape, List<ShapeHelper>>> topMap = new MultiHashMap<Integer, Map<MapShape,List<ShapeHelper>>>();
-		List<MapShape> mergedShapes = new ArrayList<MapShape>();
+		MultiHashMap<Integer, Map<MapShape, List<ShapeHelper>>> topMap = new MultiHashMap<>();
+		List<MapShape> mergedShapes = new ArrayList<>();
 		for (MapShape shape: shapes) {
 			if (shape.getMinResolution() > resolution || shape.getMaxResolution() < resolution)
 				continue;
@@ -76,8 +77,8 @@ public class ShapeMergeFilter{
 				continue;
 			}
 			if (sameTypeList.isEmpty()){
-				Map<MapShape, List<ShapeHelper>> lowMap = new LinkedHashMap<MapShape, List<ShapeHelper>>();
-				ArrayList<ShapeHelper> list = new ArrayList<ShapeHelper>();
+				Map<MapShape, List<ShapeHelper>> lowMap = new LinkedHashMap<>();
+				ArrayList<ShapeHelper> list = new ArrayList<>();
 				list.add(sh);
 				lowMap.put(shape, list);
 				topMap.add(shape.getType(),lowMap);
@@ -105,7 +106,7 @@ public class ShapeMergeFilter{
 					}
 				}
 				if (!added){
-					ArrayList<ShapeHelper> list = new ArrayList<ShapeHelper>();
+					ArrayList<ShapeHelper> list = new ArrayList<>();
 					list.add(sh);
 					lowMap.put(shape, list);
 				}
@@ -157,7 +158,7 @@ public class ShapeMergeFilter{
 	private List<ShapeHelper> addWithConnectedHoles(List<ShapeHelper> list,
 			final ShapeHelper toAdd, final int type) {
 		assert toAdd.getPoints().size() > 3;
-		List<ShapeHelper> result = new ArrayList<ShapeHelper>(list.size()+1);
+		List<ShapeHelper> result = new ArrayList<>(list.size()+1);
 		ShapeHelper shNew = new ShapeHelper(toAdd);
 		for (ShapeHelper shOld:list){
 			if (shOld.getBounds().intersects(shNew.getBounds()) == false){
@@ -224,6 +225,8 @@ public class ShapeMergeFilter{
 		List<Coord> merged = null; 
 		if (points1.size() + points2.size() - 2*sh1PositionsToCheck.size() < PolygonSplitterFilter.MAX_POINT_IN_ELEMENT){
 			merged = mergeLongestSequence(points1, points2, sh1PositionsToCheck, sh2PositionsToCheck, sameDir);
+			if (merged.isEmpty())
+				return dupShape;
 			if (merged.get(0) != merged.get(merged.size()-1))
 				merged = null;
 			else if (merged.size() > PolygonSplitterFilter.MAX_POINT_IN_ELEMENT){
@@ -262,7 +265,7 @@ public class ShapeMergeFilter{
 	 * @param s1PositionsToCheck will contain common positions in shape 1   
 	 * @param s2PositionsToCheck will contain common positions in shape 2
 	 */
-	private void findCommonCoords(List<Coord> s1, List<Coord> s2,
+	private static void findCommonCoords(List<Coord> s1, List<Coord> s2,
 			IntArrayList s1PositionsToCheck,
 			IntArrayList s2PositionsToCheck) {
 		Map<Coord, Integer> s2PosMap = new IdentityHashMap<>(s2.size() - 1);
@@ -312,7 +315,7 @@ public class ShapeMergeFilter{
 	 * @param sameDir true if both shapes are clockwise or both are ccw
 	 * @return the merged shape or null if no points are common.
 	 */
-	private List<Coord> mergeLongestSequence(List<Coord> points1, List<Coord> points2, IntArrayList sh1PositionsToCheck,
+	private static List<Coord> mergeLongestSequence(List<Coord> points1, List<Coord> points2, IntArrayList sh1PositionsToCheck,
 			IntArrayList sh2PositionsToCheck, boolean sameDir) {
 		if (sh1PositionsToCheck.isEmpty())
 			return null;
@@ -360,7 +363,11 @@ public class ShapeMergeFilter{
 		}
 		// now merge the shapes. The longest sequence of common points is removed.
 		// The remaining points are connected in the direction of the 1st shape.
-		List<Coord> merged = new ArrayList<Coord>(s1Size + s2Size - 2*longestSequence -1);
+		int remaining = s1Size + s2Size - 2*longestSequence -1;
+		if (remaining < 3) {
+			return Collections.emptyList(); // may happen with self-intersecting duplicated shapes
+		}
+		List<Coord> merged = new ArrayList<>(remaining);
 		int s1Pos = sh1PositionsToCheck.getInt(startOfLongestSequence+longestSequence);
 		for (int i = 0; i < s1Size - longestSequence - 1; i++){
 			merged.add(points1.get(s1Pos));
@@ -387,7 +394,7 @@ public class ShapeMergeFilter{
 		return merged;
 	}
  	
-	private class ShapeHelper{
+	private static class ShapeHelper{
 		final private List<Coord> points;
 		long id; // TODO: remove debugging aid
 		long areaTestVal;
@@ -440,7 +447,7 @@ public class ShapeMergeFilter{
 			return new Area(minLat, minLon, maxLat, maxLon);
 		}
 	}
-	private final static long smallArea = 1L<<6 * 1L<<6;
+	public final static long SINGLE_POINT_AREA = 1L<<6 * 1L<<6;
 	
 	/**
 	 * Calculate the high precision area size test value.  
@@ -464,7 +471,7 @@ public class ShapeMergeFilter{
 			signedAreaSize += (long) (c2.getHighPrecLon() + c1.getHighPrecLon())
 					* (c1.getHighPrecLat() - c2.getHighPrecLat());
 		}
-		if (Math.abs(signedAreaSize) < smallArea){
+		if (Math.abs(signedAreaSize) < SINGLE_POINT_AREA){
 			log.debug("very small shape near", points.get(0).toOSMURL(), "signed area in high prec map units:", signedAreaSize );
 		}
 		return signedAreaSize;
diff --git a/src/uk/me/parabola/mkgmap/main/Main.java b/src/uk/me/parabola/mkgmap/main/Main.java
index 234459f..343a9d3 100644
--- a/src/uk/me/parabola/mkgmap/main/Main.java
+++ b/src/uk/me/parabola/mkgmap/main/Main.java
@@ -21,7 +21,6 @@ import java.io.InputStreamReader;
 import java.io.PrintStream;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.HashMap;
@@ -30,6 +29,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
@@ -49,6 +49,7 @@ import uk.me.parabola.mkgmap.CommandArgsReader;
 import uk.me.parabola.mkgmap.Version;
 import uk.me.parabola.mkgmap.combiners.Combiner;
 import uk.me.parabola.mkgmap.combiners.FileInfo;
+import uk.me.parabola.mkgmap.combiners.GmapiBuilder;
 import uk.me.parabola.mkgmap.combiners.GmapsuppBuilder;
 import uk.me.parabola.mkgmap.combiners.MdrBuilder;
 import uk.me.parabola.mkgmap.combiners.MdxBuilder;
@@ -95,14 +96,16 @@ public class Main implements ArgumentProcessor {
 
 	private volatile int programRC = 0;
 
+	private final Map<String, Combiner> combinerMap = new HashMap<>();
+
 	/**
 	 * Used for unit tests
 	 */
-	public static void mainNoSystemExit(String[] args) {
+	public static void mainNoSystemExit(String... args) {
 		Main.mainStart(args);
 	}
 	
-	public static void main(String[] args) {
+	public static void main(String... args) {
 		int rc = Main.mainStart(args);
 		if (rc != 0)
 			System.exit(1);
@@ -115,7 +118,7 @@ public class Main implements ArgumentProcessor {
 	 *
 	 * @param args The command line arguments.
 	 */
-	private static int mainStart(String[] args) {
+	private static int mainStart(String... args) {
 		long start = System.currentTimeMillis();
 		System.out.println("Time started: " + new Date());
 		// We need at least one argument.
@@ -324,7 +327,7 @@ public class Main implements ArgumentProcessor {
 	}
 
 	public void removeOption(String opt) {
-		if ("tdbfile".equals(opt))
+		if (Objects.equals("tdbfile", opt))
 			createTdbFiles = false;
 	}
 
@@ -337,9 +340,9 @@ public class Main implements ArgumentProcessor {
 		if (!tdbBuilderAdded ){
 			OverviewMap overviewSource = new OverviewMapDataSource();
 			OverviewBuilder overviewBuilder = new OverviewBuilder(overviewSource);
-			addCombiner(overviewBuilder);
+			addCombiner("img", overviewBuilder);
 			TdbBuilder tdbBuilder = new TdbBuilder(overviewBuilder);
-			addCombiner(tdbBuilder);
+			addCombiner("tdb", tdbBuilder);
 			tdbBuilderAdded = true;
 		}
 	}
@@ -395,14 +398,14 @@ public class Main implements ArgumentProcessor {
 		}
 		int checked = 0;
 		for (String name : names) {
-			if (styleOption != null && !name.equals(styleOption))
+			if (styleOption != null && !Objects.equals(name, styleOption))
 				continue;
 			if (names.length > 1){
 				System.out.println("checking style: " + name);
 			}
 			++checked;
 			boolean performChecks = true;
-			if ("classpath:styles".equals(styleFile) && !"default".equals(name)){
+			if (Objects.equals("classpath:styles", styleFile) && !Objects.equals("default", name)){
 					performChecks = false;
 			}
 			Style style = readOneStyle(name, performChecks);
@@ -446,7 +449,8 @@ public class Main implements ArgumentProcessor {
 		return "en";
 	}
 
-	private void addCombiner(Combiner combiner) {
+	private void addCombiner(String name, Combiner combiner) {
+		combinerMap.put(name, combiner);
 		combiners.add(combiner);
 	}
 
@@ -536,7 +540,7 @@ public class Main implements ArgumentProcessor {
 		for (Combiner c : combiners)
 			c.init(args);
 
-		Collections.sort(filenames, new Comparator<FilenameTask>() {
+		filenames.sort(new Comparator<FilenameTask>() {
 			public int compare(FilenameTask o1, FilenameTask o2) {
 				if (!o1.getFilename().endsWith(".img") || !o2.getFilename().endsWith(".img"))
 					return o1.getFilename().compareTo(o2.getFilename());
@@ -620,24 +624,30 @@ public class Main implements ArgumentProcessor {
 
 	private void fileOptions(CommandArgs args) {
 		boolean indexOpt = args.exists("index");
-		boolean gmapOpt = args.exists("gmapsupp");
+		boolean gmapsuppOpt = args.exists("gmapsupp");
 		boolean tdbOpt = args.exists("tdbfile");
+		boolean gmapiOpt = args.exists("gmapi");
+
 		if (tdbOpt || createTdbFiles){ 
 			addTdbBuilder();
 		}
 		if (args.exists("nsis")) {
-			addCombiner(new NsisBuilder());
+			addCombiner("nsis", new NsisBuilder());
 		}
-		if (gmapOpt) {
+		if (gmapsuppOpt) {
 			GmapsuppBuilder gmapBuilder = new GmapsuppBuilder();
 			gmapBuilder.setCreateIndex(indexOpt);
 
-			addCombiner(gmapBuilder);
+			addCombiner("gmapsupp", gmapBuilder);
+		}
+
+		if (indexOpt && (tdbOpt || !gmapsuppOpt)) {
+			addCombiner("mdr", new MdrBuilder());
+			addCombiner("mdx", new MdxBuilder());
 		}
 
-		if (indexOpt && (tdbOpt || !gmapOpt)) {
-			addCombiner(new MdrBuilder());
-			addCombiner(new MdxBuilder());
+		if (gmapiOpt) {
+			addCombiner("gmapi", new GmapiBuilder(combinerMap));
 		}
 	}
 
diff --git a/src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java b/src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java
index 5bbf771..2ff0fe6 100644
--- a/src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java
+++ b/src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java
@@ -22,6 +22,8 @@ import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -65,7 +67,7 @@ public abstract class OsmMapDataSource extends MapperBasedMapDataSource
 			new HousenumberHooks(),
 	};
 	protected OsmConverter converter;
-	private final Set<String> usedTags = new HashSet<String>();
+	private final Set<String> usedTags = new HashSet<>();
 	protected ElementSaver elementSaver;
 	protected OsmReadingHooks osmReadingHooks;
 
@@ -139,12 +141,12 @@ public abstract class OsmMapDataSource extends MapperBasedMapDataSource
 	 */
 	public String[] copyrightMessages() {
 		String copyrightFileName = getConfig().getProperty("copyright-file", null);
-		if (copyrightFileName != null)
-		{
-			File file = new File(copyrightFileName);
-			List<String> copyrightArray = new ArrayList<String>();
+		if (copyrightFileName != null) {
+			List<String> copyrightArray = new ArrayList<>();
 			try {
-				BufferedReader reader = new BufferedReader(new FileReader(file));
+				File file = new File(copyrightFileName);
+				BufferedReader reader = Files.newBufferedReader(file.toPath(), Charset.forName("utf-8"));
+
 				String text;
 				while ((text = reader.readLine()) != null) {
 					copyrightArray.add(text);
diff --git a/src/uk/me/parabola/mkgmap/reader/osm/o5m/O5mBinHandler.java b/src/uk/me/parabola/mkgmap/reader/osm/o5m/O5mBinHandler.java
index b1b4863..43f38af 100644
--- a/src/uk/me/parabola/mkgmap/reader/osm/o5m/O5mBinHandler.java
+++ b/src/uk/me/parabola/mkgmap/reader/osm/o5m/O5mBinHandler.java
@@ -386,17 +386,7 @@ public class O5mBinHandler extends OsmHandler{
 				ioPos++; // skip terminating zero from uid
 				--bytesToRead;
 			}
-			int start = 0;
-			int buffPos = 0; 
-			stringPair[1] = null;
-			while(stringPair[1] == null){
-				final int b = ioBuf[ioPos++];
-				--bytesToRead;
-				cnvBuffer[buffPos++] = (byte) b;
-
-				if (b == 0)
-					stringPair[1] = new String(cnvBuffer, start, buffPos-1, "UTF-8");
-			}
+			stringPair[1] = readString();
 			long bytes = toReadStart - bytesToRead;
 			if (bytes <= MAX_STRING_PAIR_SIZE)
 				storeStringPair();
@@ -423,17 +413,7 @@ public class O5mBinHandler extends OsmHandler{
 				refType = 3;
 			stringPair[0] = REL_REF_TYPES[refType];
 				
-			int start = 0;
-			int buffPos = 0; 
-			stringPair[1] = null;
-			while(stringPair[1] == null){
-				final int b = ioBuf[ioPos++];
-				--bytesToRead;
-				cnvBuffer[buffPos++] =  (byte)b;
-
-				if (b == 0)
-					stringPair[1] = new String(cnvBuffer, start, buffPos-1, "UTF-8");
-			}
+			stringPair[1] = readString();
 			long bytes = toReadStart - bytesToRead;
 			if (bytes <= MAX_STRING_PAIR_SIZE)
 				storeStringPair();
@@ -460,18 +440,8 @@ public class O5mBinHandler extends OsmHandler{
 		if (stringRef == 0){
 			long toReadStart = bytesToRead;
 			int cnt = 0;
-			int buffPos = 0; 
-			int start = 0;
 			while (cnt < 2){
-				final int b = ioBuf[ioPos++];
-				--bytesToRead;
-				cnvBuffer[buffPos++] =  (byte)b;
-
-				if (b == 0){
-					stringPair[cnt] = new String(cnvBuffer, start, buffPos-start-1, "UTF-8");
-					++cnt;
-					start = buffPos;
-				}
+				stringPair[cnt++] = readString();
 			}
 			long bytes = toReadStart - bytesToRead;
 			if (bytes <= MAX_STRING_PAIR_SIZE)
@@ -481,6 +451,22 @@ public class O5mBinHandler extends OsmHandler{
 			setStringRefPair(stringRef);
 	}
 	
+	/**
+	 * Read a zero-terminated string (see o5m definition).
+	 * @throws IOException
+	 */
+	String readString() throws IOException {
+		int length = 0; 
+		while (true) {
+			final int b = ioBuf[ioPos++];
+			--bytesToRead;
+			if (b == 0)
+				return new String(cnvBuffer, 0, length, "UTF-8");
+			cnvBuffer[length++] = (byte) b;
+		}
+	}
+
+	
 	/** reset the delta values and string table */
 	private void reset(){
 		lastNodeId = 0; lastWayId = 0; lastRelId = 0;
diff --git a/src/uk/me/parabola/tdbfmt/Block.java b/src/uk/me/parabola/tdbfmt/Block.java
deleted file mode 100644
index 5fbe2a2..0000000
--- a/src/uk/me/parabola/tdbfmt/Block.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2007 Steve Ratcliffe
- * 
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
- * 
- *  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.
- * 
- * 
- * Author: Steve Ratcliffe
- * Create date: 23-Sep-2007
- */
-package uk.me.parabola.tdbfmt;
-
-import uk.me.parabola.log.Logger;
-import uk.me.parabola.io.StructuredInputStream;
-import uk.me.parabola.io.StructuredOutputStream;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * A block within the tdb file.  Really just a type and the contents.
- *
- * @author Steve Ratcliffe
- */
-class Block {
-	private static final Logger log = Logger.getLogger(Block.class);
-
-	private final int blockId;
-	private int blockLength;
-	private byte[] body;
-	private StructuredInputStream istream;
-	private ByteArrayOutputStream arrayBody;
-	private StructuredOutputStream ostream;
-
-	/**
-	 * Create a block that is going to be written to.
-	 * @param blockId The id for this block.
-	 */
-	Block(int blockId) {
-		this.blockId = blockId;
-	}
-
-	/**
-	 * Create a block from data that is read in from a file.
-	 * @param type The block type.
-	 * @param body The raw bytes in the block.
-	 */
-	Block(int type, byte[] body) {
-		blockId = type;
-		this.body = body;
-		this.blockLength = body.length;
-		ByteArrayInputStream stream = new ByteArrayInputStream(body);
-		this.istream = new StructuredInputStream(stream);
-	}
-
-	public int getBlockId() {
-		return blockId;
-	}
-
-	/**
-	 * Get the raw bytes for this block.  The source depends on if this block
-	 * was constructed from file data, or is being created from program calls
-	 * so that it can be written.
-	 *
-	 * @return A byte array of the raw bytes representing this block.
-	 */
-	byte[] getBody() {
-		if (body == null && arrayBody != null) {
-			byte[] bytes = arrayBody.toByteArray();
-
-			blockLength = bytes.length - 3;
-
-			// Fill in the length in the space that we left earlier.
-			bytes[1] = (byte) (blockLength & 0xff);
-			bytes[2] = (byte) ((blockLength >> 8) & 0xff);
-			return bytes;
-		}
-		return body;
-	}
-
-	/**
-	 * Get a stream for the body of this block.
-	 *
-	 * @return A structured stream that can be used to read the body of this
-	 * block.
-	 */
-	public StructuredInputStream getInputStream() {
-		arrayBody = null;
-		return this.istream;
-	}
-
-	public StructuredOutputStream getOutputStream() {
-		if (ostream == null) {
-			arrayBody = new ByteArrayOutputStream();
-			body = null;
-			ostream = new StructuredOutputStream(arrayBody);
-			try {
-				ostream.write(blockId);
-				ostream.write2(0); // This will be filled in later.
-			} catch (IOException e) {
-				log.warn("failed writing to array");
-			}
-		}
-
-		return ostream;
-	}
-
-	public void write(OutputStream stream) throws IOException {
-		byte[] b = getBody();
-		if (b != null)
-			stream.write(b);
-	}
-}
diff --git a/src/uk/me/parabola/tdbfmt/CopyrightBlock.java b/src/uk/me/parabola/tdbfmt/CopyrightBlock.java
index 3b03dd3..e84caf2 100644
--- a/src/uk/me/parabola/tdbfmt/CopyrightBlock.java
+++ b/src/uk/me/parabola/tdbfmt/CopyrightBlock.java
@@ -16,6 +16,8 @@
  */
 package uk.me.parabola.tdbfmt;
 
+import uk.me.parabola.io.FileBlock;
+import uk.me.parabola.io.StructuredOutputStream;
 import uk.me.parabola.log.Logger;
 import uk.me.parabola.io.StructuredInputStream;
 
@@ -30,17 +32,20 @@ import java.util.HashSet;
  *
  * @author Steve Ratcliffe
  */
-class CopyrightBlock {
+class CopyrightBlock extends FileBlock {
+	public static final int BLOCK_ID = 0x44;
+
 	private static final Logger log = Logger.getLogger(CopyrightBlock.class);
 	
-	private final List<CopyrightSegment> segments = new ArrayList<CopyrightSegment>();
-	private final Set<CopyrightSegment> copySet = new HashSet<CopyrightSegment>();
+	private final List<CopyrightSegment> segments = new ArrayList<>();
+	private final Set<CopyrightSegment> copySet = new HashSet<>();
 
 	CopyrightBlock() {
+		super(BLOCK_ID);
 	}
 
-	CopyrightBlock(Block block) throws IOException {
-		StructuredInputStream ds = block.getInputStream();
+	CopyrightBlock(StructuredInputStream ds) throws IOException {
+		super(BLOCK_ID);
 
 		while (!ds.testEof()) {
 			CopyrightSegment segment = new CopyrightSegment(ds);
@@ -50,9 +55,12 @@ class CopyrightBlock {
 		}
 	}
 
-	public void write(Block block) throws IOException {
+	/**
+	 * This is to overridden in a subclass.
+	 */
+	protected void writeBody(StructuredOutputStream ds) throws IOException {
 		for (CopyrightSegment seg : segments) {
-			seg.write(block);
+			seg.write(ds);
 		}
 	}
 
diff --git a/src/uk/me/parabola/tdbfmt/CopyrightSegment.java b/src/uk/me/parabola/tdbfmt/CopyrightSegment.java
index 5c5d3f8..bd16d16 100644
--- a/src/uk/me/parabola/tdbfmt/CopyrightSegment.java
+++ b/src/uk/me/parabola/tdbfmt/CopyrightSegment.java
@@ -67,8 +67,7 @@ class CopyrightSegment {
 		this.extraProperties = 0;
 	}
 
-	public void write(Block block) throws IOException {
-		StructuredOutputStream os = block.getOutputStream();
+	public void write(StructuredOutputStream os) throws IOException {
 		os.write(copyrightCode);
 		os.write(whereCode);
 		os.write2(extraProperties);
diff --git a/src/uk/me/parabola/tdbfmt/DetailMapBlock.java b/src/uk/me/parabola/tdbfmt/DetailMapBlock.java
index 8a78222..1953475 100644
--- a/src/uk/me/parabola/tdbfmt/DetailMapBlock.java
+++ b/src/uk/me/parabola/tdbfmt/DetailMapBlock.java
@@ -28,6 +28,7 @@ import uk.me.parabola.io.StructuredOutputStream;
  * @author Steve Ratcliffe
  */
 public class DetailMapBlock extends OverviewMapBlock {
+	public static final int BLOCK_ID = 0x4c;
 
 	private int tdbVersion;
 
@@ -41,19 +42,18 @@ public class DetailMapBlock extends OverviewMapBlock {
 	private int nodDataSize;
 
 	public DetailMapBlock(int tdbVersion) {
+		super(BLOCK_ID);
 		assert tdbVersion > 0;
 		this.tdbVersion = tdbVersion;
 	}
 
 	/**
 	 * Initialise this block from the raw block given.
-	 * @param block The raw block read from the file.
+	 *
 	 * @throws IOException For io problems.
 	 */
-	public DetailMapBlock(Block block) throws IOException {
-		super(block);
-
-		StructuredInputStream ds = block.getInputStream();
+	public DetailMapBlock(StructuredInputStream ds) throws IOException {
+		super(ds);
 
 		// First there are a couple of fields that we ignore.
 		int junk = ds.read2();
@@ -75,15 +75,11 @@ public class DetailMapBlock extends OverviewMapBlock {
 	/**
 	 * Write into the given block.
 	 *
-	 * @param block The block that will have been initialised to be a detail
-	 * block.
 	 * @throws IOException Problems writing, probably can't really happen as
 	 * we use an array backed stream.
 	 */
-	public void write(Block block) throws IOException {
-		super.write(block);
-
-		StructuredOutputStream os = block.getOutputStream();
+	public void writeBody(StructuredOutputStream os) throws IOException {
+		super.writeBody(os);
 
 		int n = 3;
 		if (tdbVersion >= TdbFile.TDB_V407) {
@@ -120,7 +116,7 @@ public class DetailMapBlock extends OverviewMapBlock {
 		}
 	}
 
-	public String getInnername() {
+	private String getInnername() {
 		return innername;
 	}
 
diff --git a/src/uk/me/parabola/tdbfmt/HeaderBlock.java b/src/uk/me/parabola/tdbfmt/HeaderBlock.java
index ebdb91c..5ab769a 100644
--- a/src/uk/me/parabola/tdbfmt/HeaderBlock.java
+++ b/src/uk/me/parabola/tdbfmt/HeaderBlock.java
@@ -18,6 +18,7 @@ package uk.me.parabola.tdbfmt;
 
 import java.io.IOException;
 
+import uk.me.parabola.io.FileBlock;
 import uk.me.parabola.io.StructuredInputStream;
 import uk.me.parabola.io.StructuredOutputStream;
 
@@ -26,7 +27,8 @@ import uk.me.parabola.io.StructuredOutputStream;
  *
  * @author Steve Ratcliffe
  */
-class HeaderBlock {
+class HeaderBlock extends FileBlock {
+	static final int BLOCK_ID = 0x50;
 
 	/** The map family. */
 	private short familyId;
@@ -54,11 +56,12 @@ class HeaderBlock {
 	private int codePage;
 
 	HeaderBlock(int tdbVersion) {
+		super(BLOCK_ID);
 		this.tdbVersion = tdbVersion;
 	}
 
-	HeaderBlock(Block block) throws IOException {
-		StructuredInputStream ds = block.getInputStream();
+	public HeaderBlock(StructuredInputStream ds) throws IOException {
+		super(BLOCK_ID);
 
 		productId = (short) ds.read2();
 		familyId = (short) ds.read2();
@@ -69,8 +72,10 @@ class HeaderBlock {
 		familyName = ds.readString();
 	}
 
-	public void write(Block block) throws IOException {
-		StructuredOutputStream os = block.getOutputStream();
+	/**
+	 * This is to overridden in a subclass.
+	 */
+	protected void writeBody(StructuredOutputStream os) throws IOException {
 		os.write2(productId);
 		os.write2(familyId);
 		os.write2(tdbVersion);
@@ -96,34 +101,15 @@ class HeaderBlock {
 			os.write3(0);
 			os.write4(codePage);
 			os.write4(10000);
-			os.write(1);	// map is routable
+			os.write(1);    // map is routable
 			if (enableProfile == 1)
-				os.write(1);	// map has profile information
+				os.write(1);    // map has profile information
 			else
 				os.write(0);
-			os.write(0);	// map has DEM sub files
+			os.write(0);    // map has DEM sub files
 		}
 	}
 
-	// good
-			//os.write(0);
-			//os.write(0x12);
-			//os.write(1);
-			//os.write(1);
-			//os.write(1);
-			//os.write4(0);
-			//os.write(0);
-			//os.write(0x15);
-			//os.write4(0);
-			//os.write4(0);
-			//os.write4(0);
-			//os.write4(0);
-			//os.write3(0);
-			//os.write4(1252);
-			//os.write4(10000);
-			//os.write(1);
-			//os.write(0);
-			//os.write(0);
 	public String toString() {
 		return "TDB header: "
 				+ productId
diff --git a/src/uk/me/parabola/tdbfmt/OverviewMapBlock.java b/src/uk/me/parabola/tdbfmt/OverviewMapBlock.java
index a8bc223..86506ff 100644
--- a/src/uk/me/parabola/tdbfmt/OverviewMapBlock.java
+++ b/src/uk/me/parabola/tdbfmt/OverviewMapBlock.java
@@ -19,6 +19,7 @@ package uk.me.parabola.tdbfmt;
 import java.io.IOException;
 
 import uk.me.parabola.imgfmt.app.Area;
+import uk.me.parabola.io.FileBlock;
 import uk.me.parabola.io.StructuredInputStream;
 import uk.me.parabola.io.StructuredOutputStream;
 
@@ -36,10 +37,11 @@ import uk.me.parabola.io.StructuredOutputStream;
  * 
  * @author Steve Ratcliffe
  */
-public class OverviewMapBlock {
+public class OverviewMapBlock extends FileBlock {
+	public static final int BLOCK_ID = 0x42;
+
 
 	private int mapNumber;
-	private String mapName;
 	private int parentMapNumber;
 
 	private String description;
@@ -50,11 +52,16 @@ public class OverviewMapBlock {
 	private int minLong;
 
 	public OverviewMapBlock() {
+		super(BLOCK_ID);
 		description = "overview map";
 	}
 
-	public OverviewMapBlock(Block block) throws IOException {
-		StructuredInputStream ds = block.getInputStream();
+	protected OverviewMapBlock(int blockId) {
+		super(blockId);
+	}
+
+	public OverviewMapBlock(StructuredInputStream ds) throws IOException {
+		super(BLOCK_ID);
 
 		mapNumber = ds.read4();
 		parentMapNumber = ds.read4();
@@ -67,9 +74,7 @@ public class OverviewMapBlock {
 		description = ds.readString();
 	}
 
-	public void write(Block block) throws IOException {
-		StructuredOutputStream os = block.getOutputStream();
-
+	public void writeBody(StructuredOutputStream os) throws IOException {
 		os.write4(mapNumber);
 		os.write4(parentMapNumber);
 		os.write4(maxLat);
@@ -108,7 +113,6 @@ public class OverviewMapBlock {
 	}
 
 	public void setMapName(String mapName) {
-		this.mapName = mapName;
 		try {
 			this.mapNumber = Integer.parseInt(mapName);
 		} catch (NumberFormatException e) {
@@ -116,10 +120,6 @@ public class OverviewMapBlock {
 		}
 	}
 
-	protected String getMapName() {
-		return mapName;
-	}
-
 	public void setParentMapNumber(int parentMapNumber) {
 		this.parentMapNumber = parentMapNumber;
 	}
diff --git a/src/uk/me/parabola/tdbfmt/RBlock.java b/src/uk/me/parabola/tdbfmt/RBlock.java
index 179c1c8..42320b4 100644
--- a/src/uk/me/parabola/tdbfmt/RBlock.java
+++ b/src/uk/me/parabola/tdbfmt/RBlock.java
@@ -18,17 +18,22 @@ package uk.me.parabola.tdbfmt;
 
 import java.io.IOException;
 
+import uk.me.parabola.io.FileBlock;
 import uk.me.parabola.io.StructuredOutputStream;
 
 /**
  * @author Steve Ratcliffe
  */
-public class RBlock {
+public class RBlock extends FileBlock {
+	private static final int BLOCK_ID = 'R';
+
 	private final String previewDescription = "Test preview map";
 
-	public void write(Block block) throws IOException {
-		StructuredOutputStream os = block.getOutputStream();
+	public RBlock() {
+		super(BLOCK_ID);
+	}
 
+	public void writeBody(StructuredOutputStream os) throws IOException {
 		os.write(0xc3);
 		os.writeString(previewDescription);
 	}
diff --git a/src/uk/me/parabola/tdbfmt/TBlock.java b/src/uk/me/parabola/tdbfmt/TBlock.java
index 6335514..f2fa0a7 100644
--- a/src/uk/me/parabola/tdbfmt/TBlock.java
+++ b/src/uk/me/parabola/tdbfmt/TBlock.java
@@ -18,16 +18,25 @@ package uk.me.parabola.tdbfmt;
 
 import java.io.IOException;
 
+import uk.me.parabola.io.FileBlock;
 import uk.me.parabola.io.StructuredOutputStream;
 
 /**
  * @author Steve Ratcliffe
  */
-public class TBlock {
+public class TBlock extends FileBlock {
+	private static final int BLOCK_ID = 'T';
+
 	private long sum;
 
-	public void write(Block block) throws IOException {
-		StructuredOutputStream os = block.getOutputStream();
+	public TBlock() {
+		super(BLOCK_ID);
+	}
+
+	/**
+	 * This is to overridden in a subclass.
+	 */
+	protected void writeBody(StructuredOutputStream os) throws IOException {
 		// If you change A,B,C or D the maps
 		// will not load, you can change the rest without easily visible
 		// problems although I suppose they must do something.
diff --git a/src/uk/me/parabola/tdbfmt/TdbFile.java b/src/uk/me/parabola/tdbfmt/TdbFile.java
index 0b9e33d..5156858 100644
--- a/src/uk/me/parabola/tdbfmt/TdbFile.java
+++ b/src/uk/me/parabola/tdbfmt/TdbFile.java
@@ -18,6 +18,7 @@ package uk.me.parabola.tdbfmt;
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -42,13 +43,6 @@ public class TdbFile {
 
 	public static final int TDB_V407 = 407;
 
-	private static final int BLOCK_OVERVIEW = 0x42;
-	private static final int BLOCK_HEADER = 0x50;
-	private static final int BLOCK_COPYRIGHT = 0x44;
-	private static final int BLOCK_DETAIL = 0x4c;
-	private static final int BLOCK_R = 0x52;
-	private static final int BLOCK_T = 0x54;
-
 	// The version number of the TDB format
 	private int tdbVersion;
 
@@ -56,10 +50,11 @@ public class TdbFile {
 	private HeaderBlock headerBlock;
 	private CopyrightBlock copyrightBlock = new CopyrightBlock();
 	private OverviewMapBlock overviewMapBlock;
-	private final List<DetailMapBlock> detailBlocks = new ArrayList<DetailMapBlock>();
+	private final List<DetailMapBlock> detailBlocks = new ArrayList<>();
 	private final RBlock rblock = new RBlock();
 	private final TBlock tblock = new TBlock();
 	private String overviewDescription;
+	private int codePage;
 
 	public TdbFile() {
 	}
@@ -78,13 +73,8 @@ public class TdbFile {
 	public static TdbFile read(String name) throws IOException {
 		TdbFile tdb = new TdbFile();
 
-		InputStream is = new BufferedInputStream(new FileInputStream(name));
-
-		try {
-			StructuredInputStream ds = new StructuredInputStream(is);
-			tdb.load(ds);
-		} finally {
-			is.close();
+		try (InputStream is = new BufferedInputStream(new FileInputStream(name))) {
+			tdb.load(is);
 		}
 
 		return tdb;
@@ -105,6 +95,7 @@ public class TdbFile {
 	}
 
 	public void setCodePage(int codePage) {
+		this.codePage = codePage;
 		headerBlock.setCodePage(codePage);
 	}
 
@@ -113,6 +104,9 @@ public class TdbFile {
 	 * @param msg The message to add.
 	 */
 	public void addCopyright(String msg) {
+		if (msg.isEmpty())
+			return;
+
 		CopyrightSegment seg = new CopyrightSegment(CopyrightSegment.CODE_COPYRIGHT_TEXT_STRING, 3, msg);
 		copyrightBlock.addSegment(seg);
 	}
@@ -139,47 +133,32 @@ public class TdbFile {
 	}
 
 	public void write(String name) throws IOException {
-		CheckedOutputStream stream = new CheckedOutputStream(
-				new BufferedOutputStream(new FileOutputStream(name)),
-				new CRC32());
 
 		if (headerBlock == null || overviewMapBlock == null)
 			throw new IOException("Attempting to write file without being fully set up");
 
-		try {
-			Block block = new Block(BLOCK_HEADER);
-			headerBlock.write(block);
-			block.write(stream);
+		try (CheckedOutputStream stream = new CheckedOutputStream(
+				new BufferedOutputStream(new FileOutputStream(name)),
+				new CRC32()))
+		{
+			headerBlock.writeTo(stream, codePage);
 
-			block = new Block(BLOCK_COPYRIGHT);
-			copyrightBlock.write(block);
-			block.write(stream);
+			copyrightBlock.writeTo(stream, codePage);
 
 			if (tdbVersion >= TDB_V407) {
-				block = new Block(BLOCK_R);
-				rblock.write(block);
-				block.write(stream);
+				rblock.writeTo(stream, codePage);
 			}
 
-			block = new Block(BLOCK_OVERVIEW);
-			overviewMapBlock.write(block);
-			block.write(stream);
+			overviewMapBlock.writeTo(stream, codePage);
 
 			for (DetailMapBlock detail : detailBlocks) {
-				block = new Block(BLOCK_DETAIL);
-				detail.write(block);
-				block.write(stream);
+				detail.writeTo(stream, codePage);
 			}
 
 			if (tdbVersion >= TDB_V407) {
 				tblock.setSum(stream.getChecksum().getValue());
-
-				block = new Block(BLOCK_T);
-				tblock.write(block);
-				block.write(stream);
+				tblock.writeTo(stream, codePage);
 			}
-		} finally {
-			stream.close();
 		}
 	}
 
@@ -189,56 +168,73 @@ public class TdbFile {
 	 * @param ds The stream to read from.
 	 * @throws IOException For problems reading the file.
 	 */
-	private void load(StructuredInputStream ds) throws IOException {
-
-		while (!ds.testEof()) {
-			Block block = readBlock(ds);
-
-			switch (block.getBlockId()) {
-			case BLOCK_HEADER:
-				headerBlock = new HeaderBlock(block);
-				log.info("header block seen", headerBlock);
-				break;
-			case BLOCK_COPYRIGHT:
-				log.info("copyright block");
-				copyrightBlock = new CopyrightBlock(block);
-				break;
-			case BLOCK_OVERVIEW:
-				overviewMapBlock = new OverviewMapBlock(block);
-				log.info("overview block", overviewMapBlock);
-				break;
-			case BLOCK_DETAIL:
-				DetailMapBlock db = new DetailMapBlock(block);
-				log.info("detail block", db);
-				detailBlocks.add(db);
-				break;
-			default:
-				log.warn("Unknown block in tdb file");
-				break;
+	private void load(InputStream ds) throws IOException {
+
+		boolean eof = false;
+		while (!eof) {
+			try {
+				readBlock(ds);
+			} catch (EndOfFileException ignore) {
+				eof = true;
 			}
 		}
-
 	}
 
 	/**
 	 * The file is divided into blocks.  This reads a single block.
 	 *
 	 * @param is The input stream.
-	 * @return A block from the file.
 	 * @throws IOException For problems reading the file.
 	 */
-	private Block readBlock(StructuredInputStream is) throws IOException {
+	private void readBlock(InputStream is) throws IOException {
 		int blockType = is.read();
 		if (blockType == -1)
 			throw new EndOfFileException();
-		int blockLength = is.read2();
+
+		int blockLength = readBlockLength(is);
+		if (blockLength == -1)
+			throw new EndOfFileException();
 
 		byte[] body = new byte[blockLength];
 		int n = is.read(body);
 		if (n < 0)
 			throw new IOException("failed to read block");
 
-		return new Block(blockType, body);
+		StructuredInputStream ds = new StructuredInputStream(new ByteArrayInputStream(body));
+		switch (blockType) {
+		case HeaderBlock.BLOCK_ID:
+			headerBlock = new HeaderBlock(ds);
+			log.info("header block seen", headerBlock);
+			break;
+		case CopyrightBlock.BLOCK_ID:
+			log.info("copyright block");
+			copyrightBlock = new CopyrightBlock(ds);
+			break;
+		case OverviewMapBlock.BLOCK_ID:
+			overviewMapBlock = new OverviewMapBlock(ds);
+			log.info("overview block", overviewMapBlock);
+			break;
+		case DetailMapBlock.BLOCK_ID:
+			DetailMapBlock db = new DetailMapBlock(ds);
+			log.info("detail block", db);
+			detailBlocks.add(db);
+			break;
+		default:
+			log.warn("Unknown block in tdb file");
+			break;
+		}
+	}
+
+	private int readBlockLength(InputStream is) throws IOException {
+		int b1 = is.read();
+		if (b1 < 0)
+			return -1;
+
+		int b2 = is.read();
+		if (b2 < 0)
+			return -1;
+
+		return ((b2 & 0xff) << 8) | (b1 & 0xff);
 	}
 
 	public int getTdbVersion() {
diff --git a/test/func/ArgsTest.java b/test/func/ArgsTest.java
index 23503b4..c5f873e 100644
--- a/test/func/ArgsTest.java
+++ b/test/func/ArgsTest.java
@@ -93,4 +93,10 @@ public class ArgsTest extends Base {
 
 		assertEquals("display priority", pri, ((TREHeader) treFile.getHeader()).getDisplayPriority());
 	}
+
+	@Test
+	public void testNoDescription() {
+		Outputs op = TestUtils.run("--description", Args.TEST_RESOURCE_OSM + "uk-test-1.osm.gz");
+		op.checkNoError();
+	}
 }
diff --git a/test/func/SimpleTest.java b/test/func/SimpleTest.java
index 5b378d2..b0e0c18 100644
--- a/test/func/SimpleTest.java
+++ b/test/func/SimpleTest.java
@@ -53,11 +53,8 @@ public class SimpleTest extends Base {
 	@Test
 	public void testBasic() throws FileNotFoundException {
 
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
-				"--preserve-element-order",
-				Args.TEST_RESOURCE_OSM + "uk-test-1.osm.gz"
-		});
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG, "--preserve-element-order",
+				Args.TEST_RESOURCE_OSM + "uk-test-1.osm.gz");
 
 		MapReader mr = new MapReader(Args.DEF_MAP_ID + ".img");
 		TestUtils.registerFile(mr);
@@ -77,18 +74,13 @@ public class SimpleTest extends Base {
 
 	@Test
 	public void testNoSuchFile() {
-		Main.mainNoSystemExit(new String[]{
-				"no-such-file-xyz.osm",
-		});
+		Main.mainNoSystemExit("no-such-file-xyz.osm");
 		assertFalse("no file generated", new File(Args.DEF_MAP_FILENAME).exists());
 	}
 
 	@Test
 	public void testPolish() throws FileNotFoundException {
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
-				Args.TEST_RESOURCE_MP + "test1.mp"
-		});
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG, Args.TEST_RESOURCE_MP + "test1.mp");
 
 		FileSystem fs = openFs(Args.DEF_MAP_FILENAME);
 		assertNotNull("file exists", fs);
@@ -109,7 +101,7 @@ public class SimpleTest extends Base {
 				count++;
 				System.out.println("TRE size " + size);
 				// Size varies depending on svn modified status
-				assertThat("TRE size", size, new RangeMatcher(769, 2));
+				assertThat("TRE size", size, new RangeMatcher(770, 2));
 				break;
 			case "LBL":
 				count++;
@@ -118,5 +110,6 @@ public class SimpleTest extends Base {
 			}
 		}
 		assertTrue("enough checks run", count >= 3);
+
 	}
 }
diff --git a/test/func/StructureTest.java b/test/func/StructureTest.java
index 713c3d3..016006c 100644
--- a/test/func/StructureTest.java
+++ b/test/func/StructureTest.java
@@ -72,10 +72,7 @@ public class StructureTest {
 	public static void init() throws FileNotFoundException {
 		TestUtils.deleteOutputFiles();
 
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
-				Args.TEST_RESOURCE_OSM + "uk-test-1.osm.gz"
-		});
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG, Args.TEST_RESOURCE_OSM + "uk-test-1.osm.gz");
 
 		fs = ImgFS.openFs(Args.DEF_MAP_FILENAME);
 		ImgChannel tre = fs.open(Args.DEF_MAP_ID + ".TRE", "r");
diff --git a/test/func/files/GmapsuppTest.java b/test/func/files/GmapsuppTest.java
index 6870cee..69166e6 100644
--- a/test/func/files/GmapsuppTest.java
+++ b/test/func/files/GmapsuppTest.java
@@ -17,7 +17,6 @@ import java.io.File;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
-import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
@@ -47,12 +46,10 @@ public class GmapsuppTest extends Base {
 		File f = new File(GMAPSUPP_IMG);
 		assertFalse("does not pre-exist", f.exists());
 
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG,
 				"--gmapsupp",
 				Args.TEST_RESOURCE_IMG + "63240001.img",
-				Args.TEST_RESOURCE_IMG + "63240002.img"
-		});
+				Args.TEST_RESOURCE_IMG + "63240002.img");
 
 		assertTrue("gmapsupp.img is created", f.exists());
 
@@ -72,8 +69,7 @@ public class GmapsuppTest extends Base {
 	 */
 	@Test
 	public void testMpsFile() throws IOException {
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG,
 				"--gmapsupp",
 				"--family-id=150",
 				"--product-id=24",
@@ -81,8 +77,7 @@ public class GmapsuppTest extends Base {
 				"--family-name=tst family",
 				"--area-name=tst area",
 				Args.TEST_RESOURCE_IMG + "63240001.img",
-				Args.TEST_RESOURCE_IMG + "63240002.img"
-		});
+				Args.TEST_RESOURCE_IMG + "63240002.img");
 
 		MpsFileReader reader = getMpsFile();
 		List<MapBlock> list = reader.getMaps();
@@ -108,38 +103,30 @@ public class GmapsuppTest extends Base {
 	@Test
 	public void testCombiningSupps() throws IOException {
 		TestUtils.registerFile("g1.img", "g2.img");
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG,
 				"--gmapsupp",
 				"--family-id=150",
 				"--product-id=24",
 				"--series-name=tst series",
 				"--family-name=tst family",
 				"--area-name=tst area",
-				Args.TEST_RESOURCE_IMG + "63240001.img",
-		});
+				Args.TEST_RESOURCE_IMG + "63240001.img");
 
 		File f = new File("gmapsupp.img");
 		f.renameTo(new File("g1.img"));
 
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG,
 				"--gmapsupp",
 				"--family-id=152",
 				"--product-id=26",
 				"--series-name=tst series 2",
 				"--family-name=tst family 2",
 				"--area-name=tst area 2",
-				Args.TEST_RESOURCE_IMG + "63240002.img",
-		});
+				Args.TEST_RESOURCE_IMG + "63240002.img");
+
 		f.renameTo(new File("g2.img"));
 
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
-				"--gmapsupp",
-				"g1.img",
-				"g2.img"
-		});
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG, "--gmapsupp", "g1.img", "g2.img");
 
 
 		MpsFileReader reader = getMpsFile();
@@ -173,20 +160,16 @@ public class GmapsuppTest extends Base {
 	 */
 	@Test
 	public void testDifferentFamilies() throws IOException {
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG,
 				"--gmapsupp",
-
 				"--family-id=101",
 				"--product-id=1",
 				"--series-name=tst series1",
 				Args.TEST_RESOURCE_IMG + "63240001.img",
-
 				"--family-id=102",
 				"--product-id=2",
 				"--series-name=tst series2",
-				Args.TEST_RESOURCE_IMG + "63240002.img"
-		});
+				Args.TEST_RESOURCE_IMG + "63240002.img");
 
 		MpsFileReader reader = getMpsFile();
 		List<MapBlock> list = reader.getMaps();
@@ -212,27 +195,23 @@ public class GmapsuppTest extends Base {
 	 */
 	@Test
 	public void testProductBlocks() throws IOException {
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG,
 				"--gmapsupp",
-
 				"--family-id=101",
 				"--product-id=1",
 				"--family-name=tst family1",
 				"--series-name=tst series1",
 				Args.TEST_RESOURCE_IMG + "63240001.img",
-
 				"--family-id=102",
 				"--product-id=2",
 				"--family-name=tst family2",
 				"--series-name=tst series2",
-				Args.TEST_RESOURCE_IMG + "63240002.img"
-		});
+				Args.TEST_RESOURCE_IMG + "63240002.img");
 
 		MpsFileReader reader = getMpsFile();
 
 		List<ProductBlock> products = reader.getProducts();
-		Collections.sort(products, new Comparator<ProductBlock>() {
+		products.sort(new Comparator<ProductBlock>() {
 			public int compare(ProductBlock o1, ProductBlock o2) {
 				if (o1.getFamilyId() == o2.getFamilyId())
 					return 0;
@@ -259,17 +238,14 @@ public class GmapsuppTest extends Base {
 	 */
 	@Test
 	public void testProductWithSeveralMaps() throws IOException {
-		Main.mainNoSystemExit(new String[]{
-						Args.TEST_STYLE_ARG,
-						"--gmapsupp",
-
-						"--family-id=101",
-						"--product-id=1",
-						"--family-name=tst family1",
-						"--series-name=tst series1",
-						Args.TEST_RESOURCE_IMG + "63240001.img",
-						Args.TEST_RESOURCE_IMG + "63240002.img"
-				});
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG,
+				"--gmapsupp",
+				"--family-id=101",
+				"--product-id=1",
+				"--family-name=tst family1",
+				"--series-name=tst series1",
+				Args.TEST_RESOURCE_IMG + "63240001.img",
+				Args.TEST_RESOURCE_IMG + "63240002.img");
 
 		MpsFileReader reader = getMpsFile();
 		assertEquals("number of map blocks", 2, reader.getMaps().size());
@@ -279,19 +255,16 @@ public class GmapsuppTest extends Base {
 	@Test
 	public void testWithIndex() throws IOException {
 		new File("osmmap_mdr.img").delete();
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG,
 				"--gmapsupp",
 				"--index",
 				"--latin1",
-
 				"--family-id=101",
 				"--product-id=1",
 				"--family-name=tst family1",
 				"--series-name=tst series1",
 				Args.TEST_RESOURCE_IMG + "63240001.img",
-				Args.TEST_RESOURCE_IMG + "63240002.img"
-		});
+				Args.TEST_RESOURCE_IMG + "63240002.img");
 
 		assertFalse(new File("osmmap_mdr.img").exists());
 
@@ -315,20 +288,17 @@ public class GmapsuppTest extends Base {
 	public void testWithTwoIndexes() throws IOException {
 		TestUtils.registerFile("osmmap_mdr.img", "osmmap.img", "osmmap.tbd", "osmmap.mdx");
 
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG,
 				"--gmapsupp",
 				"--index",
 				"--tdbfile",
 				"--latin1",
-
 				"--family-id=101",
 				"--product-id=1",
 				"--family-name=tst family1",
 				"--series-name=tst series1",
 				Args.TEST_RESOURCE_IMG + "63240001.img",
-				Args.TEST_RESOURCE_IMG + "63240002.img"
-		});
+				Args.TEST_RESOURCE_IMG + "63240002.img");
 
 		assertTrue(new File("osmmap_mdr.img").exists());
 
@@ -355,12 +325,10 @@ public class GmapsuppTest extends Base {
 	public void testTwoFamilyIndex() throws IOException {
 		TestUtils.registerFile("osmmap_mdr.img", "osmmap.img", "osmmap.tbd", "osmmap.mdx");
 
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG,
 				"--gmapsupp",
 				"--index",
 				"--latin1",
-
 				"--family-id=101",
 				"--product-id=1",
 				"--family-name=tst family1",
@@ -369,8 +337,7 @@ public class GmapsuppTest extends Base {
 				"--family-id=202",
 				"--family-name=tst family2",
 				"--series-name=tst series2",
-				Args.TEST_RESOURCE_OSM + "uk-test-2.osm.gz"
-		});
+				Args.TEST_RESOURCE_OSM + "uk-test-2.osm.gz");
 
 		assertFalse(new File("osmmap_mdr.img").exists());
 
@@ -407,20 +374,10 @@ public class GmapsuppTest extends Base {
 	public void testImplicitCodePageIndex() throws IOException {
 		TestUtils.registerFile("osmmap_mdr.img", "osmmap.img", "osmmap.tbd", "osmmap.mdx");
 
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
-				"--code-page=1256",
-
-				Args.TEST_RESOURCE_OSM + "uk-test-1.osm.gz",
-		});
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG, "--code-page=1256",
+				Args.TEST_RESOURCE_OSM + "uk-test-1.osm.gz");
 
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
-				"--gmapsupp",
-				"--index",
-
-				"63240001.img",
-		});
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG, "--gmapsupp", "--index", "63240001.img");
 
 		assertFalse(new File("osmmap_mdr.img").exists());
 
@@ -442,15 +399,10 @@ public class GmapsuppTest extends Base {
 	public void testWarningOnMismatchedCodePages() throws IOException {
 		TestUtils.registerFile("osmmap.img");
 
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
-				"--route",
-				"--code-page=1256",
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG, "--route", "--code-page=1256",
 				Args.TEST_RESOURCE_OSM + "uk-test-1.osm.gz",
-
 				"--latin1",
-				Args.TEST_RESOURCE_OSM + "uk-test-2.osm.gz",
-		});
+				Args.TEST_RESOURCE_OSM + "uk-test-2.osm.gz");
 
 		Outputs outputs = TestUtils.run(Args.TEST_STYLE_ARG,
 				"--gmapsupp",
@@ -465,7 +417,7 @@ public class GmapsuppTest extends Base {
 
 	private MpsFileReader getMpsFile() throws IOException {
 		FileSystem fs = openFs(GMAPSUPP_IMG);
-		MpsFileReader reader = new MpsFileReader(fs.open("MAKEGMAP.MPS", "r"));
+		MpsFileReader reader = new MpsFileReader(fs.open("MAKEGMAP.MPS", "r"), 0);
 		TestUtils.registerFile(reader);
 		return reader;
 	}
diff --git a/test/func/files/TdbTest.java b/test/func/files/TdbTest.java
index 8b60ccf..7b7d7fb 100644
--- a/test/func/files/TdbTest.java
+++ b/test/func/files/TdbTest.java
@@ -36,12 +36,9 @@ public class TdbTest extends Base {
 	 */
 	@Test
 	public void testBasic() throws IOException {
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
-				"--tdbfile",
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG, "--tdbfile",
 				Args.TEST_RESOURCE_OSM + "uk-test-1.osm.gz",
-				Args.TEST_RESOURCE_OSM + "uk-test-2.osm.gz"
-		});
+				Args.TEST_RESOURCE_OSM + "uk-test-2.osm.gz");
 
 		File f = new File(TDBNAME);
 		assertTrue("TDB was created", f.exists());
@@ -58,16 +55,7 @@ public class TdbTest extends Base {
 	public void testOptions() {
 		int thisMapname = 11112222;
 		TestUtils.registerFile(thisMapname + ".img", thisMapname + ".tdb");
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
-				"--tdbfile",
-				"--overview-mapname=" + thisMapname,
-				"--family-id=198",
-				"--product-id=2",
-				"--series-name=Test series",
-				"--family-name=Test family",
-				Args.TEST_RESOURCE_OSM + "uk-test-1.osm.gz"
-		});
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG, "--tdbfile", "--overview-mapname=" + thisMapname, "--family-id=198", "--product-id=2", "--series-name=Test series", "--family-name=Test family", Args.TEST_RESOURCE_OSM + "uk-test-1.osm.gz");
 
 		File f = new File(thisMapname + ".tdb");
 		assertTrue("TDB was created", f.exists());
diff --git a/test/func/route/SimpleRouteTest.java b/test/func/route/SimpleRouteTest.java
index 73d0da2..68ec844 100644
--- a/test/func/route/SimpleRouteTest.java
+++ b/test/func/route/SimpleRouteTest.java
@@ -36,13 +36,8 @@ public class SimpleRouteTest extends Base {
 	 */
 	@Test
 	public void testSize() throws FileNotFoundException {
-		Main.mainNoSystemExit(new String[]{
-				Args.TEST_STYLE_ARG,
-				"--preserve-element-order",
-				"--route",
-				Args.TEST_RESOURCE_OSM + "uk-test-1.osm.gz",
-				Args.TEST_RESOURCE_MP + "test1.mp"
-		});
+		Main.mainNoSystemExit(Args.TEST_STYLE_ARG, "--preserve-element-order",
+				"--route", Args.TEST_RESOURCE_OSM + "uk-test-1.osm.gz", Args.TEST_RESOURCE_MP + "test1.mp");
 
 		FileSystem fs = openFs(Args.DEF_MAP_ID + ".img");
 		assertNotNull("file exists", fs);
@@ -63,7 +58,7 @@ public class SimpleRouteTest extends Base {
 				count++;
 				System.out.println("TRE size " + size);
 				// Size varies depending on svn modified status
-				assertThat("TRE size", size, new RangeMatcher(1454, 2));
+				assertThat("TRE size", size, new RangeMatcher(1455, 2));
 				break;
 			case "LBL":
 				count++;
@@ -100,7 +95,7 @@ public class SimpleRouteTest extends Base {
 				count++;
 				System.out.println("TRE size " + size);
 				// Size varies depending on svn modified status
-				assertThat("TRE size", size, new RangeMatcher(769, 2));
+				assertThat("TRE size", size, new RangeMatcher(770, 2));
 				break;
 			case "LBL":
 				count++;
diff --git a/test/func/sources/TestSourceTest.java b/test/func/sources/TestSourceTest.java
index 8576c19..29c9139 100644
--- a/test/func/sources/TestSourceTest.java
+++ b/test/func/sources/TestSourceTest.java
@@ -33,9 +33,7 @@ public class TestSourceTest extends Base {
 	@Test
 	public void testAllElements() {
 		checkNoStdFile();
-		Main.mainNoSystemExit(new String[]{
-				"test-map:all-elements"
-		});
+		Main.mainNoSystemExit("test-map:all-elements");
 		checkStdFile();
 	}
 
@@ -44,9 +42,7 @@ public class TestSourceTest extends Base {
 	 */
 	@Test
 	public void testAllPoints() {
-		Main.mainNoSystemExit(new String[]{
-				"test-map:test-points"
-		});
+		Main.mainNoSystemExit("test-map:test-points");
 		checkStdFile();
 	}
 }

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



More information about the Pkg-grass-devel mailing list