diff -r 809e02f3a101 -r 61669e0e7f4f Makefile.in
--- a/Makefile.in	Tue Dec 23 00:08:20 2014 +0100
+++ b/Makefile.in	Wed Dec 31 17:21:54 2014 +0100
@@ -81,7 +81,7 @@
 	vpl.o teletype.o jogmap.o bushnell.o bushnell_trl.o wintec_tes.o \
 	subrip.o garmin_xt.o garmin_fit.o lowranceusr4.o \
 	mtk_locus.o googledir.o mapbar_track.o f90g_track.o mapfactor.o energympro.o \
-	mynav.o
+	mynav.o ggv_bin.o
 
 FMTS=@FMTS@
 
@@ -564,6 +564,8 @@
   garmin_tables.h grtcirc.h
 geo.o: geo.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h gbfile.h \
   cet.h inifile.h session.h src/core/datetime.h src/core/file.h
+ggv_bin.o: ggv_bin.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
+  gbfile.h cet.h inifile.h session.h src/core/datetime.h
 ggv_log.o: ggv_log.cc defs.h config.h queue.h zlib/zlib.h zlib/zconf.h \
   gbfile.h cet.h inifile.h session.h src/core/datetime.h grtcirc.h \
   jeeps/gpsmath.h jeeps/gpsport.h
diff -r 809e02f3a101 -r 61669e0e7f4f ggv_bin.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ggv_bin.cc	Wed Dec 31 17:21:54 2014 +0100
@@ -0,0 +1,521 @@
+/*
+
+    Handle Geogrid-Viewer binary overlay file format (.ovl)
+
+    Copyright (c) 2014 Ralf Horstmann <ralf@ackstorm.de>
+    Copyright (C) 2014 Robert Lipe, robertlipe+source@gpsbabel.org
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
+
+ */
+
+#include "defs.h"
+#include <QtCore/QtEndian>
+#include <QtCore/QByteArray>
+#include <QtCore/QDebug>
+#include <QtCore/QFile>
+
+#define MYNAME "ggv_bin"
+
+static QString read_fname;
+
+//***************************************************************************
+//           local helper functions
+//***************************************************************************
+
+static void
+ggv_bin_read_bytes(QFile& file, QByteArray& buf, qint64 size, const char* descr = NULL)
+{
+  if (size > file.size())
+    fatal(MYNAME ": Read size error (%s)\n", descr ? descr : "");
+  buf = file.read(size);
+  if (buf.size() < size)
+    fatal(MYNAME ": Read error (%s)\n", descr ? descr : "");
+}
+
+static quint16
+ggv_bin_read16(QFile& file, const char* descr = NULL)
+{
+  QByteArray buf;
+  quint16 res;
+
+  ggv_bin_read_bytes(file, buf, 2, descr);
+  res = qFromLittleEndian<quint16>((const uchar*)buf.constData());
+  if (global_opts.debug_level > 1)
+    qDebug("ovl: %s %u (0x%x)", descr, res, res);
+  return res;
+}
+
+static quint32
+ggv_bin_read32(QFile& file, const char* descr = NULL)
+{
+  QByteArray buf;
+  quint32 res;
+
+  ggv_bin_read_bytes(file, buf, 4, descr);
+  res = qFromLittleEndian<quint32>((const uchar*)buf.constData());
+  if (global_opts.debug_level > 1)
+    qDebug("ovl: %s %u (0x%x)", descr, res, res);
+  return res;
+}
+
+static void
+ggv_bin_read_text16(QFile& file, QByteArray& buf, const char* descr = NULL)
+{
+  quint16 len;
+  
+  len = ggv_bin_read16(file, descr);
+  ggv_bin_read_bytes(file, buf, len, descr);
+  buf[len] = 0;
+  if (global_opts.debug_level > 1)
+    qDebug() << "ovl: text" << QString::fromLatin1(buf.constData()).simplified();
+}
+
+static void
+ggv_bin_read_text32(QFile& file, QByteArray& buf, const char* descr = NULL)
+{
+  quint32 len;
+  
+  len = ggv_bin_read32(file, descr);
+  ggv_bin_read_bytes(file, buf, len, descr);
+  buf[len] = 0;
+  if (global_opts.debug_level > 1)
+    qDebug() << "ovl: text" << QString::fromLatin1(buf.constData()).simplified();
+}
+
+static double
+ggv_bin_read_double(QFile& file, const char* descr = NULL)
+{
+  QByteArray buf;
+  quint64 tmp;
+  double res;
+
+  ggv_bin_read_bytes(file, buf, sizeof(double), descr);
+  tmp = qFromLittleEndian<quint64>((const uchar*)buf.constData());
+  res = *reinterpret_cast<const double*>(&tmp);
+  return res;
+}
+
+//***************************************************************************
+//           OVL Version 2.0
+//***************************************************************************
+
+static void
+ggv_bin_read_file_v2(QFile& file, quint64 skip) {
+  QByteArray buf;
+  QString track_name;
+  QString waypt_name;
+  route_head* ggv_bin_track;
+  Waypoint* wpt;
+  double lon, lat;
+  quint16 header_type;
+  quint16 entry_type;
+  quint16 entry_subtype;
+  quint16 line_points;
+  quint64 entry_pos;
+
+  header_type = ggv_bin_read16(file, "header type");
+  switch (header_type) {
+  case 0x90:
+    // map name included, read it
+    file.read(4); // skip 4 bytes
+    ggv_bin_read_bytes(file, buf, 32, "map name");
+    buf[32] = 0;
+    if (global_opts.debug_level > 1)
+      qDebug() << "ovl: name =" << buf.constData();
+    file.seek(skip);
+    break;
+  case 0x00:
+    break;
+    // no map name, data follows directly
+  default:
+    fatal(MYNAME ": Unsupported header type (0x%x)\n", header_type);
+  }
+
+  while (!file.atEnd()) {
+    track_name.clear();
+
+    if (global_opts.debug_level > 1)
+      qDebug("------------------------------- 0x%llx", file.pos());
+
+    entry_pos  = file.pos();
+    entry_type = ggv_bin_read16(file, "entry type   ");
+    ggv_bin_read16(file, "entry group  ");
+    ggv_bin_read16(file, "entry zoom   ");
+    entry_subtype = ggv_bin_read16(file, "entry subtype");
+
+    switch (entry_subtype) {
+    case 0x01:
+      break;
+    case 0x10:
+      ggv_bin_read_text32(file, buf, "obj data");
+      track_name = QString::fromLatin1(buf.constData()).simplified();
+      if (global_opts.debug_level > 1)
+        qDebug() << "ovl: obj data =" << track_name;
+      break;
+    default:
+      fatal(MYNAME ": Unknown subtype (%hu)\n", entry_subtype);
+    }
+
+    switch (entry_type) {
+    case 0x02:
+      // text
+      ggv_bin_read16(file, "text color ");
+      ggv_bin_read16(file, "text size  ");
+      ggv_bin_read16(file, "text trans ");
+      ggv_bin_read16(file, "text font  ");
+      ggv_bin_read16(file, "text angle ");
+      lon = ggv_bin_read_double(file, "text lon   ");
+      lat = ggv_bin_read_double(file, "text lat   ");
+      ggv_bin_read_text16(file, buf, "text label");
+      waypt_name = QString::fromLatin1(buf.constData()).simplified();
+      if (global_opts.debug_level > 1)
+        qDebug() << "ovl: text =" << waypt_name;
+      wpt = new Waypoint;
+      wpt->longitude = lon;
+      wpt->latitude = lat;
+      wpt->description = waypt_name;
+      waypt_add(wpt);
+      break;
+    case 0x03:
+      // line
+    case 0x04:
+      // area
+      ggv_bin_read16(file, "line color ");
+      ggv_bin_read16(file, "line width ");
+      ggv_bin_read16(file, "line type  ");
+      line_points = ggv_bin_read16(file, "line points");
+
+      ggv_bin_track = route_head_alloc();
+      track_add_head(ggv_bin_track);
+      if (! track_name.isEmpty())
+        ggv_bin_track->rte_name = track_name;
+
+      for (int i = 1; i <= line_points; i++) {
+        lon = ggv_bin_read_double(file, "line lon");
+        lat = ggv_bin_read_double(file, "line lat");
+        wpt = new Waypoint;
+        wpt->longitude = lon;
+        wpt->latitude = lat;
+        track_add_wpt(ggv_bin_track, wpt);
+      }
+      break;
+    case 0x05:
+      // rectangle
+    case 0x06:
+      // circle
+    case 0x07:
+      // triangle
+      if (global_opts.debug_level > 1) {
+        if (entry_type == 5) qDebug() << "ovl: geom rectangle";
+        if (entry_type == 6) qDebug() << "ovl: geom circle";
+        if (entry_type == 7) qDebug() << "ovl: geom triangle";
+      }
+      ggv_bin_read16(file, "geom color ");
+      ggv_bin_read16(file, "geom prop1 ");
+      ggv_bin_read16(file, "geom prop2 ");
+      ggv_bin_read16(file, "geom angle ");
+      ggv_bin_read16(file, "geom stroke");
+      ggv_bin_read16(file, "geom area  ");
+      ggv_bin_read_double(file, "geom lon   ");
+      ggv_bin_read_double(file, "geom lat   ");
+      break;
+    case 0x09:
+      ggv_bin_read16(file, "bmp color");
+      ggv_bin_read16(file, "bmp prop1");
+      ggv_bin_read16(file, "bmp prop2");
+      ggv_bin_read16(file, "bmp prop3");
+      ggv_bin_read_double(file, "bmp lon  ");
+      ggv_bin_read_double(file, "bmp lat  ");
+      ggv_bin_read_text32(file, buf, "bmp data ");
+      break;
+    default:
+      fatal(MYNAME ": Unknown entry type (0x%hx, pos=0x%llx) \n", entry_type, entry_pos);
+    }
+  }
+}
+
+//***************************************************************************
+//           OVL Version 3.0 and 4.0
+//***************************************************************************
+
+static QString
+ggv_bin_read_common_v34(QFile& file) {
+  QByteArray buf;
+  QString res;
+  quint16 type;
+  quint64 pos;
+  
+  ggv_bin_read16(file, "entry group ");
+  ggv_bin_read16(file, "entry prop2 ");
+  ggv_bin_read16(file, "entry prop3 ");
+  ggv_bin_read16(file, "entry prop4 ");
+  ggv_bin_read16(file, "entry prop5 ");
+  ggv_bin_read16(file, "entry prop6 ");
+  ggv_bin_read16(file, "entry prop7 ");
+  ggv_bin_read16(file, "entry prop8 ");
+  ggv_bin_read16(file, "entry zoom  ");
+  ggv_bin_read16(file, "entry prop10");
+  ggv_bin_read_text16(file, buf, "entry txt");
+  res = QString::fromLatin1(buf.constData()).simplified();
+  pos = file.pos();
+  type = ggv_bin_read16(file, "entry type");
+  switch (type) {
+  case 0x01:
+    break;
+  case 0x07:
+  case 0x10:
+    ggv_bin_read_text32(file, buf, "entry object");
+    break;
+  default:
+    fatal(MYNAME ": Unkown object type (0x%hx, pos=%llx)\n", type, pos);
+  }
+  return res;
+}
+
+static void
+ggv_bin_read_file_v34(QFile& file, quint64 skip) {
+  QByteArray buf;
+  QString track_name;
+  QString waypt_name;
+  Waypoint *wpt;
+  route_head* ggv_bin_track;
+  quint16 entry_type;
+  quint64 entry_pos;
+  quint32 bmp_len;
+  quint16 line_points;
+  double lon, lat;
+
+  file.seek(skip);
+  
+  while (!file.atEnd()) {
+    if (global_opts.debug_level > 1)
+      qDebug("------------------------------- 0x%llx", file.pos());
+
+    entry_pos = file.pos();
+    entry_type = ggv_bin_read16(file, "entry type  ");
+
+    switch (entry_type) {
+    case 0x02:
+      // text
+      ggv_bin_read_common_v34(file);
+      ggv_bin_read32(file, "text prop1");
+      ggv_bin_read32(file, "text prop2");
+      ggv_bin_read16(file, "text prop3");
+      ggv_bin_read32(file, "text prop4");
+      ggv_bin_read16(file, "text ltype");
+      ggv_bin_read16(file, "text angle");
+      ggv_bin_read16(file, "text size ");
+      ggv_bin_read16(file, "text area ");
+      lon = ggv_bin_read_double(file, "text lon");
+      lat = ggv_bin_read_double(file, "text lat");
+      ggv_bin_read_double(file, "text unk");
+      ggv_bin_read_text16(file, buf, "text label");
+      wpt = new Waypoint;
+      wpt->longitude = lon;
+      wpt->latitude = lat;
+      wpt->description = QString::fromLatin1(buf.constData()).simplified();
+      waypt_add(wpt);
+      break;
+    case 0x03:
+    case 0x04:
+      // area
+    case 0x17:
+      // line
+      ggv_bin_track = route_head_alloc();
+      track_add_head(ggv_bin_track);
+      
+      track_name = ggv_bin_read_common_v34(file);
+      if (! track_name.isEmpty()) 
+        ggv_bin_track->rte_name = track_name;
+
+      ggv_bin_read16(file, "line prop1  ");
+      ggv_bin_read16(file, "line prop2  ");
+      ggv_bin_read32(file, "line prop3  ");
+      ggv_bin_read16(file, "line prop4  ");
+      ggv_bin_read32(file, "line color  ");
+      ggv_bin_read16(file, "line size   ");
+      ggv_bin_read16(file, "line stroke ");
+      line_points = ggv_bin_read16(file, "line points ");
+      if (entry_type == 0x04) {
+        // found in example.ovl generated by Geogrid-Viewer 1.0
+        ggv_bin_read16(file, "line pad    ");
+      }
+
+      for (int i=1; i <= line_points; i++) {
+        lon = ggv_bin_read_double(file, "line lon");
+        lat = ggv_bin_read_double(file, "line lat");
+        ggv_bin_read_double(file, "line unk");
+        wpt = new Waypoint;
+        wpt->longitude = lon;
+        wpt->latitude = lat;
+        track_add_wpt(ggv_bin_track, wpt);
+      }
+      break;
+    case 0x05:
+    case 0x06:
+    case 0x07:
+      // circle
+      ggv_bin_read_common_v34(file);
+      ggv_bin_read32(file, "circle prop1");
+      ggv_bin_read32(file, "circle prop2");
+      ggv_bin_read16(file, "circle prop3");
+      ggv_bin_read32(file, "circle color");
+      ggv_bin_read32(file, "circle prop5");
+      ggv_bin_read32(file, "circle prop6");
+      ggv_bin_read16(file, "circle ltype");
+      ggv_bin_read16(file, "circle angle");
+      ggv_bin_read16(file, "circle size ");
+      ggv_bin_read16(file, "circle area ");
+      ggv_bin_read_double(file, "circle lon");
+      ggv_bin_read_double(file, "circle lat");
+      ggv_bin_read_double(file, "circle unk");
+      break;
+    case 0x09:
+      ggv_bin_read_common_v34(file);
+      // bmp
+      ggv_bin_read32(file, "bmp prop1  ");
+      ggv_bin_read32(file, "bmp prop2  ");
+      ggv_bin_read16(file, "bmp prop3  ");
+      ggv_bin_read32(file, "bmp prop4  ");
+      ggv_bin_read32(file, "bmp prop5  ");
+      ggv_bin_read32(file, "bmp prop6  ");
+      lon = ggv_bin_read_double(file, "bmp lon  ");
+      lat = ggv_bin_read_double(file, "bmp lat  ");
+      ggv_bin_read_double(file, "bmp unk     ");
+      bmp_len = ggv_bin_read32(file, "bmp len    ");
+      ggv_bin_read16(file, "bmp prop   ");
+      ggv_bin_read_bytes(file, buf, bmp_len, "bmp data   ");
+      break;
+    case 0xb55c:
+    case 0xb84c:
+    case 0xba74:
+    case 0xbae4:
+    case 0xbb2c:
+      ggv_bin_read32(file, "group prop1");
+      ggv_bin_read16(file, "group prop2");
+      ggv_bin_read16(file, "group num  ");
+      ggv_bin_read_bytes(file, buf, 16, "group skip");
+      ggv_bin_read_text16(file, buf, "group text");
+      ggv_bin_read16(file, "group prop3");
+      ggv_bin_read32(file, "group prop4");
+      break;
+    case 0xb91c:
+    case 0xb154:
+    case 0xb1e0:
+    case 0xb1d0:
+    case 0xb744:
+    case 0xbae0:
+      // maybe distance measurement, group label or other?
+      ggv_bin_read_bytes(file, buf, 26, "unknown pad  ");
+      ggv_bin_read_text16(file, buf,    "unknown label");
+      ggv_bin_read32(file,              "unknown val  ");
+      break;
+    case 0xb6e8:
+      ggv_bin_read_bytes(file, buf, 32, "unknown");
+      break;
+
+      // the next two cases handles files that contain multiple
+      // parts all starting with "DOMGVCRD Ovlfile" signature,
+      // which translates to 0x44 0x4f... Skip over that part until
+      // A non-header type entry is found
+    case 0x4400:
+      ggv_bin_read_bytes(file, buf, skip, "skip header");
+      break;
+    case 0x4f44:
+      ggv_bin_read_bytes(file, buf, skip -1, "skip header");
+      break;
+    default:
+      ggv_bin_read_bytes(file, buf, 28);
+      ggv_bin_read_bytes(file, buf, 6);
+      if (QString::fromLatin1(buf.constData()).simplified() == "Gruppe") {
+        ggv_bin_read16(file, "group val1");
+        ggv_bin_read16(file, "group val2");
+      } else {
+        fatal(MYNAME ": Unknown entry type (0x%hx, pos=0x%llx) \n", entry_type, entry_pos);
+      }
+      break;
+    }
+  }
+}
+
+//***************************************************************************
+//           global callbacks called by gpsbabel main process
+//***************************************************************************
+
+static void
+ggv_bin_read_file(QFile& file)
+{
+  QByteArray buf;
+
+  ggv_bin_read_bytes(file, buf, 0x17, "magic");
+  buf[23] = 0;
+  if (global_opts.debug_level > 1) {
+    qDebug() << "ovl: header =" << buf.constData();
+  }
+
+  if (buf.startsWith("DOMGVCRD Ovlfile V2.0")) {
+    ggv_bin_read_file_v2(file, 0x0A9);
+  } else if (buf.startsWith("DOMGVCRD Ovlfile V3.0")) {
+    ggv_bin_read_file_v34(file, 0x19F);
+  } else if (buf.startsWith("DOMGVCRD Ovlfile V4.0")) {
+    ggv_bin_read_file_v34(file, 0x27F);
+  } else {
+    fatal(MYNAME ": Unsupported file format\n");
+  }
+}
+
+static void
+ggv_bin_read_init(const char* fname)
+{
+  read_fname = QString::fromUtf8(fname);
+}
+
+static void
+ggv_bin_read_deinit(void)
+{
+}
+
+static void
+ggv_bin_read(void)
+{
+  QFile file(read_fname);
+
+  if (!file.open(QIODevice::ReadOnly)) {
+    fatal(MYNAME ": Error opening file %s\n", read_fname.toStdString().c_str());
+  }
+
+  ggv_bin_read_file(file);
+  file.close();
+}
+
+ff_vecs_t ggv_bin_vecs = {
+  ff_type_file,
+  {
+    ff_cap_none,  // waypoints
+    ff_cap_read,  // tracks
+    ff_cap_none   // routes
+  },
+  ggv_bin_read_init,    // rd_init
+  NULL,                 // wr_init
+  ggv_bin_read_deinit,  // rd_deinit
+  NULL,                 // wr_deinit
+  ggv_bin_read,         // read
+  NULL,                 // write
+  NULL,                 // exit
+  NULL,                 //args
+  CET_CHARSET_ASCII, 0  //encode,fixed_encode
+  //NULL                //name dynamic/internal?
+};
diff -r 809e02f3a101 -r 61669e0e7f4f reference/ggv_bin-sample-v3.gpx
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/reference/ggv_bin-sample-v3.gpx	Wed Dec 31 17:21:54 2014 +0100
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gpx version="1.0" creator="GPSBabel - http://www.gpsbabel.org" xmlns="http://www.topografix.com/GPX/1/0">
+  <time>1970-01-01T00:00:00Z</time>
+  <bounds minlat="51.390787309" minlon="7.634582135" maxlat="51.416622730" maxlon="7.670407825"/>
+  <wpt lat="51.400591976" lon="7.655250113">
+    <name>Beispiel-Text</name>
+    <cmt>Beispiel-Text</cmt>
+    <desc>Beispiel-Text</desc>
+  </wpt>
+  <trk>
+    <name>Linie</name>
+    <trkseg>
+      <trkpt lat="51.416622730" lon="7.634582135"/>
+      <trkpt lat="51.413106821" lon="7.637561773"/>
+      <trkpt lat="51.409758874" lon="7.639529832"/>
+      <trkpt lat="51.407628129" lon="7.641820840"/>
+      <trkpt lat="51.406255307" lon="7.643586185"/>
+      <trkpt lat="51.403222581" lon="7.645616042"/>
+      <trkpt lat="51.399781311" lon="7.647298422"/>
+      <trkpt lat="51.398632218" lon="7.648984855"/>
+      <trkpt lat="51.397982280" lon="7.651087602"/>
+      <trkpt lat="51.398325694" lon="7.653592205"/>
+      <trkpt lat="51.398944395" lon="7.656591723"/>
+      <trkpt lat="51.398664437" lon="7.659617592"/>
+      <trkpt lat="51.396813518" lon="7.662832934"/>
+      <trkpt lat="51.393519865" lon="7.665658933"/>
+      <trkpt lat="51.390787309" lon="7.670407825"/>
+    </trkseg>
+  </trk>
+  <trk>
+    <name>FlÃ€che</name>
+    <trkseg>
+      <trkpt lat="51.402506568" lon="7.653684988"/>
+      <trkpt lat="51.403988399" lon="7.653569612"/>
+      <trkpt lat="51.406267829" lon="7.656377105"/>
+      <trkpt lat="51.404428210" lon="7.656646600"/>
+      <trkpt lat="51.403620311" lon="7.656742131"/>
+      <trkpt lat="51.402285607" lon="7.657930916"/>
+      <trkpt lat="51.401834671" lon="7.657800408"/>
+      <trkpt lat="51.402486377" lon="7.655841237"/>
+      <trkpt lat="51.402417535" lon="7.653759457"/>
+      <trkpt lat="51.402506568" lon="7.653684988"/>
+    </trkseg>
+  </trk>
+</gpx>
diff -r 809e02f3a101 -r 61669e0e7f4f reference/ggv_bin-sample-v3.ovl
Binary file reference/ggv_bin-sample-v3.ovl has changed
diff -r 809e02f3a101 -r 61669e0e7f4f testo.d/ggv_bin.test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/testo.d/ggv_bin.test	Wed Dec 31 17:21:54 2014 +0100
@@ -0,0 +1,6 @@
+#
+# Geogrid-Viewer binary overlay files
+#
+rm -f ${TMPDIR}/ggv_bin*
+gpsbabel -i ggv_bin -f ${REFERENCE}/ggv_bin-sample-v3.ovl -o gpx -F ${TMPDIR}/ggv_bin-sample-v3.gpx
+bincompare ${REFERENCE}/ggv_bin-sample-v3.gpx ${TMPDIR}/ggv_bin-sample-v3.gpx
diff -r 809e02f3a101 -r 61669e0e7f4f vecs.cc
--- a/vecs.cc	Tue Dec 23 00:08:20 2014 +0100
+++ b/vecs.cc	Wed Dec 31 17:21:54 2014 +0100
@@ -132,6 +132,7 @@
 extern ff_vecs_t alanwpr_vecs;
 extern ff_vecs_t alantrl_vecs;
 extern ff_vecs_t vitovtt_vecs;
+extern ff_vecs_t ggv_bin_vecs;
 extern ff_vecs_t ggv_log_vecs;
 extern ff_vecs_t g7towin_vecs;
 extern ff_vecs_t garmin_gpi_vecs;
@@ -1093,6 +1094,13 @@
     "trc",
     NULL,
   },
+  {
+    &ggv_bin_vecs,
+    "ggv_bin",
+    "Geogrid-Viewer binary overlay file (.ovl)",
+    "ovl",
+    NULL,
+  },
 #endif // MAXIMAL_ENABLED
   {
     NULL,
diff -r 809e02f3a101 -r 61669e0e7f4f xmldoc/formats/ggv_bin.xml
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xmldoc/formats/ggv_bin.xml	Wed Dec 31 17:21:54 2014 +0100
@@ -0,0 +1,11 @@
+<para>
+   Binary overlay files (.ovl) used by
+   <productname>Geogrid</productname>-Viewer.
+</para>
+<para>
+   There are multiple versions of
+   <productname>Geogrid</productname>-Viewer using different data
+   formats. This modules supports binary overlay file version 2.0, 3.0
+   and 4.0. The degree of support varies, especially not all features
+   of version 4.0 might be supported.
+</para>
