[osm-gps-map] 29/153: Imported Upstream version 0.5

Ross Gammon ross-guest at moszumanska.debian.org
Tue May 13 19:58:57 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 2de6a6e7f4c662e90ffc2e83849d9a590edc3d18
Author: David Paleino <dapal at debian.org>
Date:   Fri Jan 22 17:28:11 2010 +0100

    Imported Upstream version 0.5
---
 .gitignore                                        |   5 +-
 COPYING                                           | 674 +++++++++++++++
 Makefile.am                                       |  12 +-
 NEWS                                              |  19 +
 README                                            |   8 +-
 configure.ac                                      |  42 +-
 python/Makefile.am                                |   9 +-
 python/configure.ac                               |  10 +-
 python/{openstreetmap-gps-map.py => mapviewer.py} |  41 +-
 python/osmgpsmap.defs                             | 118 ++-
 python/osmgpsmapmodule.c                          |   7 +
 python/setup.py                                   |   4 +-
 src/Makefile.am                                   |  22 +-
 src/main.c                                        |  48 +-
 src/osm-gps-map-types.h                           |   5 +
 src/osm-gps-map.c                                 | 970 +++++++++++++---------
 src/osm-gps-map.h                                 |  90 +-
 17 files changed, 1560 insertions(+), 524 deletions(-)

diff --git a/.gitignore b/.gitignore
index 6527261..7aa6331 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@
 *.o
 *.deps/
 *.libs/
+*.tar.gz
 INSTALL
 Makefile
 autom4te.cache/
@@ -28,7 +29,7 @@ python/build/
 python/configure
 python/osmgpsmap.c
 src/Makefile
-src/openstreetmap-gps-map
+src/mapviewer
 stamp-h1
 ChangeLog
-COPYING
+
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/Makefile.am b/Makefile.am
index f5b08f0..03674ad 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,8 +3,8 @@
 
 SUBDIRS = src
 
-openstreetmap_gps_mapdocdir = ${prefix}/doc/openstreetmap-gps-map
-openstreetmap_gps_mapdoc_DATA =                 \
+osm_gps_mapdocdir = ${prefix}/doc/osm-gps-map
+osm_gps_mapdoc_DATA =                           \
 	README                                      \
 	COPYING                                     \
 	AUTHORS                                     \
@@ -26,7 +26,7 @@ EXTRA_DIST = $(openstreetmap_gps_mapdoc_DATA)   \
 	python/aclocal.m4                           \
 	python/configure                            \
 	python/osmgpsmapmodule.c                    \
-	python/openstreetmap-gps-map.py             \
+	python/mapviewer.py                         \
 	python/AUTHORS                              \
 	python/configure.ac                         \
 	python/osmgpsmap.override                   \
@@ -42,7 +42,7 @@ distclean-local:
 ChangeLog:
 	@echo Creating $@
 	@if test -d "$(srcdir)/.git"; then \
-	  (GIT_DIR=$(top_srcdir)/.git ./missing --run git log 0.3.. --stat -M -C --name-status  --date=short --no-color) | fmt --split-only > $@.tmp \
+	  (GIT_DIR=$(top_srcdir)/.git ./missing --run git log 0.4.. --stat -M -C --name-status  --date=short --no-color) | fmt --split-only > $@.tmp \
 	  && mv -f $@.tmp $@ \
 	  || ($(RM) $@.tmp; \
 	      echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \
@@ -53,8 +53,8 @@ ChangeLog:
 	  echo A git checkout and git-log is required to generate this file >> $@); \
 	fi
 
-release:
-	scp @PACKAGE at -@VERSION at .tar.gz john at open.grcnz.com:/srv/default/downloads/osm-gps-map/
+release: dist
+	scp @PACKAGE at -@VERSION at .tar.gz root at greenbirdsystems.com:/var/www/johnstowers.co.nz/files/osm-gps-map/
 
 .PHONY: ChangeLog
 
diff --git a/NEWS b/NEWS
index aac5f58..faa700c 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,23 @@
+Changes in 0.5.0
+======================
+  * Note: Many of the improvements this release was based on 
+    code from Till Harbaum
+  * GDK drawing is not supported anymore, you must have cairo installed
+  * Use automake silent rules
+  * Add keyboard navigation support to map widget
+  * Draw GPS heading in position indicator
+  * Allow disabling of tile cache
+  * You can now change the map source at runtime
+  * Redraw and performance improvements
+  * Update python bindings
+  * Build and run correctly on Windows
+  * Add OPENCYCLEMAP and OSM_PUBLIC_TRANSPORT
+  * A new "changed" signal. Connect to this to monitor when the map zoom/scroll
+    or center changes.
+  * Add osm_gps_map_source_is_valid
+
 Changes in 0.4.0
+======================
   * Map can now be constructed by passing a MAP_SOURCE ID instead of
     the map repo uri
   * Fix iter safety when purging the tile cache
diff --git a/README b/README
index 1adfa96..c7c8268 100644
--- a/README
+++ b/README
@@ -1,7 +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 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 
+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/configure.ac b/configure.ac
index edb063c..8901285 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT(osm-gps-map, 0.4.0)
+AC_INIT(osm-gps-map, 0.5.0)
 AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
 
 AC_CONFIG_SRCDIR(osmgpsmap.pc.in)
@@ -11,24 +11,36 @@ AC_PROG_CC
 AM_PROG_CC_STDC
 AC_HEADER_STDC
 
+AC_LIBTOOL_WIN32_DLL
 AM_PROG_LIBTOOL
 
-PKG_CHECK_MODULES(OPENSTREETMAP_GPS_MAP, [gtk+-2.0 libsoup-2.4 glib-2.0 >= 2.18])
+m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
+
+PKG_CHECK_MODULES(OPENSTREETMAP_GPS_MAP, [gtk+-2.0 libsoup-2.4 glib-2.0 >= 2.18 cairo >= 1.8])
 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_MSG_CHECKING([for Win32])
+case "$host" in
+  *-*-mingw*)
+    os_win32=yes
+    ;;
+  *)
+    os_win32=no
+    ;;
+esac
+AC_MSG_RESULT([$os_win32])
+AM_CONDITIONAL(OS_WIN32, [test $os_win32 = yes])
+
+# Before making a release, the LT_VERSION_INFO string should be modified.
+# The string is of the form C:R:A.
+# - If interfaces have been changed or added, but binary compatibility has
+#   been preserved, change to C+1:0:A+1
+# - If binary compatibility has been broken (eg removed or changed interfaces)
+#   change to C+1:0:0
+# - If the interface is the same as the previous version, change to C:R+1:A
+LT_VERSION_INFO=1:0:1
+AC_SUBST(LT_VERSION_INFO)
 
 CFLAGS="$CFLAGS -Wall -Wswitch-enum"
 
@@ -42,4 +54,4 @@ echo
 echo $PACKAGE v$VERSION
 echo
 echo Prefix............... : $prefix
-echo cairo................ : $enable_cairo
+echo
diff --git a/python/Makefile.am b/python/Makefile.am
index 20d13ff..c4a28ff 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -17,7 +17,11 @@ osmgpsmap_la_SOURCES = osmgpsmapmodule.c osmgpsmap.c
 #nodist_osmgpsmap_la_SOURCES = osmgpsmap.c
 
 CLEANFILES = osmgpsmap.c
-EXTRA_DIST = osmgpsmap.override $(defs_DATA)
+EXTRA_DIST = \
+	setup.py \
+	mapviewer.py \
+	osmgpsmap.override \
+	$(defs_DATA)
 
 osmgpsmap.c: osmgpsmap.defs osmgpsmap.override
 .defs.c:
@@ -33,4 +37,5 @@ osmgpsmap.c: osmgpsmap.defs osmgpsmap.override
 update-defs:
 	$(PYGTK_H2DEF) ../src/osm-gps-map.h > osmgpsmap-new.defs
 	
-
+release: dist
+	scp @PACKAGE at -@VERSION at .tar.gz root at greenbirdsystems.com:/var/www/johnstowers.co.nz/files/osm-gps-map/
diff --git a/python/configure.ac b/python/configure.ac
index 0f74ba6..3605a2b 100644
--- a/python/configure.ac
+++ b/python/configure.ac
@@ -1,5 +1,5 @@
 AC_PREREQ(2.53)
-AC_INIT(osmgpsmap-python, 0.4.0)
+AC_INIT(python-osmgpsmap, 0.5.0)
 AC_CONFIG_SRCDIR(osmgpsmap.defs)
 AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION)
 
@@ -12,6 +12,8 @@ AC_HEADER_STDC
 
 AM_PROG_LIBTOOL
 
+m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
+
 AC_ARG_ENABLE(more-warnings,
 	      [  --disable-more-warnings  Inhibit compiler warnings],
 	      set_more_warnings=no)
@@ -48,9 +50,9 @@ if test -f ../src/libosmgpsmap.la; then
 	#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"
+	#and we must link to the local lib
+	OSMGPSMAP_CFLAGS="$OSMGPSMAP_CFLAGS -I../src/"
+	OSMGPSMAP_LIBS="$OSMGPSMAP_LIBS -L../src/.libs/ -losmgpsmap"
 else
 	PKG_CHECK_MODULES(OSMGPSMAP, osmgpsmap)
 fi
diff --git a/python/openstreetmap-gps-map.py b/python/mapviewer.py
similarity index 80%
rename from python/openstreetmap-gps-map.py
rename to python/mapviewer.py
index 6dfcdc6..03c1279 100755
--- a/python/openstreetmap-gps-map.py
+++ b/python/mapviewer.py
@@ -17,18 +17,22 @@
  You should have received a copy of the GNU General Public License along
  with this program.  If not, see <http://www.gnu.org/licenses/>.
 """
-
+import math
 import sys
 import os.path
 import gtk.gdk
 import gobject
 
+gobject.threads_init()
+gtk.gdk.threads_init()
+
 #Try static lib first
 mydir = os.path.dirname(os.path.abspath(__file__))
 libdir = os.path.join(mydir, ".libs")
 sys.path.insert(0, libdir)
 
 import osmgpsmap
+print "using library: %s" % osmgpsmap.__file__
  
 class UI(gtk.Window):
     def __init__(self):
@@ -41,10 +45,16 @@ class UI(gtk.Window):
         self.vbox = gtk.VBox(False, 0)
         self.add(self.vbox)
 
-        self.osm = osmgpsmap.GpsMap(
-            tile_cache=osmgpsmap.get_default_cache_directory(),
-        )
+        self.osm = osmgpsmap.GpsMap()
         self.osm.connect('button_release_event', self.map_clicked)
+
+        #connect keyboard shortcuts
+        self.osm.set_keyboard_shortcut(osmgpsmap.KEY_FULLSCREEN, gtk.gdk.keyval_from_name("F11"))
+        self.osm.set_keyboard_shortcut(osmgpsmap.KEY_UP, gtk.gdk.keyval_from_name("Up"))
+        self.osm.set_keyboard_shortcut(osmgpsmap.KEY_DOWN, gtk.gdk.keyval_from_name("Down"))
+        self.osm.set_keyboard_shortcut(osmgpsmap.KEY_LEFT, gtk.gdk.keyval_from_name("Left"))
+        self.osm.set_keyboard_shortcut(osmgpsmap.KEY_RIGHT, gtk.gdk.keyval_from_name("Right"))
+
         self.latlon_entry = gtk.Entry()
 
         zoom_in_button = gtk.Button(stock=gtk.STOCK_ZOOM_IN)
@@ -118,10 +128,8 @@ Enter an repository URL to fetch map tiles from in the box below. Special metach
             if self.osm:
                 #remove old map
                 self.vbox.remove(self.osm)
-
             try:
                 self.osm = osmgpsmap.GpsMap(
-                    tile_cache=osmgpsmap.get_default_cache_directory(),
                     repo_uri=uri,
                     image_format=format
                 )
@@ -157,18 +165,25 @@ Enter an repository URL to fetch map tiles from in the box below. Special metach
         )
 
     def map_clicked(self, osm, event):
-        self.latlon_entry.set_text(
-            'Map Centre: latitude %s longitude %s' % (
-                self.osm.props.latitude,
-                self.osm.props.longitude
+        if event.button == 1:
+            self.latlon_entry.set_text(
+                'Map Centre: latitude %s longitude %s' % (
+                    self.osm.props.latitude,
+                    self.osm.props.longitude
+                )
             )
-        )
+        elif event.button == 2:
+            rlat, rlon = self.osm.get_co_ordinates(event.x, event.y)
+            self.osm.draw_gps(
+                    math.degrees(rlat),
+                    math.degrees(rlon),
+                    osmgpsmap.INVALID);
  
 
 if __name__ == "__main__":
-    gtk.gdk.threads_init()
-
     u = UI()
     u.show_all()
+    if os.name == "nt": gtk.gdk.threads_enter()
     gtk.main()
+    if os.name == "nt": gtk.gdk.threads_leave()
 
diff --git a/python/osmgpsmap.defs b/python/osmgpsmap.defs
index 6999044..a5f9162 100644
--- a/python/osmgpsmap.defs
+++ b/python/osmgpsmap.defs
@@ -29,6 +29,20 @@
   )
 )
 
+(define-enum Key
+  (in-module "Osm")
+  (c-name "OsmGpsMapKey_t")
+  (values
+   '("Fullscreen" "OSM_GPS_MAP_KEY_FULLSCREEN")
+   '("Zoom In" "OSM_GPS_MAP_KEY_ZOOMIN")
+   '("Zoom Out" "OSM_GPS_MAP_KEY_ZOOMOUT")
+   '("Up" "OSM_GPS_MAP_KEY_UP")
+   '("Down" "OSM_GPS_MAP_KEY_DOWN")
+   '("Left" "OSM_GPS_MAP_KEY_LEFT")
+   '("Right" "OSM_GPS_MAP_KEY_RIGHT")
+  )
+)
+
 ;; From osm-gps-map.h
 
 (define-function osm_gps_map_get_type
@@ -41,6 +55,54 @@
   (return-type "char*")
 )
 
+(define-function source_get_friendly_name
+  (c-name "osm_gps_map_source_get_friendly_name")
+  (return-type "const-char*")
+  (parameters
+    '("OsmGpsMapSource_t" "source")
+  )
+)
+
+(define-function source_get_repo_uri
+  (c-name "osm_gps_map_source_get_repo_uri")
+  (return-type "const-char*")
+  (parameters
+    '("OsmGpsMapSource_t" "source")
+  )
+)
+
+(define-function source_get_image_format
+  (c-name "osm_gps_map_source_get_image_format")
+  (return-type "const-char*")
+  (parameters
+    '("OsmGpsMapSource_t" "source")
+  )
+)
+
+(define-function source_get_min_zoom
+  (c-name "osm_gps_map_source_get_min_zoom")
+  (return-type "int")
+  (parameters
+    '("OsmGpsMapSource_t" "source")
+  )
+)
+
+(define-function source_get_max_zoom
+  (c-name "osm_gps_map_source_get_max_zoom")
+  (return-type "int")
+  (parameters
+    '("OsmGpsMapSource_t" "source")
+  )
+)
+
+(define-function osm_gps_map_source_is_valid
+  (c-name "osm_gps_map_source_is_valid")
+  (return-type "gboolean")
+  (parameters
+    '("OsmGpsMapSource_t" "source")
+  )
+)
+
 (define-method download_maps
   (of-object "OsmGpsMap")
   (c-name "osm_gps_map_download_maps")
@@ -134,15 +196,6 @@
   (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")
@@ -182,12 +235,16 @@
     '("repo_uri" (optional))
     '("proxy_uri" (optional))
     '("tile_cache" (optional))
+    '("tile_cache_base" (optional))
     '("tile_cache_is_full_path" (optional))
     '("zoom" (optional))
     '("max_zoom" (optional))
     '("min_zoom" (optional))
     '("map_x" (optional))
-    '("map_Y" (optional))
+    '("map_y" (optional))
+    '("gps_track_width" (optional))
+    '("gps_track_point_radius" (optional))
+    '("gps_track_highlight_radius" (optional))
     '("map_source" (optional))
     '("image_format" (optional))
   )
@@ -233,43 +290,14 @@
   (return-type "float")
 )
 
-(define-function source_get_repo_uri
-  (c-name "osm_gps_map_source_get_repo_uri")
-  (return-type "const-char*")
-  (parameters
-    '("OsmGpsMapSource_t" "source")
-  )
-)
-
-(define-function source_get_friendly_name
-  (c-name "osm_gps_map_source_get_friendly_name")
-  (return-type "const-char*")
-  (parameters
-    '("OsmGpsMapSource_t" "source")
-  )
-)
-
-(define-function source_get_max_zoom
-  (c-name "osm_gps_map_source_get_max_zoom")
-  (return-type "int")
-  (parameters
-    '("OsmGpsMapSource_t" "source")
-  )
-)
-
-(define-function source_get_min_zoom
-  (c-name "osm_gps_map_source_get_min_zoom")
-  (return-type "int")
+(define-method set_keyboard_shortcut
+  (of-object "OsmGpsMap")
+  (c-name "osm_gps_map_set_keyboard_shortcut")
+  (return-type "none")
   (parameters
-    '("OsmGpsMapSource_t" "source")
+    '("OsmGpsMapKey_t" "key")
+    '("guint" "keyval")
   )
 )
 
-(define-function source_get_image_format
-  (c-name "osm_gps_map_source_get_image_format")
-  (return-type "const-char*")
-  (parameters
-    '("OsmGpsMapSource_t" "source")
-  )
-)
 
diff --git a/python/osmgpsmapmodule.c b/python/osmgpsmapmodule.c
index e9b22c8..bb7898e 100644
--- a/python/osmgpsmapmodule.c
+++ b/python/osmgpsmapmodule.c
@@ -36,6 +36,13 @@ initosmgpsmap(void)
 	pyosmgpsmap_register_classes(d);
     pyosmgpsmap_add_constants(m, "OSM_GPS_MAP_");
 
+	PyModule_AddObject(m, "INVALID",
+		PyFloat_FromDouble(OSM_GPS_MAP_INVALID));
+	PyModule_AddObject(m, "CACHE_DISABLED",
+		PyString_FromString(OSM_GPS_MAP_CACHE_DISABLED));
+	PyModule_AddObject(m, "CACHE_AUTO",
+		PyString_FromString(OSM_GPS_MAP_CACHE_AUTO));
+
 	if (PyErr_Occurred()) {
 		Py_FatalError("can't initialize module osmgpsmap");
 	}
diff --git a/python/setup.py b/python/setup.py
index 055c8e5..10ec757 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -28,8 +28,8 @@ _osmgpsmap = Extension(name = 'osmgpsmap',
             libraries = get_libs('osmgpsmap pygobject-2.0'),
         )
 
-setup( name = "pyosmgpsmap",
-    version = "0.1",
+setup( name = "python-osmgpsmap",
+    version = "0.5",
     description = "python interface for osmgpsmap",
     ext_modules = [_osmgpsmap],
     )
diff --git a/src/Makefile.am b/src/Makefile.am
index 18286b8..975a34d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,18 +11,19 @@ AM_CFLAGS =\
 	 -Wall\
 	 -g
 
-bin_PROGRAMS = openstreetmap-gps-map
+bin_PROGRAMS = mapviewer
 
-openstreetmap_gps_map_SOURCES = \
+mapviewer_SOURCES = \
 	main.c
 
-openstreetmap_gps_map_DEPENDENCIES = \
+mapviewer_DEPENDENCIES = \
 	libosmgpsmap.la
 
-openstreetmap_gps_map_LDFLAGS = \
+mapviewer_LDFLAGS = \
 	-losmgpsmap -lgthread-2.0
 
-openstreetmap_gps_map_LDADD = $(OPENSTREETMAP_GPS_MAP_LIBS)
+mapviewer_LDADD = \
+	$(OPENSTREETMAP_GPS_MAP_LIBS)
 
 lib_LTLIBRARIES = \
 	libosmgpsmap.la
@@ -34,6 +35,17 @@ libosmgpsmap_la_SOURCES = \
 libosmgpsmap_la_CFLAGS = \
 	-DG_LOG_DOMAIN=\"OsmGpsMap\"
 
+if OS_WIN32
+no_undefined = -no-undefined
+endif
+
+libosmgpsmap_la_LDFLAGS = \
+	-version-info $(LT_VERSION_INFO)    \
+	$(no_undefined)
+
+libosmgpsmap_la_LIBADD = \
+	$(OPENSTREETMAP_GPS_MAP_LIBS)
+
 libosmgpsmapincdir = $(includedir)/osmgpsmap
 libosmgpsmapinc_HEADERS = \
 	osm-gps-map.h
diff --git a/src/main.c b/src/main.c
index 0603822..c0f5f92 100644
--- a/src/main.c
+++ b/src/main.c
@@ -22,14 +22,17 @@
 #include <math.h>
 #include <glib.h>
 #include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
 #include "osm-gps-map.h"
 
-static OsmGpsMapSource_t map_provider = 0;
-static gboolean maps_in_temp = FALSE;
+static OsmGpsMapSource_t map_provider = OSM_GPS_MAP_SOURCE_OPENSTREETMAP;
+static gboolean default_cache = FALSE;
+static gboolean no_cache = 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 },
+  { "default-cache", 'D', 0, G_OPTION_ARG_NONE, &default_cache, "Store maps in default cache", NULL },
+  { "no-cache", 'n', 0, G_OPTION_ARG_NONE, &no_cache, "Disable cache", 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 }
@@ -66,14 +69,15 @@ on_button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer user_d
     coord_t coord;
     OsmGpsMap *map = OSM_GPS_MAP(widget);
 
-    if ( (event->button == 1) && (event->type == GDK_2BUTTON_PRESS) )
+    if (    ((event->button == 1) || (event->button == 3)) 
+            && (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);
+                              (event->button == 1 ? OSM_GPS_MAP_INVALID : g_random_double_range(0,360)));
     }
 
     if ( (event->button == 2) && (event->type == GDK_BUTTON_PRESS) )
@@ -161,10 +165,12 @@ usage (GOptionContext *context)
     puts(g_option_context_get_help(context, TRUE, NULL));
 
     printf("Valid map sources:\n");
-    for(i=OSM_GPS_MAP_SOURCE_NULL; i <= OSM_GPS_MAP_SOURCE_YAHOO_HYBRID; i++)
+    for(i=OSM_GPS_MAP_SOURCE_NULL; i <= OSM_GPS_MAP_SOURCE_LAST; i++)
     {
         const char *name = osm_gps_map_source_get_friendly_name(i);
-        printf("\t%d:\t%s\n",i,name);
+        const char *uri = osm_gps_map_source_get_repo_uri(i);
+        if (uri != NULL)
+            printf("\t%d:\t%s\n",i,name);
     }
 }
 
@@ -179,11 +185,10 @@ main (int argc, char **argv)
     GtkWidget *zoomOutbutton;
     GtkWidget *homeButton;
     GtkWidget *cacheButton;
-    GtkWidget *map;
+    OsmGpsMap *map;
     const char *repo_uri;
     const char *friendly_name;
     char *cachedir;
-    gboolean fullpath;
     GError *error = NULL;
     GOptionContext *context;
     timeout_cb_t *data;
@@ -210,15 +215,15 @@ main (int argc, char **argv)
 
     friendly_name = osm_gps_map_source_get_friendly_name(map_provider);
 
-    if (maps_in_temp) {
-        cachedir = NULL;
-        fullpath = FALSE;
+    if (default_cache) {
+        cachedir = OSM_GPS_MAP_CACHE_AUTO;
+    } else if (no_cache) {
+        cachedir = OSM_GPS_MAP_CACHE_DISABLED;
     } else {
         char *mapcachedir;
         mapcachedir = osm_gps_map_get_default_cache_directory();
         cachedir = g_build_filename(mapcachedir,friendly_name,NULL);
         g_free(mapcachedir);
-        fullpath = TRUE;
     }
 
     if (debug)
@@ -235,17 +240,21 @@ main (int argc, char **argv)
     map = g_object_new (OSM_TYPE_GPS_MAP,
                         "map-source",map_provider,
                         "tile-cache",cachedir,
-                        "tile-cache-is-full-path",fullpath,
                         "proxy-uri",g_getenv("http_proxy"),
                         NULL);
 
-    g_free(cachedir);
+    //Enable keyboard navigation
+    osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_FULLSCREEN, GDK_F11);
+    osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_UP, GDK_Up);
+    osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_DOWN, GDK_Down);
+    osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_LEFT, GDK_Left);
+    osm_gps_map_set_keyboard_shortcut(map, OSM_GPS_MAP_KEY_RIGHT, GDK_Right);
 
     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);
+    gtk_box_pack_start (GTK_BOX(vbox), GTK_WIDGET(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);
@@ -270,7 +279,7 @@ main (int argc, char **argv)
     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->map = map;
     data->entry = entry;
     cacheButton = gtk_button_new_with_label ("Cache");
     g_signal_connect (G_OBJECT (cacheButton), "clicked",
@@ -278,9 +287,9 @@ main (int argc, char **argv)
     gtk_box_pack_start (GTK_BOX(bbox), cacheButton, FALSE, TRUE, 0);
 
     //Connect to map events
-    g_signal_connect (map, "button-press-event",
+    g_signal_connect (G_OBJECT (map), "button-press-event",
                       G_CALLBACK (on_button_press_event), (gpointer) entry);
-    g_signal_connect (map, "button-release-event",
+    g_signal_connect (G_OBJECT (map), "button-release-event",
                       G_CALLBACK (on_button_release_event), (gpointer) entry);
 
     g_signal_connect (window, "destroy",
@@ -291,6 +300,5 @@ main (int argc, char **argv)
     g_log_set_handler ("OsmGpsMap", G_LOG_LEVEL_MASK, g_log_default_handler, NULL);
     gtk_main ();
 
-    g_free(cachedir);
     return 0;
 }
diff --git a/src/osm-gps-map-types.h b/src/osm-gps-map-types.h
index 47c90df..04441ad 100644
--- a/src/osm-gps-map-types.h
+++ b/src/osm-gps-map-types.h
@@ -57,6 +57,9 @@
 //....
 #define URI_FLAG_END (1 << 8)
 
+/* equatorial radius in meters */
+#define OSM_EQ_RADIUS   (6378137.0)
+
 typedef struct {
     int x1;
     int y1;
@@ -85,6 +88,8 @@ typedef struct {
     GdkPixbuf *image;
     int w;
     int h;
+    int xoffset;
+    int yoffset;
 } image_t;
 
 #endif /* _OSM_GPS_MAP_TYPES_H_ */
diff --git a/src/osm-gps-map.c b/src/osm-gps-map.c
index 2a0a5f6..324490d 100644
--- a/src/osm-gps-map.c
+++ b/src/osm-gps-map.c
@@ -4,6 +4,7 @@
  * osm-gps-map.c
  * Copyright (C) Marcus Bauer 2008 <marcus.bauer at gmail.com>
  * Copyright (C) John Stowers 2009 <john.stowers at gmail.com>
+ * Copyright (C) Till Harbaum 2009 <till at harbaum.org>
  *
  * Contributions by
  * Everaldo Canuto 2009 <everaldo.canuto at gmail.com>
@@ -33,21 +34,23 @@
 
 #include <gdk/gdk.h>
 #include <glib.h>
+#include <glib/gstdio.h>
 #include <glib/gprintf.h>
 #include <libsoup/soup.h>
+#include <cairo.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)
 
+#define OSM_GPS_MAP_SCROLL_STEP 10
+
+#define 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"
+
 struct _OsmGpsMapPrivate
 {
     GHashTable *tile_queue;
@@ -77,8 +80,9 @@ struct _OsmGpsMapPrivate
     char *proxy_uri;
 
     //where downloaded tiles are cached
+    char *tile_dir;
+    char *tile_base_dir;
     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
@@ -95,6 +99,7 @@ struct _OsmGpsMapPrivate
     gboolean show_trip_history;
     GSList *trip_history;
     coord_t *gps;
+    float gps_heading;
     gboolean gps_valid;
 
     //additional images or tracks added to the map
@@ -116,15 +121,21 @@ struct _OsmGpsMapPrivate
     int drag_start_mouse_y;
     int drag_start_map_x;
     int drag_start_map_y;
+    guint drag_expose;
 
     //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;
 
+    //For storing keybindings
+    guint keybindings[OSM_GPS_MAP_KEY_MAX];
+
+    guint fullscreen : 1;
+    guint keybindings_enabled : 1;
     guint is_disposed : 1;
     guint dragging : 1;
-    guint center_coord_set : 1;
+    guint button_down : 1;
 };
 
 #define OSM_GPS_MAP_PRIVATE(o)  (OSM_GPS_MAP (o)->priv)
@@ -148,6 +159,7 @@ enum
     PROP_REPO_URI,
     PROP_PROXY_URI,
     PROP_TILE_CACHE_DIR,
+    PROP_TILE_CACHE_BASE_DIR,
     PROP_TILE_CACHE_DIR_IS_FULL_PATH,
     PROP_ZOOM,
     PROP_MAX_ZOOM,
@@ -175,7 +187,11 @@ static gchar    *replace_map_uri(OsmGpsMap *map, const gchar *uri, int zoom, int
 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);
+#ifdef LIBSOUP22
+static void     osm_gps_map_tile_download_complete (SoupMessage *msg, gpointer user_data);
+#else
 static void     osm_gps_map_tile_download_complete (SoupSession *session, SoupMessage *msg, gpointer user_data);
+#endif
 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);
@@ -305,6 +321,8 @@ static void
 inspect_map_uri(OsmGpsMap *map)
 {
     OsmGpsMapPrivate *priv = map->priv;
+    priv->uri_format = 0;
+    priv->the_google = FALSE;
 
     if (g_strrstr(priv->repo_uri, URI_MARKER_X))
         priv->uri_format |= URI_HAS_X;
@@ -349,7 +367,7 @@ replace_map_uri(OsmGpsMap *map, const gchar *uri, int zoom, int x, int y)
     url = g_strdup(uri);
     while (i < URI_FLAG_END)
     {
-        char *s;
+        char *s = NULL;
         char *old;
 
         old = url;
@@ -428,54 +446,8 @@ my_log_handler (const gchar * log_domain, GLogLevelFlags log_level, const gchar
 static float
 osm_gps_map_get_scale_at_point(int zoom, float rlat, float rlon)
 {
-    /* This is a naieve implementation with values from
-    http://wiki.openstreetmap.org/index.php/FAQ#What_is_the_map_scale_for_a_particular_zoom_level_of_the_map.3F  
-    http://almien.co.uk/OSM/Tools/Scale/
-
-    The true scale, becase of the mercator projection of all supported map 
-    sources, depends on the lat and lon of the point */
-    switch (zoom) {
-        case 0:
-            return 156412.0;
-        case 1:
-            return 78206.0;
-        case 2:
-            return 39135.758482;
-        case 3:
-            return 19567.879241;
-        case 4:
-            return 9783.939621;
-        case 5:
-            return 4891.969810;
-        case 6:
-            return 2445.984905;
-        case 7:
-            return 1222.992453;
-        case 8:
-            return 611.496226;
-        case 9:
-            return 305.748113;
-        case 10:
-            return 152.874057;
-        case 11:
-            return 76.437028;
-        case 12:
-            return 38.218514;
-        case 13:
-            return 19.109257;
-        case 14:
-            return 9.554629;
-        case 15:
-            return 4.777314;
-        case 16:
-            return 2.388657;
-        case 17:
-            return 1.194329;
-        case 18:
-            return 0.597164;
-    }
-
-    return 0.0;
+    /* world at zoom 1 == 512 pixels */
+    return cos(rlat) * M_PI * OSM_EQ_RADIUS / (1<<(7+zoom));
 }
 
 /* clears the trip list and all resources */
@@ -559,7 +531,7 @@ osm_gps_map_print_images (OsmGpsMap *map)
                          priv->gc_map,
                          im->image,
                          0,0,
-                         x-(im->w/2),y-(im->h/2),
+                         x-im->xoffset,y-im->yoffset,
                          im->w,im->h,
                          GDK_RGB_DITHER_NONE, 0, 0);
 
@@ -587,22 +559,15 @@ osm_gps_map_draw_gps_point (OsmGpsMap *map)
         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);
+        int mr = MAX(3*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
@@ -619,6 +584,22 @@ osm_gps_map_draw_gps_point (OsmGpsMap *map)
 
         // draw ball gradient
         if (r > 0) {
+            // draw direction arrow
+            if(!isnan(priv->gps_heading)) 
+            {
+                cairo_move_to (cr, x-r*cos(priv->gps_heading), y-r*sin(priv->gps_heading));
+                cairo_line_to (cr, x+3*r*sin(priv->gps_heading), y-3*r*cos(priv->gps_heading));
+                cairo_line_to (cr, x+r*cos(priv->gps_heading), y+r*sin(priv->gps_heading));
+                cairo_close_path (cr);
+
+                cairo_set_source_rgba (cr, 0.3, 0.3, 1.0, 0.5);
+                cairo_fill_preserve (cr);
+
+                cairo_set_line_width (cr, 1.0);
+                cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5);
+                cairo_stroke(cr);
+            }
+
             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);
@@ -639,38 +620,6 @@ osm_gps_map_draw_gps_point (OsmGpsMap *map)
                                     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
     }
 }
 
@@ -691,52 +640,113 @@ osm_gps_map_blit_tile(OsmGpsMap *map, GdkPixbuf *pixbuf, int offset_x, int offse
                      GDK_RGB_DITHER_NONE, 0, 0);
 }
 
+/* libsoup-2.2 and libsoup-2.4 use different ways to store the body data */
+#ifdef LIBSOUP22
+#define  soup_message_headers_append(a,b,c) soup_message_add_header(a,b,c)
+#define MSG_RESPONSE_BODY(a)    ((a)->response.body)
+#define MSG_RESPONSE_LEN(a)     ((a)->response.length)
+#define MSG_RESPONSE_LEN_FORMAT "%u"
+#else
+#define MSG_RESPONSE_BODY(a)    ((a)->response_body->data)
+#define MSG_RESPONSE_LEN(a)     ((a)->response_body->length)
+#define MSG_RESPONSE_LEN_FORMAT "%lld"
+#endif
+
+#ifdef LIBSOUP22
+static void
+osm_gps_map_tile_download_complete (SoupMessage *msg, gpointer user_data)
+#else
 static void
 osm_gps_map_tile_download_complete (SoupSession *session, SoupMessage *msg, gpointer user_data)
+#endif
 {
     FILE *file;
     tile_download_t *dl = (tile_download_t *)user_data;
     OsmGpsMap *map = OSM_GPS_MAP(dl->map);
     OsmGpsMapPrivate *priv = map->priv;
+    gboolean file_saved = FALSE;
 
     if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
     {
-        if (g_mkdir_with_parents(dl->folder,0700) == 0)
+        /* save tile into cachedir if one has been specified */
+        if (priv->cache_dir)
         {
-            file = g_fopen(dl->filename, "wb");
-            if (file != NULL)
+            if (g_mkdir_with_parents(dl->folder,0700) == 0)
             {
-                fwrite (msg->response_body->data, 1, msg->response_body->length, file);
-                g_debug("Wrote %lld bytes to %s", msg->response_body->length, dl->filename);
-                fclose (file);
+                file = g_fopen(dl->filename, "wb");
+                if (file != NULL)
+                {
+                    fwrite (MSG_RESPONSE_BODY(msg), 1, MSG_RESPONSE_LEN(msg), file);
+                    file_saved = TRUE;
+                    g_debug("Wrote "MSG_RESPONSE_LEN_FORMAT" bytes to %s", MSG_RESPONSE_LEN(msg), dl->filename);
+                    fclose (file);
+
+                }
+            }
+            else
+            {
+                g_warning("Error creating tile download directory: %s", 
+                          dl->folder);
+                perror("perror:");
+            }
+        }
+
+        if (dl->redraw)
+        {
+            GdkPixbuf *pixbuf = NULL;
 
-                if (dl->redraw)
+            /* if the file was actually stored on disk, we can simply */
+            /* load and decode it from that file */
+            if (priv->cache_dir)
+            {
+                if (file_saved)
                 {
-                    GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (dl->filename, NULL);
+                    pixbuf = gdk_pixbuf_new_from_file (dl->filename, NULL);
+                }
+            }
+            else
+            {
+                GdkPixbufLoader *loader;
+                char *extension = strrchr (dl->filename, '.');
 
-                    /* Store the tile into the cache */
-                    if (G_LIKELY (pixbuf))
+                /* parse file directly from memory */
+                if (extension)
+                {
+                    loader = gdk_pixbuf_loader_new_with_type (extension+1, NULL);
+                    if (!gdk_pixbuf_loader_write (loader, (unsigned char*)MSG_RESPONSE_BODY(msg), MSG_RESPONSE_LEN(msg), NULL))
                     {
-                        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;
+                        g_warning("Error: Decoding of image failed");
                     }
-                    osm_gps_map_map_redraw_idle (map);
+                    gdk_pixbuf_loader_close(loader, NULL);
+
+                    pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
+
+                    /* give up loader but keep the pixbuf */
+                    g_object_ref(pixbuf);
+                    g_object_unref(loader);
+                }
+                else
+                {
+                    g_warning("Error: Unable to determine image file format");
                 }
             }
+                
+            /* 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);
@@ -758,7 +768,11 @@ osm_gps_map_tile_download_complete (SoupSession *session, SoupMessage *msg, gpoi
         }
         else
         {
+#ifdef LIBSOUP22
+            soup_session_requeue_message(dl->session, msg);
+#else
             soup_session_requeue_message(session, msg);
+#endif
             return;
         }
     }
@@ -776,6 +790,10 @@ osm_gps_map_download_tile (OsmGpsMap *map, int zoom, int x, int y, gboolean redr
     //calculate the uri to download
     dl->uri = replace_map_uri(map, priv->repo_uri, zoom, x, y);
 
+#ifdef LIBSOUP22
+    dl->session = priv->soup_session;
+#endif
+
     //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) ||
@@ -816,6 +834,11 @@ osm_gps_map_download_tile (OsmGpsMap *map, int zoom, int x, int y, gboolean redr
                 }
             }
 
+#ifdef LIBSOUP22
+            soup_message_headers_append(msg->request_headers, 
+                                        "User-Agent", USER_AGENT);
+#endif
+
             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 {
@@ -833,7 +856,7 @@ osm_gps_map_load_cached_tile (OsmGpsMap *map, int zoom, int x, int y)
 {
     OsmGpsMapPrivate *priv = map->priv;
     gchar *filename;
-    GdkPixbuf *pixbuf;
+    GdkPixbuf *pixbuf = NULL;
     OsmCachedTile *tile;
 
     filename = g_strdup_printf("%s%c%d%c%d%c%d.%s",
@@ -945,7 +968,10 @@ osm_gps_map_load_tile (OsmGpsMap *map, int zoom, int x, int y, int offset_x, int
                 y,
                 priv->image_format);
 
-    pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
+    /* try to get file from internal cache first */
+    if(!(pixbuf = osm_gps_map_load_cached_tile(map, zoom, x, y)))
+        pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
+
     if(pixbuf)
     {
         g_debug("Found tile %s", filename);
@@ -1048,28 +1074,13 @@ osm_gps_map_print_track (OsmGpsMap *map, GSList *trackpoint_list)
     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;
@@ -1082,21 +1093,10 @@ osm_gps_map_print_track (OsmGpsMap *map, GSList *trackpoint_list)
 
         // 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);
@@ -1111,12 +1111,8 @@ osm_gps_map_print_track (OsmGpsMap *map, GSList *trackpoint_list)
                                 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 */
@@ -1172,11 +1168,14 @@ osm_gps_map_map_redraw (OsmGpsMap *map)
     if (priv->dragging)
         return FALSE;
 
+    /* undo all offsets that may have happened when dragging */
+    priv->drag_mouse_dx = 0;
+    priv->drag_mouse_dy = 0;
+
     priv->redraw_cycle++;
 
     /* draw white background to initialise pixmap */
-    gdk_draw_rectangle (
-                        priv->pixmap,
+    gdk_draw_rectangle (priv->pixmap,
                         GTK_WIDGET(map)->style->white_gc,
                         TRUE,
                         0, 0,
@@ -1189,7 +1188,6 @@ osm_gps_map_map_redraw (OsmGpsMap *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));
 
@@ -1206,8 +1204,98 @@ osm_gps_map_map_redraw_idle (OsmGpsMap *map)
 }
 
 static void
+center_coord_update(OsmGpsMap *map) {
+
+    GtkWidget *widget = GTK_WIDGET(map);
+    OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(map);
+
+    // pixel_x,y, offsets
+    gint pixel_x = priv->map_x + widget->allocation.width/2;
+    gint pixel_y = priv->map_y + widget->allocation.height/2;
+
+    priv->center_rlon = pixel2lon(priv->map_zoom, pixel_x);
+    priv->center_rlat = pixel2lat(priv->map_zoom, pixel_y);
+
+    g_signal_emit_by_name(widget, "changed");
+}
+
+static gboolean 
+on_window_key_press(GtkWidget *widget, GdkEventKey *event, OsmGpsMapPrivate *priv) 
+{
+    int i;
+    int step;
+    gboolean handled;
+    OsmGpsMap *map;
+
+    //if no keybindings are set, let the app handle them...
+    if (!priv->keybindings_enabled)
+        return FALSE;
+
+    handled = FALSE;
+    map = OSM_GPS_MAP(widget);
+    step = GTK_WIDGET(widget)->allocation.width/OSM_GPS_MAP_SCROLL_STEP;
+
+    //the map handles some keys on its own
+    for (i = 0; i < OSM_GPS_MAP_KEY_MAX; i++) {
+        //not the key we have a binding for
+        if (map->priv->keybindings[i] != event->keyval)
+            continue;
+
+        switch(i) {
+            case OSM_GPS_MAP_KEY_FULLSCREEN: {
+                GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(widget));
+                if(!priv->fullscreen)
+                    gtk_window_fullscreen(GTK_WINDOW(toplevel));
+                else
+                    gtk_window_unfullscreen(GTK_WINDOW(toplevel));
+
+                priv->fullscreen = !priv->fullscreen;
+                handled = TRUE;
+                } break;
+            case OSM_GPS_MAP_KEY_ZOOMIN:
+                osm_gps_map_set_zoom(map, priv->map_zoom+1);
+                handled = TRUE;
+                break;
+            case OSM_GPS_MAP_KEY_ZOOMOUT:
+                osm_gps_map_set_zoom(map, priv->map_zoom-1);
+                handled = TRUE;
+                break;
+            case OSM_GPS_MAP_KEY_UP:
+                priv->map_y -= step;
+                center_coord_update(map);
+                osm_gps_map_map_redraw_idle(map);
+                handled = TRUE;
+                break;
+            case OSM_GPS_MAP_KEY_DOWN:
+                priv->map_y += step;
+                center_coord_update(map);
+                osm_gps_map_map_redraw_idle(map);
+                handled = TRUE;
+                break;
+              case OSM_GPS_MAP_KEY_LEFT:
+                priv->map_x -= step;
+                center_coord_update(map);
+                osm_gps_map_map_redraw_idle(map);
+                handled = TRUE;
+                break;
+            case OSM_GPS_MAP_KEY_RIGHT:
+                priv->map_x += step;
+                center_coord_update(map);
+                osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
+                handled = TRUE;
+                break;
+            default:
+                break;
+        }
+    }
+
+    return handled;
+}
+
+static void
 osm_gps_map_init (OsmGpsMap *object)
 {
+    int i;
     OsmGpsMapPrivate *priv;
 
     priv = G_TYPE_INSTANCE_GET_PRIVATE (object, OSM_TYPE_GPS_MAP, OsmGpsMapPrivate);
@@ -1218,6 +1306,7 @@ osm_gps_map_init (OsmGpsMap *object)
     priv->trip_history = NULL;
     priv->gps = g_new0(coord_t, 1);
     priv->gps_valid = FALSE;
+    priv->gps_heading = OSM_GPS_MAP_INVALID;
 
     priv->tracks = NULL;
     priv->images = NULL;
@@ -1233,12 +1322,20 @@ osm_gps_map_init (OsmGpsMap *object)
 
     priv->map_source = -1;
 
-    //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);
+    priv->keybindings_enabled = FALSE;
+    for (i = 0; i < OSM_GPS_MAP_KEY_MAX; i++)
+        priv->keybindings[i] = 0;
 
+#ifndef LIBSOUP22
+    //Change naumber of concurrent connections option?
+    priv->soup_session =
+        soup_session_async_new_with_options(SOUP_SESSION_USER_AGENT,
+                                            USER_AGENT, NULL);
+#else
+    /* libsoup-2.2 has no special way to set the user agent, so we */
+    /* set it seperately as an extra header field for each reuest */
+    priv->soup_session = soup_session_async_new();
+#endif
     //Hash table which maps tile d/l URIs to SoupMessage requests
     priv->tile_queue = g_hash_table_new (g_str_hash, g_str_equal);
 
@@ -1258,22 +1355,37 @@ osm_gps_map_init (OsmGpsMap *object)
     GTK_WIDGET_SET_FLAGS (object, GTK_CAN_FOCUS);
 
     g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, my_log_handler, NULL);
+
+    //Setup signal handlers
+    g_signal_connect(G_OBJECT(object), "key_press_event",
+                            G_CALLBACK(on_window_key_press), priv);
 }
 
-static GObject *
-osm_gps_map_constructor (GType gtype, guint n_properties, GObjectConstructParam *properties)
+static char*
+osm_gps_map_get_cache_dir(OsmGpsMapPrivate *priv)
 {
-    GObject *object;
-    OsmGpsMapPrivate *priv;
-    OsmGpsMap *map;
-    const char *uri, *name;
+    if (priv->tile_base_dir)
+        return g_strdup(priv->tile_base_dir);
+    return osm_gps_map_get_default_cache_directory();
+}
 
-    //Always chain up to the parent constructor
-    object = G_OBJECT_CLASS(osm_gps_map_parent_class)->constructor(gtype, n_properties, properties);
-    map = OSM_GPS_MAP(object);
-    priv = OSM_GPS_MAP_PRIVATE(object);
+/* strcmp0 was introduced with glib 2.16 */
+#if ! GLIB_CHECK_VERSION (2, 16, 0)
+int g_strcmp0(const char *str1, const char *str2)
+{
+    if( str1 == NULL && str2 == NULL ) return 0;
+    if( str1 == NULL ) return -1;
+    if( str2 == NULL ) return 1;
+    return strcmp(str1, str2);
+}
+#endif
 
-    //user can specify a map source ID, or a repo URI as the map source
+static void
+osm_gps_map_setup(OsmGpsMapPrivate *priv)
+{
+    const char *uri;
+
+   //user can specify a map source ID, or a repo URI as the map source
     uri = osm_gps_map_source_get_repo_uri(OSM_GPS_MAP_SOURCE_NULL);
     if ( (priv->map_source == 0) || (strcmp(priv->repo_uri, uri) == 0) ) {
         g_debug("Using null source");
@@ -1297,24 +1409,42 @@ osm_gps_map_constructor (GType gtype, guint n_properties, GObjectConstructParam
         }
     }
 
-    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%c%s", old, G_DIR_SEPARATOR, 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);
-        }
+    if (priv->tile_dir == NULL)
+        priv->tile_dir = g_strdup(OSM_GPS_MAP_CACHE_DISABLED);
 
+    if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_DISABLED) == 0 ) {
+        priv->cache_dir = NULL;
+    } else if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_AUTO) == 0 ) {
+        char *base = osm_gps_map_get_cache_dir(priv);
+#if GLIB_CHECK_VERSION (2, 16, 0)
+        char *md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, priv->repo_uri, -1);
+#else
+        char *md5 = g_strdup(osm_gps_map_source_get_friendly_name(priv->map_source));
+#endif
+        priv->cache_dir = g_strdup_printf("%s%c%s", base, G_DIR_SEPARATOR, md5);
+        g_free(base);
         g_free(md5);
+    } else if ( g_strcmp0(priv->tile_dir, OSM_GPS_MAP_CACHE_FRIENDLY) == 0 ) {
+        char *base = osm_gps_map_get_cache_dir(priv);
+        const char *fname = osm_gps_map_source_get_friendly_name(priv->map_source);
+        priv->cache_dir = g_strdup_printf("%s%c%s", base, G_DIR_SEPARATOR, fname);
+        g_free(base);
+    } else {
+        priv->cache_dir = g_strdup(priv->tile_dir);
     }
+    g_debug("Cache dir: %s", priv->cache_dir);
+}
+
+static GObject *
+osm_gps_map_constructor (GType gtype, guint n_properties, GObjectConstructParam *properties)
+{
+    //Always chain up to the parent constructor
+    GObject *object = 
+        G_OBJECT_CLASS(osm_gps_map_parent_class)->constructor(gtype, n_properties, properties);
+
+    osm_gps_map_setup(OSM_GPS_MAP_PRIVATE(object));
 
-    inspect_map_uri(map);
+    inspect_map_uri(OSM_GPS_MAP(object));
 
     return object;
 }
@@ -1351,6 +1481,11 @@ osm_gps_map_dispose (GObject *object)
     if (priv->idle_map_redraw != 0)
         g_source_remove (priv->idle_map_redraw);
 
+    if (priv->drag_expose != 0)
+        g_source_remove (priv->drag_expose);
+
+    g_free(priv->gps);
+
     G_OBJECT_CLASS (osm_gps_map_parent_class)->dispose (object);
 }
 
@@ -1360,7 +1495,12 @@ osm_gps_map_finalize (GObject *object)
     OsmGpsMap *map = OSM_GPS_MAP(object);
     OsmGpsMapPrivate *priv = map->priv;
 
-    g_free(priv->cache_dir);
+    if (priv->tile_dir)
+        g_free(priv->tile_dir);
+
+    if (priv->cache_dir)
+        g_free(priv->cache_dir);
+
     g_free(priv->repo_uri);
     g_free(priv->image_format);
 
@@ -1396,33 +1536,34 @@ osm_gps_map_set_property (GObject *object, guint prop_id, const GValue *value, G
             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);
 
+#ifndef LIBSOUP22
+                GValue val = {0};
+
                 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
+                SoupUri* uri = soup_uri_new(priv->proxy_uri);
+                g_object_set(G_OBJECT(priv->soup_session), SOUP_SESSION_PROXY_URI, uri, NULL);
+#endif
             } else
                 priv->proxy_uri = NULL;
 
             break;
         case PROP_TILE_CACHE_DIR:
-            if ( g_value_get_string(value) )
-                priv->cache_dir = g_value_dup_string (value);
-            else {
-                priv->cache_dir = g_build_filename(
-                                    g_get_tmp_dir(),
-                                    "osmgpsmap",
-                                    NULL);
-            }
+            priv->tile_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);
+        case PROP_TILE_CACHE_BASE_DIR:
+            priv->tile_base_dir = g_value_dup_string (value);
             break;
+        case PROP_TILE_CACHE_DIR_IS_FULL_PATH:
+             g_warning("GObject property tile-cache-is-full-path depreciated");
+             break;
         case PROP_ZOOM:
             priv->map_zoom = g_value_get_int (value);
             break;
@@ -1434,11 +1575,11 @@ osm_gps_map_set_property (GObject *object, guint prop_id, const GValue *value, G
             break;
         case PROP_MAP_X:
             priv->map_x = g_value_get_int (value);
-            priv->center_coord_set = FALSE;
+            center_coord_update(map);
             break;
         case PROP_MAP_Y:
             priv->map_y = g_value_get_int (value);
-            priv->center_coord_set = FALSE;
+            center_coord_update(map);
             break;
         case PROP_GPS_TRACK_WIDTH:
             priv->ui_gps_track_width = g_value_get_int (value);
@@ -1449,9 +1590,31 @@ osm_gps_map_set_property (GObject *object, guint prop_id, const GValue *value, G
         case PROP_GPS_POINT_R2:
             priv->ui_gps_point_outer_radius = g_value_get_int (value);
             break;
-        case PROP_MAP_SOURCE:
+        case PROP_MAP_SOURCE: {
+            gint old = priv->map_source;
             priv->map_source = g_value_get_int (value);
-            break;
+            if(old >= OSM_GPS_MAP_SOURCE_NULL && 
+               priv->map_source != old &&
+               priv->map_source >= OSM_GPS_MAP_SOURCE_NULL &&
+               priv->map_source <= OSM_GPS_MAP_SOURCE_LAST) {
+
+                /* we now have to switch the entire map */
+
+                /* flush the ram cache */
+                g_hash_table_remove_all(priv->tile_cache);
+
+                osm_gps_map_setup(priv);
+
+                inspect_map_uri(map);
+
+                /* adjust zoom if necessary */
+                if(priv->map_zoom > priv->max_zoom) 
+                    osm_gps_map_set_zoom(map, priv->max_zoom);
+
+                if(priv->map_zoom < priv->min_zoom)
+                    osm_gps_map_set_zoom(map, priv->min_zoom);
+
+            } } break;
         case PROP_IMAGE_FORMAT:
             priv->image_format = g_value_dup_string (value);
             break;
@@ -1465,7 +1628,6 @@ 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;
 
@@ -1492,8 +1654,11 @@ osm_gps_map_get_property (GObject *object, guint prop_id, GValue *value, GParamS
         case PROP_TILE_CACHE_DIR:
             g_value_set_string(value, priv->cache_dir);
             break;
+        case PROP_TILE_CACHE_BASE_DIR:
+            g_value_set_string(value, priv->tile_base_dir);
+            break;
         case PROP_TILE_CACHE_DIR_IS_FULL_PATH:
-            g_value_set_boolean(value, priv->cache_dir_is_full_path);
+            g_value_set_boolean(value, FALSE);
             break;
         case PROP_ZOOM:
             g_value_set_int(value, priv->map_zoom);
@@ -1505,14 +1670,10 @@ osm_gps_map_get_property (GObject *object, guint prop_id, GValue *value, GParamS
             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));
+            g_value_set_float(value, rad2deg(priv->center_rlat));
             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));
+            g_value_set_float(value, rad2deg(priv->center_rlon));
             break;
         case PROP_MAP_X:
             g_value_set_int(value, priv->map_x);
@@ -1567,6 +1728,7 @@ osm_gps_map_button_press (GtkWidget *widget, GdkEventButton *event)
 {
     OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
 
+    priv->button_down = TRUE;
     priv->drag_counter = 0;
     priv->drag_start_mouse_x = (int) event->x;
     priv->drag_start_mouse_y = (int) event->y;
@@ -1579,8 +1741,12 @@ osm_gps_map_button_press (GtkWidget *widget, GdkEventButton *event)
 static gboolean
 osm_gps_map_button_release (GtkWidget *widget, GdkEventButton *event)
 {
+    OsmGpsMap *map = OSM_GPS_MAP(widget);
     OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
 
+    if(!priv->button_down)
+        return FALSE;
+
     if (priv->dragging)
     {
         priv->dragging = FALSE;
@@ -1591,15 +1757,27 @@ osm_gps_map_button_release (GtkWidget *widget, GdkEventButton *event)
         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;
+        center_coord_update(map);
 
-        osm_gps_map_map_redraw_idle(OSM_GPS_MAP(widget));
+        osm_gps_map_map_redraw_idle(map);
     }
 
-    priv->drag_mouse_dx = 0;
-    priv->drag_mouse_dy = 0;
-    priv->drag_counter = 0;
+    priv->drag_counter = -1;
+    priv->button_down = 0;
+
+    return FALSE;
+}
 
+static gboolean
+osm_gps_map_expose (GtkWidget *widget, GdkEventExpose  *event);
+
+static gboolean
+osm_gps_map_map_expose (GtkWidget *widget)
+{
+    OsmGpsMapPrivate *priv = OSM_GPS_MAP(widget)->priv;
+
+    priv->drag_expose = 0;
+    osm_gps_map_expose (widget, NULL);
     return FALSE;
 }
 
@@ -1610,6 +1788,9 @@ osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion  *event)
     GdkModifierType state;
     OsmGpsMapPrivate *priv = OSM_GPS_MAP_PRIVATE(widget);
 
+    if(!priv->button_down)
+        return FALSE;
+
     if (event->is_hint)
         gdk_window_get_pointer (event->window, &x, &y, &state);
     else
@@ -1623,12 +1804,18 @@ osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion  *event)
     if (!(state & GDK_BUTTON1_MASK))
         return FALSE;
 
-    priv->drag_counter++;
+    if (priv->drag_counter < 0) 
+        return FALSE;
 
-    // we havent dragged more than 6 pixels
-    if (priv->drag_counter < 6)
+    /* not yet dragged far enough? */
+    if(!priv->drag_counter &&
+       ( (x - priv->drag_start_mouse_x) * (x - priv->drag_start_mouse_x) + 
+         (y - priv->drag_start_mouse_y) * (y - priv->drag_start_mouse_y) <
+         10*10))
         return FALSE;
 
+    priv->drag_counter++;
+
     priv->dragging = TRUE;
 
     if (priv->map_auto_center)
@@ -1637,55 +1824,10 @@ osm_gps_map_motion_notify (GtkWidget *widget, GdkEventMotion  *event)
     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);
-    }
+    /* instead of redrawing directly just add an idle function */
+    if (!priv->drag_expose)
+        priv->drag_expose = 
+            g_idle_add ((GSourceFunc)osm_gps_map_map_expose, widget);
 
     return FALSE;
 }
@@ -1700,10 +1842,17 @@ osm_gps_map_configure (GtkWidget *widget, GdkEventConfigure *event)
         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);
+                        widget->window,
+                        widget->allocation.width + EXTRA_BORDER * 2,
+                        widget->allocation.height + EXTRA_BORDER * 2,
+                        -1);
+
+    // pixel_x,y, offsets
+    gint pixel_x = lon2pixel(priv->map_zoom, priv->center_rlon);
+    gint pixel_y = lat2pixel(priv->map_zoom, priv->center_rlat);
+
+    priv->map_x = pixel_x - widget->allocation.width/2;
+    priv->map_y = pixel_y - widget->allocation.height/2;
 
     /* and gc, used for clipping (I think......) */
     if(priv->gc_map)
@@ -1713,6 +1862,8 @@ osm_gps_map_configure (GtkWidget *widget, GdkEventConfigure *event)
 
     osm_gps_map_map_redraw(OSM_GPS_MAP(widget));
 
+    g_signal_emit_by_name(widget, "changed");
+
     return FALSE;
 }
 
@@ -1721,13 +1872,65 @@ 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);
+    GdkDrawable *drawable = widget->window;
+
+    if (!priv->drag_mouse_dx && !priv->drag_mouse_dy && event)
+    {
+        gdk_draw_drawable (drawable,
+                           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);
+    }
+    else
+    {
+        gdk_draw_drawable (drawable,
+                           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 (drawable,
+                                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 (drawable,
+                                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 (drawable,
+                                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 (drawable,
+                                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;
 }
@@ -1806,22 +2009,30 @@ osm_gps_map_class_init (OsmGpsMapClass *klass)
                                      g_param_spec_string ("tile-cache",
                                                           "tile cache",
                                                           "osm local tile cache dir",
-                                                          NULL,
+                                                          OSM_GPS_MAP_CACHE_AUTO,
                                                           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));
+                                     PROP_TILE_CACHE_BASE_DIR,
+                                     g_param_spec_string ("tile-cache-base",
+                                                          "tile cache-base",
+                                                          "base directory to which friendly and auto paths are appended",
+                                                          NULL,
+                                                          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",
+                                                            "DEPRECIATED",
+                                                            FALSE,
+                                                            G_PARAM_READABLE | G_PARAM_WRITABLE));
 
     g_object_class_install_property (object_class,
                                      PROP_ZOOM,
                                      g_param_spec_int ("zoom",
                                                        "zoom",
-                                                       "zoom level",
+                                                       "initial zoom level",
                                                        MIN_ZOOM, /* minimum property value */
                                                        MAX_ZOOM, /* maximum property value */
                                                        3,
@@ -1935,7 +2146,7 @@ osm_gps_map_class_init (OsmGpsMapClass *klass)
                                                        -1,           /* minimum property value */
                                                        G_MAXINT,    /* maximum property value */
                                                        -1,
-                                                       G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+                                                       G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
 
     g_object_class_install_property (object_class,
                                      PROP_IMAGE_FORMAT,
@@ -1944,6 +2155,10 @@ osm_gps_map_class_init (OsmGpsMapClass *klass)
                                                           "map source tile repository image format (jpg, png)",
                                                           OSM_IMAGE_FORMAT,
                                                           G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+    g_signal_new ("changed", OSM_TYPE_GPS_MAP,
+                  G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
 }
 
 const char* 
@@ -1954,11 +2169,17 @@ osm_gps_map_source_get_friendly_name(OsmGpsMapSource_t source)
         case OSM_GPS_MAP_SOURCE_NULL:
             return "None";
         case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:
-            return "OpenStreetMap";
+            return "OpenStreetMap I";
         case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
-            return "OpenStreetMap Renderer";
+            return "OpenStreetMap II";
         case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
             return "OpenAerialMap";
+        case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
+            return "OpenCycleMap";
+        case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
+            return "Public Transport";
+        case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
+            return "OSMC Trails";
         case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
             return "Maps-For-Free";
         case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:
@@ -1979,6 +2200,7 @@ osm_gps_map_source_get_friendly_name(OsmGpsMapSource_t source)
             return "Yahoo Satellite";
         case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
             return "Yahoo Hybrid";
+        case OSM_GPS_MAP_SOURCE_LAST:
         default:
             return NULL;
     }
@@ -2001,14 +2223,23 @@ osm_gps_map_source_get_repo_uri(OsmGpsMapSource_t source)
         case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
             /* OpenAerialMap is down, offline till furthur notice
                http://openaerialmap.org/pipermail/talk_openaerialmap.org/2008-December/000055.html */
+            return NULL;
         case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
             return "http://tah.openstreetmap.org/Tiles/tile/#Z/#X/#Y.png";
+        case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
+            return "http://c.andy.sandbox.cloudmade.com/tiles/cycle/#Z/#X/#Y.png";
+        case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
+            return "http://tile.xn--pnvkarte-m4a.de/tilegen/#Z/#X/#Y.png";
+        case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
+            return "http://topo.geofabrik.de/trails/#Z/#X/#Y.png";
         case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
             return "http://maps-for-free.com/layer/relief/z#Z/row#Y/#Z_#X-#Y.jpg";
         case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:
             return "http://mt#R.google.com/vt/v=w2.97&x=#X&y=#Y&z=#Z";
         case OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID:
-            /* No longer working  "http://mt#R.google.com/mt?n=404&v=w2t.99&x=#X&y=#Y&zoom=#S" */
+            /* No longer working
+               "http://mt#R.google.com/mt?n=404&v=w2t.99&x=#X&y=#Y&zoom=#S" */
+            return NULL;
         case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:
             return "http://khm#R.google.com/kh/v=51&x=#X&y=#Y&z=#Z";
         case OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_STREET:
@@ -2027,6 +2258,7 @@ osm_gps_map_source_get_repo_uri(OsmGpsMapSource_t source)
              *  z = zoom - (MAX_ZOOM - 17));
              */
             return NULL;
+        case OSM_GPS_MAP_SOURCE_LAST:
         default:
             return NULL;
     }
@@ -2040,6 +2272,9 @@ osm_gps_map_source_get_image_format(OsmGpsMapSource_t source)
         case OSM_GPS_MAP_SOURCE_NULL:
         case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:
         case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
+        case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
+        case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
+        case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
             return "png";
         case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
         case OSM_GPS_MAP_SOURCE_GOOGLE_STREET:
@@ -2053,6 +2288,7 @@ osm_gps_map_source_get_image_format(OsmGpsMapSource_t source)
         case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
         case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:
             return "jpg";
+        case OSM_GPS_MAP_SOURCE_LAST:
         default:
             return "bin";
     }
@@ -2073,6 +2309,8 @@ osm_gps_map_source_get_max_zoom(OsmGpsMapSource_t source)
         case OSM_GPS_MAP_SOURCE_NULL:
             return 18;
         case OSM_GPS_MAP_SOURCE_OPENSTREETMAP:
+        case OSM_GPS_MAP_SOURCE_OPENCYCLEMAP:
+        case OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT:
             return OSM_MAX_ZOOM;
         case OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER:
         case OSM_GPS_MAP_SOURCE_OPENAERIALMAP:
@@ -2085,16 +2323,25 @@ osm_gps_map_source_get_max_zoom(OsmGpsMapSource_t source)
         case OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE:
         case OSM_GPS_MAP_SOURCE_YAHOO_HYBRID:
             return 17;
+        case OSM_GPS_MAP_SOURCE_OSMC_TRAILS:
+            return 15;
         case OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE:
             return 11;
         case OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE:
             return 18;
+        case OSM_GPS_MAP_SOURCE_LAST:
         default:
             return 17;
     }
     return 17;
 }
 
+gboolean
+osm_gps_map_source_is_valid(OsmGpsMapSource_t source)
+{
+    return osm_gps_map_source_get_repo_uri(source) != NULL;
+}
+
 void
 osm_gps_map_download_maps (OsmGpsMap *map, coord_t *pt1, coord_t *pt2, int zoom_start, int zoom_end)
 {
@@ -2177,7 +2424,6 @@ osm_gps_map_set_center (OsmGpsMap *map, float latitude, float longitude)
 
     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);
@@ -2187,13 +2433,15 @@ osm_gps_map_set_center (OsmGpsMap *map, float latitude, float longitude)
     priv->map_y = pixel_y - GTK_WIDGET(map)->allocation.height/2;
 
     osm_gps_map_map_redraw_idle(map);
+
+    g_signal_emit_by_name(map, "changed");
 }
 
 int 
 osm_gps_map_set_zoom (OsmGpsMap *map, int zoom)
 {
     int zoom_old;
-    double factor;
+    double factor = 0.0;
     int width_center, height_center;
     OsmGpsMapPrivate *priv;
 
@@ -2209,22 +2457,16 @@ osm_gps_map_set_zoom (OsmGpsMap *map, int 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;
-        }
+        priv->map_x = lon2pixel(priv->map_zoom, priv->center_rlon) - width_center;
+        priv->map_y = lat2pixel(priv->map_zoom, priv->center_rlat) - height_center;
 
+        factor = pow(2, priv->map_zoom-zoom_old);
         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);
+
+        g_signal_emit_by_name(map, "changed");
     }
     return priv->map_zoom;
 }
@@ -2244,6 +2486,29 @@ osm_gps_map_add_track (OsmGpsMap *map, GSList *track)
 }
 
 void
+osm_gps_map_replace_track (OsmGpsMap *map, GSList *old_track, GSList *new_track)
+{
+    OsmGpsMapPrivate *priv;
+
+    if(!old_track) {
+        osm_gps_map_add_track (map, new_track);
+        return;
+    }
+
+    g_return_if_fail (OSM_IS_GPS_MAP (map));
+    priv = map->priv;
+
+    GSList *old = g_slist_find(priv->tracks, old_track);
+    if(!old) {
+        g_warning("track to be replaced not found");
+        return;
+    }
+
+    old->data = new_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));
@@ -2253,7 +2518,7 @@ osm_gps_map_clear_tracks (OsmGpsMap *map)
 }
 
 void
-osm_gps_map_add_image (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image)
+osm_gps_map_add_image_with_alignment (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image, float xalign, float yalign)
 {
     g_return_if_fail (OSM_IS_GPS_MAP (map));
 
@@ -2268,6 +2533,10 @@ osm_gps_map_add_image (OsmGpsMap *map, float latitude, float longitude, GdkPixbu
         im->pt.rlat = deg2rad(latitude);
         im->pt.rlon = deg2rad(longitude);
 
+        //handle alignment
+        im->xoffset = xalign * im->w;
+        im->yoffset = yalign * im->h;
+
         g_object_ref(image);
         im->image = image;
 
@@ -2277,6 +2546,12 @@ osm_gps_map_add_image (OsmGpsMap *map, float latitude, float longitude, GdkPixbu
     }
 }
 
+void
+osm_gps_map_add_image (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image)
+{
+    osm_gps_map_add_image_with_alignment (map, latitude, longitude, image, 0.5, 0.5);
+}
+
 gboolean
 osm_gps_map_remove_image (OsmGpsMap *map, GdkPixbuf *image)
 {
@@ -2309,67 +2584,6 @@ osm_gps_map_clear_images (OsmGpsMap *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;
@@ -2381,6 +2595,7 @@ osm_gps_map_draw_gps (OsmGpsMap *map, float latitude, float longitude, float hea
     priv->gps->rlat = deg2rad(latitude);
     priv->gps->rlon = deg2rad(longitude);
     priv->gps_valid = TRUE;
+    priv->gps_heading = deg2rad(heading);
 
     // pixel_x,y, offsets
     pixel_x = lon2pixel(priv->map_zoom, priv->gps->rlon);
@@ -2411,7 +2626,7 @@ osm_gps_map_draw_gps (OsmGpsMap *map, float latitude, float longitude, float hea
 
             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;
+            center_coord_update(map);
         }
     }
 
@@ -2470,9 +2685,11 @@ osm_gps_map_geographic_to_screen (OsmGpsMap *map,
     priv = map->priv;
 
     if (pixel_x)
-        *pixel_x = lon2pixel(priv->map_zoom, deg2rad(longitude)) - priv->map_x;
+        *pixel_x = lon2pixel(priv->map_zoom, deg2rad(longitude)) -
+            priv->map_x + priv->drag_mouse_dx;
     if (pixel_y)
-        *pixel_y = lat2pixel(priv->map_zoom, deg2rad(latitude)) - priv->map_y;
+        *pixel_y = lat2pixel(priv->map_zoom, deg2rad(latitude)) -
+            priv->map_y + priv->drag_mouse_dy;
 }
 
 void
@@ -2483,9 +2700,9 @@ osm_gps_map_scroll (OsmGpsMap *map, gint dx, gint dy)
     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;
+    center_coord_update(map);
 
     osm_gps_map_map_redraw_idle (map);
 }
@@ -2495,7 +2712,7 @@ osm_gps_map_get_scale(OsmGpsMap *map)
 {
     OsmGpsMapPrivate *priv;
 
-    g_return_if_fail (OSM_IS_GPS_MAP (map));
+    g_return_val_if_fail (OSM_IS_GPS_MAP (map), OSM_GPS_MAP_INVALID);
     priv = map->priv;
 
     return osm_gps_map_get_scale_at_point(priv->map_zoom, priv->center_rlat, priv->center_rlon);
@@ -2509,3 +2726,12 @@ char * osm_gps_map_get_default_cache_directory(void)
                         NULL);
 }
 
+void osm_gps_map_set_keyboard_shortcut(OsmGpsMap *map, OsmGpsMapKey_t key, guint keyval)
+{
+    g_return_if_fail (OSM_IS_GPS_MAP (map));
+    g_return_if_fail(key < OSM_GPS_MAP_KEY_MAX);
+
+    map->priv->keybindings[key] = keyval;
+    map->priv->keybindings_enabled = TRUE;
+}
+
diff --git a/src/osm-gps-map.h b/src/osm-gps-map.h
index 01a4618..6a3e740 100644
--- a/src/osm-gps-map.h
+++ b/src/osm-gps-map.h
@@ -4,6 +4,7 @@
  * osm-gps-map.h
  * Copyright (C) Marcus Bauer 2008 <marcus.bauer at gmail.com>
  * Copyright (C) John Stowers 2009 <john.stowers at gmail.com>
+ * Copyright (C) Till Harbaum 2009 <till at harbaum.org>
  *
  * Contributions by
  * Everaldo Canuto 2009 <everaldo.canuto at gmail.com>
@@ -65,6 +66,8 @@ typedef enum {
     OSM_GPS_MAP_SOURCE_OPENSTREETMAP_RENDERER,
     OSM_GPS_MAP_SOURCE_OPENAERIALMAP,
     OSM_GPS_MAP_SOURCE_MAPS_FOR_FREE,
+    OSM_GPS_MAP_SOURCE_OPENCYCLEMAP,
+    OSM_GPS_MAP_SOURCE_OSM_PUBLIC_TRANSPORT,
     OSM_GPS_MAP_SOURCE_GOOGLE_STREET,
     OSM_GPS_MAP_SOURCE_GOOGLE_SATELLITE,
     OSM_GPS_MAP_SOURCE_GOOGLE_HYBRID,
@@ -73,42 +76,61 @@ typedef enum {
     OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_HYBRID,
     OSM_GPS_MAP_SOURCE_YAHOO_STREET,
     OSM_GPS_MAP_SOURCE_YAHOO_SATELLITE,
-    OSM_GPS_MAP_SOURCE_YAHOO_HYBRID
+    OSM_GPS_MAP_SOURCE_YAHOO_HYBRID,
+    OSM_GPS_MAP_SOURCE_OSMC_TRAILS,
+
+    OSM_GPS_MAP_SOURCE_LAST
 } OsmGpsMapSource_t;
 
-GType osm_gps_map_get_type (void) G_GNUC_CONST;
-
-const char* osm_gps_map_source_get_friendly_name(OsmGpsMapSource_t source);
-const char* osm_gps_map_source_get_repo_uri(OsmGpsMapSource_t source);
-const char *osm_gps_map_source_get_image_format(OsmGpsMapSource_t source);
-int osm_gps_map_source_get_min_zoom(OsmGpsMapSource_t source);
-int osm_gps_map_source_get_max_zoom(OsmGpsMapSource_t source);
-
-char * osm_gps_map_get_default_cache_directory(void);
-
-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);
-gboolean osm_gps_map_remove_image (OsmGpsMap *map, 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);
-float osm_gps_map_get_scale(OsmGpsMap *map);
+typedef enum {
+    OSM_GPS_MAP_KEY_FULLSCREEN,
+    OSM_GPS_MAP_KEY_ZOOMIN,
+    OSM_GPS_MAP_KEY_ZOOMOUT,
+    OSM_GPS_MAP_KEY_UP,
+    OSM_GPS_MAP_KEY_DOWN,
+    OSM_GPS_MAP_KEY_LEFT,
+    OSM_GPS_MAP_KEY_RIGHT,
+    OSM_GPS_MAP_KEY_MAX
+} OsmGpsMapKey_t;
+
+#define OSM_GPS_MAP_INVALID         (0.0/0.0)
+#define OSM_GPS_MAP_CACHE_DISABLED  "none://"
+#define OSM_GPS_MAP_CACHE_AUTO      "auto://"
+#define OSM_GPS_MAP_CACHE_FRIENDLY  "friendly://"
+
+GType       osm_gps_map_get_type                    (void) G_GNUC_CONST;
+
+GtkWidget*  osm_gps_map_new                         (void);
+
+char*       osm_gps_map_get_default_cache_directory (void);
+
+const char* osm_gps_map_source_get_friendly_name    (OsmGpsMapSource_t source);
+const char* osm_gps_map_source_get_repo_uri         (OsmGpsMapSource_t source);
+const char* osm_gps_map_source_get_image_format     (OsmGpsMapSource_t source);
+int         osm_gps_map_source_get_min_zoom         (OsmGpsMapSource_t source);
+int         osm_gps_map_source_get_max_zoom         (OsmGpsMapSource_t source);
+gboolean    osm_gps_map_source_is_valid             (OsmGpsMapSource_t source);
+
+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_replace_track               (OsmGpsMap *map, GSList *old_track, GSList *new_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_add_image_with_alignment    (OsmGpsMap *map, float latitude, float longitude, GdkPixbuf *image, float xalign, float yalign);
+gboolean    osm_gps_map_remove_image                (OsmGpsMap *map, GdkPixbuf *image);
+void        osm_gps_map_clear_images                (OsmGpsMap *map);
+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);
+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);
+float       osm_gps_map_get_scale                   (OsmGpsMap *map);
+void        osm_gps_map_set_keyboard_shortcut       (OsmGpsMap *map, OsmGpsMapKey_t key, guint keyval);
 
 G_END_DECLS
 

-- 
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