[osm-gps-map] 01/153: Imported Upstream version 0.3

Ross Gammon ross-guest at moszumanska.debian.org
Tue May 13 19:58:55 UTC 2014


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

ross-guest pushed a commit to branch master
in repository osm-gps-map.

commit 53f4134256c905c57d34353b73a24a10d1c72c7b
Author: David Paleino <dapal at debian.org>
Date:   Sun Dec 13 08:43:58 2009 +0100

    Imported Upstream version 0.3
---
 .gitignore                   |   32 +
 AUTHORS                      |    3 +
 ChangeLog                    |   18 +
 Makefile.am                  |   38 +
 NEWS                         |    0
 README                       |    7 +
 TODO.tasks                   |    6 +
 autogen.sh                   |  159 ++++
 configure.ac                 |   43 +
 openstreetmap-gps-map.anjuta |   44 +
 osmgpsmap.pc.in              |   11 +
 python/AUTHORS               |    1 +
 python/ChangeLog             |    0
 python/Makefile.am           |   36 +
 python/NEWS                  |    0
 python/README                |   23 +
 python/acinclude.m4          |   66 ++
 python/configure.ac          |   66 ++
 python/osmgpsmap.defs        |  194 ++++
 python/osmgpsmap.override    |  198 ++++
 python/osmgpsmapmodule.c     |   64 ++
 python/setup.py              |   36 +
 python/test.sh               |   23 +
 src/Makefile.am              |   46 +
 src/converter.c              |  102 ++
 src/converter.h              |   45 +
 src/main.c                   |  361 +++++++
 src/osm-gps-map-types.h      |   85 ++
 src/osm-gps-map.c            | 2171 ++++++++++++++++++++++++++++++++++++++++++
 src/osm-gps-map.h            |  103 ++
 src/poi.png                  |  Bin 0 -> 1093 bytes
 31 files changed, 3981 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fb87dc4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,32 @@
+*~
+*.in
+*.la
+*.lo
+*.o
+*.deps/
+*.libs/
+INSTALL
+Makefile
+autom4te.cache/
+compile
+config.guess
+config.h
+config.log
+config.status
+config.sub
+configure
+depcomp
+install-sh
+libtool
+ltmain.sh
+missing
+osmgpsmap.pc
+python/COPYING
+python/INSTALL
+python/autom4te.cache/
+python/build/
+python/configure
+python/osmgpsmap.c
+src/Makefile
+src/openstreetmap-gps-map
+stamp-h1
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..7490d31
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,3 @@
+Marcus Bauer 2008 <marcus.bauer at gmail.com>
+John Stowers 2009 <john.stowers at gmail.com>
+Everaldo Canuto 2009 <everaldo.canuto at gmail.com>
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..c9b8f0e
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,18 @@
+2007-12-28  Johannes Schmid,,,  <jhs at idefix>
+
+	reviewed by: <delete if not using a buddy>
+
+	* project.anjuta:
+
+2007-12-23  Johannes Schmid,,,  <jhs at idefix>
+
+	reviewed by: <delete if not using a buddy>
+
+	* src/Makefile.am.tpl:
+
+2007-12-23  Johannes Schmid,,,  <jhs at idefix>
+
+	reviewed by: <delete if not using a buddy>
+
+	* src/Makefile.am.tpl:
+
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..ebe57ee
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,38 @@
+## Process this file with automake to produce Makefile.in
+## Created by Anjuta
+
+SUBDIRS = src
+
+openstreetmap_gps_mapdocdir = ${prefix}/doc/openstreetmap-gps-map
+openstreetmap_gps_mapdoc_DATA =                 \
+	README                                      \
+	COPYING                                     \
+	AUTHORS                                     \
+	ChangeLog                                   \
+	INSTALL                                     \
+	NEWS
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = osmgpsmap.pc
+
+EXTRA_DIST = $(openstreetmap_gps_mapdoc_DATA)   \
+	osmgpsmap.pc.in                             \
+	python/Makefile.am                          \
+	python/Makefile.in                          \
+	python/acinclude.m4                         \
+	python/ChangeLog                            \
+	python/osmgpsmap.defs                       \
+	python/setup.py                             \
+	python/aclocal.m4                           \
+	python/configure                            \
+	python/osmgpsmapmodule.c                    \
+	python/test.sh                              \
+	python/AUTHORS                              \
+	python/configure.ac                         \
+	python/osmgpsmap.override                   \
+	python/NEWS                                 \
+	python/README
+
+release:
+	scp @PACKAGE at -@VERSION at .tar.gz john at open.grcnz.com:/srv/default/downloads/osm-gps-map/
+
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..e69de29
diff --git a/README b/README
new file mode 100644
index 0000000..1adfa96
--- /dev/null
+++ b/README
@@ -0,0 +1,7 @@
+OSM-GPS-MAP is a Gtk mapping widget (and Python bindings) that when given 
+GPS co-ordinates, draws a GPS track, and points of interest on a moving map 
+display. 
+
+OSM-GPS-MAP Downloads map data from a number of websites, including 
+openstreetmap.org, openaerialmap.org and others and can be used to build
+desktop mapping or geolocation applications.
diff --git a/TODO.tasks b/TODO.tasks
new file mode 100644
index 0000000..d1fa282
--- /dev/null
+++ b/TODO.tasks
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<gtodo>
+  <category title="Personal" place="0"/>
+  <category title="Business" place="1"/>
+  <category title="Unfiled" place="2"/>
+</gtodo>
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..9ab346a
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,159 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+DIE=0
+
+if [ -n "$GNOME2_DIR" ]; then
+	ACLOCAL_FLAGS="-I $GNOME2_DIR/share/aclocal $ACLOCAL_FLAGS"
+	LD_LIBRARY_PATH="$GNOME2_DIR/lib:$LD_LIBRARY_PATH"
+	PATH="$GNOME2_DIR/bin:$PATH"
+	export PATH
+	export LD_LIBRARY_PATH
+fi
+
+(test -f $srcdir/configure.ac) || {
+    echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
+    echo " top-level package directory"
+    exit 1
+}
+
+(autoconf --version) < /dev/null > /dev/null 2>&1 || {
+  echo
+  echo "**Error**: You must have \`autoconf' installed."
+  echo "Download the appropriate package for your distribution,"
+  echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
+  DIE=1
+}
+
+(grep "^IT_PROG_INTLTOOL" $srcdir/configure.ac >/dev/null) && {
+  (intltoolize --version) < /dev/null > /dev/null 2>&1 || {
+    echo 
+    echo "**Error**: You must have \`intltool' installed."
+    echo "You can get it from:"
+    echo "  ftp://ftp.gnome.org/pub/GNOME/"
+    DIE=1
+  }
+}
+
+(grep "^AM_PROG_XML_I18N_TOOLS" $srcdir/configure.ac >/dev/null) && {
+  (xml-i18n-toolize --version) < /dev/null > /dev/null 2>&1 || {
+    echo
+    echo "**Error**: You must have \`xml-i18n-toolize' installed."
+    echo "You can get it from:"
+    echo "  ftp://ftp.gnome.org/pub/GNOME/"
+    DIE=1
+  }
+}
+
+(grep "^AM_PROG_LIBTOOL" $srcdir/configure.ac >/dev/null) && {
+  (libtool --version) < /dev/null > /dev/null 2>&1 || {
+    echo
+    echo "**Error**: You must have \`libtool' installed."
+    echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
+    DIE=1
+  }
+}
+
+(grep "^AM_GLIB_GNU_GETTEXT" $srcdir/configure.ac >/dev/null) && {
+  (grep "sed.*POTFILES" $srcdir/configure.ac) > /dev/null || \
+  (glib-gettextize --version) < /dev/null > /dev/null 2>&1 || {
+    echo
+    echo "**Error**: You must have \`glib' installed."
+    echo "You can get it from: ftp://ftp.gtk.org/pub/gtk"
+    DIE=1
+  }
+}
+
+(automake --version) < /dev/null > /dev/null 2>&1 || {
+  echo
+  echo "**Error**: You must have \`automake' installed."
+  echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/"
+  DIE=1
+  NO_AUTOMAKE=yes
+}
+
+
+# if no automake, don't bother testing for aclocal
+test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || {
+  echo
+  echo "**Error**: Missing \`aclocal'.  The version of \`automake'"
+  echo "installed doesn't appear recent enough."
+  echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/"
+  DIE=1
+}
+
+if test "$DIE" -eq 1; then
+  exit 1
+fi
+
+if test -z "$*"; then
+  echo "**Warning**: I am going to run \`configure' with no arguments."
+  echo "If you wish to pass any to it, please specify them on the"
+  echo \`$0\'" command line."
+  echo
+fi
+
+case $CC in
+xlc )
+  am_opt=--include-deps;;
+esac
+
+for coin in `find $srcdir -path $srcdir/CVS -prune -o -name configure.ac -print`
+do 
+  dr=`dirname $coin`
+  if test -f $dr/NO-AUTO-GEN; then
+    echo skipping $dr -- flagged as no auto-gen
+  else
+    echo processing $dr
+    ( cd $dr
+
+      aclocalinclude="$ACLOCAL_FLAGS"
+
+      if grep "^AM_GLIB_GNU_GETTEXT" configure.ac >/dev/null; then
+	echo "Creating $dr/aclocal.m4 ..."
+	test -r $dr/aclocal.m4 || touch $dr/aclocal.m4
+	echo "Running glib-gettextize...  Ignore non-fatal messages."
+	echo "no" | glib-gettextize --force --copy
+	echo "Making $dr/aclocal.m4 writable ..."
+	test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4
+      fi
+      if grep "^IT_PROG_INTLTOOL" configure.ac >/dev/null; then
+        echo "Running intltoolize..."
+	intltoolize --copy --force --automake
+      fi
+      if grep "^AM_PROG_XML_I18N_TOOLS" configure.ac >/dev/null; then
+        echo "Running xml-i18n-toolize..."
+	xml-i18n-toolize --copy --force --automake
+      fi
+      if grep "^AM_PROG_LIBTOOL" configure.ac >/dev/null; then
+	if test -z "$NO_LIBTOOLIZE" ; then 
+	  echo "Running libtoolize..."
+	  libtoolize --force --copy
+	fi
+      fi
+      echo "Running aclocal $aclocalinclude ..."
+      aclocal $aclocalinclude
+      if grep "^AM_CONFIG_HEADER" configure.ac >/dev/null; then
+	echo "Running autoheader..."
+	autoheader
+      fi
+      echo "Running automake --gnu $am_opt ..."
+      automake --add-missing --gnu $am_opt
+      echo "Running autoconf ..."
+      autoconf
+    )
+  fi
+done
+
+conf_flags="--enable-maintainer-mode"
+
+if test x$NOCONFIGURE = x; then
+  echo Running $srcdir/configure $conf_flags "$@" ...
+  $srcdir/configure $conf_flags "$@" \
+  && echo Now type \`make\' to compile. || exit 1
+else
+  echo Skipping configure process.
+fi
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..0eb98c2
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,43 @@
+AC_INIT(osm-gps-map, 0.2)
+AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
+
+AC_CONFIG_SRCDIR(osmgpsmap.pc.in)
+AM_CONFIG_HEADER(config.h)
+
+AM_MAINTAINER_MODE
+
+AC_ISC_POSIX
+AC_PROG_CC
+AM_PROG_CC_STDC
+AC_HEADER_STDC
+
+AM_PROG_LIBTOOL
+
+PKG_CHECK_MODULES(OPENSTREETMAP_GPS_MAP, [gtk+-2.0 libsoup-2.4 glib-2.0 >= 2.18])
+AC_SUBST(OPENSTREETMAP_GPS_MAP_CFLAGS)
+AC_SUBST(OPENSTREETMAP_GPS_MAP_LIBS)
+
+AC_ARG_ENABLE(cairo, 
+             [AC_HELP_STRING([--disable-cairo],
+                             [Use Gdk instead of cairo to draw the map overlay])],
+              enable_cairo="$enableval",
+              enable_cairo="yes")
+
+if test "x$enable_cairo" = "xyes"; then
+    PKG_CHECK_MODULES(CAIRO,[cairo >= 1.8])
+    AC_DEFINE(USE_CAIRO, 1, [Define if we're using cairo])
+    OPENSTREETMAP_GPS_MAP_CFLAGS="$OPENSTREETMAP_GPS_MAP_CFLAGS $CAIRO_CFLAGS"
+    OPENSTREETMAP_GPS_MAP_LIBS="$OPENSTREETMAP_GPS_MAP_LIBS $CAIRO_LIBS"
+fi
+
+AC_OUTPUT([
+osmgpsmap.pc
+Makefile
+src/Makefile
+])
+
+echo
+echo $PACKAGE v$VERSION
+echo
+echo Prefix............... : $prefix
+echo cairo................ : $enable_cairo
diff --git a/openstreetmap-gps-map.anjuta b/openstreetmap-gps-map.anjuta
new file mode 100644
index 0000000..51ddd65
--- /dev/null
+++ b/openstreetmap-gps-map.anjuta
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<anjuta>
+    <plugin name="GBF Project Manager"
+            url="http://anjuta.org/plugins/"
+            mandatory="yes">
+		<require group="Anjuta Plugin"
+                 attribute="Interfaces"
+                 value="IAnjutaProjectManager"/>
+		<require group="Project"
+                 attribute="Supported-Project-Types"
+                 value="automake"/>
+	</plugin>
+	<plugin name="Symbol Browser"
+            url="http://anjuta.org/plugins/"
+            mandatory="yes">
+		<require group="Anjuta Plugin"
+                 attribute="Interfaces"
+                 value="IAnjutaSymbolManager"/>
+	</plugin>
+	<plugin name="Make Build System"
+            url="http://anjuta.org/plugins/"
+            mandatory="yes">
+		<require group="Anjuta Plugin"
+                 attribute="Interfaces"
+                 value="IAnjutaBuildable"/>
+		<require group="Build"
+                 attribute="Supported-Build-Types"
+                 value="make"/>
+	</plugin>
+	<plugin name="Task Manager"
+            url="http://anjuta.org/plugins/"
+            mandatory="no">
+		<require group="Anjuta Plugin"
+                 attribute="Interfaces"
+                 value="IAnjutaTodo"/>
+	</plugin>
+	<plugin name="Debug Manager"
+            url="http://anjuta.org/plugins/"
+            mandatory="no">
+		<require group="Anjuta Plugin"
+                 attribute="Interfaces"
+                 value="IAnjutaDebuggerManager"/>
+	</plugin>
+</anjuta>
diff --git a/osmgpsmap.pc.in b/osmgpsmap.pc.in
new file mode 100644
index 0000000..92db45c
--- /dev/null
+++ b/osmgpsmap.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: @PACKAGE_NAME@
+Description: Moving map widget using openstreet map data
+Version: @PACKAGE_VERSION@
+Requires: gtk+-2.0 libsoup-2.4
+Libs: -L${libdir} -losmgpsmap
+Cflags: -I${includedir}/osmgpsmap
diff --git a/python/AUTHORS b/python/AUTHORS
new file mode 100644
index 0000000..c3a0b22
--- /dev/null
+++ b/python/AUTHORS
@@ -0,0 +1 @@
+John Stowers 2008 <john.stowers at gmail.com>
diff --git a/python/ChangeLog b/python/ChangeLog
new file mode 100644
index 0000000..e69de29
diff --git a/python/Makefile.am b/python/Makefile.am
new file mode 100644
index 0000000..20d13ff
--- /dev/null
+++ b/python/Makefile.am
@@ -0,0 +1,36 @@
+defsdir = $(datadir)/pygtk/2.0/defs
+defs_DATA = osmgpsmap.defs
+
+INCLUDES = \
+	$(OSMGPSMAP_CFLAGS) \
+	$(GTK_CFLAGS) \
+	$(PYGTK_CFLAGS) \
+	$(PYTHON_INCLUDES)
+
+pkgpythondir = $(pyexecdir)/gtk-2.0
+pkgpyexecdir = $(pyexecdir)/gtk-2.0
+
+pkgpyexec_LTLIBRARIES = osmgpsmap.la
+osmgpsmap_la_LDFLAGS = -module -avoid-version -export-symbols-regex initosmgpsmap
+osmgpsmap_la_LIBADD = $(OSMGPSMAP_LIBS) $(GTK_LIBS) $(PYGTK_LIBS)
+osmgpsmap_la_SOURCES = osmgpsmapmodule.c osmgpsmap.c
+#nodist_osmgpsmap_la_SOURCES = osmgpsmap.c
+
+CLEANFILES = osmgpsmap.c
+EXTRA_DIST = osmgpsmap.override $(defs_DATA)
+
+osmgpsmap.c: osmgpsmap.defs osmgpsmap.override
+.defs.c:
+	(cd $(srcdir)\
+	 && pygtk-codegen-2.0 \
+		--register $(PYGTK_DEFSDIR)/gtk-types.defs \
+	    --register $(PYGTK_DEFSDIR)/gdk-base-types.defs \
+		--override $*.override \
+		--prefix py$* $*.defs) > gen-$*.c \
+	&& cp gen-$*.c $*.c \
+	&& rm -f gen-$*.c
+
+update-defs:
+	$(PYGTK_H2DEF) ../src/osm-gps-map.h > osmgpsmap-new.defs
+	
+
diff --git a/python/NEWS b/python/NEWS
new file mode 100644
index 0000000..e69de29
diff --git a/python/README b/python/README
new file mode 100644
index 0000000..4959c7b
--- /dev/null
+++ b/python/README
@@ -0,0 +1,23 @@
+How to Build Windows Installers
+0) Make sure that mingw32 is selected as the compiler. Create (or edit) a .cfg file for distutils (distutils.cfg) 
+ 
+	eg: C:\Python25\Lib\distutils\distutils.cfg with this content: 
+	
+	[build]
+	compiler=mingw32
+
+
+1) Make sure Python is in path
+
+	$ echo $PATH
+	.:/usr/local/bin:/mingw/bin:/bin:/c/WINDOWS/system32:/c/WINDOWS:/c/WINDOWS/System32/Wbem:/c/Program Files/Altium Designer 6/System:/c/Program Files/TortoiseSVN/bin:/c/gtk/bin:/c/Python25
+
+2) Make sure the pygobject/pygtk headers and libs can be found
+
+	$ export PKG_CONFIG_PATH=/c/Python25/Lib/pkgconfig/
+	$ pkg-config.exe --libs pygobject-2.0
+	@FFI_LIBS@ -Lc:/Python25/lib -Lc:/gtk/lib -lgobject-2.0 -lglib-2.0 -lint
+	
+3) Build the windows installer
+
+	$ python setup.py bdist_wininst
diff --git a/python/acinclude.m4 b/python/acinclude.m4
new file mode 100644
index 0000000..fe90156
--- /dev/null
+++ b/python/acinclude.m4
@@ -0,0 +1,66 @@
+## this one is commonly used with AM_PATH_PYTHONDIR ...
+dnl AM_CHECK_PYMOD(MODNAME [,SYMBOL [,ACTION-IF-FOUND [,ACTION-IF-NOT-FOUND]]])
+dnl Check if a module containing a given symbol is visible to python.
+AC_DEFUN([AM_CHECK_PYMOD],
+[AC_REQUIRE([AM_PATH_PYTHON])
+py_mod_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'`
+AC_MSG_CHECKING(for ifelse([$2],[],,[$2 in ])python module $1)
+AC_CACHE_VAL(py_cv_mod_$py_mod_var, [
+ifelse([$2],[], [prog="
+import sys
+try:
+        import $1
+except ImportError:
+        sys.exit(1)
+except:
+        sys.exit(0)
+sys.exit(0)"], [prog="
+import $1
+$1.$2"])
+if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC
+  then
+    eval "py_cv_mod_$py_mod_var=yes"
+  else
+    eval "py_cv_mod_$py_mod_var=no"
+  fi
+])
+py_val=`eval "echo \`echo '$py_cv_mod_'$py_mod_var\`"`
+if test "x$py_val" != xno; then
+  AC_MSG_RESULT(yes)
+  ifelse([$3], [],, [$3
+])dnl
+else
+  AC_MSG_RESULT(no)
+  ifelse([$4], [],, [$4
+])dnl
+fi
+])
+
+dnl a macro to check for ability to create python extensions
+dnl  AM_CHECK_PYTHON_HEADERS([ACTION-IF-POSSIBLE], [ACTION-IF-NOT-POSSIBLE])
+dnl function also defines PYTHON_INCLUDES
+AC_DEFUN([AM_CHECK_PYTHON_HEADERS],
+[AC_REQUIRE([AM_PATH_PYTHON])
+AC_MSG_CHECKING(for headers required to compile python extensions)
+dnl deduce PYTHON_INCLUDES
+py_prefix=`$PYTHON -c "import sys; print sys.prefix"`
+py_exec_prefix=`$PYTHON -c "import sys; print sys.exec_prefix"`
+if test -x "$PYTHON-config"; then
+PYTHON_INCLUDES=`$PYTHON-config --includes 2>/dev/null`
+else
+PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}"
+if test "$py_prefix" != "$py_exec_prefix"; then
+  PYTHON_INCLUDES="$PYTHON_INCLUDES -I${py_exec_prefix}/include/python${PYTHON_VERSION}"
+fi
+fi
+AC_SUBST(PYTHON_INCLUDES)
+dnl check if the headers exist:
+save_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $PYTHON_INCLUDES"
+AC_TRY_CPP([#include <Python.h>],dnl
+[AC_MSG_RESULT(found)
+$1],dnl
+[AC_MSG_RESULT(not found)
+$2])
+CPPFLAGS="$save_CPPFLAGS"
+])
diff --git a/python/configure.ac b/python/configure.ac
new file mode 100644
index 0000000..385c2b5
--- /dev/null
+++ b/python/configure.ac
@@ -0,0 +1,66 @@
+AC_PREREQ(2.53)
+AC_INIT(osmgpsmap-python, 0.1)
+AC_CONFIG_SRCDIR(osmgpsmap.defs)
+AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
+
+AM_MAINTAINER_MODE
+AC_PROG_MAKE_SET
+
+AC_PROG_CC
+AM_PROG_CC_STDC
+AC_HEADER_STDC
+
+AM_PROG_LIBTOOL
+
+AC_ARG_ENABLE(more-warnings,
+	      [  --disable-more-warnings  Inhibit compiler warnings],
+	      set_more_warnings=no)
+
+if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then
+	CFLAGS="$CFLAGS \
+		-Wall -Wstrict-prototypes -Wmissing-declarations \
+		-Wmissing-prototypes -Wnested-externs -Wpointer-arith"
+fi
+
+
+AM_PATH_PYTHON()
+AM_CHECK_PYTHON_HEADERS(,AC_MSG_ERROR([install python-devel]))
+
+PKG_CHECK_MODULES(PYGTK, [pygtk-2.0 >= 2.10.0])
+
+AC_MSG_CHECKING(for pygtk defs)
+PYGTK_DEFSDIR=`$PKG_CONFIG --variable=defsdir pygtk-2.0`
+AC_SUBST(PYGTK_DEFSDIR)
+AC_MSG_RESULT($PYGTK_DEFSDIR)
+
+AC_MSG_CHECKING(for pygtk codegen)
+PYGTK_CODEGEN="$PYTHON `$PKG_CONFIG --variable=codegendir pygtk-2.0`/codegen.py"
+AC_SUBST(PYGTK_CODEGEN)
+AC_MSG_RESULT($PYGTK_CODEGEN)
+
+AC_MSG_CHECKING(for pygtk h2def)
+PYGTK_H2DEF="$PYTHON `$PKG_CONFIG --variable=codegendir pygtk-2.0`/h2def.py"
+AC_SUBST(PYGTK_H2DEF)
+AC_MSG_RESULT($PYGTK_H2DEF)
+
+if test -f ../src/libosmgpsmap.la; then
+	#Because we are building against a non installed lib, the pkgconfig
+	#file cannot tell us to also include/link gtk/soup, so we must manually do it
+	PKG_CHECK_MODULES(OSMGPSMAP, [gtk+-2.0 libsoup-2.4])
+
+	#and we must link to the static lib
+	OSMGPSMAP_CFLAGS="$OSMGPSMAP_CFLAGS -I../src"
+	OSMGPSMAP_LIBS="$OSMGPSMAP_LIBS ../src/libosmgpsmap.la"
+else
+	PKG_CHECK_MODULES(OSMGPSMAP, osmgpsmap)
+fi
+
+AC_OUTPUT([Makefile])
+
+echo
+echo $PACKAGE v$VERSION
+
+echo
+echo "Now type make to compile"
+echo
+
diff --git a/python/osmgpsmap.defs b/python/osmgpsmap.defs
new file mode 100644
index 0000000..3ac06d8
--- /dev/null
+++ b/python/osmgpsmap.defs
@@ -0,0 +1,194 @@
+;; -*- scheme -*-
+; object definitions ...
+(define-object GpsMap
+  (in-module "Osm")
+  (parent "GtkDrawingArea")
+  (c-name "OsmGpsMap")
+  (gtype-id "OSM_TYPE_GPS_MAP")
+)
+
+;; Enumerations and flags ...
+
+
+;; From osm-gps-map.h
+
+(define-function osm_gps_map_get_type
+  (c-name "osm_gps_map_get_type")
+  (return-type "GType")
+)
+
+(define-method download_maps
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_download_maps")
+  (return-type "none")
+  (parameters
+    '("coord_t*" "pt1")
+    '("coord_t*" "pt2")
+    '("int" "zoom_start")
+    '("int" "zoom_end")
+  )
+)
+
+(define-method get_bbox
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_get_bbox")
+  (return-type "none")
+  (parameters
+    '("coord_t*" "pt1")
+    '("coord_t*" "pt2")
+  )
+)
+
+(define-method set_mapcenter
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_set_mapcenter")
+  (return-type "none")
+  (parameters
+    '("float" "latitude")
+    '("float" "longitude")
+    '("int" "zoom")
+  )
+)
+
+(define-method set_center
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_set_center")
+  (return-type "none")
+  (parameters
+    '("float" "latitude")
+    '("float" "longitude")
+  )
+)
+
+(define-method set_zoom
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_set_zoom")
+  (return-type "int")
+  (parameters
+    '("int" "zoom")
+  )
+)
+
+(define-method add_track
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_add_track")
+  (return-type "none")
+  (parameters
+    '("GSList*" "track")
+  )
+)
+
+(define-method clear_tracks
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_clear_tracks")
+  (return-type "none")
+)
+
+(define-method add_image
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_add_image")
+  (return-type "none")
+  (parameters
+    '("float" "latitude")
+    '("float" "longitude")
+    '("GdkPixbuf*" "image")
+  )
+)
+
+(define-method clear_images
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_clear_images")
+  (return-type "none")
+)
+
+(define-method osd_speed
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_osd_speed")
+  (return-type "none")
+  (parameters
+    '("float" "speed")
+  )
+)
+
+(define-method draw_gps
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_draw_gps")
+  (return-type "none")
+  (parameters
+    '("float" "latitude")
+    '("float" "longitude")
+    '("float" "heading")
+  )
+)
+
+(define-method clear_gps
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_clear_gps")
+  (return-type "none")
+)
+
+(define-method get_co_ordinates
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_get_co_ordinates")
+  (return-type "coord_t")
+  (parameters
+    '("int" "pixel_x")
+    '("int" "pixel_y")
+  )
+)
+
+(define-function osm_gps_map_new
+  (c-name "osm_gps_map_new")
+  (is-constructor-of "OsmGpsMap")
+  (return-type "GtkWidget*")
+  (properties
+    '("auto_center" (optional))
+    '("record_trip_history" (optional))
+    '("show_trip-history" (optional))
+    '("auto_download" (optional))
+    '("repo_uri" (optional))
+    '("proxy_uri" (optional))
+    '("tile_cache" (optional))
+    '("tile_cache_is_full_path" (optional))
+    '("zoom" (optional))
+    '("max_zoom" (optional))
+    '("min_zoom" (optional))
+    '("map_x" (optional))
+    '("map_Y" (optional))
+  )
+)
+
+(define-method screen_to_geographic
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_screen_to_geographic")
+  (return-type "none")
+  (parameters
+    '("int" "pixel_x")
+    '("int" "pixel_y")
+    '("float*" "latitude")
+    '("float*" "longitude")
+  )
+)
+
+(define-method geographic_to_screen
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_geographic_to_screen")
+  (return-type "none")
+  (parameters
+    '("float" "latitude")
+    '("float" "longitude")
+    '("int*" "pixel_x")
+    '("int*" "pixel_y")
+  )
+)
+
+(define-method scroll
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_scroll")
+  (return-type "none")
+  (parameters
+    '("gint" "dx")
+    '("gint" "dy")
+  )
+)
+
diff --git a/python/osmgpsmap.override b/python/osmgpsmap.override
new file mode 100644
index 0000000..c5cac87
--- /dev/null
+++ b/python/osmgpsmap.override
@@ -0,0 +1,198 @@
+%%
+headers
+#include <Python.h>
+#include "osm-gps-map.h"
+#include "pygobject.h"
+#include <stdio.h>
+%%
+modulename osmgpsmap
+%%
+import gobject.GObject as PyGObject_Type
+import gtk.DrawingArea as PyGtkDrawingArea_Type
+import gtk.gdk.Pixbuf as PyGdkPixbuf_Type 
+%%
+ignore-glob
+	*_get_type
+%%
+override osm_gps_map_get_bbox noargs
+static PyObject *
+_wrap_osm_gps_map_get_bbox(PyGObject *self)
+{
+    coord_t pt1,pt2;
+
+    osm_gps_map_get_bbox(OSM_GPS_MAP(self->obj), &pt1, &pt2);
+
+    return Py_BuildValue("(dddd)", pt1.rlat, pt1.rlon, pt2.rlat, pt2.rlon);
+}
+%%
+override osm_gps_map_get_co_ordinates kwargs
+static PyObject *
+_wrap_osm_gps_map_get_co_ordinates(PyGObject *self, PyObject *args, 
+                                     PyObject *kwargs)
+{
+    static char *kwlist[] = { "pixel_x", "pixel_y", NULL };
+    int pixel_x = -1, pixel_y = -1;
+    coord_t coord;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+				     "|ii:GpsMap.get_co_ordinates",
+				     kwlist, &pixel_x, &pixel_y))
+        return NULL;
+
+    if ( pixel_x < 0 || pixel_y < 0 ) {
+    	PyErr_SetString(PyExc_ValueError, "pixel co-ordinatites must be >= 0");
+    	return NULL;
+	}
+
+    coord = osm_gps_map_get_co_ordinates(OSM_GPS_MAP(self->obj), pixel_x, pixel_y);
+
+    return Py_BuildValue("(dd)", coord.rlat, coord.rlon);
+}
+%%
+override osm_gps_map_set_center
+static PyObject *
+_wrap_osm_gps_map_set_center(PyGObject *self, PyObject *args)
+{
+    double latitude, longitude;
+
+    if (PyTuple_Size(args) == 1)
+        args = PyTuple_GetItem(args, 0);
+    if (!PyArg_ParseTuple(args, "dd;OsmGpsMap.set_center takes two floats (also in a tuple)",
+                          &latitude, &longitude))
+        return NULL;
+    osm_gps_map_set_center(OSM_GPS_MAP(self->obj), latitude, longitude);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+%%
+override osm_gps_map_screen_to_geographic
+static PyObject *
+_wrap_osm_gps_map_screen_to_geographic(PyGObject *self, PyObject *args)
+{
+    int pixel_x, pixel_y;
+    gfloat latitude, longitude;
+
+    if (PyTuple_Size(args) == 1)
+        args = PyTuple_GetItem(args, 0);
+    if (!PyArg_ParseTuple(args, "ii:OsmGpsMap.screen_to_geographic takes two"
+                          "integers (also in a tuple)", &pixel_x, &pixel_y))
+        return NULL;
+
+    osm_gps_map_screen_to_geographic(OSM_GPS_MAP(self->obj), pixel_x, pixel_y,
+                                     &latitude, &longitude);
+
+    return Py_BuildValue("(ff)", latitude, longitude);
+}
+%%
+override osm_gps_map_geographic_to_screen
+static PyObject *
+_wrap_osm_gps_map_geographic_to_screen(PyGObject *self, PyObject *args)
+{
+    int pixel_x, pixel_y;
+    gfloat latitude, longitude;
+
+    if (PyTuple_Size(args) == 1)
+        args = PyTuple_GetItem(args, 0);
+    if (!PyArg_ParseTuple(args, "ff:OsmGpsMap.geographic_to_screen takes two"
+                          "floats (also in a tuple)", &latitude, &longitude))
+        return NULL;
+
+    osm_gps_map_geographic_to_screen(OSM_GPS_MAP(self->obj),
+                                     latitude, longitude,
+                                     &pixel_x, &pixel_y);
+
+    return Py_BuildValue("(ii)", pixel_x, pixel_y);
+}
+%%
+override osm_gps_map_scroll
+static PyObject *
+_wrap_osm_gps_map_scroll(PyGObject *self, PyObject *args)
+{
+    int dx, dy;
+
+    if (PyTuple_Size(args) == 1)
+        args = PyTuple_GetItem(args, 0);
+    if (!PyArg_ParseTuple(args, "ii:OsmGpsMap.scroll takes two "
+                          "integers (also in a tuple)", &dx, &dy))
+        return NULL;
+
+    osm_gps_map_scroll(OSM_GPS_MAP(self->obj), dx, dy);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+%%
+override osm_gps_map_add_track kwargs
+static PyObject *
+_wrap_osm_gps_map_add_track(PyGObject *self, PyObject *args, 
+                                     PyObject *kwargs)
+{
+    static char *kwlist[] = { "track", NULL };
+    float rlat,rlon;
+    int i, numItems;
+    PyObject *list;
+    PyObject *coords;
+    GSList *track = NULL;
+    int err = FALSE;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!:GpsMap.add_track", kwlist, &PyList_Type, &list))
+        return NULL;
+
+    numItems = PyList_Size(list);
+    for(i = 0; i < numItems; i++)
+    {
+        coords = PyList_GetItem(list,i);
+        if(PyArg_ParseTuple(coords,"ff",&rlat,&rlon)) 
+        {
+            coord_t *c = g_new0(coord_t, 1);
+            c->rlat = rlat;
+            c->rlon = rlon;
+            track = g_slist_append(track, c);
+        }
+        else
+        {
+            err = TRUE;
+            break;
+        }
+    }
+
+    if (err) 
+    {
+    	if (track) 
+        {
+    		g_slist_foreach(track, (GFunc) g_free, NULL);
+	    	g_slist_free(track);
+        }
+        PyErr_SetString(PyExc_ValueError, "track cordinates must be a 2-tuple of lat,lon in radians");
+    	return NULL;
+    }
+    else
+    {
+        osm_gps_map_add_track(OSM_GPS_MAP(self->obj), track);
+    }
+    Py_RETURN_NONE;
+}
+%%
+override osm_gps_map_download_maps kwargs
+static PyObject *
+_wrap_osm_gps_map_download_maps(PyGObject *self, PyObject *args, 
+                                     PyObject *kwargs)
+{
+    static char *kwlist[] = { "lat1", "lon1", "lat2", "lon2", "zoom_start", "zoom_end", NULL };
+    int zoom_start, zoom_end;
+    coord_t pt1, pt2;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+				        "ffffii:GpsMap.download_maps",
+				        kwlist, &pt1.rlat,&pt1.rlon,&pt2.rlat, &pt2.rlon,
+                        &zoom_start, &zoom_end))
+        return NULL;
+
+    osm_gps_map_download_maps(OSM_GPS_MAP(self->obj), &pt1, &pt2, zoom_start, zoom_end);
+
+    Py_RETURN_NONE;
+}
+
+// vim: filetype=c
diff --git a/python/osmgpsmapmodule.c b/python/osmgpsmapmodule.c
new file mode 100644
index 0000000..c1163a3
--- /dev/null
+++ b/python/osmgpsmapmodule.c
@@ -0,0 +1,64 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * osmgpsmapmodule.
+ * Copyright (C) John Stowers 2008 <john.stowers at gmail.com>
+ * 
+ * osm-gps-map.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * 
+ * osm-gps-map.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <pygobject.h>
+#include <osm-gps-map.h>
+
+void pyosmgpsmap_register_classes(PyObject *d);
+extern PyMethodDef pyosmgpsmap_functions[];
+
+DL_EXPORT(void)
+initosmgpsmap(void)
+{
+	PyObject *m, *d;
+
+	init_pygobject();
+
+	m = Py_InitModule("osmgpsmap", pyosmgpsmap_functions);
+	d = PyModule_GetDict(m);
+
+	pyosmgpsmap_register_classes(d);
+
+	/* Add this if we ever add an enum or something to osmgpsmap. */
+#if 0
+	pyosmgpsmap_add_constants(m, "OSM_GPS_MAP_");
+#endif
+
+	/* Manually add all the Map repository strings */
+    PyModule_AddObject(m, "MAP_SOURCE_OPENSTREETMAP",
+		       PyString_FromString(MAP_SOURCE_OPENSTREETMAP));
+    PyModule_AddObject(m, "MAP_SOURCE_OPENSTREETMAP_RENDERER",
+		       PyString_FromString(MAP_SOURCE_OPENSTREETMAP_RENDERER));
+    PyModule_AddObject(m, "MAP_SOURCE_OPENAERIALMAP",
+		       PyString_FromString(MAP_SOURCE_OPENAERIALMAP));
+    PyModule_AddObject(m, "MAP_SOURCE_GOOGLE_HYBRID",
+		       PyString_FromString(MAP_SOURCE_GOOGLE_HYBRID));
+    PyModule_AddObject(m, "MAP_SOURCE_GOOGLE_SATTELITE",
+		       PyString_FromString(MAP_SOURCE_GOOGLE_SATTELITE));
+    PyModule_AddObject(m, "MAP_SOURCE_GOOGLE_SATTELITE_QUAD",
+		       PyString_FromString(MAP_SOURCE_GOOGLE_SATTELITE_QUAD));
+    PyModule_AddObject(m, "MAP_SOURCE_MAPS_FOR_FREE",
+		       PyString_FromString(MAP_SOURCE_MAPS_FOR_FREE));
+    PyModule_AddObject(m, "MAP_SOURCE_VIRTUAL_EARTH_SATTELITE",
+		       PyString_FromString(MAP_SOURCE_VIRTUAL_EARTH_SATTELITE));
+
+	if (PyErr_Occurred()) {
+		Py_FatalError("can't initialize module osmgpsmap");
+	}
+}
diff --git a/python/setup.py b/python/setup.py
new file mode 100644
index 0000000..055c8e5
--- /dev/null
+++ b/python/setup.py
@@ -0,0 +1,36 @@
+#!/usr/bin/env python
+
+import os
+from distutils.core import setup, Extension
+
+def pkg_config_parse(pkg, opt):
+    conf = os.popen('pkg-config %s %s' % (opt,pkg)).read()
+    opt = opt[-2:]
+    return [x.lstrip(opt) for x in conf.split()]
+
+def get_include(pkg):
+    return pkg_config_parse(pkg,'--cflags-only-I')
+
+def get_lib_dirs(pkg):
+    return pkg_config_parse(pkg,'--libs-only-L')
+
+def get_libs(pkg):
+    return pkg_config_parse(pkg,'--libs-only-l')
+
+#print get_libs('osmgpsmap pygobject-2.0')
+#print get_libs('osmgpsmap pygobject-2.0')
+#print get_libs('osmgpsmap pygobject-2.0')
+
+_osmgpsmap = Extension(name = 'osmgpsmap',
+            sources= ['osmgpsmapmodule.c','osmgpsmap.c'],
+            include_dirs = get_include('osmgpsmap pygobject-2.0'),
+            library_dirs = get_lib_dirs('osmgpsmap pygobject-2.0'),
+            libraries = get_libs('osmgpsmap pygobject-2.0'),
+        )
+
+setup( name = "pyosmgpsmap",
+    version = "0.1",
+    description = "python interface for osmgpsmap",
+    ext_modules = [_osmgpsmap],
+    )
+
diff --git a/python/test.sh b/python/test.sh
new file mode 100755
index 0000000..d624efb
--- /dev/null
+++ b/python/test.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+PYTHONPATH=`pwd`/.libs \
+    python -c \
+'import gtk.gdk
+import gobject
+import osmgpsmap
+
+gtk.gdk.threads_init()
+
+def print_tiles(map):
+    print map.get_property("tiles-queued")
+    return True
+
+a = gtk.Window()
+a.connect("destroy", lambda x: gtk.main_quit())
+m = osmgpsmap.GpsMap()
+
+a.add(m)
+a.show_all()
+
+gobject.timeout_add(500, print_tiles, m)
+
+gtk.main()'
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..18286b8
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,46 @@
+## Process this file with automake to produce Makefile.in
+
+## Created by Anjuta
+
+AM_CPPFLAGS = \
+	-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
+	-DPACKAGE_SRC_DIR=\""$(srcdir)"\" \
+	-DPACKAGE_DATA_DIR=\""$(datadir)"\" $(OPENSTREETMAP_GPS_MAP_CFLAGS)
+
+AM_CFLAGS =\
+	 -Wall\
+	 -g
+
+bin_PROGRAMS = openstreetmap-gps-map
+
+openstreetmap_gps_map_SOURCES = \
+	main.c
+
+openstreetmap_gps_map_DEPENDENCIES = \
+	libosmgpsmap.la
+
+openstreetmap_gps_map_LDFLAGS = \
+	-losmgpsmap -lgthread-2.0
+
+openstreetmap_gps_map_LDADD = $(OPENSTREETMAP_GPS_MAP_LIBS)
+
+lib_LTLIBRARIES = \
+	libosmgpsmap.la
+
+libosmgpsmap_la_SOURCES = \
+	converter.c \
+	osm-gps-map.c
+
+libosmgpsmap_la_CFLAGS = \
+	-DG_LOG_DOMAIN=\"OsmGpsMap\"
+
+libosmgpsmapincdir = $(includedir)/osmgpsmap
+libosmgpsmapinc_HEADERS = \
+	osm-gps-map.h
+
+noinst_HEADERS = \
+	converter.h \
+	osm-gps-map-types.h
+
+EXTRA_DIST = \
+	poi.png
diff --git a/src/converter.c b/src/converter.c
new file mode 100644
index 0000000..658c266
--- /dev/null
+++ b/src/converter.c
@@ -0,0 +1,102 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
+/* vim:set et sw=4 ts=4 cino=t0,(0: */
+/*
+ * converter.c
+ * Copyright (C) Marcus Bauer 2008 <marcus.bauer at gmail.com>
+ * Copyright (C) John Stowers 2008 <john.stowers at gmail.com>
+ *
+ * osm-gps-map.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * osm-gps-map.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <math.h>
+#include <stdio.h>
+
+#include "osm-gps-map-types.h"
+#include "converter.h"
+
+
+float
+deg2rad(float deg)
+{
+    return (deg * M_PI / 180.0);
+}
+
+float
+rad2deg(float rad)
+{
+    return (rad / M_PI * 180.0);
+}
+
+
+int
+lat2pixel(  int zoom,
+            float lat)
+{
+    float lat_m;
+    int pixel_y;
+
+    lat_m = atanh(sin(lat));
+
+    /* the formula is
+     *
+     * pixel_y = -(2^zoom * TILESIZE * lat_m) / 2PI + (2^zoom * TILESIZE) / 2
+     */
+    pixel_y = -(int)( (lat_m * TILESIZE * (1 << zoom) ) / (2*M_PI)) +
+        ((1 << zoom) * (TILESIZE/2) );
+
+
+    return pixel_y;
+}
+
+
+int
+lon2pixel(  int zoom,
+            float lon)
+{
+    int pixel_x;
+
+    /* the formula is
+     *
+     * pixel_x = (2^zoom * TILESIZE * lon) / 2PI + (2^zoom * TILESIZE) / 2
+     */
+    pixel_x = (int)(( lon * TILESIZE * (1 << zoom) ) / (2*M_PI)) +
+        ( (1 << zoom) * (TILESIZE/2) );
+    return pixel_x;
+}
+
+float
+pixel2lon(  float zoom,
+            int pixel_x)
+{
+    float lon;
+
+    lon = ((pixel_x - ( exp(zoom * M_LN2) * (TILESIZE/2) ) ) *2*M_PI) / 
+        (TILESIZE * exp(zoom * M_LN2) );
+
+    return lon;
+}
+
+float
+pixel2lat(  float zoom,
+            int pixel_y)
+{
+    float lat, lat_m;
+
+    lat_m = (-( pixel_y - ( exp(zoom * M_LN2) * (TILESIZE/2) ) ) * (2*M_PI)) /
+        (TILESIZE * exp(zoom * M_LN2));
+
+    lat = asin(tanh(lat_m));
+
+    return lat;
+}
diff --git a/src/converter.h b/src/converter.h
new file mode 100644
index 0000000..0023d9f
--- /dev/null
+++ b/src/converter.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
+/* vim:set et sw=4 ts=4 cino=t0,(0: */
+/*
+ * converter.h
+ * Copyright (C) Marcus Bauer 2008 <marcus.bauer at gmail.com>
+ * Copyright (C) John Stowers 2009 <john.stowers at gmail.com>
+ *
+ * Contributions by
+ * Everaldo Canuto 2009 <everaldo.canuto at gmail.com>
+ *
+ * osm-gps-map.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * osm-gps-map.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+float
+deg2rad(float deg);
+
+float
+rad2deg(float rad);
+
+int
+lat2pixel(  int zoom,
+            float lat);
+
+int
+lon2pixel(  int zoom,
+            float lon);
+
+float
+pixel2lon(  float zoom,
+            int pixel_x);
+
+float
+pixel2lat(  float zoom,
+            int pixel_y);
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..aa90c16
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,361 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
+/* vim:set et sw=4 ts=4 cino=t0,(0: */
+/*
+ * main.c
+ * Copyright (C) John Stowers 2008 <john.stowers at gmail.com>
+ *
+ * main.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * main.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <math.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include "osm-gps-map.h"
+
+typedef struct {
+    const char *name;
+    const char *uri;
+} map_source_t;
+
+static const map_source_t MAP_SOURCES[] = {
+    {"OpenStreetMap",           MAP_SOURCE_OPENSTREETMAP            },
+    {"OpenStreetMap Renderer",  MAP_SOURCE_OPENSTREETMAP_RENDERER   },
+    {"OpenAerialMap",           MAP_SOURCE_OPENAERIALMAP            },
+    {"Google Maps",             MAP_SOURCE_GOOGLE_MAPS              },
+    {"Google Maps Hybrid",      MAP_SOURCE_GOOGLE_HYBRID            },
+    {"Google Sattelite",        MAP_SOURCE_GOOGLE_SATTELITE         },
+    {"Google Sattelite Quad",   MAP_SOURCE_GOOGLE_SATTELITE_QUAD    },
+    {"Maps For Free",           MAP_SOURCE_MAPS_FOR_FREE            },
+    {"Virtual Earth Sattelite", MAP_SOURCE_VIRTUAL_EARTH_SATTELITE  },
+};
+
+static int map_provider = 0;
+static gboolean maps_in_temp = FALSE;
+static gboolean debug = FALSE;
+static GOptionEntry entries[] =
+{
+  { "maps-in-temp", 't', 0, G_OPTION_ARG_NONE, &maps_in_temp, "Store maps in /tmp instead of ~/Maps", NULL },
+  { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug, "Enable debugging", NULL },
+  { "map", 'm', 0, G_OPTION_ARG_INT, &map_provider, "Map source", "N" },
+  { NULL }
+};
+
+
+static GdkPixbuf *STAR_IMAGE;
+
+typedef struct {
+    OsmGpsMap *map;
+    GtkWidget *entry;
+} timeout_cb_t;
+
+float
+deg2rad(float deg)
+{
+    return (deg * M_PI / 180.0);
+}
+
+float
+rad2deg(float rad)
+{
+    return (rad / M_PI * 180.0);
+}
+
+gboolean
+on_timeout_check_tiles_in_queue(gpointer user_data)
+{
+    gchar *msg;
+    int remaining;
+    timeout_cb_t *data = (timeout_cb_t *)user_data;
+    g_object_get(data->map, "tiles-queued", &remaining,NULL);
+
+    msg = g_strdup_printf("%d tiles queued",remaining);
+    gtk_entry_set_text(GTK_ENTRY(data->entry), msg);
+    g_free(msg);
+
+    return remaining > 0;
+}
+
+gboolean
+on_button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
+{
+    coord_t coord;
+    OsmGpsMap *map = OSM_GPS_MAP(widget);
+
+    if ( (event->button == 1) && (event->type == GDK_2BUTTON_PRESS) )
+    {
+        g_debug("Double clicked %f %f", event->x, event->y);
+        coord = osm_gps_map_get_co_ordinates(map, (int)event->x, (int)event->y);
+        osm_gps_map_draw_gps (map,
+                              rad2deg(coord.rlat),
+                              rad2deg(coord.rlon),
+                              0);
+    }
+
+    if ( (event->button == 2) && (event->type == GDK_BUTTON_PRESS) )
+    {
+        coord = osm_gps_map_get_co_ordinates(map, (int)event->x, (int)event->y);
+        osm_gps_map_add_image (map,
+                               rad2deg(coord.rlat),
+                               rad2deg(coord.rlon),
+                               STAR_IMAGE);
+    }
+    return FALSE;
+}
+
+gboolean
+on_button_release_event (GtkWidget *widget, GdkEventButton *event, gpointer user_data)
+{
+    float lat,lon;
+    GtkEntry *entry = GTK_ENTRY(user_data);
+    OsmGpsMap *map = OSM_GPS_MAP(widget);
+
+    g_object_get(map, "latitude", &lat, "longitude", &lon, NULL);
+    gchar *msg = g_strdup_printf("%f,%f",lat,lon);
+    gtk_entry_set_text(entry, msg);
+    g_free(msg);
+
+    return FALSE;
+}
+
+gboolean
+on_zoom_in_clicked_event (GtkWidget *widget, gpointer user_data)
+{
+    int zoom;
+    OsmGpsMap *map = OSM_GPS_MAP(user_data);
+    g_object_get(map, "zoom", &zoom, NULL);
+    osm_gps_map_set_zoom(map, zoom+1);
+    return FALSE;
+}
+
+gboolean
+on_zoom_out_clicked_event (GtkWidget *widget, gpointer user_data)
+{
+    int zoom;
+    OsmGpsMap *map = OSM_GPS_MAP(user_data);
+    g_object_get(map, "zoom", &zoom, NULL);
+    osm_gps_map_set_zoom(map, zoom-1);
+    return FALSE;
+}
+
+gboolean
+on_home_clicked_event (GtkWidget *widget, gpointer user_data)
+{
+    OsmGpsMap *map = OSM_GPS_MAP(user_data);
+    osm_gps_map_set_mapcenter(map, -43.5326,172.6362,12);
+    return FALSE;
+}
+
+gboolean
+on_cache_clicked_event (GtkWidget *widget, gpointer user_data)
+{
+    int zoom,max_zoom;
+    coord_t pt1, pt2;
+    timeout_cb_t *data;
+
+    data = (timeout_cb_t *)user_data;
+    osm_gps_map_get_bbox(data->map, &pt1, &pt2);
+    g_object_get(data->map, "zoom", &zoom, "max-zoom", &max_zoom, NULL);
+    osm_gps_map_download_maps(data->map, &pt1, &pt2, zoom, max_zoom);
+    g_timeout_add(500, on_timeout_check_tiles_in_queue, user_data);
+
+    return FALSE;
+}
+
+void
+on_close (GtkWidget *widget, gpointer user_data)
+{
+    gtk_widget_destroy(widget);
+    gtk_main_quit();
+}
+
+void
+usage (GOptionContext *context)
+{
+    int i;
+
+    puts(g_option_context_get_help(context, TRUE, NULL));
+
+    printf("Valid map sources:\n");
+    for(i=0; i<(sizeof(MAP_SOURCES)/sizeof(MAP_SOURCES[0])); i++)
+        printf("\t%d:\t%s\n",i,MAP_SOURCES[i].name);
+}
+
+
+int
+main (int argc, char **argv)
+{
+    GtkWidget *vbox;
+    GtkWidget *bbox;
+    GtkWidget *entry;
+    GtkWidget *window;
+    GtkWidget *zoomInbutton;
+    GtkWidget *zoomOutbutton;
+    GtkWidget *homeButton;
+    GtkWidget *cacheButton;
+    GtkWidget *map;
+    char *cachedir;
+    char *homedir;
+    GError *error = NULL;
+    GOptionContext *context;
+    timeout_cb_t *data;
+
+    g_thread_init(NULL);
+    gtk_init (&argc, &argv);
+
+    context = g_option_context_new ("- test tree model performance");
+    g_option_context_set_help_enabled(context, FALSE);
+    g_option_context_add_main_entries (context, entries, NULL);
+
+    if (!g_option_context_parse (context, &argc, &argv, &error)) {
+        usage(context);
+        return 1;
+    }
+
+    if (map_provider < 0 || map_provider > (sizeof(MAP_SOURCES)/sizeof(MAP_SOURCES[0]))-1) {
+        usage(context);
+        return 2;
+    }
+
+    if (maps_in_temp)
+        homedir = g_strdup("/tmp");
+    else {
+        homedir = g_strdup(g_getenv("HOME"));
+        if (!homedir)
+            homedir = g_strdup(g_get_home_dir());
+    }
+
+    if (debug)
+        gdk_window_set_debug_updates(TRUE);
+
+    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+    gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
+
+    STAR_IMAGE = gdk_pixbuf_new_from_file_at_size ("poi.png", 24,24,NULL);
+    cachedir = g_strdup_printf("%s/Maps/%s", homedir, MAP_SOURCES[map_provider].name);
+
+    g_debug("Map Cache Dir: %s", cachedir);
+    g_debug("Map Provider: %s (%d)", MAP_SOURCES[map_provider].name, map_provider);
+
+    switch(map_provider) {
+        //0:    OpenStreetMap
+        //1:    OpenStreetMap Renderer
+        //2:    OpenAerialMap
+        //3:    Google Maps
+        //4:    Google Maps Hybrid
+        //5:    Google Sattelite
+        //6:    Google Sattelite Quad
+        //7:    Maps For Free
+        //8:    Virtual Earth Sattelite
+        case 0:
+        case 1:
+        case 2:
+        case 3:
+        case 4:
+        default:
+            map = g_object_new (OSM_TYPE_GPS_MAP,
+                                "repo-uri",MAP_SOURCES[map_provider].uri,
+                                "tile-cache",cachedir,
+                                "tile-cache-is-full-path",TRUE,
+                                "proxy-uri",g_getenv("http_proxy"),
+                                NULL);
+            break;
+        case 7:
+            //Max Zoom = 11
+            map = g_object_new (OSM_TYPE_GPS_MAP,
+                                "repo-uri",MAP_SOURCES[map_provider].uri,
+                                "tile-cache",cachedir,
+                                "tile-cache-is-full-path",TRUE,
+                                "proxy-uri",g_getenv("http_proxy"),
+                                "max-zoom",11,
+                                NULL);
+            break;
+        case 5:
+        case 6:
+            //Max Zoom = 18
+            map = g_object_new (OSM_TYPE_GPS_MAP,
+                                "repo-uri",MAP_SOURCES[map_provider].uri,
+                                "tile-cache",cachedir,
+                                "tile-cache-is-full-path",TRUE,
+                                "proxy-uri",g_getenv("http_proxy"),
+                                "max-zoom",18,
+                                NULL);
+            break;
+        case 8:
+            //Max Zoom = 20
+            map = g_object_new (OSM_TYPE_GPS_MAP,
+                                "repo-uri",MAP_SOURCES[map_provider].uri,
+                                "tile-cache",cachedir,
+                                "tile-cache-is-full-path",TRUE,
+                                "proxy-uri",g_getenv("http_proxy"),
+                                "max-zoom",20,
+                                NULL);
+            break;
+    }
+    g_free(cachedir);
+
+
+    vbox = gtk_vbox_new (FALSE, 2);
+    gtk_container_add (GTK_CONTAINER (window), vbox);
+
+    //Add the map to the box
+    gtk_box_pack_start (GTK_BOX(vbox), map, TRUE, TRUE, 0);
+    //And add a box for the buttons
+    bbox = gtk_hbox_new (TRUE, 0);
+    gtk_box_pack_start (GTK_BOX(vbox), bbox, FALSE, TRUE, 0);
+    //And add the lat/long entry
+    entry = gtk_entry_new();
+    gtk_box_pack_start (GTK_BOX(vbox), entry, FALSE, TRUE, 0);
+
+    //Add buttons to the bbox
+    zoomInbutton = gtk_button_new_from_stock (GTK_STOCK_ZOOM_IN);
+    g_signal_connect (G_OBJECT (zoomInbutton), "clicked",
+                      G_CALLBACK (on_zoom_in_clicked_event), (gpointer) map);
+    gtk_box_pack_start (GTK_BOX(bbox), zoomInbutton, FALSE, TRUE, 0);
+
+    zoomOutbutton = gtk_button_new_from_stock (GTK_STOCK_ZOOM_OUT);
+    g_signal_connect (G_OBJECT (zoomOutbutton), "clicked",
+                      G_CALLBACK (on_zoom_out_clicked_event), (gpointer) map);
+    gtk_box_pack_start (GTK_BOX(bbox), zoomOutbutton, FALSE, TRUE, 0);
+
+    homeButton = gtk_button_new_from_stock (GTK_STOCK_HOME);
+    g_signal_connect (G_OBJECT (homeButton), "clicked",
+                      G_CALLBACK (on_home_clicked_event), (gpointer) map);
+    gtk_box_pack_start (GTK_BOX(bbox), homeButton, FALSE, TRUE, 0);
+
+    data = g_new0(timeout_cb_t, 1);
+    data->map = OSM_GPS_MAP(map);
+    data->entry = entry;
+    cacheButton = gtk_button_new_with_label ("Cache");
+    g_signal_connect (G_OBJECT (cacheButton), "clicked",
+                      G_CALLBACK (on_cache_clicked_event), (gpointer) data);
+    gtk_box_pack_start (GTK_BOX(bbox), cacheButton, FALSE, TRUE, 0);
+
+    //Connect to map events
+    g_signal_connect (map, "button-press-event",
+                      G_CALLBACK (on_button_press_event), (gpointer) entry);
+    g_signal_connect (map, "button-release-event",
+                      G_CALLBACK (on_button_release_event), (gpointer) entry);
+
+    g_signal_connect (window, "destroy",
+                      G_CALLBACK (on_close), (gpointer) map);
+
+    gtk_widget_show_all (window);
+
+    g_log_set_handler ("OsmGpsMap", G_LOG_LEVEL_MASK, g_log_default_handler, NULL);
+    gtk_main ();
+
+    g_free(homedir);
+    return 0;
+}
diff --git a/src/osm-gps-map-types.h b/src/osm-gps-map-types.h
new file mode 100644
index 0000000..bc3c415
--- /dev/null
+++ b/src/osm-gps-map-types.h
@@ -0,0 +1,85 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
+/* vim:set et sw=4 ts=4 cino=t0,(0: */
+/*
+ * osm-gps-map-types.h
+ * Copyright (C) Marcus Bauer 2008 <marcus.bauer at gmail.com>
+ * Copyright (C) John Stowers 2009 <john.stowers at gmail.com>
+ *
+ * Contributions by
+ * Everaldo Canuto 2009 <everaldo.canuto at gmail.com>
+ *
+ * osm-gps-map.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * osm-gps-map.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _OSM_GPS_MAP_TYPES_H_
+#define _OSM_GPS_MAP_TYPES_H_
+
+#include <gdk/gdk.h>
+#include "osm-gps-map.h"
+
+#define TILESIZE 256
+#define MAX_ZOOM 20
+#define MIN_ZOOM 0
+
+#define URI_MARKER_X    "#X"
+#define URI_MARKER_Y    "#Y"
+#define URI_MARKER_Z    "#Z"
+#define URI_MARKER_S    "#S"
+#define URI_MARKER_Q    "#Q"
+#define URI_MARKER_Q0   "#W"
+#define URI_MARKER_YS   "#U"
+#define URI_MARKER_R    "#R"
+
+#define URI_HAS_X   (1 << 0)
+#define URI_HAS_Y   (1 << 1)
+#define URI_HAS_Z   (1 << 2)
+#define URI_HAS_S   (1 << 3)
+#define URI_HAS_Q   (1 << 4)
+#define URI_HAS_Q0  (1 << 5)
+#define URI_HAS_YS  (1 << 6)
+#define URI_HAS_R   (1 << 7)
+//....
+#define URI_FLAG_END (1 << 8)
+
+typedef struct {
+    int x1;
+    int y1;
+    int x2;
+    int y2;
+} bbox_pixel_t;
+
+typedef struct {
+    /* The details of the tile to download */
+    char *uri;
+    char *folder;
+    char *filename;
+    OsmGpsMap *map;
+    /* whether to redraw the map when the tile arrives */
+    gboolean redraw;
+} tile_download_t;
+
+typedef struct {
+    int x;
+    int y;
+    int zoom;
+} tile_t;
+
+typedef struct {
+    coord_t pt;
+    GdkPixbuf *image;
+    int w;
+    int h;
+} image_t;
+
+#endif /* _OSM_GPS_MAP_TYPES_H_ */
diff --git a/src/osm-gps-map.c b/src/osm-gps-map.c
new file mode 100644
index 0000000..e25a33a
--- /dev/null
+++ b/src/osm-gps-map.c
@@ -0,0 +1,2171 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
+/* vim:set et sw=4 ts=4 cino=t0,(0: */
+/*
+ * osm-gps-map.c
+ * Copyright (C) Marcus Bauer 2008 <marcus.bauer at gmail.com>
+ * Copyright (C) John Stowers 2009 <john.stowers at gmail.com>
+ *
+ * Contributions by
+ * Everaldo Canuto 2009 <everaldo.canuto at gmail.com>
+ *
+ * osm-gps-map.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * osm-gps-map.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <fcntl.h>
+#include <math.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gdk/gdk.h>
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <libsoup/soup.h>
+
+#include "converter.h"
+#include "osm-gps-map-types.h"
+#include "osm-gps-map.h"
+
+#ifdef USE_CAIRO
+#include <cairo.h>
+#endif
+
+#define ENABLE_DEBUG 0
+
+#define EXTRA_BORDER (TILESIZE / 2)
+
+struct _OsmGpsMapPrivate
+{
+    GHashTable *tile_queue;
+    GHashTable *missing_tiles;
+    GHashTable *tile_cache;
+
+    int map_zoom;
+    int max_zoom;
+    int min_zoom;
+    gboolean map_auto_center;
+    gboolean map_auto_download;
+    int map_x;
+    int map_y;
+
+    /* Latitude and longitude of the center of the map, in radians */
+    gfloat center_rlat;
+    gfloat center_rlon;
+
+    guint max_tile_cache_size;
+    /* Incremented at each redraw */
+    guint redraw_cycle;
+    /* ID of the idle redraw operation */
+    guint idle_map_redraw;
+
+    //how we download tiles
+    SoupSession *soup_session;
+    char *proxy_uri;
+
+    //where downloaded tiles are cached
+    char *cache_dir;
+    gboolean cache_dir_is_full_path;
+
+    //contains flags indicating the various special characters
+    //the uri string contains, that will be replaced when calculating
+    //the uri to download.
+    char *repo_uri;
+    int uri_format;
+    //flag indicating if the map source is located on the google
+    gboolean the_google;
+
+    //gps tracking state
+    gboolean record_trip_history;
+    gboolean show_trip_history;
+    GSList *trip_history;
+    coord_t *gps;
+    gboolean gps_valid;
+
+    //additional images or tracks added to the map
+    GSList *tracks;
+    GSList *images;
+
+    //Used for storing the joined tiles
+    GdkPixmap *pixmap;
+    GdkGC *gc_map;
+
+    //The tile painted when one cannot be found
+    //GdkPixbuf *missing_tile;
+
+    //For tracking click and drag
+    int drag_counter;
+    int drag_mouse_dx;
+    int drag_mouse_dy;
+    int drag_start_mouse_x;
+    int drag_start_mouse_y;
+    int drag_start_map_x;
+    int drag_start_map_y;
+
+    //for customizing the redering of the gps track
+    int ui_gps_track_width;
+    int ui_gps_point_inner_radius;
+    int ui_gps_point_outer_radius;
+
+    guint is_disposed : 1;
+    guint dragging : 1;
+    guint center_coord_set : 1;
+};
+
+#define OSM_GPS_MAP_PRIVATE(o)  (OSM_GPS_MAP (o)->priv)
+
+typedef struct
+{
+    GdkPixbuf *pixbuf;
+    /* We keep track of the number of the redraw cycle this tile was last used,
+     * so that osm_gps_map_purge_cache() can remove the older ones */
+    guint redraw_cycle;
+} OsmCachedTile;
+
+enum
+{
+    PROP_0,
+
+    PROP_AUTO_CENTER,
+    PROP_RECORD_TRIP_HISTORY,
+    PROP_SHOW_TRIP_HISTORY,
+    PROP_AUTO_DOWNLOAD,
+    PROP_REPO_URI,
+    PROP_PROXY_URI,
+    PROP_TILE_CACHE_DIR,
+    PROP_TILE_CACHE_DIR_IS_FULL_PATH,
+    PROP_ZOOM,
+    PROP_MAX_ZOOM,
+    PROP_MIN_ZOOM,
+    PROP_LATITUDE,
+    PROP_LONGITUDE,
+    PROP_MAP_X,
+    PROP_MAP_Y,
+    PROP_TILES_QUEUED,
+    PROP_GPS_TRACK_WIDTH,
+    PROP_GPS_POINT_R1,
+    PROP_GPS_POINT_R2
+};
+
+G_DEFINE_TYPE (OsmGpsMap, osm_gps_map, GTK_TYPE_DRAWING_AREA);
+
+/*
+ * Drawing function forward defintions
+ */
+static gchar    *replace_string(const gchar *src, const gchar *from, const gchar *to);
+static void     inspect_map_uri(OsmGpsMap *map);
+static gchar    *replace_map_uri(OsmGpsMap *map, const gchar *uri, int zoom, int x, int y);
+static void     osm_gps_map_print_images (OsmGpsMap *map);
+static void     osm_gps_map_draw_gps_point (OsmGpsMap *map);
+static void     osm_gps_map_blit_tile(OsmGpsMap *map, GdkPixbuf *pixbuf, int offset_x, int offset_y);
+static void     osm_gps_map_tile_download_complete (SoupSession *session, SoupMessage *msg, gpointer user_data);
+static void     osm_gps_map_download_tile (OsmGpsMap *map, int zoom, int x, int y, gboolean redraw);
+static void     osm_gps_map_load_tile (OsmGpsMap *map, int zoom, int x, int y, int offset_x, int offset_y);
+static void     osm_gps_map_fill_tiles_pixel (OsmGpsMap *map);
+static gboolean osm_gps_map_map_redraw (OsmGpsMap *map);
+static void     osm_gps_map_map_redraw_idle (OsmGpsMap *map);
+
+static void
+cached_tile_free (OsmCachedTile *tile)
+{
+    g_object_unref (tile->pixbuf);
+    g_slice_free (OsmCachedTile, tile);
+}
+
+/*
+ * Description:
+ *   Find and replace text within a string.
+ *
+ * Parameters:
+ *   src  (in) - pointer to source string
+ *   from (in) - pointer to search text
+ *   to   (in) - pointer to replacement text
+ *
+ * Returns:
+ *   Returns a pointer to dynamically-allocated memory containing string
+ *   with occurences of the text pointed to by 'from' replaced by with the
+ *   text pointed to by 'to'.
+ */
+static gchar *
+replace_string(const gchar *src, const gchar *from, const gchar *to)
+{
+    size_t size    = strlen(src) + 1;
+    size_t fromlen = strlen(from);
+    size_t tolen   = strlen(to);
+
+    /* Allocate the first chunk with enough for the original string. */
+    gchar *value = g_malloc(size);
+
+
+    /* We need to return 'value', so let's make a copy to mess around with. */
+    gchar *dst = value;
+
+    if ( value != NULL )
+    {
+        for ( ;; )
+        {
+            /* Try to find the search text. */
+            const gchar *match = g_strstr_len(src, size, from);
+            if ( match != NULL )
+            {
+                gchar *temp;
+                /* Find out how many characters to copy up to the 'match'. */
+                size_t count = match - src;
+
+
+                /* Calculate the total size the string will be after the
+                 * replacement is performed. */
+                size += tolen - fromlen;
+
+                temp = g_realloc(value, size);
+                if ( temp == NULL )
+                {
+                    g_free(value);
+                    return NULL;
+                }
+
+                /* we'll want to return 'value' eventually, so let's point it
+                 * to the memory that we are now working with.
+                 * And let's not forget to point to the right location in
+                 * the destination as well. */
+                dst = temp + (dst - value);
+                value = temp;
+
+                /*
+                 * Copy from the source to the point where we matched. Then
+                 * move the source pointer ahead by the amount we copied. And
+                 * move the destination pointer ahead by the same amount.
+                 */
+                g_memmove(dst, src, count);
+                src += count;
+                dst += count;
+
+                /* Now copy in the replacement text 'to' at the position of
+                 * the match. Adjust the source pointer by the text we replaced.
+                 * Adjust the destination pointer by the amount of replacement
+                 * text. */
+                g_memmove(dst, to, tolen);
+                src += fromlen;
+                dst += tolen;
+            }
+            else
+            {
+                /*
+                 * Copy any remaining part of the string. This includes the null
+                 * termination character.
+                 */
+                strcpy(dst, src);
+                break;
+            }
+        }
+    }
+    return value;
+}
+
+static void
+map_convert_coords_to_quadtree_string(OsmGpsMap *map, gint x, gint y, gint zoomlevel,
+                                      gchar *buffer, const gchar initial,
+                                      const gchar *const quadrant)
+{
+    gchar *ptr = buffer;
+    gint n;
+
+    if (initial)
+        *ptr++ = initial;
+
+    for(n = zoomlevel-1; n >= 0; n--)
+    {
+        gint xbit = (x >> n) & 1;
+        gint ybit = (y >> n) & 1;
+        *ptr++ = quadrant[xbit + 2 * ybit];
+    }
+
+    *ptr++ = '\0';
+}
+
+
+static void
+inspect_map_uri(OsmGpsMap *map)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+
+    if (g_strrstr(priv->repo_uri, URI_MARKER_X))
+        priv->uri_format |= URI_HAS_X;
+
+    if (g_strrstr(priv->repo_uri, URI_MARKER_Y))
+        priv->uri_format |= URI_HAS_Y;
+
+    if (g_strrstr(priv->repo_uri, URI_MARKER_Z))
+        priv->uri_format |= URI_HAS_Z;
+
+    if (g_strrstr(priv->repo_uri, URI_MARKER_S))
+        priv->uri_format |= URI_HAS_S;
+
+    if (g_strrstr(priv->repo_uri, URI_MARKER_Q))
+        priv->uri_format |= URI_HAS_Q;
+
+    if (g_strrstr(priv->repo_uri, URI_MARKER_Q0))
+        priv->uri_format |= URI_HAS_Q0;
+
+    if (g_strrstr(priv->repo_uri, URI_MARKER_YS))
+        priv->uri_format |= URI_HAS_YS;
+
+    if (g_strrstr(priv->repo_uri, URI_MARKER_R))
+        priv->uri_format |= URI_HAS_R;
+
+    if (g_strrstr(priv->repo_uri, "google.com"))
+        priv->the_google = TRUE;
+
+    g_debug("URI Format: 0x%X (google: %X)", priv->uri_format, priv->the_google);
+
+}
+
+static gchar *
+replace_map_uri(OsmGpsMap *map, const gchar *uri, int zoom, int x, int y)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+    char *url;
+    unsigned int i;
+    char location[22];
+
+    i = 1;
+    url = g_strdup(uri);
+    while (i < URI_FLAG_END)
+    {
+        char *s;
+        char *old;
+
+        old = url;
+        switch(i & priv->uri_format)
+        {
+            case URI_HAS_X:
+                s = g_strdup_printf("%d", x);
+                url = replace_string(url, URI_MARKER_X, s);
+                //g_debug("FOUND " URI_MARKER_X);
+                break;
+            case URI_HAS_Y:
+                s = g_strdup_printf("%d", y);
+                url = replace_string(url, URI_MARKER_Y, s);
+                //g_debug("FOUND " URI_MARKER_Y);
+                break;
+            case URI_HAS_Z:
+                s = g_strdup_printf("%d", zoom);
+                url = replace_string(url, URI_MARKER_Z, s);
+                //g_debug("FOUND " URI_MARKER_Z);
+                break;
+            case URI_HAS_S:
+                s = g_strdup_printf("%d", priv->max_zoom-zoom);
+                url = replace_string(url, URI_MARKER_S, s);
+                //g_debug("FOUND " URI_MARKER_S);
+                break;
+            case URI_HAS_Q:
+                map_convert_coords_to_quadtree_string(map,x,y,zoom,location,'t',"qrts");
+                s = g_strdup_printf("%s", location);
+                url = replace_string(url, URI_MARKER_Q, s);
+                //g_debug("FOUND " URI_MARKER_Q);
+                break;
+            case URI_HAS_Q0:
+                map_convert_coords_to_quadtree_string(map,x,y,zoom,location,'\0', "0123");
+                s = g_strdup_printf("%s", location);
+                url = replace_string(url, URI_MARKER_Q0, s);
+                //g_debug("FOUND " URI_MARKER_Q0);
+                break;
+            case URI_HAS_YS:
+                //              s = g_strdup_printf("%d", y);
+                //              url = replace_string(url, URI_MARKER_YS, s);
+                g_warning("FOUND " URI_MARKER_YS " NOT IMPLEMENTED");
+                //            retval = g_strdup_printf(repo->url,
+                //                    tilex,
+                //                    (1 << (MAX_ZOOM - zoom)) - tiley - 1,
+                //                    zoom - (MAX_ZOOM - 17));
+                break;
+            case URI_HAS_R:
+                s = g_strdup_printf("%d", g_random_int_range(0,4));
+                url = replace_string(url, URI_MARKER_R, s);
+                //g_debug("FOUND " URI_MARKER_R);
+                break;
+            default:
+                s = NULL;
+                break;
+        }
+
+        if (s) {
+            g_free(s);
+            g_free(old);
+        }
+
+        i = (i << 1);
+
+    }
+
+    return url;
+}
+
+static void
+my_log_handler (const gchar * log_domain, GLogLevelFlags log_level, const gchar * message, gpointer user_data)
+{
+    if (!(log_level & G_LOG_LEVEL_DEBUG) || ENABLE_DEBUG)
+        g_log_default_handler (log_domain, log_level, message, user_data);
+}
+
+/* clears the trip list and all resources */
+static void
+osm_gps_map_free_trip (OsmGpsMap *map)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+    if (priv->trip_history) {
+        g_slist_foreach(priv->trip_history, (GFunc) g_free, NULL);
+        g_slist_free(priv->trip_history);
+        priv->trip_history = NULL;
+    }
+}
+
+/* clears the tracks and all resources */
+static void
+osm_gps_map_free_tracks (OsmGpsMap *map)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+    if (priv->tracks)
+    {
+        GSList* tmp = priv->tracks;
+        while (tmp != NULL)
+        {
+            g_slist_foreach(tmp->data, (GFunc) g_free, NULL);
+            g_slist_free(tmp->data);
+            tmp = g_slist_next(tmp);
+        }
+        g_slist_free(priv->tracks);
+        priv->tracks = NULL;
+    }
+}
+
+/* free the poi image lists */
+static void
+osm_gps_map_free_images (OsmGpsMap *map)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+    if (priv->images) {
+        GSList *list;
+        for(list = priv->images; list != NULL; list = list->next)
+        {
+            image_t *im = list->data;
+            g_object_unref(im->image);
+            g_free(im);
+        }
+        g_slist_free(priv->images);
+        priv->images = NULL;
+    }
+}
+
+static void
+osm_gps_map_print_images (OsmGpsMap *map)
+{
+    GSList *list;
+    int x,y,pixel_x,pixel_y;
+    int min_x = 0,min_y = 0,max_x = 0,max_y = 0;
+    int map_x0, map_y0;
+    OsmGpsMapPrivate *priv = map->priv;
+
+    map_x0 = priv->map_x - EXTRA_BORDER;
+    map_y0 = priv->map_y - EXTRA_BORDER;
+    for(list = priv->images; list != NULL; list = list->next)
+    {
+        image_t *im = list->data;
+
+        // pixel_x,y, offsets
+        pixel_x = lon2pixel(priv->map_zoom, im->pt.rlon);
+        pixel_y = lat2pixel(priv->map_zoom, im->pt.rlat);
+
+        g_debug("Image %dx%d @: %f,%f (%d,%d)",
+                im->w, im->h,
+                im->pt.rlat, im->pt.rlon,
+                pixel_x, pixel_y);
+
+        x = pixel_x - map_x0;
+        y = pixel_y - map_y0;
+
+        gdk_draw_pixbuf (
+                         priv->pixmap,
+                         priv->gc_map,
+                         im->image,
+                         0,0,
+                         x-(im->w/2),y-(im->h/2),
+                         im->w,im->h,
+                         GDK_RGB_DITHER_NONE, 0, 0);
+
+        max_x = MAX(x+im->w,max_x);
+        min_x = MIN(x-im->w,min_x);
+        max_y = MAX(y+im->h,max_y);
+        min_y = MIN(y-im->h,min_y);
+    }
+
+    gtk_widget_queue_draw_area (
+                                GTK_WIDGET(map),
+                                min_x + EXTRA_BORDER, min_y + EXTRA_BORDER,
+                                max_x + EXTRA_BORDER, max_y + EXTRA_BORDER);
+
+}
+
+static void
+osm_gps_map_draw_gps_point (OsmGpsMap *map)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+
+    //incase we get called before we have got a gps point
+    if (priv->gps_valid) {
+        int map_x0, map_y0;
+        int x, y;
+        int r = priv->ui_gps_point_inner_radius;
+        int r2 = priv->ui_gps_point_outer_radius;
+        int lw = priv->ui_gps_track_width;
+        int mr = MAX(r,r2);
+
+        map_x0 = priv->map_x - EXTRA_BORDER;
+        map_y0 = priv->map_y - EXTRA_BORDER;
+        x = lon2pixel(priv->map_zoom, priv->gps->rlon) - map_x0;
+        y = lat2pixel(priv->map_zoom, priv->gps->rlat) - map_y0;
+#ifdef USE_CAIRO
+        cairo_t *cr;
+        cairo_pattern_t *pat;
+#else
+        GdkColor color;
+        GdkGC *marker;
+#endif
+
+#ifdef USE_CAIRO
+        cr = gdk_cairo_create(priv->pixmap);
+
+        // draw transparent area
+        if (r2 > 0) {
+            cairo_set_line_width (cr, 1.5);
+            cairo_set_source_rgba (cr, 0.75, 0.75, 0.75, 0.4);
+            cairo_arc (cr, x, y, r2, 0, 2 * M_PI);
+            cairo_fill (cr);
+            // draw transparent area border
+            cairo_set_source_rgba (cr, 0.55, 0.55, 0.55, 0.4);
+            cairo_arc (cr, x, y, r2, 0, 2 * M_PI);
+            cairo_stroke(cr);
+        }
+
+        // draw ball gradient
+        if (r > 0) {
+            pat = cairo_pattern_create_radial (x-(r/5), y-(r/5), (r/5), x,  y, r);
+            cairo_pattern_add_color_stop_rgba (pat, 0, 1, 1, 1, 1.0);
+            cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 1, 1.0);
+            cairo_set_source (cr, pat);
+            cairo_arc (cr, x, y, r, 0, 2 * M_PI);
+            cairo_fill (cr);
+            cairo_pattern_destroy (pat);
+            // draw ball border
+            cairo_set_line_width (cr, 1.0);
+            cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0);
+            cairo_arc (cr, x, y, r, 0, 2 * M_PI);
+            cairo_stroke(cr);
+        }
+
+        cairo_destroy(cr);
+        gtk_widget_queue_draw_area (GTK_WIDGET(map),
+                                    x-mr,
+                                    y-mr,
+                                    mr*2,
+                                    mr*2);
+#else
+        marker = gdk_gc_new(priv->pixmap);
+        color.red = 5000;
+        color.green = 5000;
+        color.blue = 55000;
+        gdk_gc_set_rgb_fg_color(marker, &color);
+        gdk_gc_set_line_attributes(marker, lw, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+
+        if (r2 > 0) {
+            gdk_draw_arc (priv->pixmap,
+                          marker,
+                          FALSE,            //filled
+                          x-r2, y-r2,       // x,y
+                          r2*2,r2*2,        // width, height
+                          0, 360*64);       // start-end angle 64th, from 3h, anti clockwise
+        }
+        if (r > 0) {
+            gdk_draw_arc (priv->pixmap,
+                          marker,
+                          TRUE,         //filled
+                          x-r, y-r,     // x,y
+                          r*2,r*2,      // width, height
+                          0, 360*64);   // start-end angle 64th, from 3h, anti clockwise
+        }
+
+        g_object_unref(marker);
+        gtk_widget_queue_draw_area (GTK_WIDGET(map),
+                                    x-(mr+lw),
+                                    y-(mr+lw),
+                                    (mr*2)+lw+lw,
+                                    (mr*2)+lw+lw);
+#endif
+    }
+}
+
+static void
+osm_gps_map_blit_tile(OsmGpsMap *map, GdkPixbuf *pixbuf, int offset_x, int offset_y)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+
+    g_debug("Queing redraw @ %d,%d (w:%d h:%d)", offset_x,offset_y, TILESIZE,TILESIZE);
+
+    /* draw pixbuf onto pixmap */
+    gdk_draw_pixbuf (priv->pixmap,
+                     priv->gc_map,
+                     pixbuf,
+                     0,0,
+                     offset_x,offset_y,
+                     TILESIZE,TILESIZE,
+                     GDK_RGB_DITHER_NONE, 0, 0);
+}
+
+static void
+osm_gps_map_tile_download_complete (SoupSession *session, SoupMessage *msg, gpointer user_data)
+{
+    int fd;
+    tile_download_t *dl = (tile_download_t *)user_data;
+    OsmGpsMap *map = OSM_GPS_MAP(dl->map);
+    OsmGpsMapPrivate *priv = map->priv;
+
+    if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
+    {
+        if (g_mkdir_with_parents(dl->folder,0700) == 0)
+        {
+            fd = open(dl->filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+            if (fd != -1)
+            {
+                write (fd, msg->response_body->data, msg->response_body->length);
+                g_debug("Wrote %lld bytes to %s", msg->response_body->length, dl->filename);
+                close (fd);
+
+                if (dl->redraw)
+                {
+                    GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (dl->filename, NULL);
+
+                    /* Store the tile into the cache */
+                    if (G_LIKELY (pixbuf))
+                    {
+                        OsmCachedTile *tile = g_slice_new (OsmCachedTile);
+                        tile->pixbuf = pixbuf;
+                        tile->redraw_cycle = priv->redraw_cycle;
+                        /* if the tile is already in the cache (it could be one
+                         * rendered from another zoom level), it will be
+                         * overwritten */
+                        g_hash_table_insert (priv->tile_cache, dl->filename, tile);
+                        /* NULL-ify dl->filename so that it won't be freed, as
+                         * we are using it as a key in the hash table */
+                        dl->filename = NULL;
+                    }
+                    osm_gps_map_map_redraw_idle (map);
+                }
+            }
+        }
+        else
+        {
+            g_warning("Error creating tile download directory: %s", dl->folder);
+        }
+
+        g_hash_table_remove(priv->tile_queue, dl->uri);
+
+        g_free(dl->uri);
+        g_free(dl->folder);
+        g_free(dl->filename);
+        g_free(dl);
+    }
+    else
+    {
+        g_warning("Error downloading tile: %d - %s", msg->status_code, msg->reason_phrase);
+        if (msg->status_code == SOUP_STATUS_NOT_FOUND)
+        {
+            g_hash_table_insert(priv->missing_tiles, dl->uri, NULL);
+            g_hash_table_remove(priv->tile_queue, dl->uri);
+        }
+        else if (msg->status_code == SOUP_STATUS_CANCELLED)
+        {
+            ;//application exiting
+        }
+        else
+        {
+            soup_session_requeue_message(session, msg);
+            return;
+        }
+    }
+
+
+}
+
+static void
+osm_gps_map_download_tile (OsmGpsMap *map, int zoom, int x, int y, gboolean redraw)
+{
+    SoupMessage *msg;
+    OsmGpsMapPrivate *priv = map->priv;
+    tile_download_t *dl = g_new0(tile_download_t,1);
+
+    //calculate the uri to download
+    dl->uri = replace_map_uri(map, priv->repo_uri, zoom, x, y);
+
+    //check the tile has not already been queued for download,
+    //or has been attempted, and its missing
+    if (g_hash_table_lookup_extended(priv->tile_queue, dl->uri, NULL, NULL) ||
+        g_hash_table_lookup_extended(priv->missing_tiles, dl->uri, NULL, NULL) )
+    {
+        g_debug("Tile already downloading (or missing)");
+        g_free(dl->uri);
+        g_free(dl);
+    } else {
+        dl->folder = g_strdup_printf("%s/%d/%d/",priv->cache_dir, zoom, x);
+        dl->filename = g_strdup_printf("%s/%d/%d/%d.png",priv->cache_dir, zoom, x, y);
+        dl->map = map;
+        dl->redraw = redraw;
+
+        g_debug("Download tile: %d,%d z:%d\n\t%s --> %s", x, y, zoom, dl->uri, dl->filename);
+
+        msg = soup_message_new (SOUP_METHOD_GET, dl->uri);
+        if (msg) {
+            if (priv->the_google) {
+                //Set maps.google.com as the referrer
+                g_debug("Setting Google Referrer");
+                soup_message_headers_append(msg->request_headers, "Referer", "http://maps.google.com/");
+                //For google satelite also set the appropriate cookie value
+                if (priv->uri_format & URI_HAS_Q) {
+                    const char *cookie = g_getenv("GOOGLE_COOKIE");
+                    if (cookie) {
+                        g_debug("Adding Google Cookie");
+                        soup_message_headers_append(msg->request_headers, "Cookie", cookie);
+                    }
+                }
+            }
+
+            g_hash_table_insert (priv->tile_queue, dl->uri, msg);
+            soup_session_queue_message (priv->soup_session, msg, osm_gps_map_tile_download_complete, dl);
+        } else {
+            g_warning("Could not create soup message");
+            g_free(dl->uri);
+            g_free(dl->folder);
+            g_free(dl->filename);
+            g_free(dl);
+        }
+    }
+}
+
+static GdkPixbuf *
+osm_gps_map_load_cached_tile (OsmGpsMap *map, int zoom, int x, int y)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+    gchar *filename;
+    GdkPixbuf *pixbuf;
+    OsmCachedTile *tile;
+
+    filename = g_strdup_printf("%s/%u/%u/%u.png",
+                               priv->cache_dir,
+                               zoom, x, y);
+
+    tile = g_hash_table_lookup (priv->tile_cache, filename);
+    if (tile)
+    {
+        g_free (filename);
+    }
+    else
+    {
+        pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
+        if (pixbuf)
+        {
+            tile = g_slice_new (OsmCachedTile);
+            tile->pixbuf = pixbuf;
+            g_hash_table_insert (priv->tile_cache, filename, tile);
+        }
+    }
+
+    /* set/update the redraw_cycle timestamp on the tile */
+    if (tile)
+    {
+        tile->redraw_cycle = priv->redraw_cycle;
+        pixbuf = g_object_ref (tile->pixbuf);
+    }
+
+    return pixbuf;
+}
+
+static GdkPixbuf *
+osm_gps_map_find_bigger_tile (OsmGpsMap *map, int zoom, int x, int y,
+                              int *zoom_found)
+{
+    GdkPixbuf *pixbuf;
+    int next_zoom, next_x, next_y;
+
+    if (zoom == 0) return NULL;
+    next_zoom = zoom - 1;
+    next_x = x / 2;
+    next_y = y / 2;
+    pixbuf = osm_gps_map_load_cached_tile (map, next_zoom, next_x, next_y);
+    if (pixbuf)
+        *zoom_found = next_zoom;
+    else
+        pixbuf = osm_gps_map_find_bigger_tile (map, next_zoom, next_x, next_y,
+                                               zoom_found);
+    return pixbuf;
+}
+
+static GdkPixbuf *
+osm_gps_map_render_missing_tile_upscaled (OsmGpsMap *map, int zoom,
+                                          int x, int y)
+{
+    GdkPixbuf *pixbuf, *big, *area;
+    int zoom_big, zoom_diff, area_size, area_x, area_y;
+    int modulo;
+
+    big = osm_gps_map_find_bigger_tile (map, zoom, x, y, &zoom_big);
+    if (!big) return NULL;
+
+    g_debug ("Found bigger tile (zoom = %d, wanted = %d)", zoom_big, zoom);
+
+    /* get a Pixbuf for the area to magnify */
+    zoom_diff = zoom - zoom_big;
+    area_size = TILESIZE >> zoom_diff;
+    modulo = 1 << zoom_diff;
+    area_x = (x % modulo) * area_size;
+    area_y = (y % modulo) * area_size;
+    area = gdk_pixbuf_new_subpixbuf (big, area_x, area_y,
+                                     area_size, area_size);
+    g_object_unref (big);
+    pixbuf = gdk_pixbuf_scale_simple (area, TILESIZE, TILESIZE,
+                                      GDK_INTERP_NEAREST);
+    g_object_unref (area);
+    return pixbuf;
+}
+
+static GdkPixbuf *
+osm_gps_map_render_missing_tile (OsmGpsMap *map, int zoom, int x, int y)
+{
+    /* maybe TODO: render from downscaled tiles, if the following fails */
+    return osm_gps_map_render_missing_tile_upscaled (map, zoom, x, y);
+}
+
+static void
+osm_gps_map_load_tile (OsmGpsMap *map, int zoom, int x, int y, int offset_x, int offset_y)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+    gchar *filename;
+    GdkPixbuf *pixbuf;
+
+    g_debug("Load tile %d,%d (%d,%d) z:%d", x, y, offset_x, offset_y, zoom);
+
+    filename = g_strdup_printf("%s/%u/%u/%u.png",
+                               priv->cache_dir,
+                               zoom, x, y);
+
+    pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
+    if(pixbuf)
+    {
+        g_debug("Found tile %s", filename);
+        osm_gps_map_blit_tile(map, pixbuf, offset_x,offset_y);
+        g_object_unref (pixbuf);
+    }
+    else
+    {
+        if (priv->map_auto_download)
+            osm_gps_map_download_tile(map, zoom, x, y, TRUE);
+
+        /* try to render the tile by scaling cached tiles from other zoom
+         * levels */
+        pixbuf = osm_gps_map_render_missing_tile (map, zoom, x, y);
+        if (pixbuf)
+        {
+            gdk_draw_pixbuf (priv->pixmap,
+                             priv->gc_map,
+                             pixbuf,
+                             0,0,
+                             offset_x,offset_y,
+                             TILESIZE,TILESIZE,
+                             GDK_RGB_DITHER_NONE, 0, 0);
+            g_object_unref (pixbuf);
+        }
+        else
+        {
+            //prevent some artifacts when drawing not yet loaded areas.
+            gdk_draw_rectangle (priv->pixmap,
+                                GTK_WIDGET(map)->style->white_gc,
+                                TRUE, offset_x, offset_y, TILESIZE, TILESIZE);
+        }
+    }
+    g_free(filename);
+}
+
+static void
+osm_gps_map_fill_tiles_pixel (OsmGpsMap *map)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+    int i,j, width, height, tile_x0, tile_y0, tiles_nx, tiles_ny;
+    int offset_xn = 0;
+    int offset_yn = 0;
+    int offset_x;
+    int offset_y;
+
+    g_debug("Fill tiles: %d,%d z:%d", priv->map_x, priv->map_y, priv->map_zoom);
+
+    offset_x = - priv->map_x % TILESIZE;
+    offset_y = - priv->map_y % TILESIZE;
+    if (offset_x > 0) offset_x -= TILESIZE;
+    if (offset_y > 0) offset_y -= TILESIZE;
+
+    offset_xn = offset_x + EXTRA_BORDER;
+    offset_yn = offset_y + EXTRA_BORDER;
+
+    width  = GTK_WIDGET(map)->allocation.width;
+    height = GTK_WIDGET(map)->allocation.height;
+
+    tiles_nx = (width  - offset_x) / TILESIZE + 1;
+    tiles_ny = (height - offset_y) / TILESIZE + 1;
+
+    tile_x0 =  floor((float)priv->map_x / (float)TILESIZE);
+    tile_y0 =  floor((float)priv->map_y / (float)TILESIZE);
+
+    //TODO: implement wrap around
+    for (i=tile_x0; i<(tile_x0+tiles_nx);i++)
+    {
+        for (j=tile_y0;  j<(tile_y0+tiles_ny); j++)
+        {
+            if( j<0 || i<0 || i>=exp(priv->map_zoom * M_LN2) || j>=exp(priv->map_zoom * M_LN2))
+            {
+                gdk_draw_rectangle (priv->pixmap,
+                                    GTK_WIDGET(map)->style->white_gc,
+                                    TRUE,
+                                    offset_xn, offset_yn,
+                                    TILESIZE,TILESIZE);
+            }
+            else
+            {
+                osm_gps_map_load_tile(map,
+                                      priv->map_zoom,
+                                      i,j,
+                                      offset_xn,offset_yn);
+            }
+            offset_yn += TILESIZE;
+        }
+        offset_xn += TILESIZE;
+        offset_yn = offset_y + EXTRA_BORDER;
+    }
+}
+
+static void
+osm_gps_map_print_track (OsmGpsMap *map, GSList *trackpoint_list)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+
+    GSList *list;
+    int x,y;
+    int min_x = 0,min_y = 0,max_x = 0,max_y = 0;
+    int lw = priv->ui_gps_track_width;
+    int map_x0, map_y0;
+#ifdef USE_CAIRO
+    cairo_t *cr;
+#else
+    int last_x = 0, last_y = 0;
+    GdkColor color;
+    GdkGC *gc;
+#endif
+
+#ifdef USE_CAIRO
+    cr = gdk_cairo_create(priv->pixmap);
+    cairo_set_line_width (cr, lw);
+    cairo_set_source_rgba (cr, 60000.0/65535.0, 0.0, 0.0, 0.6);
+    cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+    cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+#else
+    gc = gdk_gc_new(priv->pixmap);
+    color.green = 0;
+    color.blue = 0;
+    color.red = 60000;
+    gdk_gc_set_rgb_fg_color(gc, &color);
+    gdk_gc_set_line_attributes(gc, lw, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+#endif
+
+    map_x0 = priv->map_x - EXTRA_BORDER;
+    map_y0 = priv->map_y - EXTRA_BORDER;
+    for(list = trackpoint_list; list != NULL; list = list->next)
+    {
+        coord_t *tp = list->data;
+
+        x = lon2pixel(priv->map_zoom, tp->rlon) - map_x0;
+        y = lat2pixel(priv->map_zoom, tp->rlat) - map_y0;
+
+        // first time through loop
+        if (list == trackpoint_list) {
+#ifdef USE_CAIRO
+            cairo_move_to(cr, x, y);
+#else
+            last_x = x;
+            last_y = y;
+#endif
+        }
+
+#ifdef USE_CAIRO
+        cairo_line_to(cr, x, y);
+#else
+        gdk_draw_line (priv->pixmap, gc, x, y, last_x, last_y);
+        last_x = x;
+        last_y = y;
+#endif
+
+        max_x = MAX(x,max_x);
+        min_x = MIN(x,min_x);
+        max_y = MAX(y,max_y);
+        min_y = MIN(y,min_y);
+    }
+
+    gtk_widget_queue_draw_area (
+                                GTK_WIDGET(map),
+                                min_x - lw,
+                                min_y - lw,
+                                max_x + (lw * 2),
+                                max_y + (lw * 2));
+
+#ifdef USE_CAIRO
+    cairo_stroke(cr);
+    cairo_destroy(cr);
+#else
+    g_object_unref(gc);
+#endif
+}
+
+/* Prints the gps trip history, and any other tracks */
+static void
+osm_gps_map_print_tracks (OsmGpsMap *map)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+
+    if (priv->show_trip_history)
+        osm_gps_map_print_track (map, priv->trip_history);
+    if (priv->tracks)
+    {
+        g_debug("TRACK");
+        GSList* tmp = priv->tracks;
+        while (tmp != NULL)
+        {
+            osm_gps_map_print_track (map, tmp->data);
+            tmp = g_slist_next(tmp);
+        }
+    }
+}
+
+static void
+osm_gps_map_purge_cache (OsmGpsMap *map)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+    GHashTableIter iter;
+    OsmCachedTile *tile;
+
+    if (g_hash_table_size (priv->tile_cache) < priv->max_tile_cache_size)
+        return;
+
+    /* run through the cache, and remove the tiles which have not been used
+     * during the last redraw operation */
+    g_hash_table_iter_init (&iter, priv->tile_cache);
+    while (g_hash_table_iter_next (&iter, NULL, (gpointer)&tile))
+    {
+        if (tile->redraw_cycle != priv->redraw_cycle)
+            g_hash_table_iter_remove (&iter);
+    }
+}
+
+static gboolean
+osm_gps_map_map_redraw (OsmGpsMap *map)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+
+    priv->idle_map_redraw = 0;
+
+    /* the motion_notify handler uses priv->pixmap to redraw the area; if we
+     * change it while we are dragging, we will end up showing it in the wrong
+     * place. This could be fixed by carefully recompute the coordinates, but
+     * for now it's easier just to disable redrawing the map while dragging */
+    if (priv->dragging)
+        return FALSE;
+
+    priv->redraw_cycle++;
+
+    /* draw white background to initialise pixmap */
+    gdk_draw_rectangle (
+                        priv->pixmap,
+                        GTK_WIDGET(map)->style->white_gc,
+                        TRUE,
+                        0, 0,
+                        GTK_WIDGET(map)->allocation.width + EXTRA_BORDER * 2,
+                        GTK_WIDGET(map)->allocation.height + EXTRA_BORDER * 2);
+
+    osm_gps_map_fill_tiles_pixel(map);
+
+    osm_gps_map_print_tracks(map);
+    osm_gps_map_draw_gps_point(map);
+    osm_gps_map_print_images(map);
+
+    //osm_gps_map_osd_speed(map, 1.5);
+    osm_gps_map_purge_cache(map);
+    gtk_widget_queue_draw (GTK_WIDGET (map));
+
+    return FALSE;
+}
+
+static void
+osm_gps_map_map_redraw_idle (OsmGpsMap *map)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+
+    if (priv->idle_map_redraw == 0)
+        priv->idle_map_redraw = g_idle_add ((GSourceFunc)osm_gps_map_map_redraw, map);
+}
+
+static void
+osm_gps_map_init (OsmGpsMap *object)
+{
+    OsmGpsMapPrivate *priv;
+
+    priv = G_TYPE_INSTANCE_GET_PRIVATE (object, OSM_TYPE_GPS_MAP, OsmGpsMapPrivate);
+    object->priv = priv;
+
+    priv->pixmap = NULL;
+
+    priv->trip_history = NULL;
+    priv->gps = g_new0(coord_t, 1);
+    priv->gps_valid = FALSE;
+
+    priv->tracks = NULL;
+    priv->images = NULL;
+
+    priv->drag_counter = 0;
+    priv->drag_mouse_dx = 0;
+    priv->drag_mouse_dy = 0;
+    priv->drag_start_mouse_x = 0;
+    priv->drag_start_mouse_y = 0;
+
+    priv->uri_format = 0;
+    priv->the_google = FALSE;
+
+    //Change naumber of concurrent connections option?
+    priv->soup_session = soup_session_async_new_with_options(
+                                                             SOUP_SESSION_USER_AGENT,
+                                                             "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11",
+                                                             NULL);
+
+    //Hash table which maps tile d/l URIs to SoupMessage requests
+    priv->tile_queue = g_hash_table_new (g_str_hash, g_str_equal);
+
+    //Some mapping providers (Google) have varying degrees of tiles at multiple
+    //zoom levels
+    priv->missing_tiles = g_hash_table_new (g_str_hash, g_str_equal);
+
+    /* memory cache for most recently used tiles */
+    priv->tile_cache = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                              g_free, (GDestroyNotify)cached_tile_free);
+    priv->max_tile_cache_size = 20;
+
+    gtk_widget_add_events (GTK_WIDGET (object),
+                           GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+                           GDK_POINTER_MOTION_MASK |
+                           GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
+    GTK_WIDGET_SET_FLAGS (object, GTK_CAN_FOCUS);
+
+    g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, my_log_handler, NULL);
+}
+
+static GObject *
+osm_gps_map_constructor (GType gtype, guint n_properties, GObjectConstructParam *properties)
+{
+    GObject *object;
+    OsmGpsMapPrivate *priv;
+
+    //Always chain up to the parent constructor
+    object = G_OBJECT_CLASS(osm_gps_map_parent_class)->constructor(gtype, n_properties, properties);
+    priv = OSM_GPS_MAP_PRIVATE(object);
+
+    if (!priv->cache_dir_is_full_path) {
+        char *md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, priv->repo_uri, -1);
+
+        if (priv->cache_dir) {
+            char *old = priv->cache_dir;
+            //the new cachedir is the given cache dir + the md5 of the repo_uri
+            priv->cache_dir = g_strdup_printf("%s/%s", old, md5);
+            g_debug("Adjusting cache dir %s -> %s", old, priv->cache_dir);
+            g_free(old);
+        } else {
+            //the new cachedir is the current dir + the md5 of the repo_uri
+            priv->cache_dir = g_strdup(md5);
+        }
+
+        g_free(md5);
+    }
+
+    return object;
+}
+
+static void
+osm_gps_map_dispose (GObject *object)
+{
+    OsmGpsMap *map = OSM_GPS_MAP(object);
+    OsmGpsMapPrivate *priv = map->priv;
+
+    if (priv->is_disposed)
+        return;
+
+    priv->is_disposed = TRUE;
+
+    soup_session_abort(priv->soup_session);
+    g_object_unref(priv->soup_session);
+
+    g_hash_table_destroy(priv->tile_queue);
+    g_hash_table_destroy(priv->missing_tiles);
+    g_hash_table_destroy(priv->tile_cache);
+
+    osm_gps_map_free_images(map);
+
+    if(priv->pixmap)
+        g_object_unref (priv->pixmap);
+
+    if(priv->gc_map)
+        g_object_unref(priv->gc_map);
+
+    if (priv->idle_map_redraw != 0)
+        g_source_remove (priv->idle_map_redraw);
+
+    G_OBJECT_CLASS (osm_gps_map_parent_class)->dispose (object);
+}
+
+static void
+osm_gps_map_finalize (GObject *object)
+{
+    OsmGpsMap *map = OSM_GPS_MAP(object);
+    OsmGpsMapPrivate *priv = map->priv;
+
+    g_free(priv->cache_dir);
+    g_free(priv->repo_uri);
+
+    osm_gps_map_free_trip(map);
+    osm_gps_map_free_tracks(map);
+
+    G_OBJECT_CLASS (osm_gps_map_parent_class)->finalize (object);
+}
+
+static void
+osm_gps_map_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+    g_return_if_fail (OSM_IS_GPS_MAP (object));
+    OsmGpsMap *map = OSM_GPS_MAP(object);
+    OsmGpsMapPrivate *priv = map->priv;
+
+    switch (prop_id)
+    {
+        case PROP_AUTO_CENTER:
+            priv->map_auto_center = g_value_get_boolean (value);
+            break;
+        case PROP_RECORD_TRIP_HISTORY:
+            priv->record_trip_history = g_value_get_boolean (value);
+            break;
+        case PROP_SHOW_TRIP_HISTORY:
+            priv->show_trip_history = g_value_get_boolean (value);
+            break;
+        case PROP_AUTO_DOWNLOAD:
+            priv->map_auto_download = g_value_get_boolean (value);
+            break;
+        case PROP_REPO_URI:
+            priv->repo_uri = g_value_dup_string (value);
+            inspect_map_uri(map);
+            break;
+        case PROP_PROXY_URI:
+            if ( g_value_get_string(value) ) {
+                GValue val = {0};
+
+                priv->proxy_uri = g_value_dup_string (value);
+                g_debug("Setting proxy server: %s", priv->proxy_uri);
+
+                SoupURI* uri = soup_uri_new(priv->proxy_uri);
+                g_value_init(&val, SOUP_TYPE_URI);
+                g_value_take_boxed(&val, uri);
+
+                g_object_set_property(G_OBJECT(priv->soup_session),SOUP_SESSION_PROXY_URI,&val);
+            } else
+                priv->proxy_uri = NULL;
+
+            break;
+        case PROP_TILE_CACHE_DIR:
+            priv->cache_dir = g_value_dup_string (value);
+            break;
+        case PROP_TILE_CACHE_DIR_IS_FULL_PATH:
+            priv->cache_dir_is_full_path = g_value_get_boolean (value);
+            break;
+        case PROP_ZOOM:
+            priv->map_zoom = g_value_get_int (value);
+            break;
+        case PROP_MAX_ZOOM:
+            priv->max_zoom = g_value_get_int (value);
+            break;
+        case PROP_MIN_ZOOM:
+            priv->min_zoom = g_value_get_int (value);
+            break;
+        case PROP_MAP_X:
+            priv->map_x = g_value_get_int (value);
+            priv->center_coord_set = FALSE;
+            break;
+        case PROP_MAP_Y:
+            priv->map_y = g_value_get_int (value);
+            priv->center_coord_set = FALSE;
+            break;
+        case PROP_GPS_TRACK_WIDTH:
+            priv->ui_gps_track_width = g_value_get_int (value);
+            break;
+        case PROP_GPS_POINT_R1:
+            priv->ui_gps_point_inner_radius = g_value_get_int (value);
+            break;
+        case PROP_GPS_POINT_R2:
+            priv->ui_gps_point_outer_radius = g_value_get_int (value);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static void
+osm_gps_map_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+    g_return_if_fail (OSM_IS_GPS_MAP (object));
+    float lat,lon;
+    OsmGpsMap *map = OSM_GPS_MAP(object);
+    OsmGpsMapPrivate *priv = map->priv;
+
+    switch (prop_id)
+    {
+        case PROP_AUTO_CENTER:
+            g_value_set_boolean(value, priv->map_auto_center);
+            break;
+        case PROP_RECORD_TRIP_HISTORY:
+            g_value_set_boolean(value, priv->record_trip_history);
+            break;
+        case PROP_SHOW_TRIP_HISTORY:
+            g_value_set_boolean(value, priv->show_trip_history);
+            break;
+        case PROP_AUTO_DOWNLOAD:
+            g_value_set_boolean(value, priv->map_auto_download);
+            break;
+        case PROP_REPO_URI:
+            g_value_set_string(value, priv->repo_uri);
+            break;
+        case PROP_PROXY_URI:
+            g_value_set_string(value, priv->proxy_uri);
+            break;
+        case PROP_TILE_CACHE_DIR:
+            g_value_set_string(value, priv->cache_dir);
+            break;
+        case PROP_TILE_CACHE_DIR_IS_FULL_PATH:
+            g_value_set_boolean(value, priv->cache_dir_is_full_path);
+            break;
+        case PROP_ZOOM:
+            g_value_set_int(value, priv->map_zoom);
+            break;
+        case PROP_MAX_ZOOM:
+            g_value_set_int(value, priv->max_zoom);
+            break;
+        case PROP_MIN_ZOOM:
+            g_value_set_int(value, priv->min_zoom);
+            break;
+        case PROP_LATITUDE:
+            lat = pixel2lat(priv->map_zoom,
+                            priv->map_y + (GTK_WIDGET(map)->allocation.height / 2));
+            g_value_set_float(value, rad2deg(lat));
+            break;
+        case PROP_LONGITUDE:
+            lon = pixel2lon(priv->map_zoom,
+                            priv->map_x + (GTK_WIDGET(map)->allocation.width / 2));
+            g_value_set_float(value, rad2deg(lon));
+            break;
+        case PROP_MAP_X:
+            g_value_set_int(value, priv->map_x);
+            break;
+        case PROP_MAP_Y:
+            g_value_set_int(value, priv->map_y);
+            break;
+        case PROP_TILES_QUEUED:
+            g_value_set_int(value, g_hash_table_size(priv->tile_queue));
+            break;
+        case PROP_GPS_TRACK_WIDTH:
+            g_value_set_int(value, priv->ui_gps_track_width);
+            break;
+        case PROP_GPS_POINT_R1:
+            g_value_set_int(value, priv->ui_gps_point_inner_radius);
+            break;
+        case PROP_GPS_POINT_R2:
+            g_value_set_int(value, priv->ui_gps_point_outer_radius);
+            break;
+        default:
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+            break;
+    }
+}
+
+static gboolean
+_osm_gps_map_scroll (GtkWidget *widget, GdkEventScroll  *event)
+{
+    OsmGpsMap *map = OSM_GPS_MAP(widget);
+    OsmGpsMapPrivate *priv = map->priv;
+
+    if (event->direction == GDK_SCROLL_UP)
+    {
+        osm_gps_map_set_zoom(map, priv->map_zoom+1);
+    }
+    else
+    {
+        osm_gps_map_set_zoom(map, priv->map_zoom-1);
+    }
+
+    return FALSE;
+}
+
+static gboolean
+osm_gps_map_button_press (GtkWidget *widget, GdkEventButton *event)
+{
+    OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
+
+    priv->drag_counter = 0;
+    priv->drag_start_mouse_x = (int) event->x;
+    priv->drag_start_mouse_y = (int) event->y;
+    priv->drag_start_map_x = priv->map_x;
+    priv->drag_start_map_y = priv->map_y;
+
+    return FALSE;
+}
+
+static gboolean
+osm_gps_map_button_release (GtkWidget *widget, GdkEventButton *event)
+{
+    OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
+
+    if (priv->dragging)
+    {
+        priv->dragging = FALSE;
+
+        priv->map_x = priv->drag_start_map_x;
+        priv->map_y = priv->drag_start_map_y;
+
+        priv->map_x += (priv->drag_start_mouse_x - (int) event->x);
+        priv->map_y += (priv->drag_start_mouse_y - (int) event->y);
+
+        priv->center_coord_set = FALSE;
+
+        osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
+    }
+
+    priv->drag_mouse_dx = 0;
+    priv->drag_mouse_dy = 0;
+    priv->drag_counter = 0;
+
+    return FALSE;
+}
+
+static gboolean
+osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion  *event)
+{
+    int x, y;
+    GdkModifierType state;
+    OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
+
+    if (event->is_hint)
+        gdk_window_get_pointer (event->window, &x, &y, &state);
+    else
+    {
+        x = event->x;
+        y = event->y;
+        state = event->state;
+    }
+
+    // are we being dragged
+    if (!(state & GDK_BUTTON1_MASK))
+        return FALSE;
+
+    priv->drag_counter++;
+
+    // we havent dragged more than 6 pixels
+    if (priv->drag_counter < 6)
+        return FALSE;
+
+    priv->dragging = TRUE;
+
+    if (priv->map_auto_center)
+        g_object_set(G_OBJECT(widget), "auto-center", FALSE, NULL);
+
+    priv->drag_mouse_dx = x - priv->drag_start_mouse_x;
+    priv->drag_mouse_dy = y - priv->drag_start_mouse_y;
+
+    gdk_draw_drawable (
+                       widget->window,
+                       widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+                       priv->pixmap,
+                       0,0,
+                       priv->drag_mouse_dx - EXTRA_BORDER, priv->drag_mouse_dy - EXTRA_BORDER,
+                       -1,-1);
+
+    //Paint white outside of the map if dragging. Its less
+    //ugly than painting the corrupted map
+    if(priv->drag_mouse_dx>EXTRA_BORDER) {
+        gdk_draw_rectangle (
+                            widget->window,
+                            widget->style->white_gc,
+                            TRUE,
+                            0, 0,
+                            priv->drag_mouse_dx - EXTRA_BORDER,
+                            widget->allocation.height);
+    }
+    else if (-priv->drag_mouse_dx > EXTRA_BORDER)
+    {
+        gdk_draw_rectangle (
+                            widget->window,
+                            widget->style->white_gc,
+                            TRUE,
+                            priv->drag_mouse_dx + widget->allocation.width + EXTRA_BORDER, 0,
+                            -priv->drag_mouse_dx - EXTRA_BORDER,
+                            widget->allocation.height);
+    }
+
+    if (priv->drag_mouse_dy>EXTRA_BORDER) {
+        gdk_draw_rectangle (
+                            widget->window,
+                            widget->style->white_gc,
+                            TRUE,
+                            0, 0,
+                            widget->allocation.width,
+                            priv->drag_mouse_dy - EXTRA_BORDER);
+    }
+    else if (-priv->drag_mouse_dy > EXTRA_BORDER)
+    {
+        gdk_draw_rectangle (
+                            widget->window,
+                            widget->style->white_gc,
+                            TRUE,
+                            0, priv->drag_mouse_dy + widget->allocation.height + EXTRA_BORDER,
+                            widget->allocation.width,
+                            -priv->drag_mouse_dy - EXTRA_BORDER);
+    }
+
+    return FALSE;
+}
+
+static gboolean
+osm_gps_map_configure (GtkWidget *widget, GdkEventConfigure *event)
+{
+    OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
+
+    /* create pixmap */
+    if (priv->pixmap)
+        g_object_unref (priv->pixmap);
+
+    priv->pixmap = gdk_pixmap_new (
+                                   widget->window,
+                                   widget->allocation.width + EXTRA_BORDER * 2,
+                                   widget->allocation.height + EXTRA_BORDER * 2,
+                                   -1);
+
+    /* and gc, used for clipping (I think......) */
+    if(priv->gc_map)
+        g_object_unref(priv->gc_map);
+
+    priv->gc_map = gdk_gc_new(priv->pixmap);
+
+    osm_gps_map_map_redraw(OSM_GPS_MAP(widget));
+
+    return FALSE;
+}
+
+static gboolean
+osm_gps_map_expose (GtkWidget *widget, GdkEventExpose  *event)
+{
+    OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
+
+    gdk_draw_drawable (
+                       widget->window,
+                       widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+                       priv->pixmap,
+                       event->area.x + EXTRA_BORDER, event->area.y + EXTRA_BORDER,
+                       event->area.x, event->area.y,
+                       event->area.width, event->area.height);
+
+    return FALSE;
+}
+
+static void
+osm_gps_map_class_init (OsmGpsMapClass *klass)
+{
+    GObjectClass* object_class = G_OBJECT_CLASS (klass);
+    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+    g_type_class_add_private (klass, sizeof (OsmGpsMapPrivate));
+
+    object_class->dispose = osm_gps_map_dispose;
+    object_class->finalize = osm_gps_map_finalize;
+    object_class->constructor = osm_gps_map_constructor;
+    object_class->set_property = osm_gps_map_set_property;
+    object_class->get_property = osm_gps_map_get_property;
+
+    widget_class->expose_event = osm_gps_map_expose;
+    widget_class->configure_event = osm_gps_map_configure;
+    widget_class->button_press_event = osm_gps_map_button_press;
+    widget_class->button_release_event = osm_gps_map_button_release;
+    widget_class->motion_notify_event = osm_gps_map_motion_notify;
+    widget_class->scroll_event = _osm_gps_map_scroll;
+
+    g_object_class_install_property (object_class,
+                                     PROP_AUTO_CENTER,
+                                     g_param_spec_boolean ("auto-center",
+                                                           "auto center",
+                                                           "map auto center",
+                                                           TRUE,
+                                                           G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+    g_object_class_install_property (object_class,
+                                     PROP_RECORD_TRIP_HISTORY,
+                                     g_param_spec_boolean ("record-trip-history",
+                                                           "record trip history",
+                                                           "should all gps points be recorded in a trip history",
+                                                           TRUE,
+                                                           G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+    g_object_class_install_property (object_class,
+                                     PROP_SHOW_TRIP_HISTORY,
+                                     g_param_spec_boolean ("show-trip-history",
+                                                           "show trip history",
+                                                           "should the recorded trip history be shown on the map",
+                                                           TRUE,
+                                                           G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+    g_object_class_install_property (object_class,
+                                     PROP_AUTO_DOWNLOAD,
+                                     g_param_spec_boolean ("auto-download",
+                                                           "auto download",
+                                                           "map auto download",
+                                                           TRUE,
+                                                           G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+    g_object_class_install_property (object_class,
+                                     PROP_REPO_URI,
+                                     g_param_spec_string ("repo-uri",
+                                                          "repo uri",
+                                                          "osm repo uri",
+                                                          "http://tile.openstreetmap.org/#Z/#X/#Y.png",
+                                                          G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property (object_class,
+                                     PROP_PROXY_URI,
+                                     g_param_spec_string ("proxy-uri",
+                                                          "proxy uri",
+                                                          "http proxy uri on NULL",
+                                                          NULL,
+                                                          G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property (object_class,
+                                     PROP_TILE_CACHE_DIR,
+                                     g_param_spec_string ("tile-cache",
+                                                          "tile cache",
+                                                          "osm local tile cache dir",
+                                                          "/tmp/Maps",
+                                                          G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property (object_class,
+                                     PROP_TILE_CACHE_DIR_IS_FULL_PATH,
+                                     g_param_spec_boolean ("tile-cache-is-full-path",
+                                                           "tile cache is full path",
+                                                           "if true, the path passed to tile-cache is interpreted as the full cache path",
+                                                           FALSE,
+                                                           G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property (object_class,
+                                     PROP_ZOOM,
+                                     g_param_spec_int ("zoom",
+                                                       "zoom",
+                                                       "zoom level",
+                                                       MIN_ZOOM, /* minimum property value */
+                                                       MAX_ZOOM, /* maximum property value */
+                                                       3,
+                                                       G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property (object_class,
+                                     PROP_MAX_ZOOM,
+                                     g_param_spec_int ("max-zoom",
+                                                       "max zoom",
+                                                       "maximum zoom level",
+                                                       MIN_ZOOM, /* minimum property value */
+                                                       MAX_ZOOM, /* maximum property value */
+                                                       17,
+                                                       G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property (object_class,
+                                     PROP_MIN_ZOOM,
+                                     g_param_spec_int ("min-zoom",
+                                                       "min zoom",
+                                                       "minimum zoom level",
+                                                       MIN_ZOOM, /* minimum property value */
+                                                       MAX_ZOOM, /* maximum property value */
+                                                       1,
+                                                       G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property (object_class,
+                                     PROP_LATITUDE,
+                                     g_param_spec_float ("latitude",
+                                                         "latitude",
+                                                         "latitude in degrees",
+                                                         -90.0, /* minimum property value */
+                                                         90.0, /* maximum property value */
+                                                         0,
+                                                         G_PARAM_READABLE));
+
+    g_object_class_install_property (object_class,
+                                     PROP_LONGITUDE,
+                                     g_param_spec_float ("longitude",
+                                                         "longitude",
+                                                         "longitude in degrees",
+                                                         -180.0, /* minimum property value */
+                                                         180.0, /* maximum property value */
+                                                         0,
+                                                         G_PARAM_READABLE));
+
+    g_object_class_install_property (object_class,
+                                     PROP_MAP_X,
+                                     g_param_spec_int ("map-x",
+                                                       "map-x",
+                                                       "initial map x location",
+                                                       G_MININT, /* minimum property value */
+                                                       G_MAXINT, /* maximum property value */
+                                                       890,
+                                                       G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property (object_class,
+                                     PROP_MAP_Y,
+                                     g_param_spec_int ("map-y",
+                                                       "map-y",
+                                                       "initial map y location",
+                                                       G_MININT, /* minimum property value */
+                                                       G_MAXINT, /* maximum property value */
+                                                       515,
+                                                       G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+    g_object_class_install_property (object_class,
+                                     PROP_TILES_QUEUED,
+                                     g_param_spec_int ("tiles-queued",
+                                                       "tiles-queued",
+                                                       "number of tiles currently waiting to download",
+                                                       G_MININT, /* minimum property value */
+                                                       G_MAXINT, /* maximum property value */
+                                                       0,
+                                                       G_PARAM_READABLE));
+
+    g_object_class_install_property (object_class,
+                                     PROP_GPS_TRACK_WIDTH,
+                                     g_param_spec_int ("gps-track-width",
+                                                       "gps-track-width",
+                                                       "width of the lines drawn for the gps track",
+                                                       1,           /* minimum property value */
+                                                       G_MAXINT,    /* maximum property value */
+                                                       4,
+                                                       G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+    g_object_class_install_property (object_class,
+                                     PROP_GPS_POINT_R1,
+                                     g_param_spec_int ("gps-track-point-radius",
+                                                       "gps-track-point-radius",
+                                                       "radius of the gps point inner circle",
+                                                       0,           /* minimum property value */
+                                                       G_MAXINT,    /* maximum property value */
+                                                       5,
+                                                       G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+    g_object_class_install_property (object_class,
+                                     PROP_GPS_POINT_R2,
+                                     g_param_spec_int ("gps-track-highlight-radius",
+                                                       "gps-track-highlight-radius",
+                                                       "radius of the gps point highlight circle",
+                                                       0,           /* minimum property value */
+                                                       G_MAXINT,    /* maximum property value */
+                                                       20,
+                                                       G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
+
+}
+
+void
+osm_gps_map_download_maps (OsmGpsMap *map, coord_t *pt1, coord_t *pt2, int zoom_start, int zoom_end)
+{
+    int i,j,zoom,num_tiles;
+    OsmGpsMapPrivate *priv = map->priv;
+
+    if (pt1 && pt2)
+    {
+        gchar *filename;
+        num_tiles = 0;
+        zoom_end = CLAMP(zoom_end, priv->min_zoom, priv->max_zoom);
+        g_debug("Download maps: z:%d->%d",zoom_start, zoom_end);
+
+        for(zoom=zoom_start; zoom<=zoom_end; zoom++)
+        {
+            int x1,y1,x2,y2;
+
+            x1 = (int)floor((float)lon2pixel(zoom, pt1->rlon) / (float)TILESIZE);
+            y1 = (int)floor((float)lat2pixel(zoom, pt1->rlat) / (float)TILESIZE);
+
+            x2 = (int)floor((float)lon2pixel(zoom, pt2->rlon) / (float)TILESIZE);
+            y2 = (int)floor((float)lat2pixel(zoom, pt2->rlat) / (float)TILESIZE);
+
+            // loop x1-x2
+            for(i=x1; i<=x2; i++)
+            {
+                // loop y1 - y2
+                for(j=y1; j<=y2; j++)
+                {
+                    // x = i, y = j
+                    filename = g_strdup_printf("%s/%u/%u/%u.png", priv->cache_dir, zoom, i, j);
+                    if (!g_file_test(filename, G_FILE_TEST_EXISTS))
+                    {
+                        osm_gps_map_download_tile(map, zoom, i, j, FALSE);
+                        num_tiles++;
+                    }
+                    g_free(filename);
+                }
+            }
+            g_debug("DL @Z:%d = %d tiles",zoom,num_tiles);
+        }
+    }
+}
+
+void
+osm_gps_map_get_bbox (OsmGpsMap *map, coord_t *pt1, coord_t *pt2)
+{
+    OsmGpsMapPrivate *priv = map->priv;
+
+    if (pt1 && pt2) {
+        pt1->rlat = pixel2lat(priv->map_zoom, priv->map_y);
+        pt1->rlon = pixel2lon(priv->map_zoom, priv->map_x);
+        pt2->rlat = pixel2lat(priv->map_zoom, priv->map_y + GTK_WIDGET(map)->allocation.height);
+        pt2->rlon = pixel2lon(priv->map_zoom, priv->map_x + GTK_WIDGET(map)->allocation.width);
+
+        g_debug("BBOX: %f %f %f %f", pt1->rlat, pt1->rlon, pt2->rlat, pt2->rlon);
+    }
+}
+
+void
+osm_gps_map_set_mapcenter (OsmGpsMap *map, float latitude, float longitude, int zoom)
+{
+    osm_gps_map_set_center (map, latitude, longitude);
+    osm_gps_map_set_zoom (map, zoom);
+}
+
+void
+osm_gps_map_set_center (OsmGpsMap *map, float latitude, float longitude)
+{
+    int pixel_x, pixel_y;
+    OsmGpsMapPrivate *priv;
+
+    g_return_if_fail (OSM_IS_GPS_MAP (map));
+    priv = map->priv;
+
+    priv->center_rlat = deg2rad(latitude);
+    priv->center_rlon = deg2rad(longitude);
+    priv->center_coord_set = TRUE;
+
+    // pixel_x,y, offsets
+    pixel_x = lon2pixel(priv->map_zoom, priv->center_rlon);
+    pixel_y = lat2pixel(priv->map_zoom, priv->center_rlat);
+
+    priv->map_x = pixel_x - GTK_WIDGET(map)->allocation.width/2;
+    priv->map_y = pixel_y - GTK_WIDGET(map)->allocation.height/2;
+
+    osm_gps_map_map_redraw_idle(map);
+}
+
+int 
+osm_gps_map_set_zoom (OsmGpsMap *map, int zoom)
+{
+    int zoom_old;
+    double factor;
+    int width_center, height_center;
+    OsmGpsMapPrivate *priv;
+
+    g_return_val_if_fail (OSM_IS_GPS_MAP (map), 0);
+    priv = map->priv;
+
+    if (zoom != priv->map_zoom)
+    {
+        width_center  = GTK_WIDGET(map)->allocation.width / 2;
+        height_center = GTK_WIDGET(map)->allocation.height / 2;
+
+        zoom_old = priv->map_zoom;
+        //constrain zoom min_zoom -> max_zoom
+        priv->map_zoom = CLAMP(zoom, priv->min_zoom, priv->max_zoom);
+
+        if (priv->center_coord_set)
+        {
+            priv->map_x = lon2pixel(priv->map_zoom, priv->center_rlon) - width_center;
+            priv->map_y = lat2pixel(priv->map_zoom, priv->center_rlat) - height_center;
+        }
+        else
+        {
+            factor = exp(priv->map_zoom * M_LN2)/exp(zoom_old * M_LN2);
+            priv->map_x = ((priv->map_x + width_center) * factor) - width_center;
+            priv->map_y = ((priv->map_y + height_center) * factor) - height_center;
+        }
+
+        g_debug("Zoom changed from %d to %d factor:%f x:%d",
+                zoom_old, priv->map_zoom, factor, priv->map_x);
+
+        osm_gps_map_map_redraw_idle(map);
+    }
+    return priv->map_zoom;
+}
+
+void
+osm_gps_map_add_track (OsmGpsMap *map, GSList *track)
+{
+    OsmGpsMapPrivate *priv;
+
+    g_return_if_fail (OSM_IS_GPS_MAP (map));
+    priv = map->priv;
+
+    if (track) {
+        priv->tracks = g_slist_append(priv->tracks, track);
+        osm_gps_map_map_redraw_idle(map);
+    }
+}
+
+void
+osm_gps_map_clear_tracks (OsmGpsMap *map)
+{
+    g_return_if_fail (OSM_IS_GPS_MAP (map));
+
+    osm_gps_map_free_tracks(map);
+    osm_gps_map_map_redraw_idle(map);
+}
+
+void
+osm_gps_map_add_image (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image)
+{
+    g_return_if_fail (OSM_IS_GPS_MAP (map));
+
+    if (image) {
+        OsmGpsMapPrivate *priv = map->priv;
+        image_t *im;
+
+        //cache w/h for speed, and add image to list
+        im = g_new0(image_t,1);
+        im->w = gdk_pixbuf_get_width(image);
+        im->h = gdk_pixbuf_get_width(image);
+        im->pt.rlat = deg2rad(latitude);
+        im->pt.rlon = deg2rad(longitude);
+
+        g_object_ref(image);
+        im->image = image;
+
+        priv->images = g_slist_append(priv->images, im);
+
+        osm_gps_map_map_redraw_idle(map);
+    }
+}
+
+void
+osm_gps_map_clear_images (OsmGpsMap *map)
+{
+    g_return_if_fail (OSM_IS_GPS_MAP (map));
+
+    osm_gps_map_free_images(map);
+    osm_gps_map_map_redraw_idle(map);
+}
+
+void
+osm_gps_map_osd_speed (OsmGpsMap *map, float speed)
+{
+    OsmGpsMapPrivate *priv;
+
+    PangoContext        *context = NULL;
+    PangoLayout     *layout  = NULL;
+    PangoFontDescription    *desc    = NULL;
+
+    GdkColor color;
+    GdkGC *gc;
+
+    gchar *buffer;
+    //static int x = 10, y = 10;
+    static int width = 0, height = 0;
+
+    g_return_if_fail (OSM_IS_GPS_MAP (map));
+    priv = map->priv;
+
+    buffer = g_strdup_printf("%.0f", speed);
+
+    /* pango initialisation */
+    context = gtk_widget_get_pango_context (GTK_WIDGET(map));
+    layout  = pango_layout_new (context);
+    desc    = pango_font_description_new();
+
+    pango_font_description_set_size (desc, 40 * PANGO_SCALE);
+    pango_layout_set_font_description (layout, desc);
+    pango_layout_set_text (layout, buffer, strlen(buffer));
+
+    gc = gdk_gc_new (GTK_WIDGET(map)->window);
+
+    color.red = (0 > 50) ? 0xffff : 0;
+    color.green = 0;
+    color.blue = 0;
+
+    gdk_gc_set_rgb_fg_color (gc, &color);
+
+    /* faster / less flicker alternative:*/
+    gdk_draw_drawable (
+                       GTK_WIDGET(map)->window,
+                       GTK_WIDGET(map)->style->fg_gc[GTK_WIDGET_STATE(map)],
+                       priv->pixmap,
+                       0,0,
+                       0,0,
+                       width+10,width+10);
+
+    gdk_draw_layout(GTK_WIDGET(map)->window,
+                    gc,
+                    0, 0,
+                    layout);
+
+    /* set width and height */
+    pango_layout_get_pixel_size(layout, &width, &height);
+
+    g_free(buffer);
+    pango_font_description_free (desc);
+    g_object_unref (layout);
+    g_object_unref (gc);
+}
+
+void
+osm_gps_map_draw_gps (OsmGpsMap *map, float latitude, float longitude, float heading)
+{
+    int pixel_x, pixel_y;
+    OsmGpsMapPrivate *priv;
+
+    g_return_if_fail (OSM_IS_GPS_MAP (map));
+    priv = map->priv;
+
+    priv->gps->rlat = deg2rad(latitude);
+    priv->gps->rlon = deg2rad(longitude);
+    priv->gps_valid = TRUE;
+
+    // pixel_x,y, offsets
+    pixel_x = lon2pixel(priv->map_zoom, priv->gps->rlon);
+    pixel_y = lat2pixel(priv->map_zoom, priv->gps->rlat);
+
+    //If trip marker add to list of gps points.
+    if (priv->record_trip_history) {
+        coord_t *tp = g_new0(coord_t,1);
+        tp->rlat = priv->gps->rlat;
+        tp->rlon = priv->gps->rlon;
+        priv->trip_history = g_slist_append(priv->trip_history, tp);
+    }
+
+    // dont draw anything if we are dragging
+    if (priv->dragging) {
+        g_debug("Dragging");
+        return;
+    }
+
+    //Automatically center the map if the track approaches the edge
+    if(priv->map_auto_center)   {
+        int x = pixel_x - priv->map_x;
+        int y = pixel_y - priv->map_y;
+        int width = GTK_WIDGET(map)->allocation.width;
+        int height = GTK_WIDGET(map)->allocation.height;
+        if( x < (width/2 - width/8)     || x > (width/2 + width/8)  ||
+            y < (height/2 - height/8)   || y > (height/2 + height/8)) {
+
+            priv->map_x = pixel_x - GTK_WIDGET(map)->allocation.width/2;
+            priv->map_y = pixel_y - GTK_WIDGET(map)->allocation.height/2;
+            priv->center_coord_set = FALSE;
+        }
+    }
+
+    // this redraws the map (including the gps track, and adjusts the
+    // map center if it was changed
+    osm_gps_map_map_redraw_idle(map);
+}
+
+void
+osm_gps_map_clear_gps (OsmGpsMap *map)
+{
+    osm_gps_map_free_trip(map);
+    osm_gps_map_map_redraw_idle(map);
+}
+
+coord_t
+osm_gps_map_get_co_ordinates (OsmGpsMap *map, int pixel_x, int pixel_y)
+{
+    coord_t coord;
+    OsmGpsMapPrivate *priv = map->priv;
+
+    coord.rlat = pixel2lat(priv->map_zoom, priv->map_y + pixel_y);
+    coord.rlon = pixel2lon(priv->map_zoom, priv->map_x + pixel_x);
+    return coord;
+}
+
+GtkWidget *
+osm_gps_map_new (void)
+{
+    return g_object_new (OSM_TYPE_GPS_MAP, NULL);
+}
+
+void
+osm_gps_map_screen_to_geographic (OsmGpsMap *map, gint pixel_x, gint pixel_y,
+                                  gfloat *latitude, gfloat *longitude)
+{
+    OsmGpsMapPrivate *priv;
+
+    g_return_if_fail (OSM_IS_GPS_MAP (map));
+    priv = map->priv;
+
+    if (latitude)
+        *latitude = rad2deg(pixel2lat(priv->map_zoom, priv->map_y + pixel_y));
+    if (longitude)
+        *longitude = rad2deg(pixel2lon(priv->map_zoom, priv->map_x + pixel_x));
+}
+
+void
+osm_gps_map_geographic_to_screen (OsmGpsMap *map,
+                                  gfloat latitude, gfloat longitude,
+                                  gint *pixel_x, gint *pixel_y)
+{
+    OsmGpsMapPrivate *priv;
+
+    g_return_if_fail (OSM_IS_GPS_MAP (map));
+    priv = map->priv;
+
+    if (pixel_x)
+        *pixel_x = lon2pixel(priv->map_zoom, deg2rad(longitude)) - priv->map_x;
+    if (pixel_y)
+        *pixel_y = lat2pixel(priv->map_zoom, deg2rad(latitude)) - priv->map_y;
+}
+
+void
+osm_gps_map_scroll (OsmGpsMap *map, gint dx, gint dy)
+{
+    OsmGpsMapPrivate *priv;
+
+    g_return_if_fail (OSM_IS_GPS_MAP (map));
+    priv = map->priv;
+
+    priv->center_coord_set = FALSE;
+    priv->map_x += dx;
+    priv->map_y += dy;
+
+    osm_gps_map_map_redraw_idle (map);
+}
+
diff --git a/src/osm-gps-map.h b/src/osm-gps-map.h
new file mode 100644
index 0000000..1069976
--- /dev/null
+++ b/src/osm-gps-map.h
@@ -0,0 +1,103 @@
+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
+/* vim:set et sw=4 ts=4 cino=t0,(0: */
+/*
+ * osm-gps-map.h
+ * Copyright (C) Marcus Bauer 2008 <marcus.bauer at gmail.com>
+ * Copyright (C) John Stowers 2009 <john.stowers at gmail.com>
+ *
+ * Contributions by
+ * Everaldo Canuto 2009 <everaldo.canuto at gmail.com>
+ *
+ * osm-gps-map.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * osm-gps-map.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _OSM_GPS_MAP_H_
+#define _OSM_GPS_MAP_H_
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+G_BEGIN_DECLS
+
+#define OSM_TYPE_GPS_MAP             (osm_gps_map_get_type ())
+#define OSM_GPS_MAP(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), OSM_TYPE_GPS_MAP, OsmGpsMap))
+#define OSM_GPS_MAP_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), OSM_TYPE_GPS_MAP, OsmGpsMapClass))
+#define OSM_IS_GPS_MAP(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OSM_TYPE_GPS_MAP))
+#define OSM_IS_GPS_MAP_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), OSM_TYPE_GPS_MAP))
+#define OSM_GPS_MAP_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), OSM_TYPE_GPS_MAP, OsmGpsMapClass))
+
+typedef struct _OsmGpsMapClass OsmGpsMapClass;
+typedef struct _OsmGpsMap OsmGpsMap;
+typedef struct _OsmGpsMapPrivate OsmGpsMapPrivate;
+
+struct _OsmGpsMapClass
+{
+    GtkDrawingAreaClass parent_class;
+};
+
+struct _OsmGpsMap
+{
+    GtkDrawingArea parent_instance;
+    OsmGpsMapPrivate *priv;
+};
+
+typedef struct {
+    float rlat;
+    float rlon;
+} coord_t;
+
+//http://www.internettablettalk.com/forums/showthread.php?t=5209
+//https://garage.maemo.org/plugins/scmsvn/viewcvs.php/trunk/src/maps.c
+//http://www.ponies.me.uk/maps/GoogleTileUtils.java
+//http://www.mgmaps.com/cache/MapTileCacher.perl
+#define MAP_SOURCE_OPENSTREETMAP            "http://tile.openstreetmap.org/#Z/#X/#Y.png"
+#define MAP_SOURCE_OPENSTREETMAP_RENDERER   "http://tah.openstreetmap.org/Tiles/tile/#Z/#X/#Y.png"
+#define MAP_SOURCE_OPENAERIALMAP            "http://tile.openaerialmap.org/tiles/1.0.0/openaerialmap-900913/#Z/#X/#Y.jpg"
+#define MAP_SOURCE_GOOGLE_MAPS              "http://mt#R.google.com/mt?x=#X&y=#Y&zoom=#S"
+//No longer working
+//#define MAP_SOURCE_GOOGLE_HYBRID          "http://mt#R.google.com/mt?n=404&v=w2t.99&x=#X&y=#Y&zoom=#S"
+#define MAP_SOURCE_GOOGLE_HYBRID            "http://mt#R.google.com/mt?x=#X&y=#Y&zoom=#S"
+#define MAP_SOURCE_GOOGLE_SATTELITE         "http://khm#R.google.com/kh?n=404&v=32&x=#X&y=#Y&z=#Z"
+#define MAP_SOURCE_GOOGLE_SATTELITE_QUAD    "http://khm#R.google.com/kh?n=404&v=3&t=#Q"
+#define MAP_SOURCE_MAPS_FOR_FREE            "http://maps-for-free.com/layer/relief/z#Z/row#Y/#Z_#X-#Y.jpg"
+#define MAP_SOURCE_VIRTUAL_EARTH_SATTELITE  "http://a#R.ortho.tiles.virtualearth.net/tiles/a#W.jpeg?g=50"
+
+GType osm_gps_map_get_type (void) G_GNUC_CONST;
+void osm_gps_map_download_maps (OsmGpsMap *map, coord_t *pt1, coord_t *pt2, int zoom_start, int zoom_end);
+void osm_gps_map_get_bbox (OsmGpsMap *map, coord_t *pt1, coord_t *pt2);
+void osm_gps_map_set_mapcenter (OsmGpsMap *map, float latitude, float longitude, int zoom);
+void osm_gps_map_set_center (OsmGpsMap *map, float latitude, float longitude);
+int osm_gps_map_set_zoom (OsmGpsMap *map, int zoom);
+void osm_gps_map_add_track (OsmGpsMap *map, GSList *track);
+void osm_gps_map_clear_tracks (OsmGpsMap *map);
+void osm_gps_map_add_image (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image);
+void osm_gps_map_clear_images (OsmGpsMap *map);
+void osm_gps_map_osd_speed (OsmGpsMap *map, float speed);
+void osm_gps_map_draw_gps (OsmGpsMap *map, float latitude, float longitude, float heading);
+void osm_gps_map_clear_gps (OsmGpsMap *map);
+coord_t osm_gps_map_get_co_ordinates (OsmGpsMap *map, int pixel_x, int pixel_y);
+GtkWidget * osm_gps_map_new(void);
+void osm_gps_map_screen_to_geographic (OsmGpsMap *map,
+                                       gint pixel_x, gint pixel_y,
+                                       gfloat *latitude, gfloat *longitude);
+void osm_gps_map_geographic_to_screen (OsmGpsMap *map,
+                                       gfloat latitude, gfloat longitude,
+                                       gint *pixel_x, gint *pixel_y);
+void osm_gps_map_scroll (OsmGpsMap *map, gint dx, gint dy);
+
+G_END_DECLS
+
+#endif /* _OSM_GPS_MAP_H_ */
diff --git a/src/poi.png b/src/poi.png
new file mode 100644
index 0000000..4ab54c9
Binary files /dev/null and b/src/poi.png differ

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



More information about the Pkg-grass-devel mailing list