]> git.itanic.dy.fi Git - maemo-mapper/commitdiff
Made changes mentioned in changelog for Maemo Mapper v1.2.
authorgnuite <gnuite@gmail.com>
Thu, 19 Oct 2006 01:50:32 +0000 (01:50 +0000)
committergnuite <gnuite@gmail.com>
Thu, 19 Oct 2006 01:50:32 +0000 (01:50 +0000)
git-svn-id: svn+ssh://garage/var/lib/gforge/svnroot/maemo-mapper/trunk@28 6c538b50-5814-0410-93ad-8bdf4c0149d1

configure.ac
data/maemo-mapper.desktop
debian/changelog
debian/control
po/en_US.po
po/it_IT.po
po/nl_NL.po
src/Makefile.am
src/maemo-mapper.c
src/maemo-mapper.sh [new file with mode: 0644]

index e5dd4452065f0a1ed4be2e2343feb3f7810e5cd8..3e32f8c0918cd9a0e571259dd83e2740c3474893 100644 (file)
@@ -19,7 +19,7 @@
 #
 
 AC_INIT(Makefile.am)
-AM_INIT_AUTOMAKE(maemo-mapper, 1.1)
+AM_INIT_AUTOMAKE(maemo-mapper, 1.2)
 
 AC_PROG_CPP
 AC_CONFIG_HEADERS(src/config.h)
@@ -51,12 +51,16 @@ PKG_CHECK_MODULES(LIBXML2, libxml-2.0 >= 2.6.16)
 AC_SUBST(LIBXML2_LIBS)
 AC_SUBST(LIBXML2_CFLAGS)
 
+PKG_CHECK_MODULES(SQLITE, sqlite)
+AC_SUBST(SQLITE_LIBS)
+AC_SUBST(SQLITE_CFLAGS)
+
 
 # Localisation
 GETTEXT_PACKAGE=$PACKAGE
 AC_SUBST(GETTEXT_PACKAGE)
 AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], "${GETTEXT_PACKAGE}", [Name of gettext package])
-ALL_LINGUAS="en_US nl_NL"
+ALL_LINGUAS="en_US nl_NL it_IT"
 AM_GLIB_GNU_GETTEXT
 
 # To make application visible in maemo Task Navigator it needs a Desktop
index d921df0c6a965402c933d0e3f12f37a559670f2e..b93cfa3ebfdc44b325aee7645095449c0baeaab6 100644 (file)
@@ -3,8 +3,9 @@ Encoding=UTF-8
 Version=1.0
 Type=Application
 Name=Maemo Mapper
-Exec=/usr/bin/maemo-mapper
+Exec=/usr/bin/maemo-mapper.sh
 Icon=maemo-mapper
+StartupWMClass=maemo-mapper
 X-Window-Icon=maemo-mapper
 X-HildonDesk-ShowInToolbar=true
 X-Osso-Service=com.gnuite.maemo_mapper
index 0a4c8a9357cef279c0d60f93418fe3d2807b6442..b2dfe091c6f8b3a543afd650ea8708a094244b98 100644 (file)
@@ -1,3 +1,21 @@
+maemo-mapper (1.2) unstable; urgency=low
+
+  * Added support for multiple repositories. (closes #7)
+  * Added support for POI (including category editing). (closes #22)
+  * Added support for Textual GPS information. (closes #13)
+  * Added ability to delete or "re-download" maps. (closes #25)
+  * Added feature to zoom by more than one level at a time. (closes #39)
+  * Fixed seg fault when switching map cache directories. (closes #64)
+  * Fixed locale issue with route auto-update. (closes #62)
+  * Fixed broken hashing (wrt equals). (closes #58)
+  * Fixed crash that occurred when map uri is blank. (closes #50)
+  * Added auto-connect to internet when needed (downloading maps).
+  * Added ability to manually reset bluetooth radio.
+  * Added ability to re-assign the Escape Key.
+  * Changed IO read mechanism slightly to try to avoid bluetooth errors.
+
+ -- John Costigan <gnuite@gmail.com>  Sun, 15 Oct 2006 12:24:26 -0400
+
 maemo-mapper (1.1) unstable; urgency=low
 
   * Added ability to customize the colors. (closes #11)
index 3e79e77d4357cd39b5d611835c4dcd967602cfe8..b55004793e51b21a897a799f7b5b92793d2e8fbd 100644 (file)
@@ -9,7 +9,7 @@ Package: maemo-mapper
 Architecture: armel arm i386
 Pre-Depends: maemo-select-menu-location
 Depends: ${shlibs:Depends}
-Description: Maemo Mapper is geographical mapping softare specifically designed
+Description: Geographical mapping softare specifically designed
  for the Maemo platform and the Nokia 770 form factor.  It includes support for
  visualizing GPS input, but is functional and useful without GPS hardware.  It
  also includes features for downloading and interacting with maps, GPX data
index d8cb2d110c47dafc157a6219030b7fdab298b035..27dfec64db631ef15dd5112b03dbd85cc10d6e5a 100644 (file)
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: maemo-mapper 1.1\n"
-"Report-Msgid-Bugs-To: John Costigan <gnuite@gmail.com>\n"
-"POT-Creation-Date: 2006-07-01 05:57-0400\n"
-"PO-Revision-Date: 2006-07-09 12:26-0400\n"
+"Project-Id-Version: maemo-mapper 1.2\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-10-14 12:43-0400\n"
+"PO-Revision-Date: 2006-10-14 12:43-0400\n"
 "Last-Translator: John Costigan <gnuite@gmail.com>\n"
 "Language-Team: John Costigan <gnuite@gmail.com>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
+#: ../src/maemo-mapper.c:4237 ../src/maemo-mapper.c:9086
+msgid "Add POI"
+msgstr "Add POI"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2426
+#: ../src/maemo-mapper.c:3288
 msgid "Advance Notice"
 msgstr "Advance Notice"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1931
+#: ../src/maemo-mapper.c:8430
+msgid "Along Route - Radius:"
+msgstr "Along Route - Radius:"
+
+#: ../src/maemo-mapper.c:1029 ../src/maemo-mapper.c:1647
+#, c-format
+msgid "Alt: %d ft"
+msgstr "Alt: %d ft"
+
+#: ../src/maemo-mapper.c:1025 ../src/maemo-mapper.c:1643
+#, c-format
+msgid "Alt: %d m"
+msgstr "Alt: %d m"
+
+#: ../src/maemo-mapper.c:1520
+msgid "Altitude"
+msgstr "Altitude"
+
+#: ../src/maemo-mapper.c:2833
 msgid "An error occurred while scanning."
 msgstr "An error occurred while scanning."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2422
+#: ../src/maemo-mapper.c:6182
+msgid ""
+"An error occurred while trying to reset the bluetooth radio.\n"
+"\n"
+"Did you make sure to modify\n"
+"the /etc/sudoers file?"
+msgstr ""
+"An error occurred while trying to reset the bluetooth radio.\n"
+"\n"
+"Did you make sure to modify\n"
+"the /etc/sudoers file?"
+
+#: ../src/maemo-mapper.c:3284
 msgid "Announce"
 msgstr "Announce"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6182
+#: ../src/maemo-mapper.c:8467
 msgid "Area"
 msgstr "Area"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2391
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3031
+#: ../src/maemo-mapper.c:3253 ../src/maemo-mapper.c:4104
 msgid "Auto-Center"
 msgstr "Auto-Center"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6045
+#: ../src/maemo-mapper.c:7802
 msgid "Auto-Center Mode: Lat/Lon"
 msgstr "Auto-Center Mode: Lat/Lon"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6029
+#: ../src/maemo-mapper.c:7786
 msgid "Auto-Center Mode: Lead"
 msgstr "Auto-Center Mode: Lead"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6059
+#: ../src/maemo-mapper.c:7816
 msgid "Auto-Center Off"
 msgstr "Auto-Center Off"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3005
+#: ../src/maemo-mapper.c:4073
 msgid "Auto-Download"
 msgstr "Auto-Download"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5484
+#: ../src/maemo-mapper.c:7241
 msgid "Auto-Update"
 msgstr "Auto-Update"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6245
+#: ../src/maemo-mapper.c:8530
 msgid "Bottom-Right"
 msgstr "Bottom-Right"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2384
+#: ../src/maemo-mapper.c:3406 ../src/maemo-mapper.c:8004
 msgid "Browse..."
 msgstr "Browse..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2374
+#: ../src/maemo-mapper.c:8421
+msgid "By Area (see tab)"
+msgstr "By Area (see tab)"
+
+#: ../src/maemo-mapper.c:7994
 msgid "Cache Dir."
 msgstr "Cache Dir."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6455
+#: ../src/maemo-mapper.c:7940
+msgid ""
+"Cannot delete the last repository - there must be at lease one repository."
+msgstr ""
+"Cannot delete the last repository - there must be at lease one repository."
+
+#: ../src/maemo-mapper.c:8751
 msgid ""
 "Cannot enable GPS until a GPS Receiver MAC is set in the Settings dialog box."
 msgstr ""
 "Cannot enable GPS until a GPS Receiver MAC is set in the Settings dialog box."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2327
+#: ../src/maemo-mapper.c:9334
+msgid "Category"
+msgstr "Category"
+
+#: ../src/maemo-mapper.c:9115 ../src/maemo-mapper.c:9482
+msgid "Category: "
+msgstr "Category: "
+
+#: ../src/maemo-mapper.c:3232
 msgid "Channel"
 msgstr "Channel"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2980
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2994
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6170
+#: ../src/maemo-mapper.c:4047 ../src/maemo-mapper.c:4061
+#: ../src/maemo-mapper.c:8374
 msgid "Clear"
 msgstr "Clear"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3073
+#: ../src/maemo-mapper.c:4155
 msgid "Close"
 msgstr "Close"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2134
+#: ../src/maemo-mapper.c:3037
 msgid "Colors"
 msgstr "Colors"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2297
+#: ../src/maemo-mapper.c:3202
 msgid "Colors..."
 msgstr "Colors..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6917
+#: ../src/maemo-mapper.c:8670
+msgid "Confirm DELETION of"
+msgstr "Confirm DELETION of"
+
+#: ../src/maemo-mapper.c:7947
+msgid "Confirm delete of repository"
+msgstr "Confirm delete of repository"
+
+#: ../src/maemo-mapper.c:9802
 msgid "Confirm delete of waypoint"
 msgstr "Confirm delete of waypoint"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6384
+#: ../src/maemo-mapper.c:8676
 msgid "Confirm download of"
 msgstr "Confirm download of"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3162
+#: ../src/maemo-mapper.c:4256
 msgid "Copy Description to Clipboard"
 msgstr "Copy Description to Clipboard"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3141
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3160
+#: ../src/maemo-mapper.c:4229 ../src/maemo-mapper.c:4254
 msgid "Copy Lat/Lon to Clipboard"
 msgstr "Copy Lat/Lon to Clipboard"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2554
-msgid "Could not create Map Cache directory."
-msgstr "Could not create Map Cache directory."
-
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2698
-msgid ""
-"Could not create Map Cache directory.\n"
-"Please set a valid Map Cache directory in the Settings dialog box."
-msgstr ""
-"Could not create Map Cache directory.\n"
-"Please set a valid Map Cache directory in the Settings dialog box."
-
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5567
+#: ../src/maemo-mapper.c:7324
 msgid ""
 "Could not generate directions. Make sure your source and destination are "
 "valid."
@@ -138,210 +182,346 @@ msgstr ""
 "Could not generate directions. Make sure your source and destination are "
 "valid."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2140
+#: ../src/maemo-mapper.c:1693
+msgid "DGPS"
+msgstr "DGPS"
+
+#: ../src/maemo-mapper.c:3891
+msgid "Default"
+msgstr "Default"
+
+#: ../src/maemo-mapper.c:3043
 msgid "Defaults"
 msgstr "Defaults"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3169
+#: ../src/maemo-mapper.c:4263 ../src/maemo-mapper.c:9451
 msgid "Delete"
 msgstr "Delete"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2017
+#: ../src/maemo-mapper.c:8411
+msgid "Delete Maps"
+msgstr "Delete Maps"
+
+#: ../src/maemo-mapper.c:9236
+#, c-format
+msgid ""
+"Delete POI?\n"
+"%s"
+msgstr ""
+"Delete POI?\n"
+"%s"
+
+#: ../src/maemo-mapper.c:8128
+msgid "Delete..."
+msgstr "Delete..."
+
+#: ../src/maemo-mapper.c:9125 ../src/maemo-mapper.c:9492
+msgid "Desc.: "
+msgstr "Desc.: "
+
+#: ../src/maemo-mapper.c:2919
 msgid "Description"
 msgstr "Description"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5501
+#: ../src/maemo-mapper.c:7258
 msgid "Destination"
 msgstr "Destination"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6698
+#: ../src/maemo-mapper.c:4138
+msgid "Details..."
+msgstr "Details..."
+
+#: ../src/maemo-mapper.c:9050
 msgid "Distance to Location"
 msgstr "Distance to Location"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6889
+#: ../src/maemo-mapper.c:9773
 msgid "Distance to Waypoint"
 msgstr "Distance to Waypoint"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3001
-msgid "Download Along Route"
-msgstr "Download Along Route"
-
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3003
-msgid "Download Area..."
-msgstr "Download Area..."
+#: ../src/maemo-mapper.c:8398
+msgid "Download Maps"
+msgstr "Download Maps"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6164
-msgid "Download Maps by Area"
-msgstr "Download Maps by Area"
-
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5458
+#: ../src/maemo-mapper.c:7215
 msgid "Download Route"
 msgstr "Download Route"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3144
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3165
+#: ../src/maemo-mapper.c:4232 ../src/maemo-mapper.c:4259
 msgid "Download Route to..."
 msgstr "Download Route to..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2974
+#: ../src/maemo-mapper.c:8009
+msgid "Download Zoom Steps"
+msgstr "Download Zoom Steps"
+
+#: ../src/maemo-mapper.c:4041
 msgid "Download..."
 msgstr "Download..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3506
+#: ../src/maemo-mapper.c:4629
 msgid "Downloading maps"
 msgstr "Downloading maps"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3058
+#: ../src/maemo-mapper.c:6495
+msgid "E"
+msgstr "E"
+
+#: ../src/maemo-mapper.c:4240 ../src/maemo-mapper.c:9445
+msgid "Edit POI"
+msgstr "Edit POI"
+
+#: ../src/maemo-mapper.c:4130
 msgid "Enable GPS"
 msgstr "Enable GPS"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2438
+#: ../src/maemo-mapper.c:3300
 msgid "Enable Voice Synthesis (requires flite)"
 msgstr "Enable Voice Synthesis (requires flite)"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4738
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5623
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5666
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5717
+#: ../src/maemo-mapper.c:6018 ../src/maemo-mapper.c:7380
+#: ../src/maemo-mapper.c:7423 ../src/maemo-mapper.c:7474
 msgid "Error parsing GPX file."
 msgstr "Error parsing GPX file."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5732
+#: ../src/maemo-mapper.c:7489
 msgid "Error while writing to file"
 msgstr "Error while writing to file"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5873
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5936
+#: ../src/maemo-mapper.c:7630 ../src/maemo-mapper.c:7693
 msgid "Error writing GPX file."
 msgstr "Error writing GPX file."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:927
+#: ../src/maemo-mapper.c:3374
+msgid "Escape Key"
+msgstr "Escape Key"
+
+#: ../src/maemo-mapper.c:1834
 msgid "Establishing GPS fix"
 msgstr "Establishing GPS fix"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5559
+#: ../src/maemo-mapper.c:1697
+msgid "Estimated"
+msgstr "Estimated"
+
+#: ../src/maemo-mapper.c:7316
 msgid "Failed to connect to GPX Directions server"
 msgstr "Failed to connect to GPX Directions server"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2660
+#: ../src/maemo-mapper.c:3581
 msgid "Failed to initialize GConf.  Quitting."
 msgstr "Failed to initialize GConf.  Quitting."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1709
+#: ../src/maemo-mapper.c:2560
 msgid "Failed to initialize GConf.  Settings were not saved."
 msgstr "Failed to initialize GConf.  Settings were not saved."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4422
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4727
+#: ../src/maemo-mapper.c:5634 ../src/maemo-mapper.c:6007
 msgid "Failed to open file for"
 msgstr "Failed to open file for"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5733
+#: ../src/maemo-mapper.c:7490
 msgid "File is incomplete."
 msgstr "File is incomplete."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3053
+#: ../src/maemo-mapper.c:1565
+msgid "Fix"
+msgstr "Fix"
+
+#: ../src/maemo-mapper.c:1574
+msgid "Fix quality"
+msgstr "Fix quality"
+
+#: ../src/maemo-mapper.c:1696
+msgid "Float RTK"
+msgstr "Float RTK"
+
+#: ../src/maemo-mapper.c:4085
 msgid "Full Screen"
 msgstr "Full Screen"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2308
+#: ../src/maemo-mapper.c:3213 ../src/maemo-mapper.c:4126
 msgid "GPS"
 msgstr "GPS"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6196
+#: ../src/maemo-mapper.c:1468
+msgid "GPS Details"
+msgstr "GPS Details"
+
+#: ../src/maemo-mapper.c:5862
+msgid "GPS Info"
+msgstr "GPS Info"
+
+#: ../src/maemo-mapper.c:1481
+msgid "GPS Information"
+msgstr "GPS Information"
+
+#: ../src/maemo-mapper.c:8481
 msgid "GPS Location"
 msgstr "GPS Location"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2152
+#: ../src/maemo-mapper.c:3055
 msgid "GPS Mark"
 msgstr "GPS Mark"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3070
+#: ../src/maemo-mapper.c:1425
+#, c-format
+msgid "HDOP: %.01f"
+msgstr "HDOP: %.01f"
+
+#: ../src/maemo-mapper.c:1529
+msgid "Heading"
+msgstr "Heading"
+
+#: ../src/maemo-mapper.c:4152
 msgid "Help"
 msgstr "Help"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2992
+#: ../src/maemo-mapper.c:4059
 msgid "Insert Breakpoint"
 msgstr "Insert Breakpoint"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6338
+#: ../src/maemo-mapper.c:8618
 msgid "Invalid Bottom-Right Latitude"
 msgstr "Invalid Bottom-Right Latitude"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6345
+#: ../src/maemo-mapper.c:8625
 msgid "Invalid Bottom-Right Longitude"
 msgstr "Invalid Bottom-Right Longitude"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5159
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5170
+#: ../src/maemo-mapper.c:6670 ../src/maemo-mapper.c:6681
 msgid "Invalid NMEA input from receiver!"
 msgstr "Invalid NMEA input from receiver!"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6324
+#: ../src/maemo-mapper.c:8604
 msgid "Invalid Top-Left Latitude"
 msgstr "Invalid Top-Left Latitude"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6331
+#: ../src/maemo-mapper.c:8611
 msgid "Invalid Top-Left Longitude"
 msgstr "Invalid Top-Left Longitude"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2490
+#: ../src/maemo-mapper.c:3352
 msgid "Keep Display On Only in Fullscreen Mode"
 msgstr "Keep Display On Only in Fullscreen Mode"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3035
+#: ../src/maemo-mapper.c:9329
+msgid "Label"
+msgstr "Label"
+
+#: ../src/maemo-mapper.c:9107 ../src/maemo-mapper.c:9474
+msgid "Label: "
+msgstr "Label: "
+
+#: ../src/maemo-mapper.c:9096 ../src/maemo-mapper.c:9460
+msgid "Lat - Lon: "
+msgstr "Lat - Lon"
+
+#: ../src/maemo-mapper.c:4108
 msgid "Lat/Lon"
 msgstr "Lat/Lon"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6186
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6632
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6751
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6803
+#: ../src/maemo-mapper.c:1493 ../src/maemo-mapper.c:8471
+#: ../src/maemo-mapper.c:8984 ../src/maemo-mapper.c:9319
+#: ../src/maemo-mapper.c:9639
 msgid "Latitude"
 msgstr "Latitude"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3041
+#: ../src/maemo-mapper.c:4114
 msgid "Lead"
 msgstr "Lead"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2408
+#: ../src/maemo-mapper.c:3270
 msgid "Lead Amount"
 msgstr "Lead Amount"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2478
+#: ../src/maemo-mapper.c:3340
 msgid "Line Width"
 msgstr "Line Width"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3133
+#: ../src/maemo-mapper.c:1538
+msgid "Local time"
+msgstr "Local time"
+
+#: ../src/maemo-mapper.c:4221
 msgid "Location"
 msgstr "Location"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6190
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6633
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6752
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6804
+#: ../src/maemo-mapper.c:1502 ../src/maemo-mapper.c:8475
+#: ../src/maemo-mapper.c:8985 ../src/maemo-mapper.c:9324
+#: ../src/maemo-mapper.c:9640
 msgid "Longitude"
 msgstr "Longitude"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2012
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2312
+#: ../src/maemo-mapper.c:2914 ../src/maemo-mapper.c:3217
 msgid "MAC"
 msgstr "MAC"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2291
+#: ../src/maemo-mapper.c:5849
+msgid "Maemo Mapper"
+msgstr "Maemo Mapper"
+
+#: ../src/maemo-mapper.c:3196
 msgid "Maemo Mapper Settings"
 msgstr "Maemo Mapper Settings"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2348
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2997
+#: ../src/maemo-mapper.c:8368
+msgid "Manage Maps"
+msgstr "Manage Maps"
+
+#: ../src/maemo-mapper.c:4069
+msgid "Manage Maps..."
+msgstr "Manage Maps..."
+
+#: ../src/maemo-mapper.c:4071
+msgid "Manage Repositories..."
+msgstr "Manage Repositories..."
+
+#: ../src/maemo-mapper.c:1698
+msgid "Manual)"
+msgstr "Manual)"
+
+#: ../src/maemo-mapper.c:4064
 msgid "Maps"
 msgstr "Maps"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2474
+#: ../src/maemo-mapper.c:3336
 msgid "Misc."
 msgstr "Misc."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2572
+#: ../src/maemo-mapper.c:1288 ../src/maemo-mapper.c:6490
+msgid "N"
+msgstr "N"
+
+#: ../src/maemo-mapper.c:6493
+msgid "NE"
+msgstr "NE"
+
+#: ../src/maemo-mapper.c:6507
+msgid "NW"
+msgstr "NW"
+
+#: ../src/maemo-mapper.c:7900 ../src/maemo-mapper.c:8079
+msgid "Name"
+msgstr "Name"
+
+#: ../src/maemo-mapper.c:7890
+msgid "New Name"
+msgstr "New Name"
+
+#: ../src/maemo-mapper.c:8069
+msgid "New Repository"
+msgstr "New Repository"
+
+#: ../src/maemo-mapper.c:8131
+msgid "New..."
+msgstr "New..."
+
+#: ../src/maemo-mapper.c:415
+msgid "Next Repository"
+msgstr "Next Repository"
+
+#: ../src/maemo-mapper.c:3478
 msgid ""
 "No GPS Receiver MAC Provided.\n"
 "GPS Disabled."
@@ -349,238 +529,409 @@ msgstr ""
 "No GPS Receiver MAC Provided.\n"
 "GPS Disabled."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1938
+#: ../src/maemo-mapper.c:2840
 msgid "No bluetooth devices found."
 msgstr "No bluetooth devices found."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5926
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6074
+#: ../src/maemo-mapper.c:7683
 msgid "No route is loaded."
 msgstr "No route is loaded."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6758
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6778
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6811
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6832
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6865
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6895
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6931
+#: ../src/maemo-mapper.c:9646 ../src/maemo-mapper.c:9666
+#: ../src/maemo-mapper.c:9695 ../src/maemo-mapper.c:9716
+#: ../src/maemo-mapper.c:9749 ../src/maemo-mapper.c:9780
+#: ../src/maemo-mapper.c:9816
 msgid "No waypoints are visible."
 msgstr "No waypoints are visible."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3047
+#: ../src/maemo-mapper.c:4120
 msgid "None"
 msgstr "None"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2339
+#: ../src/maemo-mapper.c:3244
 msgid "Note: \"Channel\" refers to the device side!"
 msgstr "Note: \"Channel\" refers to the device side!"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2972
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2988
+#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:8758
+#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:8958
+msgid ""
+"NOTE: You must set a Map URI in the Repository Manager in "
+"order to download maps."
+msgstr ""
+"NOTE: You must set a Map URI in the Repository Manager in "
+"order to download maps."
+
+#: ../src/maemo-mapper.c:4039 ../src/maemo-mapper.c:4055
 msgid "Open..."
 msgstr "Open..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5490
+#: ../src/maemo-mapper.c:7247
 msgid "Origin"
 msgstr "Origin"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2463
+#: ../src/maemo-mapper.c:8405
+msgid "Overwrite"
+msgstr "Overwrite"
+
+#: ../src/maemo-mapper.c:1434
+#, c-format
+msgid "PDOP: %.01f"
+msgstr "PDOP: %.01f"
+
+#: ../src/maemo-mapper.c:3392
+msgid "POI"
+msgstr "POI"
+
+#: ../src/maemo-mapper.c:3396
+msgid "POI database"
+msgstr "POI database"
+
+#: ../src/maemo-mapper.c:9313
+msgid "POI_ID"
+msgstr "POI_ID"
+
+#: ../src/maemo-mapper.c:1694
+msgid "PPS"
+msgstr "PPS"
+
 #  This word refers to Pitch as in of a person's voice.
+#: ../src/maemo-mapper.c:3325
 msgid "Pitch"
 msgstr "Pitch"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2037
+#: ../src/maemo-mapper.c:2939
 msgid "Please select a bluetooth device from the list."
 msgstr "Please select a bluetooth device from the list."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5535
+#: ../src/maemo-mapper.c:7292
 msgid "Please specify a start location."
 msgstr "Please specify a start location."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5542
+#: ../src/maemo-mapper.c:7299
 msgid "Please specify an end location."
 msgstr "Please specify an end location."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2978
+#: ../src/maemo-mapper.c:9202
+msgid "Problem adding POI"
+msgstr "Problem adding POI"
+
+#: ../src/maemo-mapper.c:9252
+msgid "Problem deleting POI"
+msgstr "Problem deleting POI"
+
+#: ../src/maemo-mapper.c:9574
+msgid "Problem updating POI"
+msgstr "Problem updating POI"
+
+#: ../src/maemo-mapper.c:1754
+msgid "Problem with POI database"
+msgstr "Problem with POI database"
+
+#: ../src/maemo-mapper.c:1695
+msgid "Real Time Kinematic"
+msgstr "Real Time Kinematic"
+
+#: ../src/maemo-mapper.c:8125
+msgid "Rename..."
+msgstr "Rename..."
+
+#: ../src/maemo-mapper.c:8111
+msgid "Repositories"
+msgstr "Repositories"
+
+#: ../src/maemo-mapper.c:4045
 msgid "Reset"
 msgstr "Reset"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2189
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2968
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3016
+#: ../src/maemo-mapper.c:417 ../src/maemo-mapper.c:4141
+msgid "Reset Bluetooth"
+msgstr "Reset Bluetooth"
+
+#: ../src/maemo-mapper.c:3092 ../src/maemo-mapper.c:4035
+#: ../src/maemo-mapper.c:4089
 msgid "Route"
 msgstr "Route"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5618
+#: ../src/maemo-mapper.c:7375
 msgid "Route Downloaded"
 msgstr "Route Downloaded"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4736
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5663
+#: ../src/maemo-mapper.c:6016 ../src/maemo-mapper.c:7420
 msgid "Route Opened"
 msgstr "Route Opened"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5934
+#: ../src/maemo-mapper.c:7691
 msgid "Route Saved"
 msgstr "Route Saved"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6002
+#: ../src/maemo-mapper.c:7759
 msgid "Routes are now hidden"
 msgstr "Routes are now hidden"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5995
+#: ../src/maemo-mapper.c:7752
 msgid "Routes are now shown"
 msgstr "Routes are now shown"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2976
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2990
+#: ../src/maemo-mapper.c:6499
+msgid "S"
+msgstr "S"
+
+#: ../src/maemo-mapper.c:6497
+msgid "SE"
+msgstr "SE"
+
+#: ../src/maemo-mapper.c:1692
+msgid "SPS"
+msgstr "SPS"
+
+#: ../src/maemo-mapper.c:6501
+msgid "SW"
+msgstr "SW"
+
+#: ../src/maemo-mapper.c:1126 ../src/maemo-mapper.c:1241
+#: ../src/maemo-mapper.c:1407 ../src/maemo-mapper.c:6371
+#: ../src/maemo-mapper.c:6430
+msgid "Sans Serif"
+msgstr "Sans Serif"
+
+#: ../src/maemo-mapper.c:1556
+msgid "Sat in use"
+msgstr "Sat in use"
+
+#: ../src/maemo-mapper.c:1547
+msgid "Sat in view"
+msgstr "Sat in view"
+
+#: ../src/maemo-mapper.c:1488
+msgid "Satellites details"
+msgstr "Satellites details"
+
+#: ../src/maemo-mapper.c:1413
+#, c-format
+msgid "Satellites in view: %d; in use: %d"
+msgstr "Satellites in view: %d; in use: %d"
+
+#: ../src/maemo-mapper.c:4043 ../src/maemo-mapper.c:4057
 msgid "Save..."
 msgstr "Save..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2322
+#: ../src/maemo-mapper.c:3227
 msgid "Scan..."
 msgstr "Scan..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1991
+#: ../src/maemo-mapper.c:2893
 msgid "Scanning Bluetooth Devices"
 msgstr "Scanning Bluetooth Devices"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:917
+#: ../src/maemo-mapper.c:1824
 msgid "Searching for GPS receiver"
 msgstr "Searching for GPS receiver"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1982
+#: ../src/maemo-mapper.c:2884
 msgid "Select Bluetooth Device"
 msgstr "Select Bluetooth Device"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2395
+#: ../src/maemo-mapper.c:9276
+msgid "Select POI"
+msgstr "Select POI"
+
+#: ../src/maemo-mapper.c:9352
+msgid "Select one POI from the list."
+msgstr "Select one POI from the list."
+
+#: ../src/maemo-mapper.c:3257
 msgid "Sensitivity"
 msgstr "Sensitivity"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3065
+#: ../src/maemo-mapper.c:4147
 msgid "Settings..."
 msgstr "Settings..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3012
-msgid "Show"
-msgstr "Show"
+#: ../src/maemo-mapper.c:8388
+msgid "Setup"
+msgstr "Setup"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3158
+#: ../src/maemo-mapper.c:4252
 msgid "Show Description"
 msgstr "Show Description"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3146
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3167
+#: ../src/maemo-mapper.c:4234 ../src/maemo-mapper.c:4261
 msgid "Show Distance to"
 msgstr "Show Distance to"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3139
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3156
+#: ../src/maemo-mapper.c:4134
+msgid "Show Information"
+msgstr "Show Information"
+
+#: ../src/maemo-mapper.c:4227 ../src/maemo-mapper.c:4250
 msgid "Show Lat/Lon"
 msgstr "Show Lat/Lon"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2451
+#: ../src/maemo-mapper.c:3411
+msgid "Show POI below zoom"
+msgstr "Show POI below zoom"
+
+#: ../src/maemo-mapper.c:1699
+msgid "Simulation"
+msgstr "Simulation"
+
+#: ../src/maemo-mapper.c:1010 ../src/maemo-mapper.c:1628
+#, c-format
+msgid "Spd: %.1f km/h"
+msgstr "Spd: %.1f km/h"
+
+#: ../src/maemo-mapper.c:1016 ../src/maemo-mapper.c:1634
+#, c-format
+msgid "Spd: %.1f kn"
+msgstr "Spd: %.1f kn"
+
+#: ../src/maemo-mapper.c:1013 ../src/maemo-mapper.c:1631
+#, c-format
+msgid "Spd: %.1f mph"
+msgstr "Spd: %.1f mph"
+
+#: ../src/maemo-mapper.c:1511 ../src/maemo-mapper.c:3313
 msgid "Speed"
 msgstr "Speed"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6231
+#: ../src/maemo-mapper.c:413
+msgid "Toggle Tracks"
+msgstr "Toggle Tracks"
+
+#: ../src/maemo-mapper.c:8516
 msgid "Top-Left"
 msgstr "Top-Left"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2173
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2984
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3021
+#: ../src/maemo-mapper.c:3076 ../src/maemo-mapper.c:4051
+#: ../src/maemo-mapper.c:4094
 msgid "Track"
 msgstr "Track"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5714
+#: ../src/maemo-mapper.c:7471
 msgid "Track Opened"
 msgstr "Track Opened"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5871
+#: ../src/maemo-mapper.c:7628
 msgid "Track Saved"
 msgstr "Track Saved"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5976
+#: ../src/maemo-mapper.c:7733
 msgid "Tracks are now hidden"
 msgstr "Tracks are now hidden"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5969
+#: ../src/maemo-mapper.c:7726
 msgid "Tracks are now shown"
 msgstr "Tracks are now shown"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2352
+#: ../src/maemo-mapper.c:7985
 msgid "URI Format"
 msgstr "URI Format"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2495
+#: ../src/maemo-mapper.c:8221
+msgid "Unable to create cache directory for repository"
+msgstr "Unable to create cache directory for repository"
+
+#: ../src/maemo-mapper.c:3360
 msgid "Units"
 msgstr "Units"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1952
+#: ../src/maemo-mapper.c:2854
 msgid "Unknown"
 msgstr "Unknown"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5480
+#: ../src/maemo-mapper.c:7237
 msgid "Use GPS Location"
 msgstr "Use GPS Location"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3026
+#: ../src/maemo-mapper.c:1443
+#, c-format
+msgid "VDOP: %.01f"
+msgstr "VDOP: %.01f"
+
+#: ../src/maemo-mapper.c:4099
 msgid "Velocity Vector"
 msgstr "Velocity Vector"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6212
+#: ../src/maemo-mapper.c:4081
+msgid "View"
+msgstr "View"
+
+#: ../src/maemo-mapper.c:8497
 msgid "View Center"
 msgstr "View Center"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3151
+#: ../src/maemo-mapper.c:8025
+msgid "View Zoom Steps"
+msgstr "View Zoom Steps"
+
+#: ../src/maemo-mapper.c:6504
+msgid "W"
+msgstr "W"
+
+#: ../src/maemo-mapper.c:4245
 msgid "Waypoint"
 msgstr "Waypoint"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6260
+#: ../src/maemo-mapper.c:8445
 msgid "Zoom"
 msgstr "Zoom"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6263
+#: ../src/maemo-mapper.c:8451
 msgid "Zoom Levels to Download: (0 -> most detail)"
 msgstr "Zoom Levels to Download: (0 -> most detail)"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2361
-msgid "Zoom Steps"
-msgstr "Zoom Steps"
-
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4888
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4948
+#: ../src/maemo-mapper.c:6170 ../src/maemo-mapper.c:6243
 msgid "Zoom to Level"
 msgstr "Zoom to Level"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:142
+#: ../src/maemo-mapper.c:394
 msgid "km"
 msgstr "km"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6385
+#: ../src/maemo-mapper.c:8671 ../src/maemo-mapper.c:8677
 msgid "maps"
 msgstr "maps"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:143
+#: ../src/maemo-mapper.c:396
 msgid "mi."
 msgstr "mi."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:144
+#: ../src/maemo-mapper.c:398
 msgid "n.m."
 msgstr "n.m."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4424
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4728
+#: ../src/maemo-mapper.c:1569 ../src/maemo-mapper.c:1681
+#: ../src/maemo-mapper.c:6388
+msgid "nofix"
+msgstr "nofix"
+
+#: ../src/maemo-mapper.c:1578 ../src/maemo-mapper.c:1687
+#: ../src/maemo-mapper.c:1700
+msgid "none"
+msgstr "none"
+
+#: ../src/maemo-mapper.c:5636 ../src/maemo-mapper.c:6008
 msgid "reading"
 msgstr "reading"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6385
+#: ../src/maemo-mapper.c:1761
+msgid "select label from poi limit 1"
+msgstr "select label from poi limit 1"
+
+#: ../src/maemo-mapper.c:8677
 msgid "up to about"
 msgstr "up to about"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4424
+#: ../src/maemo-mapper.c:5636
 msgid "writing"
 msgstr "writing"
 
+#~ msgid ""
+#~ "Failed to open or create database:\n"
+#~ "%s"
+#~ msgstr ""
+#~ "Failed to open or create database:\n"
+#~ "%s"
+
+#~ msgid "Point%06d"
+#~ msgstr "Point%06d"
index 236d6b0431d0ee8e5d37d558e7d22625abbfba83..6b868f383d6f49fa1839fb999096ab05f1ccd13c 100644 (file)
@@ -10,8 +10,8 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: maemo-mapper 1.1\n"
-"Report-Msgid-Bugs-To: John Costigan <gnuite@gmail.com>\n"
-"POT-Creation-Date: 2006-07-01 05:57-0400\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-10-14 12:43-0400\n"
 "PO-Revision-Date: 2006-07-09 12:26-0400\n"
 "Last-Translator: Alessandro Pasotti <apasotti@gmail.com>\n"
 "Language-Team: Alessandro Pasotti <apasotti@gmail.com>\n"
@@ -19,328 +19,525 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
+#: ../src/maemo-mapper.c:4237 ../src/maemo-mapper.c:9086
+msgid "Add POI"
+msgstr "Add POI"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2426
+#: ../src/maemo-mapper.c:3288
 msgid "Advance Notice"
 msgstr "Anticipo avvisi"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1931
+#: ../src/maemo-mapper.c:8430
+msgid "Along Route - Radius:"
+msgstr "Along Route - Radius:"
+
+#: ../src/maemo-mapper.c:1029 ../src/maemo-mapper.c:1647
+#, c-format
+msgid "Alt: %d ft"
+msgstr "Alt: %d ft"
+
+#: ../src/maemo-mapper.c:1025 ../src/maemo-mapper.c:1643
+#, c-format
+msgid "Alt: %d m"
+msgstr "Alt: %d m"
+
+#: ../src/maemo-mapper.c:1520
+#, fuzzy
+msgid "Altitude"
+msgstr "Latitudine"
+
+#: ../src/maemo-mapper.c:2833
 msgid "An error occurred while scanning."
 msgstr "Si Ã¨ verificato un errore durante la scansione."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2422
+#: ../src/maemo-mapper.c:6182
+msgid ""
+"An error occurred while trying to reset the bluetooth radio.\n"
+"\n"
+"Did you make sure to modify\n"
+"the /etc/sudoers file?"
+msgstr ""
+"An error occurred while trying to reset the bluetooth radio.\n"
+"\n"
+"Did you make sure to modify\n"
+"the /etc/sudoers file?"
+
+#: ../src/maemo-mapper.c:3284
 msgid "Announce"
 msgstr "Avvisi"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6182
+#: ../src/maemo-mapper.c:8467
 msgid "Area"
 msgstr "Area"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2391
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3031
+#: ../src/maemo-mapper.c:3253 ../src/maemo-mapper.c:4104
 msgid "Auto-Center"
 msgstr "Centro automatico"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6045
+#: ../src/maemo-mapper.c:7802
 msgid "Auto-Center Mode: Lat/Lon"
 msgstr "Modalità centro automatico: Lat/Lon"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6029
+#: ../src/maemo-mapper.c:7786
 msgid "Auto-Center Mode: Lead"
 msgstr "Modalità centro automatico: vettore"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6059
+#: ../src/maemo-mapper.c:7816
 msgid "Auto-Center Off"
 msgstr "Disabilita centro automatico"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3005
+#: ../src/maemo-mapper.c:4073
 msgid "Auto-Download"
 msgstr "Scaricamento automatico"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5484
+#: ../src/maemo-mapper.c:7241
 msgid "Auto-Update"
 msgstr "Aggiornamento automatico"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6245
+#: ../src/maemo-mapper.c:8530
 msgid "Bottom-Right"
 msgstr "Basso destra"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2384
+#: ../src/maemo-mapper.c:3406 ../src/maemo-mapper.c:8004
 msgid "Browse..."
 msgstr "Scegli..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2374
+#: ../src/maemo-mapper.c:8421
+msgid "By Area (see tab)"
+msgstr "By Area (see tab)"
+
+#: ../src/maemo-mapper.c:7994
 msgid "Cache Dir."
 msgstr "Cartella cache."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6455
+#: ../src/maemo-mapper.c:7940
+msgid ""
+"Cannot delete the last repository - there must be at lease one repository."
+msgstr ""
+"Cannot delete the last repository - there must be at lease one repository."
+
+#: ../src/maemo-mapper.c:8751
 msgid ""
 "Cannot enable GPS until a GPS Receiver MAC is set in the Settings dialog box."
 msgstr ""
-"Impossibile abilitare il GPS finché non viene impostato un indirizzo MAC nella finestra Impostazioni."
+"Impossibile abilitare il GPS finché non viene impostato un indirizzo MAC "
+"nella finestra Impostazioni."
+
+#: ../src/maemo-mapper.c:9334
+msgid "Category"
+msgstr "Category"
+
+#: ../src/maemo-mapper.c:9115 ../src/maemo-mapper.c:9482
+msgid "Category: "
+msgstr "Category: "
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2327
+#: ../src/maemo-mapper.c:3232
 msgid "Channel"
 msgstr "Canale"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2980
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2994
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6170
+#: ../src/maemo-mapper.c:4047 ../src/maemo-mapper.c:4061
+#: ../src/maemo-mapper.c:8374
 msgid "Clear"
 msgstr "Cancella"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3073
+#: ../src/maemo-mapper.c:4155
 msgid "Close"
 msgstr "Chiudi"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2134
+#: ../src/maemo-mapper.c:3037
 msgid "Colors"
 msgstr "Colori"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2297
+#: ../src/maemo-mapper.c:3202
 msgid "Colors..."
 msgstr "Colori..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6917
+#: ../src/maemo-mapper.c:8670
+msgid "Confirm DELETION of"
+msgstr "Confirm DELETION of"
+
+#: ../src/maemo-mapper.c:7947
+#, fuzzy
+msgid "Confirm delete of repository"
+msgstr "Conferma l'eliminazione del waypoint"
+
+#: ../src/maemo-mapper.c:9802
 msgid "Confirm delete of waypoint"
 msgstr "Conferma l'eliminazione del waypoint"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6384
+#: ../src/maemo-mapper.c:8676
 msgid "Confirm download of"
 msgstr "Conferma il download di"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3162
+#: ../src/maemo-mapper.c:4256
 msgid "Copy Description to Clipboard"
 msgstr "Copia la descrizione negli appunti"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3141
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3160
+#: ../src/maemo-mapper.c:4229 ../src/maemo-mapper.c:4254
 msgid "Copy Lat/Lon to Clipboard"
 msgstr "Copia Lat/Lon negli appunti"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2554
-msgid "Could not create Map Cache directory."
-msgstr "Impossibile creare la cartella cache per le mappe."
-
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2698
-msgid ""
-"Could not create Map Cache directory.\n"
-"Please set a valid Map Cache directory in the Settings dialog box."
-msgstr ""
-"Impossibile creare la cartella cache per le mappe.\n"
-"Imposta un percorso valido per la cartella nella finestra Impostazioni."
-
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5567
+#: ../src/maemo-mapper.c:7324
 msgid ""
 "Could not generate directions. Make sure your source and destination are "
 "valid."
 msgstr ""
-"Impossibile generare le indicazioni. Controlla che la partenza e l'arrivo siano validi."
+"Impossibile generare le indicazioni. Controlla che la partenza e l'arrivo "
+"siano validi."
+
+#: ../src/maemo-mapper.c:1693
+#, fuzzy
+msgid "DGPS"
+msgstr "GPS"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2140
+#: ../src/maemo-mapper.c:3891
+#, fuzzy
+msgid "Default"
+msgstr "Default"
+
+#: ../src/maemo-mapper.c:3043
 msgid "Defaults"
 msgstr "Default"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3169
+#: ../src/maemo-mapper.c:4263 ../src/maemo-mapper.c:9451
 msgid "Delete"
 msgstr "Elimina"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2017
+#: ../src/maemo-mapper.c:8411
+#, fuzzy
+msgid "Delete Maps"
+msgstr "Elimina"
+
+#: ../src/maemo-mapper.c:9236
+#, fuzzy, c-format
+msgid ""
+"Delete POI?\n"
+"%s"
+msgstr "Elimina"
+
+#: ../src/maemo-mapper.c:8128
+#, fuzzy
+msgid "Delete..."
+msgstr "Elimina"
+
+#: ../src/maemo-mapper.c:9125 ../src/maemo-mapper.c:9492
+msgid "Desc.: "
+msgstr "Desc.: "
+
+#: ../src/maemo-mapper.c:2919
 msgid "Description"
 msgstr "Descrizione"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5501
+#: ../src/maemo-mapper.c:7258
 msgid "Destination"
 msgstr "Destinazione"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6698
+#: ../src/maemo-mapper.c:4138
+#, fuzzy
+msgid "Details..."
+msgstr "Impostazioni..."
+
+#: ../src/maemo-mapper.c:9050
 msgid "Distance to Location"
 msgstr "Distanza per la località"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6889
+#: ../src/maemo-mapper.c:9773
 msgid "Distance to Waypoint"
 msgstr "Distanza per il waypoint"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3001
-msgid "Download Along Route"
-msgstr "Scarica lungo la rotta"
-
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3003
-msgid "Download Area..."
-msgstr "Scarica area..."
-
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6164
-msgid "Download Maps by Area"
-msgstr "Scarica le mappe per area"
+#: ../src/maemo-mapper.c:8398
+#, fuzzy
+msgid "Download Maps"
+msgstr "Scaricamento mappe in corso"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5458
+#: ../src/maemo-mapper.c:7215
 msgid "Download Route"
 msgstr "Scarica rotta"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3144
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3165
+#: ../src/maemo-mapper.c:4232 ../src/maemo-mapper.c:4259
 msgid "Download Route to..."
 msgstr "Scarica la rotta per..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2974
+#: ../src/maemo-mapper.c:8009
+#, fuzzy
+msgid "Download Zoom Steps"
+msgstr "Scarica rotta"
+
+#: ../src/maemo-mapper.c:4041
 msgid "Download..."
 msgstr "Scarica..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3506
+#: ../src/maemo-mapper.c:4629
 msgid "Downloading maps"
 msgstr "Scaricamento mappe in corso"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3058
+#: ../src/maemo-mapper.c:6495
+msgid "E"
+msgstr "E"
+
+#: ../src/maemo-mapper.c:4240 ../src/maemo-mapper.c:9445
+msgid "Edit POI"
+msgstr "Edit POI"
+
+#: ../src/maemo-mapper.c:4130
 msgid "Enable GPS"
 msgstr "Abilita GPS"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2438
+#: ../src/maemo-mapper.c:3300
 msgid "Enable Voice Synthesis (requires flite)"
 msgstr "Abilita sintesi vocale (necessita di flite)"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4738
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5623
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5666
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5717
+#: ../src/maemo-mapper.c:6018 ../src/maemo-mapper.c:7380
+#: ../src/maemo-mapper.c:7423 ../src/maemo-mapper.c:7474
 msgid "Error parsing GPX file."
 msgstr "Errore analizzando il file GPX."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5732
+#: ../src/maemo-mapper.c:7489
 msgid "Error while writing to file"
 msgstr "Errore scrivendo sul file"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5873
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5936
+#: ../src/maemo-mapper.c:7630 ../src/maemo-mapper.c:7693
 msgid "Error writing GPX file."
 msgstr "Errore scrivendo il file GPX."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:927
+#: ../src/maemo-mapper.c:3374
+msgid "Escape Key"
+msgstr "Escape Key"
+
+#: ../src/maemo-mapper.c:1834
 msgid "Establishing GPS fix"
 msgstr "Connessione con il GPS in corso"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5559
+#: ../src/maemo-mapper.c:1697
+msgid "Estimated"
+msgstr "Estimated"
+
+#: ../src/maemo-mapper.c:7316
 msgid "Failed to connect to GPX Directions server"
 msgstr "Impossibile connettersi al server delle indicazioni GPX"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2660
+#: ../src/maemo-mapper.c:3581
 msgid "Failed to initialize GConf.  Quitting."
 msgstr "Impossibile inizializzare GConf.  Esco."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1709
+#: ../src/maemo-mapper.c:2560
 msgid "Failed to initialize GConf.  Settings were not saved."
-msgstr "Impossibile inizializzare GConf.  Le impostazioni non sono state salvate."
+msgstr ""
+"Impossibile inizializzare GConf.  Le impostazioni non sono state salvate."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4422
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4727
+#: ../src/maemo-mapper.c:5634 ../src/maemo-mapper.c:6007
 msgid "Failed to open file for"
 msgstr "Impossibile aprire il file per"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5733
+#: ../src/maemo-mapper.c:7490
 msgid "File is incomplete."
 msgstr "Il file Ã¨ incompleto."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3053
+#: ../src/maemo-mapper.c:1565
+msgid "Fix"
+msgstr "Fix"
+
+#: ../src/maemo-mapper.c:1574
+msgid "Fix quality"
+msgstr "Fix quality"
+
+#: ../src/maemo-mapper.c:1696
+msgid "Float RTK"
+msgstr "Float RTK"
+
+#: ../src/maemo-mapper.c:4085
 msgid "Full Screen"
 msgstr "Schermo intero"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2308
+#: ../src/maemo-mapper.c:3213 ../src/maemo-mapper.c:4126
 msgid "GPS"
 msgstr "GPS"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6196
+#: ../src/maemo-mapper.c:1468
+msgid "GPS Details"
+msgstr "GPS Details"
+
+#: ../src/maemo-mapper.c:5862
+msgid "GPS Info"
+msgstr "GPS Info"
+
+#: ../src/maemo-mapper.c:1481
+#, fuzzy
+msgid "GPS Information"
+msgstr "Località GPS"
+
+#: ../src/maemo-mapper.c:8481
 msgid "GPS Location"
 msgstr "Località GPS"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2152
+#: ../src/maemo-mapper.c:3055
 msgid "GPS Mark"
 msgstr "GPS Mark"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3070
+#: ../src/maemo-mapper.c:1425
+#, c-format
+msgid "HDOP: %.01f"
+msgstr "HDOP: %.01f"
+
+#: ../src/maemo-mapper.c:1529
+#, fuzzy
+msgid "Heading"
+msgstr "lettura"
+
+#: ../src/maemo-mapper.c:4152
 msgid "Help"
 msgstr "Aiuto"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2992
+#: ../src/maemo-mapper.c:4059
 msgid "Insert Breakpoint"
 msgstr "Inserisci sosta"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6338
+#: ../src/maemo-mapper.c:8618
 msgid "Invalid Bottom-Right Latitude"
 msgstr "Latitudine in basso a destra errata"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6345
+#: ../src/maemo-mapper.c:8625
 msgid "Invalid Bottom-Right Longitude"
 msgstr "Longitudine in basso a destra errata"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5159
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5170
+#: ../src/maemo-mapper.c:6670 ../src/maemo-mapper.c:6681
 msgid "Invalid NMEA input from receiver!"
 msgstr "Dati NMEA dal ricevitore errati!"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6324
+#: ../src/maemo-mapper.c:8604
 msgid "Invalid Top-Left Latitude"
 msgstr "Latitudine in alto a sinistra errata"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6331
+#: ../src/maemo-mapper.c:8611
 msgid "Invalid Top-Left Longitude"
 msgstr "Longitudine in alto a sinistra errata"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2490
+#: ../src/maemo-mapper.c:3352
 msgid "Keep Display On Only in Fullscreen Mode"
-msgstr "Mantieni lo schermo sempre acceso solo quando in modalità a schermo intero"
+msgstr ""
+"Mantieni lo schermo sempre acceso solo quando in modalità a schermo intero"
+
+#: ../src/maemo-mapper.c:9329
+msgid "Label"
+msgstr "Label"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3035
+#: ../src/maemo-mapper.c:9107 ../src/maemo-mapper.c:9474
+msgid "Label: "
+msgstr "Label: "
+
+#: ../src/maemo-mapper.c:9096 ../src/maemo-mapper.c:9460
+#, fuzzy
+msgid "Lat - Lon: "
+msgstr "Lat/Lon"
+
+#: ../src/maemo-mapper.c:4108
 msgid "Lat/Lon"
 msgstr "Lat/Lon"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6186
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6632
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6751
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6803
+#: ../src/maemo-mapper.c:1493 ../src/maemo-mapper.c:8471
+#: ../src/maemo-mapper.c:8984 ../src/maemo-mapper.c:9319
+#: ../src/maemo-mapper.c:9639
 msgid "Latitude"
 msgstr "Latitudine"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3041
+#: ../src/maemo-mapper.c:4114
 msgid "Lead"
 msgstr "Anticipo"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2408
+#: ../src/maemo-mapper.c:3270
 msgid "Lead Amount"
 msgstr "Lunghezza anticipo"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2478
+#: ../src/maemo-mapper.c:3340
 msgid "Line Width"
 msgstr "Spessore linea"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3133
+#: ../src/maemo-mapper.c:1538
+#, fuzzy
+msgid "Local time"
+msgstr "Località"
+
+#: ../src/maemo-mapper.c:4221
 msgid "Location"
 msgstr "Località"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6190
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6633
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6752
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6804
+#: ../src/maemo-mapper.c:1502 ../src/maemo-mapper.c:8475
+#: ../src/maemo-mapper.c:8985 ../src/maemo-mapper.c:9324
+#: ../src/maemo-mapper.c:9640
 msgid "Longitude"
 msgstr "Longitudine"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2012
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2312
+#: ../src/maemo-mapper.c:2914 ../src/maemo-mapper.c:3217
 msgid "MAC"
 msgstr "MAC"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2291
+#: ../src/maemo-mapper.c:5849
+#, fuzzy
+msgid "Maemo Mapper"
+msgstr "Impostazioni Maemo Mapper"
+
+#: ../src/maemo-mapper.c:3196
 msgid "Maemo Mapper Settings"
 msgstr "Impostazioni Maemo Mapper"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2348
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2997
+#: ../src/maemo-mapper.c:8368
+msgid "Manage Maps"
+msgstr "Manage Maps"
+
+#: ../src/maemo-mapper.c:4069
+msgid "Manage Maps..."
+msgstr "Manage Maps..."
+
+#: ../src/maemo-mapper.c:4071
+msgid "Manage Repositories..."
+msgstr "Manage Repositories..."
+
+#: ../src/maemo-mapper.c:1698
+msgid "Manual)"
+msgstr "Manual)"
+
+#: ../src/maemo-mapper.c:4064
 msgid "Maps"
 msgstr "Mappe"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2474
+#: ../src/maemo-mapper.c:3336
 msgid "Misc."
 msgstr "Varie"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2572
+#: ../src/maemo-mapper.c:1288 ../src/maemo-mapper.c:6490
+msgid "N"
+msgstr "N"
+
+#: ../src/maemo-mapper.c:6493
+msgid "NE"
+msgstr "NE"
+
+#: ../src/maemo-mapper.c:6507
+msgid "NW"
+msgstr "NW"
+
+#: ../src/maemo-mapper.c:7900 ../src/maemo-mapper.c:8079
+msgid "Name"
+msgstr "Name"
+
+#: ../src/maemo-mapper.c:7890
+msgid "New Name"
+msgstr "New Name"
+
+#: ../src/maemo-mapper.c:8069
+msgid "New Repository"
+msgstr "New Repository"
+
+#: ../src/maemo-mapper.c:8131
+#, fuzzy
+msgid "New..."
+msgstr "Apri..."
+
+#: ../src/maemo-mapper.c:415
+msgid "Next Repository"
+msgstr "Next Repository"
+
+#: ../src/maemo-mapper.c:3478
 msgid ""
 "No GPS Receiver MAC Provided.\n"
 "GPS Disabled."
@@ -348,238 +545,439 @@ msgstr ""
 "Nessun indirzzo MAC impostato per il ricevitore GPS.\n"
 "GPS disabilitato."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1938
+#: ../src/maemo-mapper.c:2840
 msgid "No bluetooth devices found."
 msgstr "Non ho trovato nessun apparecchio bluetooth."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5926
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6074
+#: ../src/maemo-mapper.c:7683
 msgid "No route is loaded."
 msgstr "Nessuna rotta caricata."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6758
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6778
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6811
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6832
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6865
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6895
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6931
+#: ../src/maemo-mapper.c:9646 ../src/maemo-mapper.c:9666
+#: ../src/maemo-mapper.c:9695 ../src/maemo-mapper.c:9716
+#: ../src/maemo-mapper.c:9749 ../src/maemo-mapper.c:9780
+#: ../src/maemo-mapper.c:9816
 msgid "No waypoints are visible."
 msgstr "Non ci sono waypoint visibili."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3047
+#: ../src/maemo-mapper.c:4120
 msgid "None"
 msgstr "None"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2339
+#: ../src/maemo-mapper.c:3244
 msgid "Note: \"Channel\" refers to the device side!"
 msgstr "Nota: \"Canale\" si riferisce al lato del dispositivo!"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2972
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2988
+#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:8758
+#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:8958
+msgid ""
+"NOTE: You must set a Map URI in the Repository Manager in "
+"order to download maps."
+msgstr ""
+"NOTE: You must set a Map URI in the Repository Manager in "
+"order to download maps."
+
+#: ../src/maemo-mapper.c:4039 ../src/maemo-mapper.c:4055
 msgid "Open..."
 msgstr "Apri..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5490
+#: ../src/maemo-mapper.c:7247
 msgid "Origin"
 msgstr "Partenza"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2463
+#: ../src/maemo-mapper.c:8405
+msgid "Overwrite"
+msgstr "Overwrite"
+
+#: ../src/maemo-mapper.c:1434
+#, c-format
+msgid "PDOP: %.01f"
+msgstr "PDOP: %.01f"
+
+#: ../src/maemo-mapper.c:3392
+msgid "POI"
+msgstr "POI"
+
+#: ../src/maemo-mapper.c:3396
+msgid "POI database"
+msgstr "POI database"
+
+#: ../src/maemo-mapper.c:9313
+msgid "POI_ID"
+msgstr "POI_ID"
+
+#: ../src/maemo-mapper.c:1694
+#, fuzzy
+msgid "PPS"
+msgstr "GPS"
+
 #  This word refers to Pitch as in of a person's voice.
+#: ../src/maemo-mapper.c:3325
 msgid "Pitch"
 msgstr "Intonazione"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2037
+#: ../src/maemo-mapper.c:2939
 msgid "Please select a bluetooth device from the list."
 msgstr "Scegli dalla lista un dispositivo bluetooth."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5535
+#: ../src/maemo-mapper.c:7292
 msgid "Please specify a start location."
 msgstr "Indica una località di partenza."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5542
+#: ../src/maemo-mapper.c:7299
 msgid "Please specify an end location."
 msgstr "Indica una località di arrivo."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2978
+#: ../src/maemo-mapper.c:9202
+msgid "Problem adding POI"
+msgstr "Problem adding POI"
+
+#: ../src/maemo-mapper.c:9252
+msgid "Problem deleting POI"
+msgstr "Problem deleting POI"
+
+#: ../src/maemo-mapper.c:9574
+msgid "Problem updating POI"
+msgstr "Problem updating POI"
+
+#: ../src/maemo-mapper.c:1754
+msgid "Problem with POI database"
+msgstr "Problem with POI database"
+
+#: ../src/maemo-mapper.c:1695
+msgid "Real Time Kinematic"
+msgstr "Real Time Kinematic"
+
+#: ../src/maemo-mapper.c:8125
+#, fuzzy
+msgid "Rename..."
+msgstr "Apri..."
+
+#: ../src/maemo-mapper.c:8111
+msgid "Repositories"
+msgstr "Repositories"
+
+#: ../src/maemo-mapper.c:4045
 msgid "Reset"
 msgstr "Reimposta"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2189
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2968
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3016
+#: ../src/maemo-mapper.c:417 ../src/maemo-mapper.c:4141
+#, fuzzy
+msgid "Reset Bluetooth"
+msgstr "Scegli il dispositivo bluetooth"
+
+#: ../src/maemo-mapper.c:3092 ../src/maemo-mapper.c:4035
+#: ../src/maemo-mapper.c:4089
 msgid "Route"
 msgstr "Rotta"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5618
+#: ../src/maemo-mapper.c:7375
 msgid "Route Downloaded"
 msgstr "Rotta scaricata"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4736
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5663
+#: ../src/maemo-mapper.c:6016 ../src/maemo-mapper.c:7420
 msgid "Route Opened"
 msgstr "Rotta aperta"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5934
+#: ../src/maemo-mapper.c:7691
 msgid "Route Saved"
 msgstr "Rotta salvata"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6002
+#: ../src/maemo-mapper.c:7759
 msgid "Routes are now hidden"
 msgstr "Adesso le rotte sono nascoste"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5995
+#: ../src/maemo-mapper.c:7752
 msgid "Routes are now shown"
 msgstr "Le rotte non sono mostrate"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2976
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2990
+#: ../src/maemo-mapper.c:6499
+msgid "S"
+msgstr "S"
+
+#: ../src/maemo-mapper.c:6497
+msgid "SE"
+msgstr "SE"
+
+#: ../src/maemo-mapper.c:1692
+#, fuzzy
+msgid "SPS"
+msgstr "GPS"
+
+#: ../src/maemo-mapper.c:6501
+msgid "SW"
+msgstr "SW"
+
+#: ../src/maemo-mapper.c:1126 ../src/maemo-mapper.c:1241
+#: ../src/maemo-mapper.c:1407 ../src/maemo-mapper.c:6371
+#: ../src/maemo-mapper.c:6430
+msgid "Sans Serif"
+msgstr "Sans Serif"
+
+#: ../src/maemo-mapper.c:1556
+msgid "Sat in use"
+msgstr "Sat in use"
+
+#: ../src/maemo-mapper.c:1547
+msgid "Sat in view"
+msgstr "Sat in view"
+
+#: ../src/maemo-mapper.c:1488
+msgid "Satellites details"
+msgstr "Satellites details"
+
+#: ../src/maemo-mapper.c:1413
+#, c-format
+msgid "Satellites in view: %d; in use: %d"
+msgstr "Satellites in view: %d; in use: %d"
+
+#: ../src/maemo-mapper.c:4043 ../src/maemo-mapper.c:4057
 msgid "Save..."
 msgstr "Salva..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2322
+#: ../src/maemo-mapper.c:3227
 msgid "Scan..."
 msgstr "Cerca..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1991
+#: ../src/maemo-mapper.c:2893
 msgid "Scanning Bluetooth Devices"
 msgstr "Sto cercando i dispositivi bluetooth"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:917
+#: ../src/maemo-mapper.c:1824
 msgid "Searching for GPS receiver"
 msgstr "Sto cercando un ricevitore GPS"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1982
+#: ../src/maemo-mapper.c:2884
 msgid "Select Bluetooth Device"
 msgstr "Scegli il dispositivo bluetooth"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2395
+#: ../src/maemo-mapper.c:9276
+msgid "Select POI"
+msgstr "Select POI"
+
+#: ../src/maemo-mapper.c:9352
+#, fuzzy
+msgid "Select one POI from the list."
+msgstr "Scegli dalla lista un dispositivo bluetooth."
+
+#: ../src/maemo-mapper.c:3257
 msgid "Sensitivity"
 msgstr "Sensibilità"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3065
+#: ../src/maemo-mapper.c:4147
 msgid "Settings..."
 msgstr "Impostazioni..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3012
-msgid "Show"
-msgstr "Mostra"
+#: ../src/maemo-mapper.c:8388
+msgid "Setup"
+msgstr "Setup"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3158
+#: ../src/maemo-mapper.c:4252
 msgid "Show Description"
 msgstr "Mostra descrizione"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3146
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3167
+#: ../src/maemo-mapper.c:4234 ../src/maemo-mapper.c:4261
 msgid "Show Distance to"
 msgstr "Mostra la distanza verso"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3139
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3156
+#: ../src/maemo-mapper.c:4134
+#, fuzzy
+msgid "Show Information"
+msgstr "Mostra Lat/Lon"
+
+#: ../src/maemo-mapper.c:4227 ../src/maemo-mapper.c:4250
 msgid "Show Lat/Lon"
 msgstr "Mostra Lat/Lon"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2451
+#: ../src/maemo-mapper.c:3411
+msgid "Show POI below zoom"
+msgstr "Show POI below zoom"
+
+#: ../src/maemo-mapper.c:1699
+msgid "Simulation"
+msgstr "Simulation"
+
+#: ../src/maemo-mapper.c:1010 ../src/maemo-mapper.c:1628
+#, c-format
+msgid "Spd: %.1f km/h"
+msgstr "Spd: %.1f km/h"
+
+#: ../src/maemo-mapper.c:1016 ../src/maemo-mapper.c:1634
+#, c-format
+msgid "Spd: %.1f kn"
+msgstr "Spd: %.1f kn"
+
+#: ../src/maemo-mapper.c:1013 ../src/maemo-mapper.c:1631
+#, c-format
+msgid "Spd: %.1f mph"
+msgstr "Spd: %.1f mph"
+
+#: ../src/maemo-mapper.c:1511 ../src/maemo-mapper.c:3313
 msgid "Speed"
 msgstr "Velocità"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6231
+#: ../src/maemo-mapper.c:413
+msgid "Toggle Tracks"
+msgstr "Toggle Tracks"
+
+#: ../src/maemo-mapper.c:8516
 msgid "Top-Left"
 msgstr "In alto a sinistra"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2173
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2984
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3021
+#: ../src/maemo-mapper.c:3076 ../src/maemo-mapper.c:4051
+#: ../src/maemo-mapper.c:4094
 msgid "Track"
 msgstr "Percorso"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5714
+#: ../src/maemo-mapper.c:7471
 msgid "Track Opened"
 msgstr "Percorso aperto"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5871
+#: ../src/maemo-mapper.c:7628
 msgid "Track Saved"
 msgstr "Percorso salvato"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5976
+#: ../src/maemo-mapper.c:7733
 msgid "Tracks are now hidden"
 msgstr "Adesso i percorsi sono nascosti"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5969
+#: ../src/maemo-mapper.c:7726
 msgid "Tracks are now shown"
 msgstr "I percorsi non sono mostrati"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2352
+#: ../src/maemo-mapper.c:7985
 msgid "URI Format"
 msgstr "Formato URI"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2495
+#: ../src/maemo-mapper.c:8221
+msgid "Unable to create cache directory for repository"
+msgstr "Unable to create cache directory for repository"
+
+#: ../src/maemo-mapper.c:3360
 msgid "Units"
 msgstr "Unità"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1952
+#: ../src/maemo-mapper.c:2854
 msgid "Unknown"
 msgstr "Sconosciuto"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5480
+#: ../src/maemo-mapper.c:7237
 msgid "Use GPS Location"
 msgstr "Usa la località del GPS"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3026
+#: ../src/maemo-mapper.c:1443
+#, c-format
+msgid "VDOP: %.01f"
+msgstr "VDOP: %.01f"
+
+#: ../src/maemo-mapper.c:4099
 msgid "Velocity Vector"
 msgstr "Vettor di velocità"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6212
+#: ../src/maemo-mapper.c:4081
+msgid "View"
+msgstr "View"
+
+#: ../src/maemo-mapper.c:8497
 msgid "View Center"
 msgstr "Mostra centro"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3151
+#: ../src/maemo-mapper.c:8025
+#, fuzzy
+msgid "View Zoom Steps"
+msgstr "Intervalli di zoom"
+
+#: ../src/maemo-mapper.c:6504
+msgid "W"
+msgstr "W"
+
+#: ../src/maemo-mapper.c:4245
 msgid "Waypoint"
 msgstr "Waypoint"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6260
+#: ../src/maemo-mapper.c:8445
 msgid "Zoom"
 msgstr "Zoom"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6263
+#: ../src/maemo-mapper.c:8451
 msgid "Zoom Levels to Download: (0 -> most detail)"
 msgstr "Livelli di Zoom da scaricare: (0 -> massimo dettaglio)"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2361
-msgid "Zoom Steps"
-msgstr "Intervalli di zoom"
-
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4888
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4948
+#: ../src/maemo-mapper.c:6170 ../src/maemo-mapper.c:6243
 msgid "Zoom to Level"
 msgstr "Zoom al livello"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:142
+#: ../src/maemo-mapper.c:394
 msgid "km"
 msgstr "km"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6385
+#: ../src/maemo-mapper.c:8671 ../src/maemo-mapper.c:8677
 msgid "maps"
 msgstr "mappe"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:143
+#: ../src/maemo-mapper.c:396
 msgid "mi."
 msgstr "mi."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:144
+#: ../src/maemo-mapper.c:398
 msgid "n.m."
 msgstr "n.m."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4424
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4728
+#: ../src/maemo-mapper.c:1569 ../src/maemo-mapper.c:1681
+#: ../src/maemo-mapper.c:6388
+msgid "nofix"
+msgstr "nofix"
+
+#: ../src/maemo-mapper.c:1578 ../src/maemo-mapper.c:1687
+#: ../src/maemo-mapper.c:1700
+#, fuzzy
+msgid "none"
+msgstr "None"
+
+#: ../src/maemo-mapper.c:5636 ../src/maemo-mapper.c:6008
 msgid "reading"
 msgstr "lettura"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6385
+#: ../src/maemo-mapper.c:1761
+msgid "select label from poi limit 1"
+msgstr "select label from poi limit 1"
+
+#: ../src/maemo-mapper.c:8677
 msgid "up to about"
 msgstr "fino a circa"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4424
+#: ../src/maemo-mapper.c:5636
 msgid "writing"
 msgstr "scrittura"
 
+#~ msgid "Could not create Map Cache directory."
+#~ msgstr "Impossibile creare la cartella cache per le mappe."
+
+#~ msgid ""
+#~ "Could not create Map Cache directory.\n"
+#~ "Please set a valid Map Cache directory in the Settings dialog box."
+#~ msgstr ""
+#~ "Impossibile creare la cartella cache per le mappe.\n"
+#~ "Imposta un percorso valido per la cartella nella finestra Impostazioni."
+
+#~ msgid "Download Along Route"
+#~ msgstr "Scarica lungo la rotta"
+
+#~ msgid "Download Area..."
+#~ msgstr "Scarica area..."
+
+#~ msgid "Download Maps by Area"
+#~ msgstr "Scarica le mappe per area"
+
+#~ msgid ""
+#~ "Failed to open or create database:\n"
+#~ "%s"
+#~ msgstr ""
+#~ "Failed to open or create database:\n"
+#~ "%s"
+
+#~ msgid "Point%06d"
+#~ msgstr "Point%06d"
+
+#~ msgid "Show"
+#~ msgstr "Mostra"
index 08dc8487f3bb24b8c66adaf28964a3a23148b3f6..cc313736a0f84927568ad790e2e2213d11aca01e 100644 (file)
@@ -10,8 +10,8 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: maemo-mapper 1.0.2\n"
-"Report-Msgid-Bugs-To: John Costigan <gnuite@gmail.com>\n"
-"POT-Creation-Date: 2006-07-01 05:57-0400\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2006-10-14 12:43-0400\n"
 "PO-Revision-Date: 2006-07-04 09:56+0200\n"
 "Last-Translator: Mischa Molhoek <mischamolhoek@gmail.com>\n"
 "Language-Team: John Costigan <gnuite@gmail.com>\n"
@@ -19,119 +19,165 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2426
+#: ../src/maemo-mapper.c:4237 ../src/maemo-mapper.c:9086
+msgid "Add POI"
+msgstr "Add POI"
+
+#: ../src/maemo-mapper.c:3288
 msgid "Advance Notice"
 msgstr "Aankondiging"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1931
+#: ../src/maemo-mapper.c:8430
+msgid "Along Route - Radius:"
+msgstr "Along Route - Radius:"
+
+#: ../src/maemo-mapper.c:1029 ../src/maemo-mapper.c:1647
+#, c-format
+msgid "Alt: %d ft"
+msgstr "Alt: %d ft"
+
+#: ../src/maemo-mapper.c:1025 ../src/maemo-mapper.c:1643
+#, c-format
+msgid "Alt: %d m"
+msgstr "Alt: %d m"
+
+#: ../src/maemo-mapper.c:1520
+#, fuzzy
+msgid "Altitude"
+msgstr "Breedtegraad"
+
+#: ../src/maemo-mapper.c:2833
 msgid "An error occurred while scanning."
 msgstr "An error occurred while scanning."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2422
+#: ../src/maemo-mapper.c:6182
+msgid ""
+"An error occurred while trying to reset the bluetooth radio.\n"
+"\n"
+"Did you make sure to modify\n"
+"the /etc/sudoers file?"
+msgstr ""
+"An error occurred while trying to reset the bluetooth radio.\n"
+"\n"
+"Did you make sure to modify\n"
+"the /etc/sudoers file?"
+
+#: ../src/maemo-mapper.c:3284
 msgid "Announce"
 msgstr "Aankondigen"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6182
+#: ../src/maemo-mapper.c:8467
 msgid "Area"
 msgstr "Gebied"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2391
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3031
+#: ../src/maemo-mapper.c:3253 ../src/maemo-mapper.c:4104
 msgid "Auto-Center"
 msgstr "Automatisch-Centreren"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6045
+#: ../src/maemo-mapper.c:7802
 msgid "Auto-Center Mode: Lat/Lon"
 msgstr "Automatisch-Centreren Mode: Lengtegr/Breedtegr"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6029
+#: ../src/maemo-mapper.c:7786
 msgid "Auto-Center Mode: Lead"
 msgstr "Automatisch-Centreren Mode: Lead"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6059
+#: ../src/maemo-mapper.c:7816
 msgid "Auto-Center Off"
 msgstr "Automatisch-Centreren Uit"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3005
+#: ../src/maemo-mapper.c:4073
 msgid "Auto-Download"
 msgstr "Automatisch-Downloaden"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5484
+#: ../src/maemo-mapper.c:7241
 msgid "Auto-Update"
 msgstr "Automatisch-Updaten"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6245
+#: ../src/maemo-mapper.c:8530
 msgid "Bottom-Right"
 msgstr "Rechts-onder"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2384
+#: ../src/maemo-mapper.c:3406 ../src/maemo-mapper.c:8004
 msgid "Browse..."
 msgstr "Blader..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2374
+#: ../src/maemo-mapper.c:8421
+msgid "By Area (see tab)"
+msgstr "By Area (see tab)"
+
+#: ../src/maemo-mapper.c:7994
 msgid "Cache Dir."
 msgstr "Cache Dir."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6455
+#: ../src/maemo-mapper.c:7940
+msgid ""
+"Cannot delete the last repository - there must be at lease one repository."
+msgstr ""
+"Cannot delete the last repository - there must be at lease one repository."
+
+#: ../src/maemo-mapper.c:8751
 msgid ""
 "Cannot enable GPS until a GPS Receiver MAC is set in the Settings dialog box."
 msgstr ""
 "Kan GPS niet aanzetten totdat GPS MAC adres is ingevoerd in het Configuratie "
 "scherm"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2327
+#: ../src/maemo-mapper.c:9334
+msgid "Category"
+msgstr "Category"
+
+#: ../src/maemo-mapper.c:9115 ../src/maemo-mapper.c:9482
+msgid "Category: "
+msgstr "Category: "
+
+#: ../src/maemo-mapper.c:3232
 msgid "Channel"
 msgstr "Kanaal"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2980
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2994
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6170
+#: ../src/maemo-mapper.c:4047 ../src/maemo-mapper.c:4061
+#: ../src/maemo-mapper.c:8374
 msgid "Clear"
 msgstr "Opschonen"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3073
+#: ../src/maemo-mapper.c:4155
 msgid "Close"
 msgstr "Sluiten"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2134
+#: ../src/maemo-mapper.c:3037
 msgid "Colors"
 msgstr "Colors"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2297
+#: ../src/maemo-mapper.c:3202
 msgid "Colors..."
 msgstr "Colors..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6917
+#: ../src/maemo-mapper.c:8670
+msgid "Confirm DELETION of"
+msgstr "Confirm DELETION of"
+
+#: ../src/maemo-mapper.c:7947
+#, fuzzy
+msgid "Confirm delete of repository"
+msgstr "Confirm delete of waypoint"
+
+#: ../src/maemo-mapper.c:9802
 msgid "Confirm delete of waypoint"
 msgstr "Confirm delete of waypoint"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6384
+#: ../src/maemo-mapper.c:8676
 msgid "Confirm download of"
 msgstr "Bevestig download van"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3162
+#: ../src/maemo-mapper.c:4256
 msgid "Copy Description to Clipboard"
 msgstr "Copy Description to Clipboard"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3141
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3160
+#: ../src/maemo-mapper.c:4229 ../src/maemo-mapper.c:4254
 msgid "Copy Lat/Lon to Clipboard"
 msgstr "Copy Lat/Lon to Clipboard"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2554
-msgid "Could not create Map Cache directory."
-msgstr "Kan de landkaarten cache folder niet aanmaken."
-
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2698
-msgid ""
-"Could not create Map Cache directory.\n"
-"Please set a valid Map Cache directory in the Settings dialog box."
-msgstr ""
-"Kan de landkaarten cache folder niet aanmaken\n"
-"Vul a.u.b. in het configuratie scherm een geldige landkaarten cache folder "
-"in."
-
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5567
+#: ../src/maemo-mapper.c:7324
 msgid ""
 "Could not generate directions. Make sure your source and destination are "
 "valid."
@@ -139,210 +185,357 @@ msgstr ""
 "Could not generate directions. Make sure your source and destination are "
 "valid."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2140
+#: ../src/maemo-mapper.c:1693
+#, fuzzy
+msgid "DGPS"
+msgstr "GPS"
+
+#: ../src/maemo-mapper.c:3891
+#, fuzzy
+msgid "Default"
+msgstr "Defaults"
+
+#: ../src/maemo-mapper.c:3043
 msgid "Defaults"
 msgstr "Defaults"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3169
+#: ../src/maemo-mapper.c:4263 ../src/maemo-mapper.c:9451
 msgid "Delete"
 msgstr "Delete"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2017
+#: ../src/maemo-mapper.c:8411
+#, fuzzy
+msgid "Delete Maps"
+msgstr "Delete"
+
+#: ../src/maemo-mapper.c:9236
+#, fuzzy, c-format
+msgid ""
+"Delete POI?\n"
+"%s"
+msgstr "Delete"
+
+#: ../src/maemo-mapper.c:8128
+#, fuzzy
+msgid "Delete..."
+msgstr "Delete"
+
+#: ../src/maemo-mapper.c:9125 ../src/maemo-mapper.c:9492
+msgid "Desc.: "
+msgstr "Desc.: "
+
+#: ../src/maemo-mapper.c:2919
 msgid "Description"
 msgstr "Description"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5501
+#: ../src/maemo-mapper.c:7258
 msgid "Destination"
 msgstr "Bestemming"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6698
+#: ../src/maemo-mapper.c:4138
+#, fuzzy
+msgid "Details..."
+msgstr "Instellingen..."
+
+#: ../src/maemo-mapper.c:9050
 msgid "Distance to Location"
 msgstr "Distance to Location"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6889
+#: ../src/maemo-mapper.c:9773
 msgid "Distance to Waypoint"
 msgstr "Distance to Waypoint"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3001
-msgid "Download Along Route"
-msgstr "Download Langs Route"
-
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3003
-msgid "Download Area..."
-msgstr "Download Gebied..."
-
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6164
-msgid "Download Maps by Area"
-msgstr "Download Landkaarten van Gebied"
+#: ../src/maemo-mapper.c:8398
+#, fuzzy
+msgid "Download Maps"
+msgstr "Landkaarten worden gedownload"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5458
+#: ../src/maemo-mapper.c:7215
 msgid "Download Route"
 msgstr "Download Route"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3144
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3165
+#: ../src/maemo-mapper.c:4232 ../src/maemo-mapper.c:4259
 msgid "Download Route to..."
 msgstr "Download Route to..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2974
+#: ../src/maemo-mapper.c:8009
+#, fuzzy
+msgid "Download Zoom Steps"
+msgstr "Download Route"
+
+#: ../src/maemo-mapper.c:4041
 msgid "Download..."
 msgstr "Download..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3506
+#: ../src/maemo-mapper.c:4629
 msgid "Downloading maps"
 msgstr "Landkaarten worden gedownload"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3058
+#: ../src/maemo-mapper.c:6495
+msgid "E"
+msgstr "E"
+
+#: ../src/maemo-mapper.c:4240 ../src/maemo-mapper.c:9445
+msgid "Edit POI"
+msgstr "Edit POI"
+
+#: ../src/maemo-mapper.c:4130
 msgid "Enable GPS"
 msgstr "Activeer GPS"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2438
+#: ../src/maemo-mapper.c:3300
 msgid "Enable Voice Synthesis (requires flite)"
 msgstr "Activeer Spraak (heeft geinstallerde flite nodig)"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4738
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5623
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5666
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5717
+#: ../src/maemo-mapper.c:6018 ../src/maemo-mapper.c:7380
+#: ../src/maemo-mapper.c:7423 ../src/maemo-mapper.c:7474
 msgid "Error parsing GPX file."
 msgstr "Fout by verwerken GPX bestand."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5732
+#: ../src/maemo-mapper.c:7489
 msgid "Error while writing to file"
 msgstr "Fout bij schrijven GPX bestand"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5873
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5936
+#: ../src/maemo-mapper.c:7630 ../src/maemo-mapper.c:7693
 msgid "Error writing GPX file."
 msgstr "Fout bij schrijven GPX bestand."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:927
+#: ../src/maemo-mapper.c:3374
+msgid "Escape Key"
+msgstr "Escape Key"
+
+#: ../src/maemo-mapper.c:1834
 msgid "Establishing GPS fix"
 msgstr "GPS zoekt satellieten"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5559
+#: ../src/maemo-mapper.c:1697
+msgid "Estimated"
+msgstr "Estimated"
+
+#: ../src/maemo-mapper.c:7316
 msgid "Failed to connect to GPX Directions server"
 msgstr "Verbinding met GPX server mislukt"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2660
+#: ../src/maemo-mapper.c:3581
 msgid "Failed to initialize GConf.  Quitting."
 msgstr "initialiseren GConf mislukt.  Programma wordt afgesloten."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1709
+#: ../src/maemo-mapper.c:2560
 msgid "Failed to initialize GConf.  Settings were not saved."
 msgstr "initialiseren GConf mislukt.  Instellingen niet opgeslagen."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4422
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4727
+#: ../src/maemo-mapper.c:5634 ../src/maemo-mapper.c:6007
 msgid "Failed to open file for"
 msgstr "Bestand kon niet geopend worden voor"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5733
+#: ../src/maemo-mapper.c:7490
 msgid "File is incomplete."
 msgstr "Bestand is niet onvolledig."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3053
+#: ../src/maemo-mapper.c:1565
+msgid "Fix"
+msgstr "Fix"
+
+#: ../src/maemo-mapper.c:1574
+msgid "Fix quality"
+msgstr "Fix quality"
+
+#: ../src/maemo-mapper.c:1696
+msgid "Float RTK"
+msgstr "Float RTK"
+
+#: ../src/maemo-mapper.c:4085
 msgid "Full Screen"
 msgstr "Volledig Scherm"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2308
+#: ../src/maemo-mapper.c:3213 ../src/maemo-mapper.c:4126
 msgid "GPS"
 msgstr "GPS"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6196
+#: ../src/maemo-mapper.c:1468
+msgid "GPS Details"
+msgstr "GPS Details"
+
+#: ../src/maemo-mapper.c:5862
+msgid "GPS Info"
+msgstr "GPS Info"
+
+#: ../src/maemo-mapper.c:1481
+#, fuzzy
+msgid "GPS Information"
+msgstr "GPS Locatie"
+
+#: ../src/maemo-mapper.c:8481
 msgid "GPS Location"
 msgstr "GPS Locatie"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2152
+#: ../src/maemo-mapper.c:3055
 msgid "GPS Mark"
 msgstr "GPS Mark"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3070
+#: ../src/maemo-mapper.c:1425
+#, c-format
+msgid "HDOP: %.01f"
+msgstr "HDOP: %.01f"
+
+#: ../src/maemo-mapper.c:1529
+#, fuzzy
+msgid "Heading"
+msgstr "lezen"
+
+#: ../src/maemo-mapper.c:4152
 msgid "Help"
 msgstr "Help"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2992
+#: ../src/maemo-mapper.c:4059
 msgid "Insert Breakpoint"
 msgstr "Insert Breakpoint"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6338
+#: ../src/maemo-mapper.c:8618
 msgid "Invalid Bottom-Right Latitude"
 msgstr "Ongeldige Rechts-Onder Breedtegraad"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6345
+#: ../src/maemo-mapper.c:8625
 msgid "Invalid Bottom-Right Longitude"
 msgstr "Ongeldige Rechts-Onder Lengtegraad"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5159
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5170
+#: ../src/maemo-mapper.c:6670 ../src/maemo-mapper.c:6681
 msgid "Invalid NMEA input from receiver!"
 msgstr "Ongeldige NMEA invoer van ontvanger!"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6324
+#: ../src/maemo-mapper.c:8604
 msgid "Invalid Top-Left Latitude"
 msgstr "Ongeldige Links-Boven Breedtegraad"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6331
+#: ../src/maemo-mapper.c:8611
 msgid "Invalid Top-Left Longitude"
 msgstr "Ongeldige Links-Boven Lengtegraad"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2490
+#: ../src/maemo-mapper.c:3352
 msgid "Keep Display On Only in Fullscreen Mode"
 msgstr "Hou het display alleen aan in volledig scherm mode"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3035
+#: ../src/maemo-mapper.c:9329
+msgid "Label"
+msgstr "Label"
+
+#: ../src/maemo-mapper.c:9107 ../src/maemo-mapper.c:9474
+msgid "Label: "
+msgstr "Label: "
+
+#: ../src/maemo-mapper.c:9096 ../src/maemo-mapper.c:9460
+#, fuzzy
+msgid "Lat - Lon: "
+msgstr "Breedte/Lengtegraad"
+
+#: ../src/maemo-mapper.c:4108
 msgid "Lat/Lon"
 msgstr "Breedte/Lengtegraad"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6186
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6632
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6751
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6803
+#: ../src/maemo-mapper.c:1493 ../src/maemo-mapper.c:8471
+#: ../src/maemo-mapper.c:8984 ../src/maemo-mapper.c:9319
+#: ../src/maemo-mapper.c:9639
 msgid "Latitude"
 msgstr "Breedtegraad"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3041
+#: ../src/maemo-mapper.c:4114
 msgid "Lead"
 msgstr "Vooraf"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2408
+#: ../src/maemo-mapper.c:3270
 msgid "Lead Amount"
 msgstr "Hoeveel Vooraf"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2478
+#: ../src/maemo-mapper.c:3340
 msgid "Line Width"
 msgstr "Lijn Breedte"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3133
+#: ../src/maemo-mapper.c:1538
+#, fuzzy
+msgid "Local time"
+msgstr "Locatie"
+
+#: ../src/maemo-mapper.c:4221
 msgid "Location"
 msgstr "Locatie"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6190
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6633
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6752
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6804
+#: ../src/maemo-mapper.c:1502 ../src/maemo-mapper.c:8475
+#: ../src/maemo-mapper.c:8985 ../src/maemo-mapper.c:9324
+#: ../src/maemo-mapper.c:9640
 msgid "Longitude"
 msgstr "Lengtegraad"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2012
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2312
+#: ../src/maemo-mapper.c:2914 ../src/maemo-mapper.c:3217
 msgid "MAC"
 msgstr "MAC"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2291
+#: ../src/maemo-mapper.c:5849
+#, fuzzy
+msgid "Maemo Mapper"
+msgstr "Maemo Mapper Instellingen"
+
+#: ../src/maemo-mapper.c:3196
 msgid "Maemo Mapper Settings"
 msgstr "Maemo Mapper Instellingen"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2348
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2997
+#: ../src/maemo-mapper.c:8368
+msgid "Manage Maps"
+msgstr "Manage Maps"
+
+#: ../src/maemo-mapper.c:4069
+msgid "Manage Maps..."
+msgstr "Manage Maps..."
+
+#: ../src/maemo-mapper.c:4071
+msgid "Manage Repositories..."
+msgstr "Manage Repositories..."
+
+#: ../src/maemo-mapper.c:1698
+msgid "Manual)"
+msgstr "Manual)"
+
+#: ../src/maemo-mapper.c:4064
 msgid "Maps"
 msgstr "Kaarten"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2474
+#: ../src/maemo-mapper.c:3336
 msgid "Misc."
 msgstr "Misc."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2572
+#: ../src/maemo-mapper.c:1288 ../src/maemo-mapper.c:6490
+msgid "N"
+msgstr "N"
+
+#: ../src/maemo-mapper.c:6493
+msgid "NE"
+msgstr "NE"
+
+#: ../src/maemo-mapper.c:6507
+msgid "NW"
+msgstr "NW"
+
+#: ../src/maemo-mapper.c:7900 ../src/maemo-mapper.c:8079
+msgid "Name"
+msgstr "Name"
+
+#: ../src/maemo-mapper.c:7890
+msgid "New Name"
+msgstr "New Name"
+
+#: ../src/maemo-mapper.c:8069
+msgid "New Repository"
+msgstr "New Repository"
+
+#: ../src/maemo-mapper.c:8131
+#, fuzzy
+msgid "New..."
+msgstr "Open..."
+
+#: ../src/maemo-mapper.c:415
+msgid "Next Repository"
+msgstr "Next Repository"
+
+#: ../src/maemo-mapper.c:3478
 msgid ""
 "No GPS Receiver MAC Provided.\n"
 "GPS Disabled."
@@ -350,238 +543,440 @@ msgstr ""
 "Geen GPS MAC adres opgegeven.\n"
 "GPS uitgeschakeld."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1938
+#: ../src/maemo-mapper.c:2840
 msgid "No bluetooth devices found."
 msgstr "No bluetooth devices found."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5926
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6074
+#: ../src/maemo-mapper.c:7683
 msgid "No route is loaded."
 msgstr "No route is loaded."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6758
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6778
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6811
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6832
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6865
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6895
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6931
+#: ../src/maemo-mapper.c:9646 ../src/maemo-mapper.c:9666
+#: ../src/maemo-mapper.c:9695 ../src/maemo-mapper.c:9716
+#: ../src/maemo-mapper.c:9749 ../src/maemo-mapper.c:9780
+#: ../src/maemo-mapper.c:9816
 msgid "No waypoints are visible."
 msgstr "No waypoints are visible."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3047
+#: ../src/maemo-mapper.c:4120
 msgid "None"
 msgstr "Geen"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2339
+#: ../src/maemo-mapper.c:3244
 msgid "Note: \"Channel\" refers to the device side!"
 msgstr ""
 "Opmerking: met \"Kanaal\" wordt bedoeld de instellingen van de GPS ontvanger!"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2972
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2988
+#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:8758
+#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:8958
+msgid ""
+"NOTE: You must set a Map URI in the Repository Manager in "
+"order to download maps."
+msgstr ""
+"NOTE: You must set a Map URI in the Repository Manager in "
+"order to download maps."
+
+#: ../src/maemo-mapper.c:4039 ../src/maemo-mapper.c:4055
 msgid "Open..."
 msgstr "Open..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5490
+#: ../src/maemo-mapper.c:7247
 msgid "Origin"
 msgstr "Oorsprong"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2463
+#: ../src/maemo-mapper.c:8405
+msgid "Overwrite"
+msgstr "Overwrite"
+
+#: ../src/maemo-mapper.c:1434
+#, c-format
+msgid "PDOP: %.01f"
+msgstr "PDOP: %.01f"
+
+#: ../src/maemo-mapper.c:3392
+msgid "POI"
+msgstr "POI"
+
+#: ../src/maemo-mapper.c:3396
+msgid "POI database"
+msgstr "POI database"
+
+#: ../src/maemo-mapper.c:9313
+msgid "POI_ID"
+msgstr "POI_ID"
+
+#: ../src/maemo-mapper.c:1694
+#, fuzzy
+msgid "PPS"
+msgstr "GPS"
+
+#: ../src/maemo-mapper.c:3325
 msgid "Pitch"
 msgstr "Hoogte"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2037
+#: ../src/maemo-mapper.c:2939
 msgid "Please select a bluetooth device from the list."
 msgstr "Please select a bluetooth device from the list."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5535
+#: ../src/maemo-mapper.c:7292
 msgid "Please specify a start location."
 msgstr "Geef een start locatie op a.u.b."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5542
+#: ../src/maemo-mapper.c:7299
 msgid "Please specify an end location."
 msgstr "Geef een bestemmings locatie op a.u.b."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2978
+#: ../src/maemo-mapper.c:9202
+msgid "Problem adding POI"
+msgstr "Problem adding POI"
+
+#: ../src/maemo-mapper.c:9252
+msgid "Problem deleting POI"
+msgstr "Problem deleting POI"
+
+#: ../src/maemo-mapper.c:9574
+msgid "Problem updating POI"
+msgstr "Problem updating POI"
+
+#: ../src/maemo-mapper.c:1754
+msgid "Problem with POI database"
+msgstr "Problem with POI database"
+
+#: ../src/maemo-mapper.c:1695
+msgid "Real Time Kinematic"
+msgstr "Real Time Kinematic"
+
+#: ../src/maemo-mapper.c:8125
+#, fuzzy
+msgid "Rename..."
+msgstr "Open..."
+
+#: ../src/maemo-mapper.c:8111
+msgid "Repositories"
+msgstr "Repositories"
+
+#: ../src/maemo-mapper.c:4045
 msgid "Reset"
 msgstr "Reset"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2189
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2968
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3016
+#: ../src/maemo-mapper.c:417 ../src/maemo-mapper.c:4141
+#, fuzzy
+msgid "Reset Bluetooth"
+msgstr "Select Bluetooth Device"
+
+#: ../src/maemo-mapper.c:3092 ../src/maemo-mapper.c:4035
+#: ../src/maemo-mapper.c:4089
 msgid "Route"
 msgstr "Route"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5618
+#: ../src/maemo-mapper.c:7375
 msgid "Route Downloaded"
 msgstr "Route Downloaded"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4736
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5663
+#: ../src/maemo-mapper.c:6016 ../src/maemo-mapper.c:7420
 msgid "Route Opened"
 msgstr "Route Geopend"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5934
+#: ../src/maemo-mapper.c:7691
 msgid "Route Saved"
 msgstr "Route Opgeslagen"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6002
+#: ../src/maemo-mapper.c:7759
 msgid "Routes are now hidden"
 msgstr "Routes zijn nu verborgen"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5995
+#: ../src/maemo-mapper.c:7752
 msgid "Routes are now shown"
 msgstr "Routes zijn nu zichtbaar"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2976
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2990
+#: ../src/maemo-mapper.c:6499
+msgid "S"
+msgstr "S"
+
+#: ../src/maemo-mapper.c:6497
+msgid "SE"
+msgstr "SE"
+
+#: ../src/maemo-mapper.c:1692
+#, fuzzy
+msgid "SPS"
+msgstr "GPS"
+
+#: ../src/maemo-mapper.c:6501
+msgid "SW"
+msgstr "SW"
+
+#: ../src/maemo-mapper.c:1126 ../src/maemo-mapper.c:1241
+#: ../src/maemo-mapper.c:1407 ../src/maemo-mapper.c:6371
+#: ../src/maemo-mapper.c:6430
+msgid "Sans Serif"
+msgstr "Sans Serif"
+
+#: ../src/maemo-mapper.c:1556
+msgid "Sat in use"
+msgstr "Sat in use"
+
+#: ../src/maemo-mapper.c:1547
+msgid "Sat in view"
+msgstr "Sat in view"
+
+#: ../src/maemo-mapper.c:1488
+msgid "Satellites details"
+msgstr "Satellites details"
+
+#: ../src/maemo-mapper.c:1413
+#, c-format
+msgid "Satellites in view: %d; in use: %d"
+msgstr "Satellites in view: %d; in use: %d"
+
+#: ../src/maemo-mapper.c:4043 ../src/maemo-mapper.c:4057
 msgid "Save..."
 msgstr "Opslaan..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2322
+#: ../src/maemo-mapper.c:3227
 msgid "Scan..."
 msgstr "Scan..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1991
+#: ../src/maemo-mapper.c:2893
 msgid "Scanning Bluetooth Devices"
 msgstr "Scanning Bluetooth Devices"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:917
+#: ../src/maemo-mapper.c:1824
 msgid "Searching for GPS receiver"
 msgstr "Er wordt naar GPS ontvanger gezocht"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1982
+#: ../src/maemo-mapper.c:2884
 msgid "Select Bluetooth Device"
 msgstr "Select Bluetooth Device"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2395
+#: ../src/maemo-mapper.c:9276
+msgid "Select POI"
+msgstr "Select POI"
+
+#: ../src/maemo-mapper.c:9352
+#, fuzzy
+msgid "Select one POI from the list."
+msgstr "Please select a bluetooth device from the list."
+
+#: ../src/maemo-mapper.c:3257
 msgid "Sensitivity"
 msgstr "Gevoeligheid"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3065
+#: ../src/maemo-mapper.c:4147
 msgid "Settings..."
 msgstr "Instellingen..."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3012
-msgid "Show"
-msgstr "Weergeven"
+#: ../src/maemo-mapper.c:8388
+msgid "Setup"
+msgstr "Setup"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3158
+#: ../src/maemo-mapper.c:4252
 msgid "Show Description"
 msgstr "Show Description"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3146
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3167
+#: ../src/maemo-mapper.c:4234 ../src/maemo-mapper.c:4261
 msgid "Show Distance to"
 msgstr "Show Distance to"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3139
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3156
+#: ../src/maemo-mapper.c:4134
+#, fuzzy
+msgid "Show Information"
+msgstr "Show Lat/Lon"
+
+#: ../src/maemo-mapper.c:4227 ../src/maemo-mapper.c:4250
 msgid "Show Lat/Lon"
 msgstr "Show Lat/Lon"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2451
+#: ../src/maemo-mapper.c:3411
+msgid "Show POI below zoom"
+msgstr "Show POI below zoom"
+
+#: ../src/maemo-mapper.c:1699
+msgid "Simulation"
+msgstr "Simulation"
+
+#: ../src/maemo-mapper.c:1010 ../src/maemo-mapper.c:1628
+#, c-format
+msgid "Spd: %.1f km/h"
+msgstr "Spd: %.1f km/h"
+
+#: ../src/maemo-mapper.c:1016 ../src/maemo-mapper.c:1634
+#, c-format
+msgid "Spd: %.1f kn"
+msgstr "Spd: %.1f kn"
+
+#: ../src/maemo-mapper.c:1013 ../src/maemo-mapper.c:1631
+#, c-format
+msgid "Spd: %.1f mph"
+msgstr "Spd: %.1f mph"
+
+#: ../src/maemo-mapper.c:1511 ../src/maemo-mapper.c:3313
 msgid "Speed"
 msgstr "Snelheid"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6231
+#: ../src/maemo-mapper.c:413
+msgid "Toggle Tracks"
+msgstr "Toggle Tracks"
+
+#: ../src/maemo-mapper.c:8516
 msgid "Top-Left"
 msgstr "Links-Boven"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2173
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2984
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3021
+#: ../src/maemo-mapper.c:3076 ../src/maemo-mapper.c:4051
+#: ../src/maemo-mapper.c:4094
 msgid "Track"
 msgstr "Route"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5714
+#: ../src/maemo-mapper.c:7471
 msgid "Track Opened"
 msgstr "Route Geopend"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5871
+#: ../src/maemo-mapper.c:7628
 msgid "Track Saved"
 msgstr "Route Opgeslagen"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5976
+#: ../src/maemo-mapper.c:7733
 msgid "Tracks are now hidden"
 msgstr "Routes zijn nu verborgen"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5969
+#: ../src/maemo-mapper.c:7726
 msgid "Tracks are now shown"
 msgstr "Routes zijn nu zichtbaar"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2352
+#: ../src/maemo-mapper.c:7985
 msgid "URI Format"
 msgstr "URI Formaat"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2495
+#: ../src/maemo-mapper.c:8221
+msgid "Unable to create cache directory for repository"
+msgstr "Unable to create cache directory for repository"
+
+#: ../src/maemo-mapper.c:3360
 msgid "Units"
 msgstr "Units"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:1952
+#: ../src/maemo-mapper.c:2854
 msgid "Unknown"
 msgstr "Unknown"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:5480
+#: ../src/maemo-mapper.c:7237
 msgid "Use GPS Location"
 msgstr "Bebruik GPS Locatie"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3026
+#: ../src/maemo-mapper.c:1443
+#, c-format
+msgid "VDOP: %.01f"
+msgstr "VDOP: %.01f"
+
+#: ../src/maemo-mapper.c:4099
 msgid "Velocity Vector"
 msgstr "Snelheids Factor"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6212
+#: ../src/maemo-mapper.c:4081
+msgid "View"
+msgstr "View"
+
+#: ../src/maemo-mapper.c:8497
 msgid "View Center"
 msgstr "Bekijk Midden"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:3151
+#: ../src/maemo-mapper.c:8025
+#, fuzzy
+msgid "View Zoom Steps"
+msgstr "Vergrootings-Stappen"
+
+#: ../src/maemo-mapper.c:6504
+msgid "W"
+msgstr "W"
+
+#: ../src/maemo-mapper.c:4245
 msgid "Waypoint"
 msgstr "Waypoint"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6260
+#: ../src/maemo-mapper.c:8445
 msgid "Zoom"
 msgstr "Vergroot"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6263
+#: ../src/maemo-mapper.c:8451
 msgid "Zoom Levels to Download: (0 -> most detail)"
 msgstr "Vergrotings-niveaus om te Downloaden: (0 -> meeste detail)"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:2361
-msgid "Zoom Steps"
-msgstr "Vergrootings-Stappen"
-
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4888
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4948
+#: ../src/maemo-mapper.c:6170 ../src/maemo-mapper.c:6243
 msgid "Zoom to Level"
 msgstr "Zoom to Level"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:142
+#: ../src/maemo-mapper.c:394
 msgid "km"
 msgstr "km"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6385
+#: ../src/maemo-mapper.c:8671 ../src/maemo-mapper.c:8677
 msgid "maps"
 msgstr "landkaarten"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:143
+#: ../src/maemo-mapper.c:396
 msgid "mi."
 msgstr "mi."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:144
+#: ../src/maemo-mapper.c:398
 msgid "n.m."
 msgstr "n.m."
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4424
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4728
+#: ../src/maemo-mapper.c:1569 ../src/maemo-mapper.c:1681
+#: ../src/maemo-mapper.c:6388
+msgid "nofix"
+msgstr "nofix"
+
+#: ../src/maemo-mapper.c:1578 ../src/maemo-mapper.c:1687
+#: ../src/maemo-mapper.c:1700
+#, fuzzy
+msgid "none"
+msgstr "Geen"
+
+#: ../src/maemo-mapper.c:5636 ../src/maemo-mapper.c:6008
 msgid "reading"
 msgstr "lezen"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:6385
+#: ../src/maemo-mapper.c:1761
+msgid "select label from poi limit 1"
+msgstr "select label from poi limit 1"
+
+#: ../src/maemo-mapper.c:8677
 msgid "up to about"
 msgstr "ongeveer"
 
-#: /home/gnuite/src/maemo-mapper/src/maemo-mapper.c:4424
+#: ../src/maemo-mapper.c:5636
 msgid "writing"
 msgstr "writing"
 
+#~ msgid "Could not create Map Cache directory."
+#~ msgstr "Kan de landkaarten cache folder niet aanmaken."
+
+#~ msgid ""
+#~ "Could not create Map Cache directory.\n"
+#~ "Please set a valid Map Cache directory in the Settings dialog box."
+#~ msgstr ""
+#~ "Kan de landkaarten cache folder niet aanmaken\n"
+#~ "Vul a.u.b. in het configuratie scherm een geldige landkaarten cache "
+#~ "folder in."
+
+#~ msgid "Download Along Route"
+#~ msgstr "Download Langs Route"
+
+#~ msgid "Download Area..."
+#~ msgstr "Download Gebied..."
+
+#~ msgid "Download Maps by Area"
+#~ msgstr "Download Landkaarten van Gebied"
+
+#~ msgid ""
+#~ "Failed to open or create database:\n"
+#~ "%s"
+#~ msgstr ""
+#~ "Failed to open or create database:\n"
+#~ "%s"
+
+#~ msgid "Point%06d"
+#~ msgstr "Point%06d"
+
+#~ msgid "Show"
+#~ msgstr "Weergeven"
index e6783cee846ef5d6ed5e32f0ead789fd79f82822..6c73748f296dae04bc3ddaaa90152b09e30502c7 100644 (file)
 
 bin_PROGRAMS = maemo-mapper
 
-maemo_mapper_CFLAGS = $(GTK_CFLAGS) $(OSSO_CFLAGS) $(HILDON_CFLAGS) $(GNOME_VFS_CFLAGS) $(GCONF_CFLAGS) $(LIBXML2_CFLAGS)
+maemo_mapper_CFLAGS = $(GTK_CFLAGS) $(OSSO_CFLAGS) $(HILDON_CFLAGS) $(GNOME_VFS_CFLAGS) $(GCONF_CFLAGS) $(LIBXML2_CFLAGS) $(SQLITE_CFLAGS)
 
-maemo_mapper_LDADD = $(GTK_LIBS) $(OSSO_LIBS) $(HILDON_LIBS) $(GNOME_VFS_LIBS) $(GCONF_LIBS) $(LIBXML2_LIBS) -lbluetooth
+maemo_mapper_LDADD = $(GTK_LIBS) $(OSSO_LIBS) $(HILDON_LIBS) $(GNOME_VFS_LIBS) $(GCONF_LIBS) $(LIBXML2_LIBS) $(SQLITE_LIBS) -lbluetooth
 
 maemo_mapper_SOURCES = maemo-mapper.c
+
+bin_SCRIPTS = maemo-mapper.sh
+
index 76155aa57c19504419904a01271c410d73dcff8f..c125947be2e0e0f657508e23e5ed562aafae81c5 100644 (file)
@@ -60,6 +60,8 @@
 #include <bluetooth/hci_lib.h>
 #include <bluetooth/rfcomm.h>
 
+#include <sqlite.h>
+
 /****************************************************************************
  * BELOW: DEFINES ***********************************************************
  ****************************************************************************/
 /* Pans are done two "grids" at a time, or 64 pixels. */
 #define PAN_UNITS (grid2unit(2))
 
-#define INITIAL_DOWNLOAD_RETRIES (2)
-
-#define UNITS_KM _("km")
-#define UNITS_MI _("mi.")
-#define UNITS_NM _("n.m.")
+#define INITIAL_DOWNLOAD_RETRIES (3)
 
 #define GCONF_KEY_PREFIX "/apps/maemo/maemo-mapper"
 #define GCONF_KEY_RCVR_MAC GCONF_KEY_PREFIX"/receiver_mac"
 #define GCONF_KEY_VOICE_PITCH GCONF_KEY_PREFIX"/voice_pitch"
 #define GCONF_KEY_ALWAYS_KEEP_ON GCONF_KEY_PREFIX"/always_keep_on"
 #define GCONF_KEY_UNITS GCONF_KEY_PREFIX"/units"
+#define GCONF_KEY_ESCAPE_KEY GCONF_KEY_PREFIX"/escape_key"
+
+#define GCONF_KEY_POI_DB GCONF_KEY_PREFIX"/poi_db"
+#define GCONF_KEY_POI_ZOOM GCONF_KEY_PREFIX"/poi_zoom"
 
 #define GCONF_KEY_COLOR_MARK GCONF_KEY_PREFIX"/color_mark"
 #define GCONF_KEY_COLOR_MARK_VELOCITY GCONF_KEY_PREFIX"/color_mark_velocity"
 #define GCONF_KEY_COLOR_ROUTE GCONF_KEY_PREFIX"/color_route"
 #define GCONF_KEY_COLOR_ROUTE_WAY GCONF_KEY_PREFIX"/color_route_way"
 #define GCONF_KEY_COLOR_ROUTE_NEXTWAY GCONF_KEY_PREFIX"/color_route_nextway"
+#define GCONF_KEY_COLOR_POI GCONF_KEY_PREFIX"/color_poi"
 
 #define GCONF_KEY_AUTOCENTER_MODE GCONF_KEY_PREFIX"/autocenter_mode"
 #define GCONF_KEY_LEAD_AMOUNT GCONF_KEY_PREFIX"/lead_amount"
 #define GCONF_KEY_SHOWVELVEC GCONF_KEY_PREFIX"/show_velocity_vector"
 #define GCONF_KEY_ENABLE_GPS GCONF_KEY_PREFIX"/enable_gps"
 #define GCONF_KEY_ROUTE_LOCATIONS GCONF_KEY_PREFIX"/route_locations"
+#define GCONF_KEY_REPOSITORIES GCONF_KEY_PREFIX"/repositories"
+#define GCONF_KEY_CURRREPO GCONF_KEY_PREFIX"/curr_repo"
+#define GCONF_KEY_GPS_INFO GCONF_KEY_PREFIX"/gps_info"
+
 
 #define XML_DATE_FORMAT "%FT%T"
 
     } \
 };
 
-#define EARTH_RADIUS_KM (6371.f)
-#define EARTH_RADIUS_MI (3958.75587f)
-#define EARTH_RADIUS_NM (3440.06479f)
-
 #define MERCATOR_SPAN (-6.28318377773622f)
 #define MERCATOR_TOP (3.14159188886811f)
 #define latlon2unit(lat, lon, unitx, unity) { \
@@ -385,6 +388,65 @@ typedef enum
     ERROR,
 } SaxState;
 
+/** POI dialog action **/
+typedef enum
+{
+    ACTION_ADD_POI,
+    ACTION_EDIT_POI,
+} POIAction;
+
+/** Category list **/
+typedef enum
+{
+    CAT_ID,
+    CAT_ENABLED,
+    CAT_LABEL,
+    CAT_DESCRIPTION,
+    CAT_NUM_COLUMNS
+} CategoryList;
+
+/** POI list **/
+typedef enum
+{
+    POI_INDEX,
+    POI_LATITUDE,
+    POI_LONGITUDE,
+    POI_LABEL,
+    POI_CATEGORY,
+    POI_NUM_COLUMNS
+} POIList;
+
+/** This enum defines the possible units we can use. */
+typedef enum
+{
+    UNITS_KM,
+#define UNITS_KM_TEXT _("km")
+    UNITS_MI,
+#define UNITS_MI_TEXT _("mi.")
+    UNITS_NM,
+#define UNITS_NM_TEXT _("n.m.")
+} UnitType;
+gchar *UNITS_TEXT[3];
+#define EARTH_RADIUS (3440.06479f)
+gfloat UNITS_CONVERT[] =
+{
+    1.85200,
+    1.15077945,
+    1.f,
+};
+
+typedef enum
+{
+    ESCAPE_KEY_TOGGLE_TRACKS,
+#define ESCAPE_KEY_TOGGLE_TRACKS_TEXT _("Toggle Tracks")
+    ESCAPE_KEY_CHANGE_REPO,
+#define ESCAPE_KEY_CHANGE_REPO_TEXT _("Next Repository")
+    ESCAPE_KEY_RESET_BLUETOOTH,
+#define ESCAPE_KEY_RESET_BLUETOOTH_TEXT _("Reset Bluetooth")
+} EscapeKeyAction;
+gchar *ESCAPE_KEY_TEXT[3];
+
+
 /** A general definition of a point in the Maemo Mapper unit system. */
 typedef struct _Point Point;
 struct _Point {
@@ -451,6 +513,14 @@ struct _SaxData {
     GString *chars;
 };
 
+/** Data used during action: add or edit category/poi **/
+typedef struct _DeletePOI DeletePOI;
+struct _DeletePOI {
+    GtkWidget *dialog;
+    gchar *txt_label;
+    guint id;
+};
+
 /** Data used during the asynchronous progress update phase of automatic map
  * downloading. */
 typedef struct _ProgressUpdateInfo ProgressUpdateInfo;
@@ -460,7 +530,7 @@ struct _ProgressUpdateInfo
     GList *src_list;
     GList *dest_list;
     guint tilex, tiley, zoom; /* for refresh. */
-    gint retries_left;
+    gint retries_left; /* if equal to zero, it means we're DELETING maps. */
     guint hash;
 };
 
@@ -476,13 +546,52 @@ struct _AutoRouteDownloadData {
     guint bytes_maxsize;
 };
 
+/** Data regarding a map repository. */
+typedef struct _RepoData RepoData;
+struct _RepoData {
+    gchar *name;
+    gchar *url;
+    gchar *cache_dir;
+    guint dl_zoom_steps;
+    guint view_zoom_steps;
+    GtkWidget *menu_item;
+};
+
+/** GPS Data and Satellite **/
+typedef struct _GpsData GpsData;
+struct _GpsData {
+    guint fix;
+    guint fixquality;
+    struct tm time;    /* gps fix time */
+    struct tm timeloc;    /* local time */
+    gfloat latitude;
+    gfloat longitude;
+    gchar slatitude[15];
+    gchar slongitude[15];
+    gfloat speed;    /* in knots */
+    gfloat maxspeed;    /* in knots */
+    guint altitude; /* in meters */
+    gfloat heading;
+    gfloat hdop;
+    gfloat pdop;
+    gfloat vdop;
+    guint satinview;
+    guint satinuse;
+    guint satforfix[12];
+};
+
+typedef struct _GpsSatelliteData GpsSatelliteData;
+struct _GpsSatelliteData {
+    guint prn;
+    guint elevation;
+    guint azimuth;
+    guint snr;
+};
 
 /****************************************************************************
  * ABOVE: TYPEDEFS **********************************************************
  ****************************************************************************/
 
-
-
 /****************************************************************************
  * BELOW: DATA **************************************************************
  ****************************************************************************/
@@ -502,9 +611,32 @@ static GtkWidget *_map_widget = NULL;
 /** The backing pixmap of _map_widget. */
 static GdkPixmap *_map_pixmap = NULL;
 
+static GtkWidget *_gps_widget = NULL;
+static GtkWidget *_text_lat = NULL;
+static GtkWidget *_text_lon = NULL;
+static GtkWidget *_text_speed = NULL;
+static GtkWidget *_text_alt = NULL;
+static GtkWidget *_sat_panel = NULL;
+static GtkWidget *_text_time = NULL;
+static GtkWidget *_heading_panel = NULL;
+
+static GtkWidget *_sat_details_panel = NULL;
+static GtkWidget *_sdi_lat = NULL;
+static GtkWidget *_sdi_lon = NULL;
+static GtkWidget *_sdi_spd = NULL;
+static GtkWidget *_sdi_alt = NULL;
+static GtkWidget *_sdi_hea = NULL;
+static GtkWidget *_sdi_tim = NULL;
+static GtkWidget *_sdi_vie = NULL;
+static GtkWidget *_sdi_use = NULL;
+static GtkWidget *_sdi_fix = NULL;
+static GtkWidget *_sdi_fqu = NULL;
+static GtkWidget *_sdi_msp = NULL;
 
 /** The file descriptor of our connection with the GPS receiver. */
 static gint _fd = -1;
+static gchar _gps_read_buf[256];
+static guint _gps_read_buf_pos = 0;
 
 /** The GIOChannel through which communication with the GPS receiver is
  * performed. */
@@ -532,6 +664,9 @@ static gfloat _heading = 0;
 static gint _vel_offsetx = 0;
 static gint _vel_offsety = 0;
 
+static GpsData _gps;
+static GpsSatelliteData _gps_sat[12];
+gboolean _satdetails_on = FALSE;
 
 /** The current connection state. */
 static ConnState _conn_state = RCVR_OFF;
@@ -608,6 +743,7 @@ static GdkGC *_gc_track_break = NULL;
 static GdkGC *_gc_route = NULL;
 static GdkGC *_gc_route_way = NULL;
 static GdkGC *_gc_route_nextway = NULL;
+static GdkGC *_gc_poi = NULL;
 static GdkColor _color_mark = {0, 0, 0, 0};
 static GdkColor _color_mark_velocity = {0, 0, 0, 0};
 static GdkColor _color_mark_old = {0, 0, 0, 0};
@@ -616,6 +752,7 @@ static GdkColor _color_track_break = {0, 0, 0, 0};
 static GdkColor _color_route = {0, 0, 0, 0};
 static GdkColor _color_route_way = {0, 0, 0, 0};
 static GdkColor _color_route_nextway = {0, 0, 0, 0};
+static GdkColor _color_poi = {0, 0, 0, 0};
 static GdkColor DEFAULT_COLOR_MARK = {0, 0x0000, 0x0000, 0xc000};
 static GdkColor DEFAULT_COLOR_MARK_VELOCITY = {0, 0x6000, 0x6000, 0xf800};
 static GdkColor DEFAULT_COLOR_MARK_OLD = {0, 0x8000, 0x8000, 0x8000};
@@ -624,6 +761,7 @@ static GdkColor DEFAULT_COLOR_TRACK_BREAK = {0, 0xa000, 0x0000, 0x0000};
 static GdkColor DEFAULT_COLOR_ROUTE = {0, 0x0000, 0xa000, 0x0000};
 static GdkColor DEFAULT_COLOR_ROUTE_WAY = {0, 0x0000, 0x8000, 0x0000};
 static GdkColor DEFAULT_COLOR_ROUTE_NEXTWAY = {0, 0x0000, 0x6000, 0x0000};
+static GdkColor DEFAULT_COLOR_POI = {0, 0xa000, 0x0000, 0xa000};
 
 /** MAIN MENU ITEMS. */
 static GtkWidget *_menu_route_download_item = NULL;
@@ -635,8 +773,9 @@ static GtkWidget *_menu_track_open_item = NULL;
 static GtkWidget *_menu_track_save_item = NULL;
 static GtkWidget *_menu_track_mark_way_item = NULL;
 static GtkWidget *_menu_track_clear_item = NULL;
-static GtkWidget *_menu_maps_dlroute_item = NULL;
-static GtkWidget *_menu_maps_dlarea_item = NULL;
+static GtkWidget *_menu_maps_submenu = NULL;
+static GtkWidget *_menu_maps_mapman_item = NULL;
+static GtkWidget *_menu_maps_repoman_item = NULL;
 static GtkWidget *_menu_auto_download_item = NULL;
 static GtkWidget *_menu_show_tracks_item = NULL;
 static GtkWidget *_menu_show_routes_item = NULL;
@@ -646,7 +785,11 @@ static GtkWidget *_menu_ac_lead_item = NULL;
 static GtkWidget *_menu_ac_none_item = NULL;
 static GtkWidget *_menu_fullscreen_item = NULL;
 static GtkWidget *_menu_enable_gps_item = NULL;
+static GtkWidget *_menu_gps_show_info_item = NULL;
+static GtkWidget *_menu_gps_details_item = NULL;
+static GtkWidget *_menu_gps_reset_item = NULL;
 static GtkWidget *_menu_settings_item = NULL;
+static GtkWidget *_menu_poi_item = NULL;
 static GtkWidget *_menu_help_item = NULL;
 static GtkWidget *_menu_close_item = NULL;
 
@@ -658,6 +801,8 @@ static GtkWidget *_cmenu_loc_show_latlon_item = NULL;
 static GtkWidget *_cmenu_loc_clip_latlon_item = NULL;
 static GtkWidget *_cmenu_loc_route_to_item = NULL;
 static GtkWidget *_cmenu_loc_distance_to_item = NULL;
+static GtkWidget *_cmenu_add_poi = NULL;
+static GtkWidget *_cmenu_edit_poi = NULL;
 
 static GtkWidget *_cmenu_way_show_latlon_item = NULL;
 static GtkWidget *_cmenu_way_show_desc_item = NULL;
@@ -680,33 +825,42 @@ static GHashTable *_downloads_hash = NULL;
 /** CONFIGURATION INFORMATION. */
 static struct sockaddr_rc _rcvr_addr = { 0 };
 static gchar *_rcvr_mac = NULL;
-static gchar *_map_dir_name = NULL;
-static gchar *_map_uri_format = NULL;
 static gchar *_route_dir_uri = NULL;
 static gchar *_track_file_uri = NULL;
 static CenterMode _center_mode = CENTER_LEAD;
 static gboolean _fullscreen = FALSE;
 static gboolean _enable_gps = FALSE;
+static gboolean _gps_info = FALSE;
 static gint _show_tracks = 0;
 static gboolean _show_velvec = TRUE;
 static gboolean _auto_download = FALSE;
-static guint _zoom_steps = 2;
 static guint _lead_ratio = 5;
 static guint _center_ratio = 7;
 static guint _draw_line_width = 5;
-static guint _announce_notice_ratio = 6;
+static guint _announce_notice_ratio = 8;
 static gboolean _enable_voice = TRUE;
 static gboolean _always_keep_on = FALSE;
 static gdouble _voice_speed = 1.0;
 static gint _voice_pitch = 0;
 static GSList *_loc_list;
 static GtkListStore *_loc_model;
-static gchar *_units = NULL;
+static UnitType _units = UNITS_KM;
+static EscapeKeyAction _escape_key = ESCAPE_KEY_TOGGLE_TRACKS;
+
+static GList *_repo_list = NULL;
+static RepoData *_curr_repo = NULL;
+
+/** POI */
+static gchar *_poi_db = NULL;
+static sqlite *_db = NULL;
+static guint _poi_zoom = 6;
+static gboolean _dbconn = FALSE;
 
 /** The singleton auto-route-download data. */
 static AutoRouteDownloadData _autoroute_data;
 
 static gchar XML_TZONE[7];
+static gint _gmtoffset = 0;
 
 /****************************************************************************
  * ABOVE: DATA **************************************************************
@@ -736,6 +890,12 @@ static gboolean
 map_cb_button_press(GtkWidget *widget, GdkEventButton *event);
 static gboolean
 map_cb_button_release(GtkWidget *widget, GdkEventButton *event);
+static gboolean
+heading_panel_expose(GtkWidget *widget, GdkEventExpose *event);
+static gboolean
+sat_panel_expose(GtkWidget *widget, GdkEventExpose *event);
+static gboolean
+sat_details_panel_expose(GtkWidget *widget, GdkEventExpose *event);
 
 static gboolean
 channel_cb_error(GIOChannel *src, GIOCondition condition, gpointer data);
@@ -770,11 +930,16 @@ static gboolean
 menu_cb_show_routes(GtkAction *action);
 static gboolean
 menu_cb_show_velvec(GtkAction *action);
+static gboolean
+menu_cb_category(GtkAction *action);
 
+
+static gboolean
+menu_cb_maps_select(GtkAction *action, gpointer new_repo);
 static gboolean
-menu_cb_maps_dlroute(GtkAction *action);
+menu_cb_mapman(GtkAction *action);
 static gboolean
-menu_cb_maps_dlarea(GtkAction *action);
+menu_cb_maps_repoman(GtkAction *action);
 static gboolean
 menu_cb_auto_download(GtkAction *action);
 
@@ -794,6 +959,10 @@ static gboolean
 cmenu_cb_loc_route_to(GtkAction *action);
 static gboolean
 cmenu_cb_loc_distance_to(GtkAction *action);
+static gboolean
+cmenu_cb_add_poi(GtkAction *action);
+static gboolean
+cmenu_cb_edit_poi(GtkAction *action);
 
 static gboolean
 cmenu_cb_way_show_latlon(GtkAction *action);
@@ -815,6 +984,12 @@ static gboolean
 menu_cb_fullscreen(GtkAction *action);
 static gboolean
 menu_cb_enable_gps(GtkAction *action);
+static gboolean
+menu_cb_gps_show_info(GtkAction *action);
+static gboolean
+menu_cb_gps_details(GtkAction *action);
+static gboolean
+menu_cb_gps_reset(GtkAction *action);
 
 static gboolean
 menu_cb_settings(GtkAction *action);
@@ -841,3265 +1016,4354 @@ auto_route_dl_idle();
  * BELOW: ROUTINES **********************************************************
  ****************************************************************************/
 
-static gfloat
-calculate_distance(gfloat lat1, gfloat lon1, gfloat lat2, gfloat lon2)
+static gboolean
+gps_display_details(void)
 {
-    gfloat dlat, dlon, slat, slon, a;
+    gchar *buffer, strtime[15];
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* Convert to radians. */
-    lat1 *= (PI / 180.f);
-    lon1 *= (PI / 180.f);
-    lat2 *= (PI / 180.f);
-    lon2 *= (PI / 180.f);
+    if(_gps.fix < 2)
+    {
+        /* no fix no fun */
+        gtk_label_set_label(GTK_LABEL(_sdi_lat), " --- ");
+        gtk_label_set_label(GTK_LABEL(_sdi_lon), " --- ");
+        gtk_label_set_label(GTK_LABEL(_sdi_spd), " --- ");
+        gtk_label_set_label(GTK_LABEL(_sdi_alt), " --- ");
+        gtk_label_set_label(GTK_LABEL(_sdi_hea), " --- ");
+        gtk_label_set_label(GTK_LABEL(_sdi_tim), " --:--:-- ");
+    }
+    else
+    {
+        gfloat speed = _gps.speed * UNITS_CONVERT[_units];
 
-    dlat = lat2 - lat1;
-    dlon = lon2 - lon1;
-    
-    slat = sinf(dlat / 2.f);
-    slon = sinf(dlon / 2.f);
-    a = (slat * slat) + (cosf(lat1) * cosf(lat2) * slon * slon);
+        /* latitude */
+        gtk_label_set_label(GTK_LABEL(_sdi_lat), _gps.slatitude);
+
+        /* longitude */
+        gtk_label_set_label(GTK_LABEL(_sdi_lon), _gps.slongitude);
+
+        /* speed */
+        switch(_units)
+        {
+            case UNITS_MI:
+                buffer = g_strdup_printf("%.1f mph", speed);
+                break;
+            case UNITS_NM:
+                buffer = g_strdup_printf("%.1f kn", speed);
+                break;
+            default:
+                buffer = g_strdup_printf("%.1f km/h", speed);
+                break;
+        }
+        gtk_label_set_label(GTK_LABEL(_sdi_spd), buffer);
+        g_free(buffer);
+
+        /* altitude */
+        switch(_units)
+        {
+            case UNITS_MI:
+            case UNITS_NM:
+                buffer = g_strdup_printf("%d ft",
+                        (guint)(_gps.altitude * 3.2808399f));
+                break;
+            default:
+                buffer = g_strdup_printf("%d m", _gps.altitude);
+                break;
+        }
+        gtk_label_set_label(GTK_LABEL(_sdi_alt), buffer);
+        g_free(buffer);
+
+        /* heading */
+        buffer = g_strdup_printf("%0.0f\u00b0", _gps.heading);
+        gtk_label_set_label(GTK_LABEL(_sdi_hea), buffer);
+        g_free(buffer);
+
+        /* local time */
+        strftime(strtime, 15, "%X", &_gps.timeloc);
+        gtk_label_set_label(GTK_LABEL(_sdi_tim), strtime);
+    }
+
+    /* Sat in view */
+    buffer = g_strdup_printf("%d", _gps.satinview);
+    gtk_label_set_label(GTK_LABEL(_sdi_vie), buffer);
+    g_free(buffer);
+
+    /* Sat in use */
+    buffer = g_strdup_printf("%d", _gps.satinuse);
+    gtk_label_set_label(GTK_LABEL(_sdi_use), buffer);
+    g_free(buffer);
+
+    /* fix */
+    switch(_gps.fix)
+    {
+        case 2:
+        case 3: buffer = g_strdup_printf("%dD fix", _gps.fix); break;
+        default: buffer = g_strdup_printf("nofix"); break;
+    }
+    gtk_label_set_label(GTK_LABEL(_sdi_fix), buffer);
+    g_free(buffer);
+
+    if(_gps.fix == 1)
+        buffer = g_strdup("none");
+    else
+    {
+        switch (_gps.fixquality)
+        {
+            case 1 : buffer = g_strdup_printf(_("SPS")); break;
+            case 2 : buffer = g_strdup_printf(_("DGPS")); break;
+            case 3 : buffer = g_strdup_printf(_("PPS")); break;
+            case 4 : buffer = g_strdup_printf(_("Real Time Kinematic")); break;
+            case 5 : buffer = g_strdup_printf(_("Float RTK")); break;
+            case 6 : buffer = g_strdup_printf(_("Estimated")); break;
+            case 7 : buffer = g_strdup_printf(_("Manual)")); break;
+            case 8 : buffer = g_strdup_printf(_("Simulation")); break;
+            default : buffer = g_strdup_printf(_("none")); break;
+        }
+    }
+    gtk_label_set_label(GTK_LABEL(_sdi_fqu), buffer);
+    g_free(buffer);
+
+    /* max speed */
+    {
+        gfloat maxspeed = _gps.maxspeed * UNITS_CONVERT[_units];
 
-    return (2.f * atan2f(sqrtf(a), sqrtf(1.f - a))) *
-            (!strcmp(_units, UNITS_MI) ? EARTH_RADIUS_MI :
-             !strcmp(_units, UNITS_NM) ? EARTH_RADIUS_NM : 
-             EARTH_RADIUS_KM);
+        /* speed */
+        switch(_units)
+        {
+            case UNITS_MI:
+                buffer = g_strdup_printf("%.1f mph", maxspeed);
+                break;
+            case UNITS_NM:
+                buffer = g_strdup_printf("%.1f kn", maxspeed);
+                break;
+            default:
+                buffer = g_strdup_printf("%.1f km/h", maxspeed);
+                break;
+        }
+        gtk_label_set_label(GTK_LABEL(_sdi_msp), buffer);
+        g_free(buffer);
+    }
+
+    /* refresh sat panel */
+    gtk_widget_queue_draw_area(GTK_WIDGET(_sat_details_panel),
+        0, 0,
+        _sat_details_panel->allocation.width,
+        _sat_details_panel->allocation.height);
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return TRUE;
 }
 
-/**
- * Pop up a modal dialog box with simple error information in it.
- */
 static void
-popup_error(GtkWidget *window, const gchar *error)
+gps_display_data(void)
 {
-    GtkWidget *dialog;
-    printf("%s(\"%s\")\n", __PRETTY_FUNCTION__, error);
+    gchar *buffer, strtime[15];
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    dialog = hildon_note_new_information(GTK_WINDOW(window), error);
+    if(_gps.fix < 2)
+    {
+        /* no fix no fun */
+        gtk_label_set_label(GTK_LABEL(_text_lat), " --- ");
+        gtk_label_set_label(GTK_LABEL(_text_lon), " --- ");
+        gtk_label_set_label(GTK_LABEL(_text_speed), " --- ");
+        gtk_label_set_label(GTK_LABEL(_text_alt), " --- ");
+        gtk_label_set_label(GTK_LABEL(_text_time), " --:--:-- ");
+    }
+    else
+    {
+        gfloat speed = _gps.speed * UNITS_CONVERT[_units];
 
-    gtk_dialog_run(GTK_DIALOG(dialog));
-    gtk_widget_destroy(dialog);
+        /* latitude */
+        gtk_label_set_label(GTK_LABEL(_text_lat), _gps.slatitude);
+
+        /* longitude */
+        gtk_label_set_label(GTK_LABEL(_text_lon), _gps.slongitude);
+
+        /* speed */
+        switch(_units)
+        {
+            case UNITS_MI:
+                buffer = g_strdup_printf("Spd: %.1f mph", speed);
+                break;
+            case UNITS_NM:
+                buffer = g_strdup_printf("Spd: %.1f kn", speed);
+                break;
+            default:
+                buffer = g_strdup_printf("Spd: %.1f km/h", speed);
+                break;
+        }
+        gtk_label_set_label(GTK_LABEL(_text_speed), buffer);
+        g_free(buffer);
+
+        /* altitude */
+        switch(_units)
+        {
+            case UNITS_MI:
+            case UNITS_NM:
+                buffer = g_strdup_printf("Alt: %d ft",
+                        (guint)(_gps.altitude * 3.2808399f));
+                break;
+            default:
+                buffer = g_strdup_printf("Alt: %d m", _gps.altitude);
+        }
+        gtk_label_set_label(GTK_LABEL(_text_alt), buffer);
+        g_free(buffer);
+
+        /* local time */
+        strftime(strtime, 15, "%X", &_gps.timeloc);
+        gtk_label_set_label(GTK_LABEL(_sdi_tim), strtime);
+    }
+
+    /* refresh sat panel */
+    gtk_widget_queue_draw_area(GTK_WIDGET(_sat_panel),
+        0, 0,
+        _sat_panel->allocation.width,
+        _sat_panel->allocation.height);
+
+    /* refresh heading panel*/
+    gtk_widget_queue_draw_area(GTK_WIDGET(_heading_panel),
+        0, 0,
+        _heading_panel->allocation.width,
+        _heading_panel->allocation.height);
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return;
 }
 
-/**
- * Set the connection state.  This function controls all connection-related
- * banners.
- */
 static void
-set_conn_state(ConnState new_conn_state)
+gps_hide_text(void)
 {
-    printf("%s(%d)\n", __PRETTY_FUNCTION__, new_conn_state);
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    switch(_conn_state = new_conn_state)
+    /* Clear gps data */
+    _gps.fix = 1;
+    _gps.satinuse = 0;
+    _gps.satinview = 0;
+
+    if(_gps_info)
+        gps_display_data();
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+static void
+gps_show_info(void)
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    if(_gps_info && _enable_gps)
+        gtk_widget_show_all(GTK_WIDGET(_gps_widget));
+    else
     {
-        case RCVR_OFF:
-        case RCVR_FIXED:
-            if(_connect_banner)
-            {
-                gtk_widget_destroy(_connect_banner);
-                _connect_banner = NULL;
-            }
-            if(_fix_banner)
-            {
-                gtk_widget_destroy(_fix_banner);
-                _fix_banner = NULL;
-            }
-            break;
-        case RCVR_DOWN:
-            if(_fix_banner)
-            {
-                gtk_widget_destroy(_fix_banner);
-                _fix_banner = NULL;
-            }
-            if(!_connect_banner)
-                _connect_banner = hildon_banner_show_animation(
-                        _window, NULL, _("Searching for GPS receiver"));
-            break;
-        case RCVR_UP:
-            if(_connect_banner)
-            {
-                gtk_widget_destroy(_connect_banner);
-                _connect_banner = NULL;
-            }
-            if(!_fix_banner)
-                _fix_banner = hildon_banner_show_progress(
-                        _window, NULL, _("Establishing GPS fix"));
-            break;
-        default: ; /* to quell warning. */
+        gps_hide_text();
+        gtk_widget_hide_all(GTK_WIDGET(_gps_widget));
     }
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
-/**
- * Updates _near_point, _next_way, and _next_wpt.  If quick is FALSE (as
- * it is when this function is called from route_find_nearest_point), then
- * the entire list (starting from _near_point) is searched.  Otherwise, we
- * stop searching when we find a point that is farther away.
- */
-static gboolean
-route_update_nears(gboolean quick)
+static void
+draw_sat_info(GtkWidget *widget, guint x0, guint y0,
+        guint width, guint height, gboolean showsnr)
 {
-    gboolean ret = FALSE;
-    Point *curr, *near;
-    WayPoint *wcurr, *wnext;
-    guint near_dist_rough;
-    printf("%s(%d)\n", __PRETTY_FUNCTION__, quick);
-    
-    /* If we have waypoints (_next_way != NULL), then determine the "next
-     * waypoint", which is defined as the waypoint after the nearest point,
-     * UNLESS we've passed that waypoint, in which case the waypoint after
-     * that waypoint becomes the "next" waypoint. */
-    if(_next_way)
+    PangoContext *context = NULL;
+    PangoLayout *layout = NULL;
+    PangoFontDescription *fontdesc = NULL;
+    GdkColor color;
+    GdkGC *gc1, *gc2, *gc;
+    guint step, i, j, snr_height, bymargin, xoffset, yoffset;
+    guint x, y, x1, y1;
+    gchar *tmp = NULL;
+
+    xoffset = x0;
+    yoffset = y0;
+    /* Bootom margin - 12% */
+    bymargin = height * 0.88f;
+
+    /* Bottom line */
+    gdk_draw_line(widget->window,
+        widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+        xoffset + 5, yoffset + bymargin,
+        xoffset + width - 10 - 2, yoffset + bymargin);
+    gdk_draw_line(widget->window,
+        widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+        xoffset + 5, yoffset + bymargin - 1,
+        xoffset + width - 10 - 2, yoffset + bymargin - 1);
+
+    context = gtk_widget_get_pango_context(widget);
+    layout = pango_layout_new(context);
+    fontdesc =  pango_font_description_new();
+
+    pango_font_description_set_family(fontdesc,"Sans Serif");
+
+    if(_gps.satinview > 0 )
     {
-        /* First, set near_dist_rough with the new distance from _near_point. */
-        near = _near_point;
-        near_dist_rough = DISTANCE_ROUGH(_pos, *near);
+        pango_font_description_set_size(fontdesc, 8*PANGO_SCALE);
 
-        /* Now, search _route for a closer point.  If quick is TRUE, then we'll
-         * only search forward, only as long as we keep finding closer points.
-         */
-        for(curr = _near_point; curr++ != _route.tail; )
+        pango_layout_set_font_description (layout, fontdesc);
+        pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
+
+        /* Left margin - 5pix, Right margin - 5pix */
+        step = (width - 10) / _gps.satinview;
+
+        color.red = 0;
+        color.green = 0;
+        color.blue = 0;
+        gc1 = gdk_gc_new (widget->window);
+        gdk_gc_set_rgb_fg_color (gc1, &color);
+
+        color.red = 0;
+        color.green = 0;
+        color.blue = 0xffff;
+        gc2 = gdk_gc_new (widget->window);
+        gdk_gc_set_rgb_fg_color (gc2, &color);
+
+        for(i = 0; i < _gps.satinview; i++)
         {
-            if(curr->unity)
+            /* Sat used or not */
+            gc = gc1;
+            for(j = 0; j < _gps.satinuse ; j++)
             {
-                guint dist_rough = DISTANCE_ROUGH(_pos, *curr);
-                if(dist_rough <= near_dist_rough)
+                if(_gps.satforfix[j] == _gps_sat[i].prn)
                 {
-                    near = curr;
-                    near_dist_rough = dist_rough;
-                }
-                else if(quick)
+                    gc = gc2;
                     break;
+                }
             }
-        }
 
-        /* Update _near_point. */
-        _near_point = near;
-        _near_point_dist_rough = near_dist_rough;
+            x = 5 + i * step;
+            snr_height = _gps_sat[i].snr * height * 0.78f / 100;
+            y = height * 0.1f + (height * 0.78f - snr_height);
 
-        for(wnext = wcurr = _next_way; wcurr != _route.wtail; wcurr++)
-        {
-            if(wcurr->point < near
-            /* Okay, this else if expression warrants explanation.  If the
-             * nearest track point happens to be a waypoint, then we want to
-             * check if we have "passed" that waypoint.  To check this, we
-             * test the distance from _pos to the waypoint and from _pos to
-             * _next_wpt, and if the former is increasing and the latter is
-             * decreasing, then we have passed the waypoint, and thus we
-             * should skip it.  Note that if there is no _next_wpt, then
-             * there is no next waypoint, so we do not skip it in that case. */
-                || (wcurr->point == near && quick
-                    && (_next_wpt
-                     && (DISTANCE_ROUGH(_pos, *near) > _next_way_dist_rough
-                      && DISTANCE_ROUGH(_pos, *_next_wpt)
-                                                     < _next_wpt_dist_rough))))
-                wnext = wcurr + 1;
-            else
-                break;
-        }
+            /* draw sat rectangle... */
+            gdk_draw_rectangle(widget->window,
+                    gc,
+                    TRUE,
+                    xoffset + x,
+                    yoffset + y,
+                    step - 2,
+                    snr_height);
 
-        if(wnext == _route.wtail && (wnext->point < near
-                || (wnext->point == near && quick
-                    && (!_next_wpt
-                     || (DISTANCE_ROUGH(_pos, *near) > _next_way_dist_rough
-                      &&DISTANCE_ROUGH(_pos, *_next_wpt)
-                                                     < _next_wpt_dist_rough)))))
-        {
-            _next_way = NULL;
-            _next_wpt = NULL;
-            _next_way_dist_rough = -1;
-            _next_wpt_dist_rough = -1;
-            ret = TRUE;
-        }
-        /* Only update _next_way (and consequently _next_wpt) if _next_way is
-         * different, and record that fact for return. */
-        else
-        {
-            if(!quick || _next_way != wnext)
+            if(showsnr && _gps_sat[i].snr > 0)
             {
-                _next_way = wnext;
-                _next_wpt = wnext->point;
-                if(_next_wpt == _route.tail)
-                    _next_wpt = NULL;
-                else
-                {
-                    while(!(++_next_wpt)->unity)
-                    {
-                        if(_next_wpt == _route.tail)
-                        {
-                            _next_wpt = NULL;
-                            break;
-                        }
-                    }
-                }
-                ret = TRUE;
+                /* ...snr.. */
+                tmp = g_strdup_printf("%02d", _gps_sat[i].snr);
+                pango_layout_set_text(layout, tmp, 2);
+                pango_layout_get_pixel_size(layout, &x1, &y1);
+                gdk_draw_layout(widget->window,
+                    widget->style->fg_gc[GTK_STATE_NORMAL],
+                    xoffset + x + ((step - 2) - x1)/2,
+                    yoffset + y - 15,
+                    layout);
+                g_free(tmp);
             }
-            _next_way_dist_rough = DISTANCE_ROUGH(_pos, *wnext->point);
-            if(_next_wpt)
-                _next_wpt_dist_rough = DISTANCE_ROUGH(_pos, *_next_wpt);
+
+            /* ...and sat number */
+            tmp = g_strdup_printf("%02d", _gps_sat[i].prn);
+            pango_layout_set_text(layout, tmp, 2);
+            pango_layout_get_pixel_size(layout, &x1, &y1);
+            gdk_draw_layout(widget->window,
+                widget->style->fg_gc[GTK_STATE_NORMAL],
+                xoffset + x + ((step - 2) - x1)/2 ,
+                yoffset + bymargin + 1,
+                layout);
+            g_free(tmp);
         }
+        g_object_unref (gc1);
+        g_object_unref (gc2);
     }
 
-    vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, ret);
-    return ret;
-}
-
-/**
- * Reset the _near_point data by searching the entire route for the nearest
- * route point and waypoint.
- */
-static void
-route_find_nearest_point()
-{
-    printf("%s()\n", __PRETTY_FUNCTION__);
-
-    /* Initialize _near_point. */
-    _near_point = _route.head;
-    while(!_near_point->unity && _near_point != _route.tail)
-        _near_point++;
-
-    /* Initialize _next_way. */
-    if(_route.wtail == _route.whead - 1
-            || (_autoroute_data.enabled && _route.wtail == _route.whead))
-        _next_way = NULL;
-    else
-        /* We have at least one waypoint. */
-        _next_way = (_autoroute_data.enabled ? _route.whead + 1 : _route.whead);
-    _next_way_dist_rough = -1;
-
-    /* Initialize _next_wpt. */
-    _next_wpt = NULL;
-    _next_wpt_dist_rough = -1;
-
-    route_update_nears(FALSE);
+    pango_font_description_free (fontdesc);
+    g_object_unref (layout);
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return;
 }
 
-/**
- * Render a single track line to _map_pixmap.  If either point on the line
- * is a break (defined as unity == 0), a circle is drawn at the other point.
- * IT IS AN ERROR FOR BOTH POINTS TO INDICATE A BREAK.
- */
 static void
-map_render_segment(GdkGC *gc_norm, GdkGC *gc_alt,
-        guint unitx1, guint unity1, guint unitx2, guint unity2)
+draw_sat_details(GtkWidget *widget, guint x0, guint y0,
+        guint width, guint height)
 {
-    vprintf("%s()\n", __PRETTY_FUNCTION__);
-
-    if(!unity1)
-    {
-        guint x2, y2;
-        x2 = unit2bufx(unitx2);
-        y2 = unit2bufy(unity2);
-        /* Make sure this circle will be visible. */
-        if((x2 < BUF_WIDTH_PIXELS)
-                && (y2 < BUF_HEIGHT_PIXELS))
-            gdk_draw_arc(_map_pixmap, gc_alt,
-                    FALSE, /* FALSE: not filled. */
-                    x2 - _draw_line_width,
-                    y2 - _draw_line_width,
-                    2 * _draw_line_width,
-                    2 * _draw_line_width,
-                    0, /* start at 0 degrees. */
-                    360 * 64);
-    }
-    else if(!unity2)
+    guint i, j, x, y, size, halfsize, xoffset, yoffset;
+    guint x1, y1;
+    gfloat tmp;
+    GdkColor color;
+    GdkGC *gc1, *gc2, *gc3, *gc;
+    PangoContext *context = NULL;
+    PangoLayout *layout = NULL;
+    PangoFontDescription *fontdesc = NULL;
+    gchar *buffer = NULL;
+
+    size = MIN(width, height);
+    halfsize = size/2;
+    if(width > height)
     {
-        guint x1, y1;
-        x1 = unit2bufx(unitx1);
-        y1 = unit2bufy(unity1);
-        /* Make sure this circle will be visible. */
-        if((x1 < BUF_WIDTH_PIXELS)
-                && ((unsigned)y1 < BUF_HEIGHT_PIXELS))
-            gdk_draw_arc(_map_pixmap, gc_alt,
-                    FALSE, /* FALSE: not filled. */
-                    x1 - _draw_line_width,
-                    y1 - _draw_line_width,
-                    2 * _draw_line_width,
-                    2 * _draw_line_width,
-                    0, /* start at 0 degrees. */
-                    360 * 64);
+        xoffset = x0 + (width - height - 10) / 2;
+        yoffset = y0 + 5;
     }
     else
     {
-        gint x1, y1, x2, y2;
-        x1 = unit2bufx(unitx1);
-        y1 = unit2bufy(unity1);
-        x2 = unit2bufx(unitx2);
-        y2 = unit2bufy(unity2);
-        /* Make sure this line could possibly be visible. */
-        if(!((x1 > BUF_WIDTH_PIXELS && x2 > BUF_WIDTH_PIXELS)
-                || (x1 < 0 && x2 < 0)
-                || (y1 > BUF_HEIGHT_PIXELS && y2 > BUF_HEIGHT_PIXELS)
-                || (y1 < 0 && y2 < 0)))
-            gdk_draw_line(_map_pixmap, gc_norm, x1, y1, x2, y2);
+        xoffset = x0 + 5;
+        yoffset = y0 + (height - width - 10) / 2;
+    }
+
+    context = gtk_widget_get_pango_context(widget);
+    layout = pango_layout_new(context);
+    fontdesc =  pango_font_description_new();
+
+    pango_font_description_set_family(fontdesc,"Sans Serif");
+    pango_font_description_set_size(fontdesc, 10*PANGO_SCALE);
+    pango_layout_set_font_description (layout, fontdesc);
+    pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
+
+    /* 90 */
+    gdk_draw_arc(widget->window,
+            widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+            FALSE,
+            xoffset + 2, yoffset + 2, size - 4, size - 4,
+            0, 64 * 360);
+
+    /* 60 */
+    gdk_draw_arc(widget->window,
+            widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+            FALSE,
+            xoffset + size/6, yoffset + size/6,
+            size/6*4, size/6*4,
+            0, 64 * 360);
+
+    /* 30 */
+    gdk_draw_arc(widget->window,
+            widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+            FALSE,
+            xoffset + size/6*2, yoffset + size/6*2,
+            size/6*2, size/6*2,
+            0, 64 * 360);
+
+    guint line[12] = {0,30,60,90,120,150,180,210,240,270,300,330};
+
+    for(i = 0; i < 6; i++)
+    {
+        /* line */
+        tmp = (line[i] * (1.f / 180.f)) * PI;
+        gdk_draw_line(widget->window,
+            widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+            xoffset + halfsize + (halfsize -2) * sinf(tmp),
+            yoffset + halfsize - (halfsize -2) * cosf(tmp),
+            xoffset + halfsize - (halfsize -2) * sinf(tmp),
+            yoffset + halfsize + (halfsize -2) * cosf(tmp));
     }
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
-
-/**
- * Render all track data onto the _map_pixmap.  Note that this does not
- * clear the pixmap of previous track data (use map_force_redraw() for
- * that), and also note that this method does not queue any redraws, so it
- * is up to the caller to decide which part of the track really needs to be
- * redrawn.
- */
-static void
-map_render_track()
-{
-    TrackPoint *curr;
-    printf("%s()\n", __PRETTY_FUNCTION__);
-
-    for(curr = _track.head; curr != _track.tail; curr++)
-        map_render_segment(_gc_track, _gc_track_break,
-                curr->point.unitx, curr->point.unity,
-                curr[1].point.unitx, curr[1].point.unity);
-
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
-
-/**
- * Render all track data onto the _map_pixmap.  Note that this does not
- * clear the pixmap of previous track data (use map_force_redraw() for
- * that), and also note that this method does not queue any redraws, so it
- * is up to the caller to decide which part of the track really needs to be
- * redrawn.
- */
-static void
-map_render_route()
-{
-    Point *curr;
-    WayPoint *wcurr;
-    printf("%s()\n", __PRETTY_FUNCTION__);
-
-    _visible_way_first = _visible_way_last = NULL;
-    for(curr = _route.head, wcurr = _route.whead; curr != _route.tail; curr++)
+    for(i = 0; i < 12; i++)
     {
-        if(wcurr <= _route.wtail && curr == wcurr->point)
-        {
-            guint x1 = unit2bufx(wcurr->point->unitx);
-            guint y1 = unit2bufy(wcurr->point->unity);
-            if((x1 < BUF_WIDTH_PIXELS)
-                    && (y1 < BUF_HEIGHT_PIXELS))
-            {
-                gdk_draw_arc(_map_pixmap,
-                        (wcurr==_next_way ? _gc_route_nextway : _gc_route_way),
-                        FALSE, /* FALSE: not filled. */
-                        x1 - _draw_line_width,
-                        y1 - _draw_line_width,
-                        2 * _draw_line_width,
-                        2 * _draw_line_width,
-                        0, /* start at 0 degrees. */
-                        360 * 64);
-                if(!_visible_way_first)
-                    _visible_way_first = wcurr;
-                _visible_way_last = wcurr;
-            }
-            wcurr++;
-            if(!curr[1].unity)
-                continue;
-        }
-        map_render_segment(_gc_route, _gc_route_way,
-                curr->unitx, curr->unity, curr[1].unitx, curr[1].unity);
+        tmp = (line[i] * (1.f / 180.f)) * PI;
+        /* azimuth */
+        if(line[i] == 0)
+            buffer = g_strdup_printf("N");
+        else
+            buffer = g_strdup_printf("%d\u00b0", line[i]);
+        pango_layout_set_text(layout, buffer, strlen(buffer));
+        pango_layout_get_pixel_size(layout, &x, &y);
+        gdk_draw_layout(widget->window,
+            widget->style->fg_gc[GTK_STATE_NORMAL],
+            (xoffset + halfsize + (halfsize - size/12) * sinf(tmp)) - x/2,
+            (yoffset + halfsize - (halfsize - size/12) * cosf(tmp)) - y/2,
+            layout);
+        g_free(buffer);
     }
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
-
-static void
-map_render_paths()
-{
-    printf("%s()\n", __PRETTY_FUNCTION__);
-
-    if((_show_tracks & ROUTES_MASK) && _route.head)
+    /* elevation 30 */
+    tmp = (30 * (1.f / 180.f)) * PI;
+    buffer = g_strdup_printf("30\u00b0");
+    pango_layout_set_text(layout, buffer, strlen(buffer));
+    pango_layout_get_pixel_size(layout, &x, &y);
+    gdk_draw_layout(widget->window,
+        widget->style->fg_gc[GTK_STATE_NORMAL],
+        (xoffset + halfsize + size/6*2 * sinf(tmp)) - x/2,
+        (yoffset + halfsize - size/6*2 * cosf(tmp)) - y/2,
+        layout);
+    g_free(buffer);
+
+    /* elevation 60 */
+    tmp = (30 * (1.f / 180.f)) * PI;
+    buffer = g_strdup_printf("60\u00b0");
+    pango_layout_set_text(layout, buffer, strlen(buffer));
+    pango_layout_get_pixel_size(layout, &x, &y);
+    gdk_draw_layout(widget->window,
+        widget->style->fg_gc[GTK_STATE_NORMAL],
+        (xoffset + halfsize + size/6 * sinf(tmp)) - x/2,
+        (yoffset + halfsize - size/6 * cosf(tmp)) - y/2,
+        layout);
+    g_free(buffer);
+
+    color.red = 0;
+    color.green = 0;
+    color.blue = 0;
+    gc1 = gdk_gc_new (widget->window);
+    gdk_gc_set_rgb_fg_color (gc1, &color);
+
+    color.red = 0;
+    color.green = 0;
+    color.blue = 0xffff;
+    gc2 = gdk_gc_new (widget->window);
+    gdk_gc_set_rgb_fg_color (gc2, &color);
+
+    color.red = 0xffff;
+    color.green = 0xffff;
+    color.blue = 0xffff;
+    gc3 = gdk_gc_new (widget->window);
+    gdk_gc_set_rgb_fg_color (gc3, &color);
+
+    for(i = 0; i < _gps.satinview; i++)
     {
-        map_render_route();
-        if(_next_way == NULL)
+        /* satellite track */
+        tmp = (_gps_sat[i].azimuth * (1.f / 180.f)) * PI;
+        x = xoffset + halfsize + (90 - _gps_sat[i].elevation)
+            * halfsize / 90 * sinf(tmp);
+        y = yoffset + halfsize - (90 - _gps_sat[i].elevation)
+            * halfsize/90 * cosf(tmp);
+        gdk_draw_point (widget->window, gc2, x, y);
+
+        /* Sat used or not */
+        gc = gc1;
+        for(j = 0; j < _gps.satinuse ; j++)
         {
-            guint x1 = unit2bufx(_route.tail[-1].unitx);
-            guint y1 = unit2bufy(_route.tail[-1].unity);
-            if((x1 < BUF_WIDTH_PIXELS)
-                    && (y1 < BUF_HEIGHT_PIXELS))
+            if(_gps.satforfix[j] == _gps_sat[i].prn)
             {
-                gdk_draw_arc(_map_pixmap,
-                        _gc_route_nextway,
-                        FALSE, /* FALSE: not filled. */
-                        x1 - _draw_line_width,
-                        y1 - _draw_line_width,
-                        2 * _draw_line_width,
-                        2 * _draw_line_width,
-                        0, /* start at 0 degrees. */
-                        360 * 64);
+                gc = gc2;
+                break;
             }
         }
+
+        tmp = (_gps_sat[i].azimuth * (1.f / 180.f)) * PI;
+        x = xoffset + halfsize
+            + (90 - _gps_sat[i].elevation)*halfsize/90 * sinf(tmp);
+        y = yoffset + halfsize
+            - (90 - _gps_sat[i].elevation)*halfsize/90 * cosf(tmp);
+
+        gdk_draw_arc (widget->window,
+            gc, TRUE,
+            x - 10, y - 10, 20, 20,
+            0, 64 * 360);
+
+        buffer = g_strdup_printf("%02d", _gps_sat[i].prn);
+        pango_layout_set_text(layout, buffer, strlen(buffer));
+        pango_layout_get_pixel_size(layout, &x1, &y1);
+        gdk_draw_layout(widget->window,
+            gc3,
+            x - x1/2,
+            y - y1/2,
+            layout);
+        g_free(buffer);
     }
-    if(_show_tracks & TRACKS_MASK)
-        map_render_track();
+    g_object_unref (gc1);
+    g_object_unref (gc2);
+    g_object_unref (gc3);
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    pango_font_description_free (fontdesc);
+    g_object_unref (layout);
+
+    return;
 }
 
-static void
-track_resize(Track *track, guint size)
-{
-    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    if(track->head + size != track->cap)
-    {
-        TrackPoint *old_head = track->head;
-        track->head = g_renew(TrackPoint, old_head, size);
-        track->cap = track->head + size;
-        if(track->head != old_head)
-            track->tail = track->head + (track->tail - old_head);
-    }
+static gboolean
+sat_details_panel_expose(GtkWidget *widget, GdkEventExpose *event)
+{
+    guint width, height, x, y;
+    PangoContext *context = NULL;
+    PangoLayout *layout = NULL;
+    PangoFontDescription *fontdesc = NULL;
+    gchar *buffer = NULL;
+
+    width = widget->allocation.width;
+    height = widget->allocation.height * 0.9;
+
+    draw_sat_info(widget, 0, 0, width/2, height, TRUE);
+    draw_sat_details(widget, width/2, 0, width/2, height);
+
+    context = gtk_widget_get_pango_context(widget);
+    layout = pango_layout_new(context);
+    fontdesc =  pango_font_description_new();
+
+    pango_font_description_set_family(fontdesc,"Sans Serif");
+    pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
+    pango_font_description_set_size(fontdesc, 14*PANGO_SCALE);
+    pango_layout_set_font_description (layout, fontdesc);
+
+    buffer = g_strdup_printf(
+        _("Satellites in view: %d; in use: %d"),
+        _gps.satinview,
+        _gps.satinuse);
+    pango_layout_set_text(layout, buffer, strlen(buffer));
+    pango_layout_get_pixel_size(layout, &x, &y);
+    gdk_draw_layout(widget->window,
+        widget->style->fg_gc[GTK_STATE_NORMAL],
+        10,
+        height*0.9 + 10,
+        layout);
+    g_free(buffer);
+
+    buffer = g_strdup_printf(_("HDOP: %.01f"), _gps.hdop);
+    pango_layout_set_text(layout, buffer, strlen(buffer));
+    pango_layout_get_pixel_size(layout, &x, &y);
+    gdk_draw_layout(widget->window,
+        widget->style->fg_gc[GTK_STATE_NORMAL],
+        (width/8) - x/2,
+        (height/6) - y/2,
+        layout);
+    g_free(buffer);
+    buffer = g_strdup_printf(_("PDOP: %.01f"), _gps.pdop);
+    pango_layout_set_text(layout, buffer, strlen(buffer));
+    pango_layout_get_pixel_size(layout, &x, &y);
+    gdk_draw_layout(widget->window,
+        widget->style->fg_gc[GTK_STATE_NORMAL],
+        (width/8) - x/2,
+        (height/6) - y/2 + 20,
+        layout);
+    g_free(buffer);
+    buffer = g_strdup_printf(_("VDOP: %.01f"), _gps.vdop);
+    pango_layout_set_text(layout, buffer, strlen(buffer));
+    pango_layout_get_pixel_size(layout, &x, &y);
+    gdk_draw_layout(widget->window,
+        widget->style->fg_gc[GTK_STATE_NORMAL],
+        (width/8) - x/2,
+        (height/6) - y/2 + 40,
+        layout);
+    g_free(buffer);
+
+    pango_font_description_free (fontdesc);
+    g_object_unref (layout);
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return TRUE;
 }
 
 static void
-route_resize(Route *route, guint size)
+gps_details(void)
 {
+    GtkWidget *dialog;
+    GtkWidget *table;
+    GtkWidget *label;
+    GtkWidget *notebook;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    if(route->head + size != route->cap)
-    {
-        Point *old_head = route->head;
-        WayPoint *curr;
-        route->head = g_renew(Point, old_head, size);
-        route->cap = route->head + size;
-        if(route->head != old_head)
-        {
-            route->tail = route->head + (route->tail - old_head);
+    dialog = gtk_dialog_new_with_buttons(_("GPS Details"),
+            GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+            NULL);
 
-            /* Adjust all of the waypoints. */
-            for(curr = route->whead - 1; curr++ != route->wtail; )
-                curr->point = route->head + (curr->point - old_head);
-        }
-    }
+    gtk_window_set_default_size(GTK_WINDOW(dialog), 600, 300);
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+            notebook = gtk_notebook_new(), TRUE, TRUE, 0);
 
-static void
-route_wresize(Route *route, guint wsize)
-{
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    /* textual info */
+    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+            table = gtk_table_new(4, 6, FALSE),
+            label = gtk_label_new(_("GPS Information")));
 
-    if(route->whead + wsize != route->wcap)
+    _sat_details_panel = gtk_drawing_area_new ();
+    gtk_widget_set_size_request (_sat_details_panel, 300, 300);
+    /* sat details info */
+    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+            _sat_details_panel,
+            label = gtk_label_new(_("Satellites details")));
+    g_signal_connect (G_OBJECT (_sat_details_panel), "expose_event",
+                        G_CALLBACK (sat_details_panel_expose), NULL);
+
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Latitude")),
+            0, 1, 0, 1, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            _sdi_lat = gtk_label_new(" --- "),
+            1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(_sdi_lat), 0.f, 0.5f);
+
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Longitude")),
+            0, 1, 1, 2, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            _sdi_lon = gtk_label_new(" --- "),
+            1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(_sdi_lon), 0.f, 0.5f);
+
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Speed")),
+            0, 1, 2, 3, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            _sdi_spd = gtk_label_new(" --- "),
+            1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(_sdi_spd), 0.f, 0.5f);
+
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Altitude")),
+            0, 1, 3, 4, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            _sdi_alt = gtk_label_new(" --- "),
+            1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(_sdi_alt), 0.f, 0.5f);
+
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Heading")),
+            0, 1, 4, 5, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            _sdi_hea = gtk_label_new(" --- "),
+            1, 2, 4, 5, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(_sdi_hea), 0.f, 0.5f);
+
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Local time")),
+            0, 1, 5, 6, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            _sdi_tim = gtk_label_new(_(" --:--:-- ")),
+            1, 2, 5, 6, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(_sdi_tim), 0.f, 0.5f);
+
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Sat in view")),
+            2, 3, 0, 1, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            _sdi_vie = gtk_label_new("0"),
+            3, 4, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(_sdi_vie), 0.f, 0.5f);
+
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Sat in use")),
+            2, 3, 1, 2, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            _sdi_use = gtk_label_new("0"),
+            3, 4, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(_sdi_use), 0.f, 0.5f);
+
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Fix")),
+            2, 3, 2, 3, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            _sdi_fix = gtk_label_new(_("nofix")),
+            3, 4, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(_sdi_fix), 0.f, 0.5f);
+
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Fix Quality")),
+            2, 3, 3, 4, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            _sdi_fqu = gtk_label_new(_("none")),
+            3, 4, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(_sdi_fix), 0.f, 0.5f);
+
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Max speed")),
+            2, 3, 5, 6, GTK_EXPAND | GTK_FILL, 0, 20, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            _sdi_msp = gtk_label_new(" --- "),
+            3, 4, 5, 6, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(_sdi_msp), 0.f, 0.5f);
+
+    gtk_widget_show_all(dialog);
+    _satdetails_on = TRUE;
+    gps_display_details();
+    while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
     {
-        WayPoint *old_whead = route->whead;
-        route->whead = g_renew(WayPoint, old_whead, wsize);
-        route->wtail = route->whead + (route->wtail - old_whead);
-        route->wcap = route->whead + wsize;
+        _satdetails_on = FALSE;
+        break;
     }
+    gtk_widget_destroy(dialog);
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
-#define MACRO_TRACK_INCREMENT_TAIL(track) { \
-    if(++(track).tail == (track).cap) \
-        track_resize(&(track), (track).cap - (track).head + ARRAY_CHUNK_SIZE); \
-}
+static gfloat
+calculate_distance(gfloat lat1, gfloat lon1, gfloat lat2, gfloat lon2)
+{
+    gfloat dlat, dlon, slat, slon, a;
 
-#define MACRO_ROUTE_INCREMENT_TAIL(route) { \
-    if(++(route).tail == (route).cap) \
-        route_resize(&(route), (route).cap - (route).head + ARRAY_CHUNK_SIZE); \
-}
+    /* Convert to radians. */
+    lat1 *= (PI / 180.f);
+    lon1 *= (PI / 180.f);
+    lat2 *= (PI / 180.f);
+    lon2 *= (PI / 180.f);
 
-#define MACRO_ROUTE_INCREMENT_WTAIL(route) { \
-    if(++(route).wtail == (route).wcap) \
-        route_wresize(&(route), \
-                (route).wcap - (route).whead + ARRAY_CHUNK_SIZE); \
+    dlat = lat2 - lat1;
+    dlon = lon2 - lon1;
+
+    slat = sinf(dlat / 2.f);
+    slon = sinf(dlon / 2.f);
+    a = (slat * slat) + (cosf(lat1) * cosf(lat2) * slon * slon);
+
+    return ((2.f * atan2f(sqrtf(a), sqrtf(1.f - a))) * EARTH_RADIUS)
+        * UNITS_CONVERT[_units];
 }
 
 /**
- * Add a point to the _track list.  This function is slightly overloaded,
- * since it is what houses the check for "have we moved
- * significantly": it also initiates the re-calculation of the _near_point
- * data, as well as calling osso_display_state_on() when we have the focus.
- *
- * If a non-zero time is given, then the current position (as taken from the
- * _pos variable) is appended to _track with the given time.  If time is zero,
- * then _pos_null is appended to _track with time zero (this produces a "break"
- * in the track).
+ * Pop up a modal dialog box with simple error information in it.
  */
 static void
-track_add(time_t time, gboolean newly_fixed)
+popup_error(GtkWidget *window, const gchar *error)
 {
-    Point pos = (time == 0 ? _pos_null : _pos);
-    printf("%s(%u, %u)\n", __PRETTY_FUNCTION__, pos.unitx, pos.unity);
-
-    if(abs((gint)pos.unitx - _track.tail->point.unitx) > _draw_line_width
-    || abs((gint)pos.unity - _track.tail->point.unity) > _draw_line_width)
-    {
-        if(time && _route.head
-                && (newly_fixed ? (route_find_nearest_point(), TRUE)
-                                : route_update_nears(TRUE)))
-        {
-            map_render_paths();
-            MACRO_QUEUE_DRAW_AREA();
-        }
-        if(_show_tracks & TRACKS_MASK)
-        {
-            /* Instead of calling map_render_paths(), we'll draw the new line
-             * ourselves and call gtk_widget_queue_draw_area(). */
-            gint tx1, ty1, tx2, ty2;
-            map_render_segment(_gc_track, _gc_track_break,
-                    _track.tail->point.unitx, _track.tail->point.unity,
-                    pos.unitx, pos.unity);
-            if(time && _track.tail->point.unity)
-            {
-                tx1 = unit2x(_track.tail->point.unitx);
-                ty1 = unit2y(_track.tail->point.unity);
-                tx2 = unit2x(pos.unitx);
-                ty2 = unit2y(pos.unity);
-                gtk_widget_queue_draw_area(_map_widget,
-                        MIN(tx1, tx2) - _draw_line_width,
-                        MIN(ty1, ty2) - _draw_line_width,
-                        abs(tx1 - tx2) + (2 * _draw_line_width),
-                        abs(ty1 - ty2) + (2 * _draw_line_width));
-            }
-        }
-        MACRO_TRACK_INCREMENT_TAIL(_track);
-
-        _track.tail->point = pos;
-        _track.tail->time = time;
-
-        if(_autoroute_data.enabled && !_autoroute_data.in_progress
-                && _near_point_dist_rough > 400)
-        {
-            _autoroute_data.in_progress = TRUE;
-            g_idle_add((GSourceFunc)auto_route_dl_idle, NULL);
-        }
+    GtkWidget *dialog;
+    printf("%s(\"%s\")\n", __PRETTY_FUNCTION__, error);
 
-        /* Keep the display on. */
-        KEEP_DISPLAY_ON();
-    }
+    dialog = hildon_note_new_information(GTK_WINDOW(window), error);
 
-    /* Check if we should announce upcoming waypoints. */
-    if(time && _next_way_dist_rough
-            < (10 + (guint)_speed) * _announce_notice_ratio * 5)
-    {
-        if(_enable_voice && strcmp(_next_way->desc, _last_spoken_phrase))
-        {
-            g_free(_last_spoken_phrase);
-            _last_spoken_phrase = g_strdup(_next_way->desc);
-            printf("Sending to flite: %s\n", _last_spoken_phrase);
-            hildon_play_system_sound(
-                    "/usr/share/sounds/ui-information_note.wav");
-            osso_rpc_async_run(_osso,
-                    "com.nokia.flite",
-                    "/com/nokia/flite",
-                    "com.nokia.flite",
-                    "flite_tts",
-                    NULL,
-                    NULL,
-                    DBUS_TYPE_UINT32,
-                    getpid(),
-                    DBUS_TYPE_STRING,
-                    _last_spoken_phrase,
-                    DBUS_TYPE_UINT32,
-                    18,
-                    DBUS_TYPE_DOUBLE,
-                    _voice_speed,
-                    DBUS_TYPE_DOUBLE,
-                    _voice_pitch,
-                    DBUS_TYPE_STRING,
-                    g_strdup("cmu_us_kal"),
-                    DBUS_TYPE_INVALID);
-        }
-        hildon_banner_show_information(_window, NULL, _next_way->desc);
-    }
+    gtk_dialog_run(GTK_DIALOG(dialog));
+    gtk_widget_destroy(dialog);
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
-/**
- * Disconnect from the receiver.  This method cleans up any and everything
- * that might be associated with the receiver.
- */
 static void
-rcvr_disconnect()
+db_connect()
 {
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    gchar buffer[100];
+    gchar *perror;
+    gchar **pszResult;
+    guint nRow, nColumn;
 
-    /* Remove watches. */
-    if(_clater_sid)
-    {
-        g_source_remove(_clater_sid);
-        _clater_sid = 0;
-    }
-    if(_error_sid)
-    {
-        g_source_remove(_error_sid);
-        _error_sid = 0;
-    }
-    if(_connect_sid)
-    {
-        g_source_remove(_connect_sid);
-        _connect_sid = 0;
-    }
-    if(_input_sid)
-    {
-        g_source_remove(_input_sid);
-        _input_sid = 0;
-    }
+    _dbconn = FALSE;
 
-    /* Destroy the GIOChannel object. */
-    if(_channel)
+    if(!_poi_db)
+        return;
+
+    if((_db = sqlite_open(_poi_db, 0666, &perror)) == NULL)
     {
-        g_io_channel_shutdown(_channel, FALSE, NULL);
-        g_io_channel_unref(_channel);
-        _channel = NULL;
+        gchar buffer2[200];
+        sprintf(buffer2, "%s: %s", _("Problem with POI database"), perror);
+        popup_error(_window, buffer2);
+        g_free(perror);
+        return;
     }
 
-    /* Close the file descriptor. */
-    if(_fd != -1)
+    if(sqlite_get_table(_db, "select label from poi limit 1",
+        &pszResult, &nRow, &nColumn, NULL) != SQLITE_OK)
     {
-        close(_fd);
-        _fd = -1;
+        if(SQLITE_OK != sqlite_exec(_db,
+                "create table poi (poi_id integer PRIMARY KEY, lat real, "
+                "lon real, label text, desc text, cat_id integer);"
+                "create table category (cat_id integer PRIMARY KEY,"
+                "label text, desc text, enabled integer);"
+                "insert into category (label, desc, enabled) "
+                "values ('Fuel',"
+                  "'Stations for purchasing fuel for vehicles.', 1);"
+                "insert into category (label, desc, enabled) "
+                "values ('Residence', "
+                  "'Houses, apartments, or other residences of import.', 1);"
+                "insert into category (label, desc, enabled) "
+                "values ('Dining', "
+                  "'Places to eat or drink.', 1);"
+                "insert into category (label, desc, enabled) "
+                "values ('Shopping/Services', "
+                  "'Places to shop or acquire services.', 1);"
+                "insert into category (label, desc, enabled) "
+                "values ('Recreation', "
+                  "'Indoor or Outdoor places to have fun.', 1);"
+                "insert into category (label, desc, enabled) "
+                "values ('Transportation', "
+                  "'Bus stops, airports, train stations, etc.', 1);"
+                "insert into category (label, desc, enabled) "
+                "values ('Lodging', "
+                  "'Places to stay temporarily or for the night.', 1);"
+                "insert into category (label, desc, enabled) "
+                "values ('School', "
+                  "'Elementary schools, college campuses, etc.', 1);"
+                "insert into category (label, desc, enabled) "
+                "values ('Business', "
+                  "'General places of business.', 1);"
+                "insert into category (label, desc, enabled) "
+                "values ('Landmark', "
+                  "'General landmarks.', 1);"
+                "insert into category (label, desc, enabled) "
+                "values ('Other', "
+                  "'Miscellaneous category for everything else.', 1);",
+                NULL,
+                NULL,
+                &perror)
+                && (sqlite_get_table(_db, "select label from poi limit 1",
+                        &pszResult, &nRow, &nColumn, NULL) != SQLITE_OK))
+        {
+            sprintf(buffer, _("Failed to open or create database:\n%s"),
+                    _poi_db);
+            popup_error(_window, buffer);
+            sqlite_close(_db);
+            return;
+        }
     }
+    else
+        sqlite_free_table(pszResult);
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    _dbconn = TRUE;
 }
 
-static void rcvr_connect_later(); /* Forward declaration. */
-
 /**
- * Connect to the receiver.
- * This method assumes that _fd is -1 and _channel is NULL.  If unsure, call
- * rcvr_disconnect() first.
- * Since this is an idle function, this function returns whether or not it
- * should be called again, which is always FALSE.
+ * Set the connection state.  This function controls all connection-related
+ * banners.
  */
-static gboolean
-rcvr_connect_now()
+static void
+set_conn_state(ConnState new_conn_state)
 {
-    printf("%s(%d)\n", __PRETTY_FUNCTION__, _conn_state);
-
-    if(_conn_state == RCVR_DOWN && _rcvr_mac) {
-#ifndef DEBUG
-        /* Create the file descriptor. */
-        if(*_rcvr_mac == '/')
-            _fd = open(_rcvr_mac, O_RDONLY);
-        else
-            _fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+    printf("%s(%d)\n", __PRETTY_FUNCTION__, new_conn_state);
 
-        /* If file descriptor creation failed, try again later.  Note that
-         * there is no need to call rcvr_disconnect() because the file
-         * descriptor creation is the first step, so if it fails, there's
-         * nothing to clean up. */
-        if(_fd == -1)
-            rcvr_connect_later();
-        else
-        {
-            _channel = g_io_channel_unix_new(_fd);
-            g_io_channel_set_flags(_channel, G_IO_FLAG_NONBLOCK, NULL);
-            _error_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE,
-                    G_IO_ERR | G_IO_HUP, channel_cb_error, NULL, NULL);
-            _connect_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE,
-                    G_IO_OUT, channel_cb_connect, NULL, NULL);
-            if(*_rcvr_mac != '/'
-                    && connect(_fd, (struct sockaddr*)&_rcvr_addr,
-                        sizeof(_rcvr_addr))
-                    && errno != EAGAIN)
+    switch(_conn_state = new_conn_state)
+    {
+        case RCVR_OFF:
+        case RCVR_FIXED:
+            if(_connect_banner)
             {
-                /* Connection failed.  Disconnect and try again later. */
-                rcvr_disconnect();
-                rcvr_connect_later();
+                gtk_widget_destroy(_connect_banner);
+                _connect_banner = NULL;
             }
-        }
-#else
-        /* We're in DEBUG mode, so instead of connecting, skip to FIXED. */
-        set_conn_state(RCVR_FIXED);
-#endif
+            if(_fix_banner)
+            {
+                gtk_widget_destroy(_fix_banner);
+                _fix_banner = NULL;
+            }
+            break;
+        case RCVR_DOWN:
+            if(_fix_banner)
+            {
+                gtk_widget_destroy(_fix_banner);
+                _fix_banner = NULL;
+            }
+            if(!_connect_banner)
+                _connect_banner = hildon_banner_show_animation(
+                        _window, NULL, _("Searching for GPS receiver"));
+            break;
+        case RCVR_UP:
+            if(_connect_banner)
+            {
+                gtk_widget_destroy(_connect_banner);
+                _connect_banner = NULL;
+            }
+            if(!_fix_banner)
+                _fix_banner = hildon_banner_show_progress(
+                        _window, NULL, _("Establishing GPS fix"));
+            break;
+        default: ; /* to quell warning. */
     }
 
-    _clater_sid = 0;
-
-    vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
-    return FALSE;
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
 /**
- * Place a request to connect about 1 second after the function is called.
+ * Updates _near_point, _next_way, and _next_wpt.  If quick is FALSE (as
+ * it is when this function is called from route_find_nearest_point), then
+ * the entire list (starting from _near_point) is searched.  Otherwise, we
+ * stop searching when we find a point that is farther away.
  */
-static void
-rcvr_connect_later()
+static gboolean
+route_update_nears(gboolean quick)
 {
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    gboolean ret = FALSE;
+    Point *curr, *near;
+    WayPoint *wcurr, *wnext;
+    guint near_dist_rough;
+    printf("%s(%d)\n", __PRETTY_FUNCTION__, quick);
+    
+    /* If we have waypoints (_next_way != NULL), then determine the "next
+     * waypoint", which is defined as the waypoint after the nearest point,
+     * UNLESS we've passed that waypoint, in which case the waypoint after
+     * that waypoint becomes the "next" waypoint. */
+    if(_next_way)
+    {
+        /* First, set near_dist_rough with the new distance from _near_point. */
+        near = _near_point;
+        near_dist_rough = DISTANCE_ROUGH(_pos, *near);
 
-    _clater_sid = g_timeout_add(1000, (GSourceFunc)rcvr_connect_now, NULL);
+        /* Now, search _route for a closer point.  If quick is TRUE, then we'll
+         * only search forward, only as long as we keep finding closer points.
+         */
+        for(curr = _near_point; curr++ != _route.tail; )
+        {
+            if(curr->unity)
+            {
+                guint dist_rough = DISTANCE_ROUGH(_pos, *curr);
+                if(dist_rough <= near_dist_rough)
+                {
+                    near = curr;
+                    near_dist_rough = dist_rough;
+                }
+                else if(quick)
+                    break;
+            }
+        }
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+        /* Update _near_point. */
+        _near_point = near;
+        _near_point_dist_rough = near_dist_rough;
+
+        for(wnext = wcurr = _next_way; wcurr != _route.wtail; wcurr++)
+        {
+            if(wcurr->point < near
+            /* Okay, this else if expression warrants explanation.  If the
+             * nearest track point happens to be a waypoint, then we want to
+             * check if we have "passed" that waypoint.  To check this, we
+             * test the distance from _pos to the waypoint and from _pos to
+             * _next_wpt, and if the former is increasing and the latter is
+             * decreasing, then we have passed the waypoint, and thus we
+             * should skip it.  Note that if there is no _next_wpt, then
+             * there is no next waypoint, so we do not skip it in that case. */
+                || (wcurr->point == near && quick
+                    && (_next_wpt
+                     && (DISTANCE_ROUGH(_pos, *near) > _next_way_dist_rough
+                      && DISTANCE_ROUGH(_pos, *_next_wpt)
+                                                     < _next_wpt_dist_rough))))
+                wnext = wcurr + 1;
+            else
+                break;
+        }
+
+        if(wnext == _route.wtail && (wnext->point < near
+                || (wnext->point == near && quick
+                    && (!_next_wpt
+                     || (DISTANCE_ROUGH(_pos, *near) > _next_way_dist_rough
+                      &&DISTANCE_ROUGH(_pos, *_next_wpt)
+                                                     < _next_wpt_dist_rough)))))
+        {
+            _next_way = NULL;
+            _next_wpt = NULL;
+            _next_way_dist_rough = -1;
+            _next_wpt_dist_rough = -1;
+            ret = TRUE;
+        }
+        /* Only update _next_way (and consequently _next_wpt) if _next_way is
+         * different, and record that fact for return. */
+        else
+        {
+            if(!quick || _next_way != wnext)
+            {
+                _next_way = wnext;
+                _next_wpt = wnext->point;
+                if(_next_wpt == _route.tail)
+                    _next_wpt = NULL;
+                else
+                {
+                    while(!(++_next_wpt)->unity)
+                    {
+                        if(_next_wpt == _route.tail)
+                        {
+                            _next_wpt = NULL;
+                            break;
+                        }
+                    }
+                }
+                ret = TRUE;
+            }
+            _next_way_dist_rough = DISTANCE_ROUGH(_pos, *wnext->point);
+            if(_next_wpt)
+                _next_wpt_dist_rough = DISTANCE_ROUGH(_pos, *_next_wpt);
+        }
+    }
+
+    vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, ret);
+    return ret;
 }
 
 /**
- * Convert the float lat/lon/speed/heading data into integer units.
+ * Reset the _near_point data by searching the entire route for the nearest
+ * route point and waypoint.
  */
 static void
-integerize_data()
+route_find_nearest_point()
 {
-    gfloat tmp;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    latlon2unit(_pos_lat, _pos_lon, _pos.unitx, _pos.unity);
+    /* Initialize _near_point. */
+    _near_point = _route.head;
+    while(!_near_point->unity && _near_point != _route.tail)
+        _near_point++;
 
-    tmp = (_heading * (1.f / 180.f)) * PI;
-    _vel_offsetx = (gint)(floorf(_speed * sinf(tmp) + 0.5f));
-    _vel_offsety = -(gint)(floorf(_speed * cosf(tmp) + 0.5f));
+    /* Initialize _next_way. */
+    if(_route.wtail == _route.whead - 1
+            || (_autoroute_data.enabled && _route.wtail == _route.whead))
+        _next_way = NULL;
+    else
+        /* We have at least one waypoint. */
+        _next_way = (_autoroute_data.enabled ? _route.whead + 1 : _route.whead);
+    _next_way_dist_rough = -1;
+
+    /* Initialize _next_wpt. */
+    _next_wpt = NULL;
+    _next_wpt_dist_rough = -1;
+
+    route_update_nears(FALSE);
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
 /**
- * Update all GdkGC objects to reflect the current _draw_line_width.
+ * Render a single track line to _map_pixmap.  If either point on the line
+ * is a break (defined as unity == 0), a circle is drawn at the other point.
+ * IT IS AN ERROR FOR BOTH POINTS TO INDICATE A BREAK.
  */
-#define UPDATE_GC(gc) \
-    gdk_gc_set_line_attributes(gc, \
-            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
 static void
-update_gcs()
+map_render_segment(GdkGC *gc_norm, GdkGC *gc_alt,
+        guint unitx1, guint unity1, guint unitx2, guint unity2)
 {
-    printf("%s()\n", __PRETTY_FUNCTION__);
-
-    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
-            &_color_mark);
-    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
-            &_color_mark_velocity);
-    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
-            &_color_mark_old);
-    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
-            &_color_track);
-    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
-            &_color_track_break);
-    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
-            &_color_route);
-    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
-            &_color_route_way);
-    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
-            &_color_route_nextway);
+    vprintf("%s()\n", __PRETTY_FUNCTION__);
 
-    if(_gc_mark)
+    if(!unity1)
     {
-        g_object_unref(_gc_mark);
-        g_object_unref(_gc_mark_velocity);
-        g_object_unref(_gc_mark_old);
-        g_object_unref(_gc_track);
-        g_object_unref(_gc_track_break);
-        g_object_unref(_gc_route);
-        g_object_unref(_gc_route_way);
-        g_object_unref(_gc_route_nextway);
+        guint x2, y2;
+        x2 = unit2bufx(unitx2);
+        y2 = unit2bufy(unity2);
+        /* Make sure this circle will be visible. */
+        if((x2 < BUF_WIDTH_PIXELS)
+                && (y2 < BUF_HEIGHT_PIXELS))
+            gdk_draw_arc(_map_pixmap, gc_alt,
+                    FALSE, /* FALSE: not filled. */
+                    x2 - _draw_line_width,
+                    y2 - _draw_line_width,
+                    2 * _draw_line_width,
+                    2 * _draw_line_width,
+                    0, /* start at 0 degrees. */
+                    360 * 64);
+    }
+    else if(!unity2)
+    {
+        guint x1, y1;
+        x1 = unit2bufx(unitx1);
+        y1 = unit2bufy(unity1);
+        /* Make sure this circle will be visible. */
+        if((x1 < BUF_WIDTH_PIXELS)
+                && ((unsigned)y1 < BUF_HEIGHT_PIXELS))
+            gdk_draw_arc(_map_pixmap, gc_alt,
+                    FALSE, /* FALSE: not filled. */
+                    x1 - _draw_line_width,
+                    y1 - _draw_line_width,
+                    2 * _draw_line_width,
+                    2 * _draw_line_width,
+                    0, /* start at 0 degrees. */
+                    360 * 64);
+    }
+    else
+    {
+        gint x1, y1, x2, y2;
+        x1 = unit2bufx(unitx1);
+        y1 = unit2bufy(unity1);
+        x2 = unit2bufx(unitx2);
+        y2 = unit2bufy(unity2);
+        /* Make sure this line could possibly be visible. */
+        if(!((x1 > BUF_WIDTH_PIXELS && x2 > BUF_WIDTH_PIXELS)
+                || (x1 < 0 && x2 < 0)
+                || (y1 > BUF_HEIGHT_PIXELS && y2 > BUF_HEIGHT_PIXELS)
+                || (y1 < 0 && y2 < 0)))
+            gdk_draw_line(_map_pixmap, gc_norm, x1, y1, x2, y2);
     }
 
-    /* _gc_mark is used to draw the mark when data is current. */
-    _gc_mark = gdk_gc_new(_map_pixmap);
-    gdk_gc_set_foreground(_gc_mark, &_color_mark);
-    gdk_gc_set_line_attributes(_gc_mark,
-            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
-
-    /* _gc_mark_old is used to draw the mark when data is old. */
-    _gc_mark_old = gdk_gc_new(_map_pixmap);
-    gdk_gc_set_foreground(_gc_mark_old, &_color_mark_old);
-    gdk_gc_set_line_attributes(_gc_mark_old,
-            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
-
-    /* _gc_mark_velocity is used to draw the vel_current line. */
-    _gc_mark_velocity = gdk_gc_new(_map_pixmap);
-    gdk_gc_set_foreground(_gc_mark_velocity, &_color_mark_velocity);
-    gdk_gc_set_line_attributes(_gc_mark_velocity,
-            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
-
-    /* _gc_track is used to draw the track line. */
-    _gc_track = gdk_gc_new(_map_pixmap);
-    gdk_gc_set_foreground(_gc_track, &_color_track);
-    gdk_gc_set_line_attributes(_gc_track,
-            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
-
-    /* _gc_track_break is used to draw the track_break dots. */
-    _gc_track_break = gdk_gc_new(_map_pixmap);
-    gdk_gc_set_foreground(_gc_track_break, &_color_track_break);
-    gdk_gc_set_line_attributes(_gc_track_break,
-            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
-
-    /* _gc_route is used to draw the route line. */
-    _gc_route = gdk_gc_new(_map_pixmap);
-    gdk_gc_set_foreground(_gc_route, &_color_route);
-    gdk_gc_set_line_attributes(_gc_route,
-            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
 
-    /* _way_gc is used to draw the waypoint dots. */
-    _gc_route_way = gdk_gc_new(_map_pixmap);
-    gdk_gc_set_foreground(_gc_route_way, &_color_route_way);
-    gdk_gc_set_line_attributes(_gc_route_way,
-            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+/**
+ * Render all track data onto the _map_pixmap.  Note that this does not
+ * clear the pixmap of previous track data (use map_force_redraw() for
+ * that), and also note that this method does not queue any redraws, so it
+ * is up to the caller to decide which part of the track really needs to be
+ * redrawn.
+ */
+static void
+map_render_track()
+{
+    TrackPoint *curr;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* _gc_route_nextway is used to draw the next_way labels. */
-    _gc_route_nextway = gdk_gc_new(_map_pixmap);
-    gdk_gc_set_foreground(_gc_route_nextway, &_color_route_nextway);
-    gdk_gc_set_line_attributes(_gc_route_nextway,
-            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+    for(curr = _track.head; curr != _track.tail; curr++)
+        map_render_segment(_gc_track, _gc_track_break,
+                curr->point.unitx, curr->point.unity,
+                curr[1].point.unitx, curr[1].point.unity);
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
 /**
- * Change the map cache directory and update dependent variables.
+ * Render all track data onto the _map_pixmap.  Note that this does not
+ * clear the pixmap of previous track data (use map_force_redraw() for
+ * that), and also note that this method does not queue any redraws, so it
+ * is up to the caller to decide which part of the track really needs to be
+ * redrawn.
  */
-static gboolean
-config_set_map_dir_name(gchar *new_map_dir_name)
+static void
+map_render_route()
 {
-    GnomeVFSURI *map_dir_uri;
-    gboolean retval = FALSE;
+    Point *curr;
+    WayPoint *wcurr;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* Rest of the function devoted to making sure the directory exists. */
-    map_dir_uri = gnome_vfs_uri_new(new_map_dir_name);
-    if(!gnome_vfs_uri_exists(map_dir_uri))
+    _visible_way_first = _visible_way_last = NULL;
+    for(curr = _route.head, wcurr = _route.whead; curr != _route.tail; curr++)
     {
-        GnomeVFSURI *parent, *curr_uri;
-        GList *list = NULL;
-
-        list = g_list_prepend(list, curr_uri = map_dir_uri);
-        while(GNOME_VFS_ERROR_NOT_FOUND == gnome_vfs_make_directory_for_uri(
-                        parent = gnome_vfs_uri_get_parent(curr_uri), 0755))
-            list = g_list_prepend(list, curr_uri = parent);
-
-        while(list != NULL)
+        if(wcurr <= _route.wtail && curr == wcurr->point)
         {
-            retval = (GNOME_VFS_OK == gnome_vfs_make_directory_for_uri(
-                        (GnomeVFSURI*)list->data, 0755));
-            gnome_vfs_uri_unref((GnomeVFSURI*)list->data);
-            list = g_list_remove(list, list->data);
+            guint x1 = unit2bufx(wcurr->point->unitx);
+            guint y1 = unit2bufy(wcurr->point->unity);
+            if((x1 < BUF_WIDTH_PIXELS)
+                    && (y1 < BUF_HEIGHT_PIXELS))
+            {
+                gdk_draw_arc(_map_pixmap,
+                        (wcurr==_next_way ? _gc_route_nextway : _gc_route_way),
+                        FALSE, /* FALSE: not filled. */
+                        x1 - _draw_line_width,
+                        y1 - _draw_line_width,
+                        2 * _draw_line_width,
+                        2 * _draw_line_width,
+                        0, /* start at 0 degrees. */
+                        360 * 64);
+                if(!_visible_way_first)
+                    _visible_way_first = wcurr;
+                _visible_way_last = wcurr;
+            }
+            wcurr++;
+            if(!curr[1].unity)
+                continue;
         }
-        /* Retval now equals result of last make-dir attempt. */
+        map_render_segment(_gc_route, _gc_route_way,
+                curr->unitx, curr->unity, curr[1].unitx, curr[1].unity);
     }
-    else
-        retval = TRUE;
 
-    if(retval)
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+static void
+map_render_paths()
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    if((_show_tracks & ROUTES_MASK) && _route.head)
     {
-        if(_map_dir_name)
-            g_free(_map_dir_name);
-        _map_dir_name = new_map_dir_name;
+        map_render_route();
+        if(_next_way == NULL)
+        {
+            guint x1 = unit2bufx(_route.tail[-1].unitx);
+            guint y1 = unit2bufy(_route.tail[-1].unity);
+            if((x1 < BUF_WIDTH_PIXELS)
+                    && (y1 < BUF_HEIGHT_PIXELS))
+            {
+                gdk_draw_arc(_map_pixmap,
+                        _gc_route_nextway,
+                        FALSE, /* FALSE: not filled. */
+                        x1 - _draw_line_width,
+                        y1 - _draw_line_width,
+                        2 * _draw_line_width,
+                        2 * _draw_line_width,
+                        0, /* start at 0 degrees. */
+                        360 * 64);
+            }
+        }
     }
+    if(_show_tracks & TRACKS_MASK)
+        map_render_track();
 
-    vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, retval);
-    return retval;
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
-/**
- * Save all configuration data to GCONF.
- */
 static void
-config_save()
+track_resize(Track *track, guint size)
 {
-    GConfClient *gconf_client = gconf_client_get_default();
-    gchar buffer[16];
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    if(!gconf_client)
+    if(track->head + size != track->cap)
     {
-        popup_error(_window,
-                _("Failed to initialize GConf.  Settings were not saved."));
-        return;
+        TrackPoint *old_head = track->head;
+        track->head = g_renew(TrackPoint, old_head, size);
+        track->cap = track->head + size;
+        if(track->head != old_head)
+            track->tail = track->head + (track->tail - old_head);
     }
 
-    /* Save Receiver MAC from GConf. */
-    if(_rcvr_mac)
-        gconf_client_set_string(gconf_client,
-                GCONF_KEY_RCVR_MAC, _rcvr_mac, NULL);
-    else
-        gconf_client_unset(gconf_client,
-                GCONF_KEY_RCVR_MAC, NULL);
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
 
-    /* Save Receiver Channel to GConf. */
-    gconf_client_set_int(gconf_client,
-            GCONF_KEY_RCVR_CHAN, _rcvr_addr.rc_channel, NULL);
+static void
+route_resize(Route *route, guint size)
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* Save Map Download URI Format. */
-    if(_map_uri_format)
-        gconf_client_set_string(gconf_client,
-                GCONF_KEY_MAP_URI_FORMAT, _map_uri_format, NULL);
+    if(route->head + size != route->cap)
+    {
+        Point *old_head = route->head;
+        WayPoint *curr;
+        route->head = g_renew(Point, old_head, size);
+        route->cap = route->head + size;
+        if(route->head != old_head)
+        {
+            route->tail = route->head + (route->tail - old_head);
 
-    /* Save Map Download Zoom Steps. */
-    gconf_client_set_int(gconf_client,
-            GCONF_KEY_MAP_ZOOM_STEPS, _zoom_steps, NULL);
+            /* Adjust all of the waypoints. */
+            for(curr = route->whead - 1; curr++ != route->wtail; )
+                curr->point = route->head + (curr->point - old_head);
+        }
+    }
 
-    /* Save Map Cache Directory. */
-    if(_map_dir_name)
-        gconf_client_set_string(gconf_client,
-            GCONF_KEY_MAP_DIR_NAME, _map_dir_name, NULL);
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
 
-    /* Save Auto-Download. */
-    gconf_client_set_bool(gconf_client,
-            GCONF_KEY_AUTO_DOWNLOAD, _auto_download, NULL);
+static void
+route_wresize(Route *route, guint wsize)
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* Save Auto-Center Sensitivity. */
-    gconf_client_set_int(gconf_client,
-            GCONF_KEY_CENTER_SENSITIVITY, _center_ratio, NULL);
+    if(route->whead + wsize != route->wcap)
+    {
+        WayPoint *old_whead = route->whead;
+        route->whead = g_renew(WayPoint, old_whead, wsize);
+        route->wtail = route->whead + (route->wtail - old_whead);
+        route->wcap = route->whead + wsize;
+    }
 
-    /* Save Auto-Center Lead Amount. */
-    gconf_client_set_int(gconf_client,
-            GCONF_KEY_LEAD_AMOUNT, _lead_ratio, NULL);
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
 
-    /* Save Draw Line Width. */
-    gconf_client_set_int(gconf_client,
-            GCONF_KEY_DRAW_LINE_WIDTH, _draw_line_width, NULL);
+#define MACRO_TRACK_INCREMENT_TAIL(track) { \
+    if(++(track).tail == (track).cap) \
+        track_resize(&(track), (track).cap - (track).head + ARRAY_CHUNK_SIZE); \
+}
 
-    /* Save Announce Advance Notice Ratio. */
-    gconf_client_set_int(gconf_client,
-            GCONF_KEY_ANNOUNCE_NOTICE, _announce_notice_ratio, NULL);
+#define MACRO_ROUTE_INCREMENT_TAIL(route) { \
+    if(++(route).tail == (route).cap) \
+        route_resize(&(route), (route).cap - (route).head + ARRAY_CHUNK_SIZE); \
+}
 
-    /* Save Enable Voice flag. */
-    gconf_client_set_bool(gconf_client,
-            GCONF_KEY_ENABLE_VOICE, _enable_voice, NULL);
+#define MACRO_ROUTE_INCREMENT_WTAIL(route) { \
+    if(++(route).wtail == (route).wcap) \
+        route_wresize(&(route), \
+                (route).wcap - (route).whead + ARRAY_CHUNK_SIZE); \
+}
 
-    /* Save Keep On When Fullscreen flag. */
-    gconf_client_set_bool(gconf_client,
-            GCONF_KEY_ALWAYS_KEEP_ON, _always_keep_on, NULL);
+/**
+ * Add a point to the _track list.  This function is slightly overloaded,
+ * since it is what houses the check for "have we moved
+ * significantly": it also initiates the re-calculation of the _near_point
+ * data, as well as calling osso_display_state_on() when we have the focus.
+ *
+ * If a non-zero time is given, then the current position (as taken from the
+ * _pos variable) is appended to _track with the given time.  If time is zero,
+ * then _pos_null is appended to _track with time zero (this produces a "break"
+ * in the track).
+ */
+static void
+track_add(time_t time, gboolean newly_fixed)
+{
+    Point pos = (time == 0 ? _pos_null : _pos);
+    printf("%s(%u, %u)\n", __PRETTY_FUNCTION__, pos.unitx, pos.unity);
 
-    /* Save Units. */
-    gconf_client_set_string(gconf_client,
-            GCONF_KEY_UNITS, _units, NULL);
+    printf("A: %p\n", _track.tail);
+    printf("A.1: %d %d\n", _track.tail->point.unitx, _track.tail->point.unity);
+    if(abs((gint)pos.unitx - _track.tail->point.unitx) > _draw_line_width
+    || abs((gint)pos.unity - _track.tail->point.unity) > _draw_line_width)
+    {
+        printf("B\n");
+        if(time && _route.head
+                && (newly_fixed ? (route_find_nearest_point(), TRUE)
+                                : route_update_nears(TRUE)))
+        {
+            map_render_paths();
+            MACRO_QUEUE_DRAW_AREA();
+        }
+        printf("C\n");
+        if(_show_tracks & TRACKS_MASK)
+        {
+            /* Instead of calling map_render_paths(), we'll draw the new line
+             * ourselves and call gtk_widget_queue_draw_area(). */
+            gint tx1, ty1, tx2, ty2;
+            printf("C.a\n");
+            map_render_segment(_gc_track, _gc_track_break,
+                    _track.tail->point.unitx, _track.tail->point.unity,
+                    pos.unitx, pos.unity);
+            if(time && _track.tail->point.unity)
+            {
+                printf("C.b\n");
+                tx1 = unit2x(_track.tail->point.unitx);
+                ty1 = unit2y(_track.tail->point.unity);
+                tx2 = unit2x(pos.unitx);
+                ty2 = unit2y(pos.unity);
+                gtk_widget_queue_draw_area(_map_widget,
+                        MIN(tx1, tx2) - _draw_line_width,
+                        MIN(ty1, ty2) - _draw_line_width,
+                        abs(tx1 - tx2) + (2 * _draw_line_width),
+                        abs(ty1 - ty2) + (2 * _draw_line_width));
+            }
+        }
+        printf("D\n");
+        MACRO_TRACK_INCREMENT_TAIL(_track);
+        printf("E\n");
 
-    /* Save last saved latitude. */
-    gconf_client_set_float(gconf_client,
-            GCONF_KEY_LAT, _pos_lat, NULL);
+        _track.tail->point = pos;
+        _track.tail->time = time;
 
-    /* Save last saved longitude. */
-    gconf_client_set_float(gconf_client,
-            GCONF_KEY_LON, _pos_lon, NULL);
+        printf("F\n");
+        if(_autoroute_data.enabled && !_autoroute_data.in_progress
+                && _near_point_dist_rough > 400)
+        {
+            printf("F.a\n");
+            _autoroute_data.in_progress = TRUE;
+            g_idle_add((GSourceFunc)auto_route_dl_idle, NULL);
+        }
+        printf("G\n");
 
-    /* Save last center point. */
+        /* Keep the display on. */
+        KEEP_DISPLAY_ON();
+    }
+
+    /* Check if we should announce upcoming waypoints. */
+    if(time && _next_way_dist_rough
+            < (20 + (guint)_speed) * _announce_notice_ratio * 3)
     {
-        gfloat center_lat, center_lon;
-        unit2latlon(_center.unitx, _center.unity, center_lat, center_lon);
+        if(_enable_voice && strcmp(_next_way->desc, _last_spoken_phrase))
+        {
+            g_free(_last_spoken_phrase);
+            _last_spoken_phrase = g_strdup(_next_way->desc);
+            if(!fork())
+            {
+                /* We are the fork child.  Synthesize the voice. */
+                hildon_play_system_sound(
+                        "/usr/share/sounds/ui-information_note.wav");
+                sleep(1);
+#               define _voice_synth_path "/usr/bin/flite"
+                printf("%s %s\n", _voice_synth_path, _last_spoken_phrase);
+                execl(_voice_synth_path, _voice_synth_path,
+                        "-t", _last_spoken_phrase, (char *)NULL);
+                exit(0);
+            }
+        }
+        hildon_banner_show_information(_window, NULL, _next_way->desc);
+    }
 
-        /* Save last center latitude. */
-        gconf_client_set_float(gconf_client,
-                GCONF_KEY_CENTER_LAT, center_lat, NULL);
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
 
-        /* Save last center longitude. */
-        gconf_client_set_float(gconf_client,
-                GCONF_KEY_CENTER_LON, center_lon, NULL);
-    }
+/**
+ * Disconnect from the receiver.  This method cleans up any and everything
+ * that might be associated with the receiver.
+ */
+static void
+rcvr_disconnect()
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* Save last Zoom Level. */
-    gconf_client_set_int(gconf_client,
-            GCONF_KEY_ZOOM, _zoom, NULL);
+    /* Remove watches. */
+    if(_clater_sid)
+    {
+        g_source_remove(_clater_sid);
+        _clater_sid = 0;
+    }
+    if(_error_sid)
+    {
+        g_source_remove(_error_sid);
+        _error_sid = 0;
+    }
+    if(_connect_sid)
+    {
+        g_source_remove(_connect_sid);
+        _connect_sid = 0;
+    }
+    if(_input_sid)
+    {
+        g_source_remove(_input_sid);
+        _input_sid = 0;
+    }
 
-    /* Save Route Directory. */
-    if(_route_dir_uri)
-        gconf_client_set_string(gconf_client,
-                GCONF_KEY_ROUTEDIR, _route_dir_uri, NULL);
+    /* Destroy the GIOChannel object. */
+    if(_channel)
+    {
+        g_io_channel_shutdown(_channel, FALSE, NULL);
+        g_io_channel_unref(_channel);
+        _channel = NULL;
+    }
 
-    /* Save Last Track File. */
-    if(_track_file_uri)
-        gconf_client_set_string(gconf_client,
-                GCONF_KEY_TRACKFILE, _track_file_uri, NULL);
+    /* Close the file descriptor. */
+    if(_fd != -1)
+    {
+        close(_fd);
+        _fd = -1;
+    }
 
-    /* Save Auto-Center Mode. */
-    gconf_client_set_int(gconf_client,
-            GCONF_KEY_AUTOCENTER_MODE, _center_mode, NULL);
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
 
-    /* Save Show Tracks flag. */
-    gconf_client_set_bool(gconf_client,
-            GCONF_KEY_SHOWTRACKS, _show_tracks & TRACKS_MASK, NULL);
+static void rcvr_connect_later(); /* Forward declaration. */
 
-    /* Save Show Routes flag. */
-    gconf_client_set_bool(gconf_client,
-            GCONF_KEY_SHOWROUTES, _show_tracks & ROUTES_MASK, NULL);
+/**
+ * Connect to the receiver.
+ * This method assumes that _fd is -1 and _channel is NULL.  If unsure, call
+ * rcvr_disconnect() first.
+ * Since this is an idle function, this function returns whether or not it
+ * should be called again, which is always FALSE.
+ */
+static gboolean
+rcvr_connect_now()
+{
+    printf("%s(%d)\n", __PRETTY_FUNCTION__, _conn_state);
 
-    /* Save Show Velocity Vector flag. */
-    gconf_client_set_bool(gconf_client,
-            GCONF_KEY_SHOWVELVEC, _show_velvec, NULL);
+    if(_conn_state == RCVR_DOWN && _rcvr_mac) {
+#ifndef DEBUG
+        /* Create the file descriptor. */
+        if(*_rcvr_mac == '/')
+            _fd = open(_rcvr_mac, O_RDONLY);
+        else
+            _fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
 
-    /* Save Enable GPS flag. */
-    gconf_client_set_bool(gconf_client,
-            GCONF_KEY_ENABLE_GPS, _enable_gps, NULL);
+        /* If file descriptor creation failed, try again later.  Note that
+         * there is no need to call rcvr_disconnect() because the file
+         * descriptor creation is the first step, so if it fails, there's
+         * nothing to clean up. */
+        if(_fd == -1)
+            rcvr_connect_later();
+        else
+        {
+            _gps_read_buf_pos = 0;
+            _channel = g_io_channel_unix_new(_fd);
+            g_io_channel_set_flags(_channel, G_IO_FLAG_NONBLOCK, NULL);
+            _error_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE,
+                    G_IO_ERR | G_IO_HUP, channel_cb_error, NULL, NULL);
+            _connect_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE,
+                    G_IO_OUT, channel_cb_connect, NULL, NULL);
+            if(*_rcvr_mac != '/'
+                    && connect(_fd, (struct sockaddr*)&_rcvr_addr,
+                        sizeof(_rcvr_addr))
+                    && errno != EAGAIN)
+            {
+                /* Connection failed.  Disconnect and try again later. */
+                rcvr_disconnect();
+                rcvr_connect_later();
+            }
+        }
+#else
+        /* We're in DEBUG mode, so instead of connecting, skip to FIXED. */
+        set_conn_state(RCVR_FIXED);
+#endif
+    }
 
-    /* Save Route Locations. */
-    gconf_client_set_list(gconf_client,
-            GCONF_KEY_ROUTE_LOCATIONS, GCONF_VALUE_STRING, _loc_list, NULL);
+    _clater_sid = 0;
 
-    /* Save Colors. */
-    sprintf(buffer, "#%02x%02x%02x",
-            _color_mark.red >> 8,
-            _color_mark.green >> 8,
-            _color_mark.blue >> 8);
-    gconf_client_set_string(gconf_client,
-            GCONF_KEY_COLOR_MARK, buffer, NULL);
+    vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+    return FALSE;
+}
 
-    sprintf(buffer, "#%02x%02x%02x",
-            _color_mark_velocity.red >> 8,
-            _color_mark_velocity.green >> 8,
-            _color_mark_velocity.blue >> 8);
-    gconf_client_set_string(gconf_client,
-            GCONF_KEY_COLOR_MARK_VELOCITY, buffer, NULL);
+/**
+ * Place a request to connect about 1 second after the function is called.
+ */
+static void
+rcvr_connect_later()
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    sprintf(buffer, "#%02x%02x%02x",
-            _color_mark_old.red >> 8,
-            _color_mark_old.green >> 8,
-            _color_mark_old.blue >> 8);
-    gconf_client_set_string(gconf_client,
-            GCONF_KEY_COLOR_MARK_OLD, buffer, NULL);
+    _clater_sid = g_timeout_add(1000, (GSourceFunc)rcvr_connect_now, NULL);
 
-    sprintf(buffer, "#%02x%02x%02x",
-            _color_track.red >> 8,
-            _color_track.green >> 8,
-            _color_track.blue >> 8);
-    gconf_client_set_string(gconf_client,
-            GCONF_KEY_COLOR_TRACK, buffer, NULL);
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
 
-    sprintf(buffer, "#%02x%02x%02x",
-            _color_track_break.red >> 8,
-            _color_track_break.green >> 8,
-            _color_track_break.blue >> 8);
-    gconf_client_set_string(gconf_client,
-            GCONF_KEY_COLOR_TRACK_BREAK, buffer, NULL);
-
-    sprintf(buffer, "#%02x%02x%02x",
-            _color_route.red >> 8,
-            _color_route.green >> 8,
-            _color_route.blue >> 8);
-    gconf_client_set_string(gconf_client,
-            GCONF_KEY_COLOR_ROUTE, buffer, NULL);
-
-    sprintf(buffer, "#%02x%02x%02x",
-            _color_route_way.red >> 8,
-            _color_route_way.green >> 8,
-            _color_route_way.blue >> 8);
-    gconf_client_set_string(gconf_client,
-            GCONF_KEY_COLOR_ROUTE_WAY, buffer, NULL);
+/**
+ * Convert the float lat/lon/speed/heading data into integer units.
+ */
+static void
+integerize_data()
+{
+    gfloat tmp;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    sprintf(buffer, "#%02x%02x%02x",
-            _color_route_nextway.red >> 8,
-            _color_route_nextway.green >> 8,
-            _color_route_nextway.blue >> 8);
-    gconf_client_set_string(gconf_client,
-            GCONF_KEY_COLOR_ROUTE_NEXTWAY, buffer, NULL);
+    latlon2unit(_pos_lat, _pos_lon, _pos.unitx, _pos.unity);
 
-    g_object_unref(gconf_client);
+    tmp = (_heading * (1.f / 180.f)) * PI;
+    _vel_offsetx = (gint)(floorf(_speed * sinf(tmp) + 0.5f));
+    _vel_offsety = -(gint)(floorf(_speed * cosf(tmp) + 0.5f));
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
+/**
+ * Update all GdkGC objects to reflect the current _draw_line_width.
+ */
+#define UPDATE_GC(gc) \
+    gdk_gc_set_line_attributes(gc, \
+            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
 static void
-force_min_visible_bars(HildonControlbar *control_bar, gint num_bars)
+update_gcs()
 {
-    GValue val;
-    memset(&val, 0, sizeof(val));
-    g_value_init(&val, G_TYPE_INT);
-    g_value_set_int(&val, num_bars);
-    g_object_set_property(G_OBJECT(control_bar), "minimum-visible-bars", &val);
-}
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
+    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+            &_color_mark);
+    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+            &_color_mark_velocity);
+    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+            &_color_mark_old);
+    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+            &_color_track);
+    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+            &_color_track_break);
+    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+            &_color_route);
+    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+            &_color_route_way);
+    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+            &_color_route_nextway);
+    gdk_color_alloc(gtk_widget_get_colormap(_map_widget),
+            &_color_poi);
 
-typedef struct _ScanInfo ScanInfo;
-struct _ScanInfo {
-    GtkWidget *settings_dialog;
-    GtkWidget *txt_rcvr_mac;
-    GtkWidget *scan_dialog;
-    GtkWidget *banner;
-    GtkListStore *store;
-    guint sid;
-};
+    if(_gc_mark)
+    {
+        g_object_unref(_gc_mark);
+        g_object_unref(_gc_mark_velocity);
+        g_object_unref(_gc_mark_old);
+        g_object_unref(_gc_track);
+        g_object_unref(_gc_track_break);
+        g_object_unref(_gc_route);
+        g_object_unref(_gc_route_way);
+        g_object_unref(_gc_route_nextway);
+        g_object_unref(_gc_poi);
+    }
 
-static gboolean
-scan_bluetooth_idle(ScanInfo *scan_info)
-{
-    gint devid, num_rsp;
-    GtkTreeIter iter;
-    inquiry_info *ii = NULL;
+    /* _gc_mark is used to draw the mark when data is current. */
+    _gc_mark = gdk_gc_new(_map_pixmap);
+    gdk_gc_set_foreground(_gc_mark, &_color_mark);
+    gdk_gc_set_line_attributes(_gc_mark,
+            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
 
-    devid = hci_get_route(NULL);
+    /* _gc_mark_old is used to draw the mark when data is old. */
+    _gc_mark_old = gdk_gc_new(_map_pixmap);
+    gdk_gc_set_foreground(_gc_mark_old, &_color_mark_old);
+    gdk_gc_set_line_attributes(_gc_mark_old,
+            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
 
-    ii = (inquiry_info*)malloc(255 * sizeof(inquiry_info));
-    num_rsp = hci_inquiry(devid, 4, 255, NULL, &ii, IREQ_CACHE_FLUSH);
+    /* _gc_mark_velocity is used to draw the vel_current line. */
+    _gc_mark_velocity = gdk_gc_new(_map_pixmap);
+    gdk_gc_set_foreground(_gc_mark_velocity, &_color_mark_velocity);
+    gdk_gc_set_line_attributes(_gc_mark_velocity,
+            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
 
-    if(num_rsp < 0)
-    {
-        gtk_widget_destroy(scan_info->banner);
-        gtk_widget_hide(scan_info->scan_dialog);
-        popup_error(scan_info->settings_dialog,
-                _("An error occurred while scanning."));
-    }
-    else if(num_rsp == 0)
-    {
-        gtk_widget_destroy(scan_info->banner);
-        gtk_widget_hide(scan_info->scan_dialog);
-        popup_error(scan_info->settings_dialog,
-                _("No bluetooth devices found."));
-    }
-    else
-    {
-        guint i;
-        gint sock = hci_open_dev(devid);
-        for(i = 0; i < num_rsp; i++)
-        {
-            gchar addr[19] = { 0 };
-            gchar name[256] = { 0 };
+    /* _gc_track is used to draw the track line. */
+    _gc_track = gdk_gc_new(_map_pixmap);
+    gdk_gc_set_foreground(_gc_track, &_color_track);
+    gdk_gc_set_line_attributes(_gc_track,
+            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
 
-            ba2str(&ii[i].bdaddr, addr);
-            memset(name, 0, sizeof(name));
-            if(hci_read_remote_name(sock, &ii[i].bdaddr, sizeof(name), name, 0))
-                strcpy(name, _("Unknown"));
+    /* _gc_track_break is used to draw the track_break dots. */
+    _gc_track_break = gdk_gc_new(_map_pixmap);
+    gdk_gc_set_foreground(_gc_track_break, &_color_track_break);
+    gdk_gc_set_line_attributes(_gc_track_break,
+            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
 
-            gtk_list_store_append(scan_info->store, &iter);
-            gtk_list_store_set(scan_info->store, &iter,
-                    0, g_strdup(addr),
-                    1, g_strdup(name),
-                    -1);
-        }
-        close(sock);
-        gtk_widget_destroy(scan_info->banner);
-    }
-    free(ii);
-    scan_info->sid = 0;
-    return FALSE;
+    /* _gc_route is used to draw the route line. */
+    _gc_route = gdk_gc_new(_map_pixmap);
+    gdk_gc_set_foreground(_gc_route, &_color_route);
+    gdk_gc_set_line_attributes(_gc_route,
+            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+
+    /* _way_gc is used to draw the waypoint dots. */
+    _gc_route_way = gdk_gc_new(_map_pixmap);
+    gdk_gc_set_foreground(_gc_route_way, &_color_route_way);
+    gdk_gc_set_line_attributes(_gc_route_way,
+            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+
+    /* _gc_route_nextway is used to draw the next_way labels. */
+    _gc_route_nextway = gdk_gc_new(_map_pixmap);
+    gdk_gc_set_foreground(_gc_route_nextway, &_color_route_nextway);
+    gdk_gc_set_line_attributes(_gc_route_nextway,
+            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+
+    /* _gc_poi is used to draw the default POI icon. */
+    _gc_poi = gdk_gc_new(_map_pixmap);
+    gdk_gc_set_foreground(_gc_poi, &_color_poi);
+    gdk_gc_set_background(_gc_poi, &_color_poi);
+    gdk_gc_set_line_attributes(_gc_poi,
+            _draw_line_width, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
 /**
- * Scan for all bluetooth devices.  This method can take a few seconds,
- * during which the UI will freeze.
+ * Save all configuration data to GCONF.
  */
-static gboolean
-scan_bluetooth(GtkWidget *widget, ScanInfo *scan_info)
+static void
+config_save()
 {
-    /* Do an hci_inquiry for our boy. */
-    GtkWidget *dialog;
-    GtkWidget *lst_devices;
-    GtkTreeViewColumn *column;
-    GtkCellRenderer *renderer;
+    GConfClient *gconf_client = gconf_client_get_default();
+    gchar buffer[16];
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    dialog = gtk_dialog_new_with_buttons(_("Select Bluetooth Device"),
-            GTK_WINDOW(scan_info->settings_dialog), GTK_DIALOG_MODAL,
-            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
-            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
-            NULL);
+    if(!gconf_client)
+    {
+        popup_error(_window,
+                _("Failed to initialize GConf.  Settings were not saved."));
+        return;
+    }
 
-    scan_info->scan_dialog = dialog;
+    /* Save Receiver MAC from GConf. */
+    if(_rcvr_mac)
+        gconf_client_set_string(gconf_client,
+                GCONF_KEY_RCVR_MAC, _rcvr_mac, NULL);
+    else
+        gconf_client_unset(gconf_client,
+                GCONF_KEY_RCVR_MAC, NULL);
 
-    scan_info->banner = hildon_banner_show_animation(dialog, NULL,
-            _("Scanning Bluetooth Devices"));
+    /* Save Receiver Channel to GConf. */
+    gconf_client_set_int(gconf_client,
+            GCONF_KEY_RCVR_CHAN, _rcvr_addr.rc_channel, NULL);
 
-    scan_info->store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
+    /* Save Map Download URI Format. */
+    gconf_client_set_string(gconf_client,
+            GCONF_KEY_MAP_URI_FORMAT, _curr_repo->url, NULL);
 
-    scan_info->sid = g_idle_add((GSourceFunc)scan_bluetooth_idle, scan_info);
+    /* Save Map Download Zoom Steps. */
+    gconf_client_set_int(gconf_client,
+            GCONF_KEY_MAP_ZOOM_STEPS, _curr_repo->dl_zoom_steps, NULL);
 
-    gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 300);
+    /* Save Map Cache Directory. */
+    if(_curr_repo->cache_dir)
+        gconf_client_set_string(gconf_client,
+            GCONF_KEY_MAP_DIR_NAME, _curr_repo->cache_dir, NULL);
 
-    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
-            lst_devices = gtk_tree_view_new_with_model(
-                GTK_TREE_MODEL(scan_info->store)), TRUE, TRUE, 0);
+    /* Save Auto-Download. */
+    gconf_client_set_bool(gconf_client,
+            GCONF_KEY_AUTO_DOWNLOAD, _auto_download, NULL);
 
-    g_object_unref(G_OBJECT(scan_info->store));
+    /* Save Auto-Center Sensitivity. */
+    gconf_client_set_int(gconf_client,
+            GCONF_KEY_CENTER_SENSITIVITY, _center_ratio, NULL);
 
-    gtk_tree_selection_set_mode(
-            gtk_tree_view_get_selection(GTK_TREE_VIEW(lst_devices)),
-            GTK_SELECTION_SINGLE);
-    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(lst_devices), TRUE);
+    /* Save Auto-Center Lead Amount. */
+    gconf_client_set_int(gconf_client,
+            GCONF_KEY_LEAD_AMOUNT, _lead_ratio, NULL);
 
-    renderer = gtk_cell_renderer_text_new();
-    column = gtk_tree_view_column_new_with_attributes(
-            _("MAC"), renderer, "text", 0);
-    gtk_tree_view_append_column(GTK_TREE_VIEW(lst_devices), column);
+    /* Save Draw Line Width. */
+    gconf_client_set_int(gconf_client,
+            GCONF_KEY_DRAW_LINE_WIDTH, _draw_line_width, NULL);
 
-    renderer = gtk_cell_renderer_text_new();
-    column = gtk_tree_view_column_new_with_attributes(
-            _("Description"), renderer, "text", 1);
-    gtk_tree_view_append_column(GTK_TREE_VIEW(lst_devices), column);
+    /* Save Announce Advance Notice Ratio. */
+    gconf_client_set_int(gconf_client,
+            GCONF_KEY_ANNOUNCE_NOTICE, _announce_notice_ratio, NULL);
 
-    gtk_widget_show_all(dialog);
+    /* Save Enable Voice flag. */
+    gconf_client_set_bool(gconf_client,
+            GCONF_KEY_ENABLE_VOICE, _enable_voice, NULL);
 
-    while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
-    {
-        GtkTreeIter iter;
-        if(gtk_tree_selection_get_selected(
-                    gtk_tree_view_get_selection(GTK_TREE_VIEW(lst_devices)),
-                    NULL, &iter))
-        {
-            gchar *mac;
-            gtk_tree_model_get(GTK_TREE_MODEL(scan_info->store),
-                    &iter, 0, &mac, -1);
-            gtk_entry_set_text(GTK_ENTRY(scan_info->txt_rcvr_mac), mac);
-            break;
-        }
-        else
-            popup_error(dialog,
-                    _("Please select a bluetooth device from the list."));
-    }
+    /* Save Keep On When Fullscreen flag. */
+    gconf_client_set_bool(gconf_client,
+            GCONF_KEY_ALWAYS_KEEP_ON, _always_keep_on, NULL);
 
-    if(scan_info->sid)
-        g_source_remove(scan_info->sid);
-    gtk_widget_destroy(dialog);
+    /* Save Units. */
+    gconf_client_set_string(gconf_client,
+            GCONF_KEY_UNITS, UNITS_TEXT[_units], NULL);
 
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
-}
+    /* Save Escape Key Function. */
+    gconf_client_set_string(gconf_client,
+            GCONF_KEY_ESCAPE_KEY, ESCAPE_KEY_TEXT[_escape_key], NULL);
 
-typedef struct _BrowseInfo BrowseInfo;
-struct _BrowseInfo {
-    GtkWidget *dialog;
-    GtkWidget *txt_map_dir_name;
-};
+    /* Save last saved latitude. */
+    gconf_client_set_float(gconf_client,
+            GCONF_KEY_LAT, _pos_lat, NULL);
 
-static gboolean
-settings_dialog_browse(GtkWidget *widget, BrowseInfo *browse_info)
-{
-    GtkWidget *dialog;
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    /* Save last saved longitude. */
+    gconf_client_set_float(gconf_client,
+            GCONF_KEY_LON, _pos_lon, NULL);
 
-    dialog = GTK_WIDGET(
-            hildon_file_chooser_dialog_new(GTK_WINDOW(browse_info->dialog),
-            GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER));
+    /* Save last center point. */
+    {
+        gfloat center_lat, center_lon;
+        unit2latlon(_center.unitx, _center.unity, center_lat, center_lon);
 
-    gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), TRUE);
-    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
-            gtk_entry_get_text(GTK_ENTRY(browse_info->txt_map_dir_name)));
+        /* Save last center latitude. */
+        gconf_client_set_float(gconf_client,
+                GCONF_KEY_CENTER_LAT, center_lat, NULL);
 
-    if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)))
-    {
-        gchar *filename = gtk_file_chooser_get_filename(
-                GTK_FILE_CHOOSER(dialog));
-        gtk_entry_set_text(GTK_ENTRY(browse_info->txt_map_dir_name), filename);
-        g_free(filename);
+        /* Save last center longitude. */
+        gconf_client_set_float(gconf_client,
+                GCONF_KEY_CENTER_LON, center_lon, NULL);
     }
 
-    gtk_widget_destroy(dialog);
+    /* Save last Zoom Level. */
+    gconf_client_set_int(gconf_client,
+            GCONF_KEY_ZOOM, _zoom, NULL);
 
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
-}
+    /* Save Route Directory. */
+    if(_route_dir_uri)
+        gconf_client_set_string(gconf_client,
+                GCONF_KEY_ROUTEDIR, _route_dir_uri, NULL);
 
-typedef struct _ColorsDialogInfo ColorsDialogInfo;
-struct _ColorsDialogInfo {
-    GtkWidget *col_mark;
-    GtkWidget *col_mark_velocity;
-    GtkWidget *col_mark_old;
-    GtkWidget *col_track;
-    GtkWidget *col_track_break;
-    GtkWidget *col_route;
-    GtkWidget *col_route_way;
-    GtkWidget *col_route_nextway;
-};
+    /* Save the repositories. */
+    {
+        GList *curr = _repo_list;
+        GSList *temp_list = NULL;
+        gint curr_repo_index = 0;
+        
+        for(curr = _repo_list; curr != NULL; curr = curr->next)
+        {
+            /* Build from each part of a repo, delimited by newline characters:
+             * 1. url
+             * 2. cache_dir
+             * 3. dl_zoom_steps
+             * 4. view_zoom_steps
+             */
+            RepoData *rd = curr->data;
+            gchar buffer[1024];
+            sprintf(buffer, "%s\n%s\n%s\n%d\n%d\n",
+                    rd->name,
+                    rd->url,
+                    rd->cache_dir,
+                    rd->dl_zoom_steps,
+                    rd->view_zoom_steps);
+            temp_list = g_slist_append(temp_list, g_strdup(buffer));
+            if(rd == _curr_repo)
+                gconf_client_set_int(gconf_client,
+                        GCONF_KEY_CURRREPO, curr_repo_index, NULL);
+            curr_repo_index++;
+        }
+        gconf_client_set_list(gconf_client,
+                GCONF_KEY_REPOSITORIES, GCONF_VALUE_STRING, temp_list, NULL);
+    }
 
-static gboolean
-settings_dialog_colors_reset(GtkWidget *widget, ColorsDialogInfo *cdi)
-{
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi->col_mark),
-            &DEFAULT_COLOR_MARK);
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi->col_mark_velocity),
-            &DEFAULT_COLOR_MARK_VELOCITY);
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi->col_mark_old),
-            &DEFAULT_COLOR_MARK_OLD);
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi->col_track),
-            &DEFAULT_COLOR_TRACK);
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi->col_track_break),
-            &DEFAULT_COLOR_TRACK_BREAK);
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi->col_route),
-            &DEFAULT_COLOR_ROUTE);
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi->col_route_way),
-            &DEFAULT_COLOR_ROUTE_WAY);
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi->col_route_nextway),
-            &DEFAULT_COLOR_ROUTE_NEXTWAY);
-    return TRUE;
-}
+    /* Save Last Track File. */
+    if(_track_file_uri)
+        gconf_client_set_string(gconf_client,
+                GCONF_KEY_TRACKFILE, _track_file_uri, NULL);
 
-static gboolean
-settings_dialog_colors(GtkWidget *widget, GtkWidget *parent)
-{
-    GtkWidget *dialog;
-    GtkWidget *table;
-    GtkWidget *label;
-    GtkWidget *btn_defaults;
-    ColorsDialogInfo cdi;
-    printf("%s()\n", __PRETTY_FUNCTION__);
-    
-    dialog = gtk_dialog_new_with_buttons(_("Colors"),
-            GTK_WINDOW(parent), GTK_DIALOG_MODAL,
-            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
-            NULL);
+    /* Save Auto-Center Mode. */
+    gconf_client_set_int(gconf_client,
+            GCONF_KEY_AUTOCENTER_MODE, _center_mode, NULL);
 
-    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
-            btn_defaults = gtk_button_new_with_label(_("Defaults")));
-    g_signal_connect(G_OBJECT(btn_defaults), "clicked",
-                      G_CALLBACK(settings_dialog_colors_reset), &cdi);
+    /* Save Show Tracks flag. */
+    gconf_client_set_bool(gconf_client,
+            GCONF_KEY_SHOWTRACKS, _show_tracks & TRACKS_MASK, NULL);
 
-    gtk_dialog_add_button(GTK_DIALOG(dialog),
-            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+    /* Save Show Routes flag. */
+    gconf_client_set_bool(gconf_client,
+            GCONF_KEY_SHOWROUTES, _show_tracks & ROUTES_MASK, NULL);
 
-    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
-            table = gtk_table_new(4, 3, FALSE), TRUE, TRUE, 0);
+    /* Save Show Velocity Vector flag. */
+    gconf_client_set_bool(gconf_client,
+            GCONF_KEY_SHOWVELVEC, _show_velvec, NULL);
 
-    /* Mark. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("GPS Mark")),
-            0, 1, 0, 1, GTK_FILL, 0, 2, 4);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            cdi.col_mark = hildon_color_button_new(),
-            1, 2, 0, 1, 0, 0, 2, 4);
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi.col_mark), &_color_mark);
-    gtk_table_attach(GTK_TABLE(table),
-            cdi.col_mark_velocity = hildon_color_button_new(),
-            2, 3, 0, 1, 0, 0, 2, 4);
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi.col_mark_velocity), &_color_mark_velocity);
-    gtk_table_attach(GTK_TABLE(table),
-            cdi.col_mark_old = hildon_color_button_new(),
-            3, 4, 0, 1, 0, 0, 2, 4);
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi.col_mark_old), &_color_mark_old);
+    /* Save Enable GPS flag. */
+    gconf_client_set_bool(gconf_client,
+            GCONF_KEY_ENABLE_GPS, _enable_gps, NULL);
 
-    /* Track. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Track")),
-            0, 1, 1, 2, GTK_FILL, 0, 2, 4);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            cdi.col_track = hildon_color_button_new(),
-            1, 2, 1, 2, 0, 0, 2, 4);
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi.col_track), &_color_track);
-    gtk_table_attach(GTK_TABLE(table),
-            cdi.col_track_break = hildon_color_button_new(),
-            2, 3, 1, 2, 0, 0, 2, 4);
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi.col_track_break), &_color_track_break);
+    /* Save Route Locations. */
+    gconf_client_set_list(gconf_client,
+            GCONF_KEY_ROUTE_LOCATIONS, GCONF_VALUE_STRING, _loc_list, NULL);
 
-    /* Route. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Route")),
-            0, 1, 2, 3, GTK_FILL, 0, 2, 4);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            cdi.col_route = hildon_color_button_new(),
-            1, 2, 2, 3, 0, 0, 2, 4);
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi.col_route), &_color_route);
-    gtk_table_attach(GTK_TABLE(table),
-            cdi.col_route_way = hildon_color_button_new(),
-            2, 3, 2, 3, 0, 0, 2, 4);
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi.col_route_way), &_color_route_way);
-    gtk_table_attach(GTK_TABLE(table),
-            cdi.col_route_nextway = hildon_color_button_new(),
-            3, 4, 2, 3, 0, 0, 2, 4);
-    hildon_color_button_set_color(
-            HILDON_COLOR_BUTTON(cdi.col_route_nextway), &_color_route_nextway);
+    /* Save GPS Info flag. */
+    gconf_client_set_bool(gconf_client,
+            GCONF_KEY_GPS_INFO, _gps_info, NULL);
 
-    gtk_widget_show_all(dialog);
+    /* Save Colors. */
+    sprintf(buffer, "#%02x%02x%02x",
+            _color_mark.red >> 8,
+            _color_mark.green >> 8,
+            _color_mark.blue >> 8);
+    gconf_client_set_string(gconf_client,
+            GCONF_KEY_COLOR_MARK, buffer, NULL);
 
-    while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
-    {
-        GdkColor *color;
+    sprintf(buffer, "#%02x%02x%02x",
+            _color_mark_velocity.red >> 8,
+            _color_mark_velocity.green >> 8,
+            _color_mark_velocity.blue >> 8);
+    gconf_client_set_string(gconf_client,
+            GCONF_KEY_COLOR_MARK_VELOCITY, buffer, NULL);
 
-        color = hildon_color_button_get_color(
-                HILDON_COLOR_BUTTON(cdi.col_mark));
-        _color_mark = *color;
+    sprintf(buffer, "#%02x%02x%02x",
+            _color_mark_old.red >> 8,
+            _color_mark_old.green >> 8,
+            _color_mark_old.blue >> 8);
+    gconf_client_set_string(gconf_client,
+            GCONF_KEY_COLOR_MARK_OLD, buffer, NULL);
 
-        color = hildon_color_button_get_color(
-                HILDON_COLOR_BUTTON(cdi.col_mark_velocity));
-        _color_mark_velocity = *color;
+    sprintf(buffer, "#%02x%02x%02x",
+            _color_track.red >> 8,
+            _color_track.green >> 8,
+            _color_track.blue >> 8);
+    gconf_client_set_string(gconf_client,
+            GCONF_KEY_COLOR_TRACK, buffer, NULL);
 
-        color = hildon_color_button_get_color(
-                HILDON_COLOR_BUTTON(cdi.col_mark_old));
-        _color_mark_old = *color;
+    sprintf(buffer, "#%02x%02x%02x",
+            _color_track_break.red >> 8,
+            _color_track_break.green >> 8,
+            _color_track_break.blue >> 8);
+    gconf_client_set_string(gconf_client,
+            GCONF_KEY_COLOR_TRACK_BREAK, buffer, NULL);
 
-        color = hildon_color_button_get_color(
-                HILDON_COLOR_BUTTON(cdi.col_track));
-        _color_track = *color;
+    sprintf(buffer, "#%02x%02x%02x",
+            _color_route.red >> 8,
+            _color_route.green >> 8,
+            _color_route.blue >> 8);
+    gconf_client_set_string(gconf_client,
+            GCONF_KEY_COLOR_ROUTE, buffer, NULL);
 
-        color = hildon_color_button_get_color(
-                HILDON_COLOR_BUTTON(cdi.col_track_break));
-        _color_track_break = *color;
+    sprintf(buffer, "#%02x%02x%02x",
+            _color_route_way.red >> 8,
+            _color_route_way.green >> 8,
+            _color_route_way.blue >> 8);
+    gconf_client_set_string(gconf_client,
+            GCONF_KEY_COLOR_ROUTE_WAY, buffer, NULL);
 
-        color = hildon_color_button_get_color(
-                HILDON_COLOR_BUTTON(cdi.col_route));
-        _color_route = *color;
+    sprintf(buffer, "#%02x%02x%02x",
+            _color_route_nextway.red >> 8,
+            _color_route_nextway.green >> 8,
+            _color_route_nextway.blue >> 8);
+    gconf_client_set_string(gconf_client,
+            GCONF_KEY_COLOR_ROUTE_NEXTWAY, buffer, NULL);
 
-        color = hildon_color_button_get_color(
-                HILDON_COLOR_BUTTON(cdi.col_route_way));
-        _color_route_way = *color;
+    sprintf(buffer, "#%02x%02x%02x",
+            _color_poi.red >> 8,
+            _color_poi.green >> 8,
+            _color_poi.blue >> 8);
+    gconf_client_set_string(gconf_client,
+            GCONF_KEY_COLOR_POI, buffer, NULL);
 
-        color = hildon_color_button_get_color(
-                HILDON_COLOR_BUTTON(cdi.col_route_nextway));
-        _color_route_nextway = *color;
+    /* Save POI database. */
+    if(_poi_db)
+        gconf_client_set_string(gconf_client,
+                GCONF_KEY_POI_DB, _poi_db, NULL);
+    else
+        gconf_client_unset(gconf_client, GCONF_KEY_POI_DB, NULL);
 
-        update_gcs();
-        break;
+   /* Save Show POI below zoom. */
+    gconf_client_set_int(gconf_client,
+            GCONF_KEY_POI_ZOOM, _poi_zoom, NULL);
+
+    g_object_unref(gconf_client);
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+static void
+force_min_visible_bars(HildonControlbar *control_bar, gint num_bars)
+{
+    GValue val;
+    memset(&val, 0, sizeof(val));
+    g_value_init(&val, G_TYPE_INT);
+    g_value_set_int(&val, num_bars);
+    g_object_set_property(G_OBJECT(control_bar), "minimum-visible-bars", &val);
+}
+
+
+typedef struct _ScanInfo ScanInfo;
+struct _ScanInfo {
+    GtkWidget *settings_dialog;
+    GtkWidget *txt_rcvr_mac;
+    GtkWidget *scan_dialog;
+    GtkWidget *banner;
+    GtkListStore *store;
+    guint sid;
+};
+
+static gboolean
+scan_bluetooth_idle(ScanInfo *scan_info)
+{
+    gint devid, num_rsp;
+    GtkTreeIter iter;
+    inquiry_info *ii = NULL;
+
+    devid = hci_get_route(NULL);
+
+    ii = (inquiry_info*)malloc(255 * sizeof(inquiry_info));
+    num_rsp = hci_inquiry(devid, 4, 255, NULL, &ii, IREQ_CACHE_FLUSH);
+
+    if(num_rsp < 0)
+    {
+        gtk_widget_destroy(scan_info->banner);
+        gtk_widget_hide(scan_info->scan_dialog);
+        popup_error(scan_info->settings_dialog,
+                _("An error occurred while scanning."));
+    }
+    else if(num_rsp == 0)
+    {
+        gtk_widget_destroy(scan_info->banner);
+        gtk_widget_hide(scan_info->scan_dialog);
+        popup_error(scan_info->settings_dialog,
+                _("No bluetooth devices found."));
     }
+    else
+    {
+        guint i;
+        gint sock = hci_open_dev(devid);
+        for(i = 0; i < num_rsp; i++)
+        {
+            gchar addr[19] = { 0 };
+            gchar name[256] = { 0 };
 
-    gtk_widget_destroy(dialog);
+            ba2str(&ii[i].bdaddr, addr);
+            memset(name, 0, sizeof(name));
+            if(hci_read_remote_name(sock, &ii[i].bdaddr, sizeof(name), name, 0))
+                strcpy(name, _("Unknown"));
 
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
+            gtk_list_store_append(scan_info->store, &iter);
+            gtk_list_store_set(scan_info->store, &iter,
+                    0, g_strdup(addr),
+                    1, g_strdup(name),
+                    -1);
+        }
+        close(sock);
+        gtk_widget_destroy(scan_info->banner);
+    }
+    free(ii);
+    scan_info->sid = 0;
+    return FALSE;
 }
 
 /**
- * Bring up the Settings dialog.  Return TRUE if and only if the recever
- * information has changed (MAC or channel).
+ * Scan for all bluetooth devices.  This method can take a few seconds,
+ * during which the UI will freeze.
  */
 static gboolean
-settings_dialog()
+scan_bluetooth(GtkWidget *widget, ScanInfo *scan_info)
 {
+    /* Do an hci_inquiry for our boy. */
     GtkWidget *dialog;
-    GtkWidget *notebook;
-    GtkWidget *table;
-    GtkWidget *hbox;
-    GtkWidget *hbox2;
-    GtkWidget *label;
-    GtkWidget *txt_rcvr_mac;
-    GtkWidget *num_rcvr_chan;
-    GtkWidget *txt_map_uri_format;
-    GtkWidget *txt_map_dir_name;
-    GtkWidget *num_zoom_steps;
-    GtkWidget *num_center_ratio;
-    GtkWidget *num_lead_ratio;
-    GtkWidget *num_announce_notice;
-    GtkWidget *chk_enable_voice;
-    GtkWidget *num_voice_speed;
-    GtkWidget *num_voice_pitch;
-    GtkWidget *num_draw_line_width;
-    GtkWidget *chk_always_keep_on;
-    GtkWidget *cmb_units;
-    GtkWidget *btn_scan;
-    GtkWidget *btn_browse;
-    GtkWidget *btn_colors;
-    BrowseInfo browse_info = {0, 0};
-    ScanInfo scan_info = {0};
-    gboolean rcvr_changed = FALSE;
+    GtkWidget *lst_devices;
+    GtkTreeViewColumn *column;
+    GtkCellRenderer *renderer;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    dialog = gtk_dialog_new_with_buttons(_("Maemo Mapper Settings"),
-            GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+    dialog = gtk_dialog_new_with_buttons(_("Select Bluetooth Device"),
+            GTK_WINDOW(scan_info->settings_dialog), GTK_DIALOG_MODAL,
             GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
             NULL);
 
-    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
-            btn_colors = gtk_button_new_with_label(_("Colors...")));
+    scan_info->scan_dialog = dialog;
 
-    gtk_dialog_add_button(GTK_DIALOG(dialog),
-            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+    scan_info->banner = hildon_banner_show_animation(dialog, NULL,
+            _("Scanning Bluetooth Devices"));
 
-    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
-            notebook = gtk_notebook_new(), TRUE, TRUE, 0);
-    
-    /* Receiver page. */
-    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
-            table = gtk_table_new(2, 3, FALSE),
-            label = gtk_label_new(_("GPS")));
+    scan_info->store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
 
-    /* Receiver MAC Address. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("MAC")),
-            0, 1, 0, 1, GTK_FILL, 0, 2, 4);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            hbox = gtk_hbox_new(FALSE, 4),
-            1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
-    gtk_box_pack_start(GTK_BOX(hbox),
-            txt_rcvr_mac = gtk_entry_new(),
-            TRUE, TRUE, 0);
-    gtk_box_pack_start(GTK_BOX(hbox),
-            btn_scan = gtk_button_new_with_label(_("Scan...")),
-            FALSE, FALSE, 0);
+    scan_info->sid = g_idle_add((GSourceFunc)scan_bluetooth_idle, scan_info);
 
-    /* Receiver Channel. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Channel")),
-            0, 1, 1, 2, GTK_FILL, 0, 2, 4);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
-            1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
-    gtk_container_add(GTK_CONTAINER(label),
-            num_rcvr_chan = hildon_number_editor_new(0, 255));
+    gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 300);
 
-    /* Note!. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(
-                _("Note: \"Channel\" refers to the device side!")),
-            0, 2, 2, 3, GTK_FILL, 0, 2, 4);
-    gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
-    gtk_misc_set_alignment(GTK_MISC(label), 0.5f, 0.5f);
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+            lst_devices = gtk_tree_view_new_with_model(
+                GTK_TREE_MODEL(scan_info->store)), TRUE, TRUE, 0);
 
+    g_object_unref(G_OBJECT(scan_info->store));
 
-    /* Maps page. */
-    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
-            table = gtk_table_new(2, 3, FALSE),
-            label = gtk_label_new(_("Maps")));
+    gtk_tree_selection_set_mode(
+            gtk_tree_view_get_selection(GTK_TREE_VIEW(lst_devices)),
+            GTK_SELECTION_SINGLE);
+    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(lst_devices), TRUE);
 
-    /* Map download URI. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("URI Format")),
-            0, 1, 0, 1, GTK_FILL, 0, 2, 4);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            txt_map_uri_format = gtk_entry_new(),
-            1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes(
+            _("MAC"), renderer, "text", 0);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(lst_devices), column);
 
-    /* Zoom Steps. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Zoom Steps")),
-            0, 1, 1, 2, GTK_FILL, 0, 2, 4);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
-            1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
-    gtk_container_add(GTK_CONTAINER(label),
-            num_zoom_steps = hildon_controlbar_new());
-    hildon_controlbar_set_range(HILDON_CONTROLBAR(num_zoom_steps), 1, 4);
-    force_min_visible_bars(HILDON_CONTROLBAR(num_zoom_steps), 1);
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes(
+            _("Description"), renderer, "text", 1);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(lst_devices), column);
 
-    /* Map Directory. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Cache Dir.")),
-            0, 1, 2, 3, GTK_FILL, 0, 2, 4);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            hbox = gtk_hbox_new(FALSE, 4),
-            1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
-    gtk_box_pack_start(GTK_BOX(hbox),
-            txt_map_dir_name = gtk_entry_new(),
-            TRUE, TRUE, 0);
-    gtk_box_pack_start(GTK_BOX(hbox),
-            btn_browse = gtk_button_new_with_label(_("Browse...")),
-            FALSE, FALSE, 0);
+    gtk_widget_show_all(dialog);
 
+    while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
+    {
+        GtkTreeIter iter;
+        if(gtk_tree_selection_get_selected(
+                    gtk_tree_view_get_selection(GTK_TREE_VIEW(lst_devices)),
+                    NULL, &iter))
+        {
+            gchar *mac;
+            gtk_tree_model_get(GTK_TREE_MODEL(scan_info->store),
+                    &iter, 0, &mac, -1);
+            gtk_entry_set_text(GTK_ENTRY(scan_info->txt_rcvr_mac), mac);
+            break;
+        }
+        else
+            popup_error(dialog,
+                    _("Please select a bluetooth device from the list."));
+    }
 
-    /* Auto-Center page. */
-    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
-            table = gtk_table_new(2, 2, FALSE),
-            label = gtk_label_new(_("Auto-Center")));
+    if(scan_info->sid)
+        g_source_remove(scan_info->sid);
+    gtk_widget_destroy(dialog);
 
-    /* Auto-Center Sensitivity. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Sensitivity")),
-            0, 1, 0, 1, GTK_FILL, 0, 2, 4);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
-            1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
-    gtk_container_add(GTK_CONTAINER(label),
-            num_center_ratio = hildon_controlbar_new());
-    hildon_controlbar_set_range(HILDON_CONTROLBAR(num_center_ratio), 1, 10);
-    force_min_visible_bars(HILDON_CONTROLBAR(num_center_ratio), 1);
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-    /* Lead Amount. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Lead Amount")),
-            0, 1, 1, 2, GTK_FILL, 0, 2, 4);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
-            1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
-    gtk_container_add(GTK_CONTAINER(label),
-            num_lead_ratio = hildon_controlbar_new());
-    hildon_controlbar_set_range(HILDON_CONTROLBAR(num_lead_ratio), 1, 10);
-    force_min_visible_bars(HILDON_CONTROLBAR(num_lead_ratio), 1);
+typedef struct _BrowseInfo BrowseInfo;
+struct _BrowseInfo {
+    GtkWidget *dialog;
+    GtkWidget *txt;
+};
 
-    /* Announcement. */
-    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
-            table = gtk_table_new(2, 3, FALSE),
-            label = gtk_label_new(_("Announce")));
+static gboolean
+settings_dialog_browse_forfile(GtkWidget *widget, BrowseInfo *browse_info)
+{
+    GtkWidget *dialog;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* Announcement Advance Notice. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Advance Notice")),
-            0, 1, 0, 1, GTK_FILL, 0, 2, 4);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            num_announce_notice = hildon_controlbar_new(),
-            1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
-    hildon_controlbar_set_range(HILDON_CONTROLBAR(num_announce_notice), 1, 20);
-    force_min_visible_bars(HILDON_CONTROLBAR(num_announce_notice), 1);
+    dialog = GTK_WIDGET(
+            hildon_file_chooser_dialog_new(GTK_WINDOW(browse_info->dialog),
+            GTK_FILE_CHOOSER_ACTION_OPEN));
 
-    /* Enable Voice. */
-    gtk_table_attach(GTK_TABLE(table),
-            chk_enable_voice = gtk_check_button_new_with_label(
-                _("Enable Voice Synthesis (requires flite)")),
-            0, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_enable_voice),
-            _enable_voice);
+    gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), TRUE);
+    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
+            gtk_entry_get_text(GTK_ENTRY(browse_info->txt)));
 
-    /* Voice Speed and Pitch. */
-    gtk_table_attach(GTK_TABLE(table),
-            hbox = gtk_hbox_new(FALSE, 12),
-            0, 2, 2, 3, 0, 0, 2, 6);
-    gtk_box_pack_start(GTK_BOX(hbox),
-            hbox2 = gtk_hbox_new(FALSE, 4),
-            TRUE, TRUE, 4);
-    gtk_box_pack_start(GTK_BOX(hbox2),
-            label = gtk_label_new(_("Speed")),
-            TRUE, TRUE, 0);
-    gtk_box_pack_start(GTK_BOX(hbox2),
-            num_voice_speed = hildon_controlbar_new(),
-            TRUE, TRUE, 0);
-    hildon_controlbar_set_range(HILDON_CONTROLBAR(num_voice_speed), 1, 10);
-    force_min_visible_bars(HILDON_CONTROLBAR(num_voice_speed), 1);
+    if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)))
+    {
+        gchar *filename = gtk_file_chooser_get_filename(
+                GTK_FILE_CHOOSER(dialog));
+        gtk_entry_set_text(GTK_ENTRY(browse_info->txt), filename);
+        g_free(filename);
+    }
 
-    gtk_box_pack_start(GTK_BOX(hbox),
-            hbox2 = gtk_hbox_new(FALSE, 4),
-            TRUE, TRUE, 4);
-    gtk_box_pack_start(GTK_BOX(hbox2),
-            label = gtk_label_new(_("Pitch")),
-            TRUE, TRUE, 0);
-    gtk_box_pack_start(GTK_BOX(hbox2),
-            num_voice_pitch = hildon_controlbar_new(),
-            TRUE, TRUE, 0);
-    hildon_controlbar_set_range(HILDON_CONTROLBAR(num_voice_pitch), -2, 8);
-    force_min_visible_bars(HILDON_CONTROLBAR(num_voice_pitch), 1);
+    gtk_widget_destroy(dialog);
 
-    /* Misc. page. */
-    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
-            table = gtk_table_new(2, 3, FALSE),
-            label = gtk_label_new(_("Misc.")));
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-    /* Line Width. */
+
+typedef struct _ColorsDialogInfo ColorsDialogInfo;
+struct _ColorsDialogInfo {
+    GtkWidget *col_mark;
+    GtkWidget *col_mark_velocity;
+    GtkWidget *col_mark_old;
+    GtkWidget *col_track;
+    GtkWidget *col_track_break;
+    GtkWidget *col_route;
+    GtkWidget *col_route_way;
+    GtkWidget *col_route_nextway;
+    GtkWidget *col_poi;
+};
+
+static gboolean
+settings_dialog_colors_reset(GtkWidget *widget, ColorsDialogInfo *cdi)
+{
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi->col_mark),
+            &DEFAULT_COLOR_MARK);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi->col_mark_velocity),
+            &DEFAULT_COLOR_MARK_VELOCITY);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi->col_mark_old),
+            &DEFAULT_COLOR_MARK_OLD);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi->col_track),
+            &DEFAULT_COLOR_TRACK);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi->col_track_break),
+            &DEFAULT_COLOR_TRACK_BREAK);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi->col_route),
+            &DEFAULT_COLOR_ROUTE);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi->col_route_way),
+            &DEFAULT_COLOR_ROUTE_WAY);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi->col_route_nextway),
+            &DEFAULT_COLOR_ROUTE_NEXTWAY);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi->col_poi),
+            &DEFAULT_COLOR_POI);
+    return TRUE;
+}
+
+static gboolean
+settings_dialog_colors(GtkWidget *widget, GtkWidget *parent)
+{
+    GtkWidget *dialog;
+    GtkWidget *table;
+    GtkWidget *label;
+    GtkWidget *btn_defaults;
+    ColorsDialogInfo cdi;
+    printf("%s()\n", __PRETTY_FUNCTION__);
+    
+    dialog = gtk_dialog_new_with_buttons(_("Colors"),
+            GTK_WINDOW(parent), GTK_DIALOG_MODAL,
+            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+            NULL);
+
+    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
+            btn_defaults = gtk_button_new_with_label(_("Defaults")));
+    g_signal_connect(G_OBJECT(btn_defaults), "clicked",
+                      G_CALLBACK(settings_dialog_colors_reset), &cdi);
+
+    gtk_dialog_add_button(GTK_DIALOG(dialog),
+            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+            table = gtk_table_new(4, 3, FALSE), TRUE, TRUE, 0);
+
+    /* Mark. */
     gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Line Width")),
+            label = gtk_label_new(_("GPS Mark")),
             0, 1, 0, 1, GTK_FILL, 0, 2, 4);
     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
     gtk_table_attach(GTK_TABLE(table),
-            num_draw_line_width = hildon_controlbar_new(),
-            1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
-    hildon_controlbar_set_range(HILDON_CONTROLBAR(num_draw_line_width), 1, 20);
-    force_min_visible_bars(HILDON_CONTROLBAR(num_draw_line_width), 1);
+            cdi.col_mark = hildon_color_button_new(),
+            1, 2, 0, 1, 0, 0, 2, 4);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi.col_mark), &_color_mark);
+    gtk_table_attach(GTK_TABLE(table),
+            cdi.col_mark_velocity = hildon_color_button_new(),
+            2, 3, 0, 1, 0, 0, 2, 4);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi.col_mark_velocity), &_color_mark_velocity);
+    gtk_table_attach(GTK_TABLE(table),
+            cdi.col_mark_old = hildon_color_button_new(),
+            3, 4, 0, 1, 0, 0, 2, 4);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi.col_mark_old), &_color_mark_old);
 
-    /* Keep Display On Only When Fullscreen. */
+    /* Track. */
     gtk_table_attach(GTK_TABLE(table),
-            chk_always_keep_on = gtk_check_button_new_with_label(
-                _("Keep Display On Only in Fullscreen Mode")),
-            0, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+            label = gtk_label_new(_("Track")),
+            0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            cdi.col_track = hildon_color_button_new(),
+            1, 2, 1, 2, 0, 0, 2, 4);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi.col_track), &_color_track);
+    gtk_table_attach(GTK_TABLE(table),
+            cdi.col_track_break = hildon_color_button_new(),
+            2, 3, 1, 2, 0, 0, 2, 4);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi.col_track_break), &_color_track_break);
 
-    /* Units. */
+    /* Route. */
     gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Units")),
+            label = gtk_label_new(_("Route")),
             0, 1, 2, 3, GTK_FILL, 0, 2, 4);
     gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
     gtk_table_attach(GTK_TABLE(table),
-            label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
-            1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
-    gtk_container_add(GTK_CONTAINER(label),
-            cmb_units = gtk_combo_box_new_text());
-    gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_units), UNITS_KM);
-    gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_units), UNITS_MI);
-    gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_units), UNITS_NM);
-
-    /* Connect signals. */
-    scan_info.settings_dialog = dialog;
-    scan_info.txt_rcvr_mac = txt_rcvr_mac;
-    g_signal_connect(G_OBJECT(btn_scan), "clicked",
-                      G_CALLBACK(scan_bluetooth), &scan_info);
-    browse_info.dialog = dialog;
-    browse_info.txt_map_dir_name = txt_map_dir_name;
-    g_signal_connect(G_OBJECT(btn_browse), "clicked",
-                      G_CALLBACK(settings_dialog_browse), &browse_info);
-    g_signal_connect(G_OBJECT(btn_colors), "clicked",
-                      G_CALLBACK(settings_dialog_colors), dialog);
-
-    /* Initialize fields. */
-    if(_rcvr_mac)
-        gtk_entry_set_text(GTK_ENTRY(txt_rcvr_mac), _rcvr_mac);
-    hildon_number_editor_set_value(HILDON_NUMBER_EDITOR(num_rcvr_chan),
-            _rcvr_addr.rc_channel);
-    if(_map_uri_format)
-        gtk_entry_set_text(GTK_ENTRY(txt_map_uri_format), _map_uri_format);
-    hildon_controlbar_set_value(HILDON_CONTROLBAR(num_zoom_steps), _zoom_steps);
-    if(_map_dir_name)
-        gtk_entry_set_text(GTK_ENTRY(txt_map_dir_name), _map_dir_name);
-    hildon_controlbar_set_value(HILDON_CONTROLBAR(num_center_ratio),
-            _center_ratio);
-    hildon_controlbar_set_value(HILDON_CONTROLBAR(num_lead_ratio),
-            _lead_ratio);
-    hildon_controlbar_set_value(HILDON_CONTROLBAR(num_announce_notice),
-            _announce_notice_ratio);
-    hildon_controlbar_set_value(HILDON_CONTROLBAR(num_voice_speed),
-            (gint)(_voice_speed * 3 + 0.5));
-    hildon_controlbar_set_value(HILDON_CONTROLBAR(num_voice_pitch),
-            _voice_pitch);
-    hildon_controlbar_set_value(HILDON_CONTROLBAR(num_draw_line_width),
-            _draw_line_width);
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_always_keep_on),
-            !_always_keep_on);
-    gtk_combo_box_set_active(GTK_COMBO_BOX(cmb_units),
-            !strcmp(_units, UNITS_MI) ? 1 :
-            !strcmp(_units, UNITS_NM) ? 2 : 0);
+            cdi.col_route = hildon_color_button_new(),
+            1, 2, 2, 3, 0, 0, 2, 4);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi.col_route), &_color_route);
+    gtk_table_attach(GTK_TABLE(table),
+            cdi.col_route_way = hildon_color_button_new(),
+            2, 3, 2, 3, 0, 0, 2, 4);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi.col_route_way), &_color_route_way);
+    gtk_table_attach(GTK_TABLE(table),
+            cdi.col_route_nextway = hildon_color_button_new(),
+            3, 4, 2, 3, 0, 0, 2, 4);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi.col_route_nextway), &_color_route_nextway);
+    
+    /* POI. */
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("POI")),
+            0, 1, 3, 4, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            cdi.col_poi = hildon_color_button_new(),
+            1, 2, 3, 4, 0, 0, 2, 4);
+    hildon_color_button_set_color(
+            HILDON_COLOR_BUTTON(cdi.col_poi), &_color_poi);
 
     gtk_widget_show_all(dialog);
 
     while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
     {
-        if(!config_set_map_dir_name(gnome_vfs_expand_initial_tilde(
-                gtk_entry_get_text(GTK_ENTRY(txt_map_dir_name)))))
-        {
-            popup_error(dialog, _("Could not create Map Cache directory."));
-            continue;
-        }
-
-        /* Set _rcvr_mac if necessary. */
-        if(!*gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac)))
-        {
-            /* User specified no rcvr mac - set _rcvr_mac to NULL. */
-            if(_rcvr_mac)
-            {
-                g_free(_rcvr_mac);
-                _rcvr_mac = NULL;
-                rcvr_changed = TRUE;
-            }
-            if(_enable_gps)
-            {
-                gtk_check_menu_item_set_active(
-                        GTK_CHECK_MENU_ITEM(_menu_enable_gps_item), FALSE);
-                popup_error(dialog, _("No GPS Receiver MAC Provided.\n"
-                        "GPS Disabled."));
-                rcvr_changed = TRUE;
-            }
-        }
-        else if(!_rcvr_mac || strcmp(_rcvr_mac,
-                      gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac))))
-        {
-            /* User specified a new rcvr mac. */
-            if(_rcvr_mac)
-                g_free(_rcvr_mac);
-            _rcvr_mac = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac)));
-            str2ba(_rcvr_mac, &_rcvr_addr.rc_bdaddr);
-            rcvr_changed = TRUE;
-        }
-
-        if(_rcvr_addr.rc_channel != hildon_number_editor_get_value(
-                    HILDON_NUMBER_EDITOR(num_rcvr_chan)))
-        {
-            _rcvr_addr.rc_channel = hildon_number_editor_get_value(
-                    HILDON_NUMBER_EDITOR(num_rcvr_chan));
-            rcvr_changed = TRUE;
-        }
-
-        if(_map_uri_format)
-            g_free(_map_uri_format);
-        if(strlen(gtk_entry_get_text(GTK_ENTRY(txt_map_uri_format))))
-            _map_uri_format = g_strdup(gtk_entry_get_text(
-                        GTK_ENTRY(txt_map_uri_format)));
-        else
-            _map_uri_format = NULL;
-
-        _zoom_steps = hildon_controlbar_get_value(
-                HILDON_CONTROLBAR(num_zoom_steps));
+        GdkColor *color;
 
-        _center_ratio = hildon_controlbar_get_value(
-                HILDON_CONTROLBAR(num_center_ratio));
+        color = hildon_color_button_get_color(
+                HILDON_COLOR_BUTTON(cdi.col_mark));
+        _color_mark = *color;
 
-        _lead_ratio = hildon_controlbar_get_value(
-                HILDON_CONTROLBAR(num_lead_ratio));
+        color = hildon_color_button_get_color(
+                HILDON_COLOR_BUTTON(cdi.col_mark_velocity));
+        _color_mark_velocity = *color;
 
-        _draw_line_width = hildon_controlbar_get_value(
-                HILDON_CONTROLBAR(num_draw_line_width));
+        color = hildon_color_button_get_color(
+                HILDON_COLOR_BUTTON(cdi.col_mark_old));
+        _color_mark_old = *color;
 
-        _always_keep_on = !gtk_toggle_button_get_active(
-                GTK_TOGGLE_BUTTON(chk_always_keep_on));
+        color = hildon_color_button_get_color(
+                HILDON_COLOR_BUTTON(cdi.col_track));
+        _color_track = *color;
 
-        g_free(_units);
-        _units = gtk_combo_box_get_active_text(GTK_COMBO_BOX(cmb_units));
+        color = hildon_color_button_get_color(
+                HILDON_COLOR_BUTTON(cdi.col_track_break));
+        _color_track_break = *color;
 
-        _announce_notice_ratio = hildon_controlbar_get_value(
-                HILDON_CONTROLBAR(num_announce_notice));
+        color = hildon_color_button_get_color(
+                HILDON_COLOR_BUTTON(cdi.col_route));
+        _color_route = *color;
 
-        _voice_speed = hildon_controlbar_get_value(
-                HILDON_CONTROLBAR(num_voice_speed)) / 3.0;
+        color = hildon_color_button_get_color(
+                HILDON_COLOR_BUTTON(cdi.col_route_way));
+        _color_route_way = *color;
 
-        _voice_pitch = hildon_controlbar_get_value(
-                HILDON_CONTROLBAR(num_voice_pitch));
+        color = hildon_color_button_get_color(
+                HILDON_COLOR_BUTTON(cdi.col_route_nextway));
+        _color_route_nextway = *color;
 
-        _enable_voice = gtk_toggle_button_get_active(
-                GTK_TOGGLE_BUTTON(chk_enable_voice));
+        color = hildon_color_button_get_color(
+                HILDON_COLOR_BUTTON(cdi.col_poi));
+        _color_poi = *color;
 
         update_gcs();
-
-        config_save();
         break;
     }
 
-    gtk_widget_hide(dialog); /* Destroying causes a crash (!?!?!??!) */
+    gtk_widget_destroy(dialog);
 
-    vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, rcvr_changed);
-    return rcvr_changed;
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
 }
 
 /**
- * Initialize all configuration from GCONF.  This should not be called more
- * than once during execution.
+ * Bring up the Settings dialog.  Return TRUE if and only if the recever
+ * information has changed (MAC or channel).
  */
-static void
-config_init()
+static gboolean
+settings_dialog()
 {
-    GConfValue *value;
-    GConfClient *gconf_client = gconf_client_get_default();
-    gchar *str;
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    GtkWidget *dialog;
+    GtkWidget *notebook;
+    GtkWidget *table;
+    GtkWidget *hbox;
+    GtkWidget *hbox2;
+    GtkWidget *label;
+    GtkWidget *txt_rcvr_mac;
+    GtkWidget *num_rcvr_chan;
+    GtkWidget *num_center_ratio;
+    GtkWidget *num_lead_ratio;
+    GtkWidget *num_announce_notice;
+    GtkWidget *chk_enable_voice;
+    GtkWidget *num_voice_speed;
+    GtkWidget *num_voice_pitch;
+    GtkWidget *num_draw_line_width;
+    GtkWidget *chk_always_keep_on;
+    GtkWidget *cmb_units;
+    GtkWidget *cmb_escape_key;
+    GtkWidget *btn_scan;
+    GtkWidget *btn_colors;
 
-    if(!gconf_client)
-    {
-        popup_error(_window, _("Failed to initialize GConf.  Quitting."));
-        exit(1);
-    }
+    GtkWidget *txt_poi_db;
+    GtkWidget *btn_browsepoi;
+    GtkWidget *num_poi_zoom;
 
-    /* Get Receiver MAC from GConf.  Default is scanned via hci_inquiry. */
-    {
-        _rcvr_mac = gconf_client_get_string(
-                gconf_client, GCONF_KEY_RCVR_MAC, NULL);
-        if(_rcvr_mac)
-            str2ba(_rcvr_mac, &_rcvr_addr.rc_bdaddr);
-    }
+    BrowseInfo browse_info = {0, 0};
+    ScanInfo scan_info = {0};
+    gboolean rcvr_changed = FALSE;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* Get Receiver Channel from GConf.  Default is 1. */
-    _rcvr_addr.rc_family = AF_BLUETOOTH;
-    _rcvr_addr.rc_channel = gconf_client_get_int(gconf_client,
-            GCONF_KEY_RCVR_CHAN, NULL);
-    if(_rcvr_addr.rc_channel < 1)
-        _rcvr_addr.rc_channel = 1;
+    dialog = gtk_dialog_new_with_buttons(_("Maemo Mapper Settings"),
+            GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+            NULL);
 
-    /* Get Map Download URI Format.  Default is NULL. */
-    _map_uri_format = gconf_client_get_string(gconf_client,
-            GCONF_KEY_MAP_URI_FORMAT, NULL);
+    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
+            btn_colors = gtk_button_new_with_label(_("Colors...")));
 
-    /* Get Map Download Zoom Steps.  Default is 2. */
-    _zoom_steps = gconf_client_get_int(gconf_client,
-            GCONF_KEY_MAP_ZOOM_STEPS, NULL);
-    if(!_zoom_steps)
-        _zoom_steps = 2;
+    gtk_dialog_add_button(GTK_DIALOG(dialog),
+            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
 
-    /* Get Map Cache Directory.  Default is "~/apps/maemo-mapper". */
-    {
-        gchar *tmp = gconf_client_get_string(gconf_client,
-                GCONF_KEY_MAP_DIR_NAME, NULL);
-        if(!tmp)
-            tmp = g_strdup("~/apps/maemo-mapper");
-        if(!config_set_map_dir_name(gnome_vfs_expand_initial_tilde(tmp)))
-        {
-            popup_error(_window,
-                    _("Could not create Map Cache directory.\n"
-                    "Please set a valid Map Cache directory in the Settings"
-                    " dialog box."));
-        }
-        g_free(tmp);
-    }
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+            notebook = gtk_notebook_new(), TRUE, TRUE, 0);
+    
+    /* Receiver page. */
+    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+            table = gtk_table_new(2, 3, FALSE),
+            label = gtk_label_new(_("GPS")));
 
-    /* Get Auto-Download.  Default is FALSE. */
-    _auto_download = gconf_client_get_bool(gconf_client,
-            GCONF_KEY_AUTO_DOWNLOAD, NULL);
+    /* Receiver MAC Address. */
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("MAC")),
+            0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            hbox = gtk_hbox_new(FALSE, 4),
+            1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            txt_rcvr_mac = gtk_entry_new(),
+            TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            btn_scan = gtk_button_new_with_label(_("Scan...")),
+            FALSE, FALSE, 0);
 
-    /* Get Center Ratio - Default is 3. */
-    _center_ratio = gconf_client_get_int(gconf_client,
-            GCONF_KEY_CENTER_SENSITIVITY, NULL);
-    if(!_center_ratio)
-        _center_ratio = 7;
+    /* Receiver Channel. */
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Channel")),
+            0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+            1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_container_add(GTK_CONTAINER(label),
+            num_rcvr_chan = hildon_number_editor_new(0, 255));
 
-    /* Get Lead Ratio - Default is 5. */
-    _lead_ratio = gconf_client_get_int(gconf_client,
-            GCONF_KEY_LEAD_AMOUNT, NULL);
-    if(!_lead_ratio)
-        _lead_ratio = 5;
+    /* Note!. */
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(
+                _("Note: \"Channel\" refers to the device side!")),
+            0, 2, 2, 3, GTK_FILL, 0, 2, 4);
+    gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
+    gtk_misc_set_alignment(GTK_MISC(label), 0.5f, 0.5f);
 
-    /* Get Draw Line Width- Default is 5. */
-    _draw_line_width = gconf_client_get_int(gconf_client,
-            GCONF_KEY_DRAW_LINE_WIDTH, NULL);
-    if(!_draw_line_width)
-        _draw_line_width = 5;
 
-    /* Get Announce Advance Notice - Default is 30. */
-    value = gconf_client_get(gconf_client, GCONF_KEY_ANNOUNCE_NOTICE, NULL);
-    if(value)
-    {
-        _announce_notice_ratio = gconf_value_get_int(value);
-        gconf_value_free(value);
-    }
-    else
-        _announce_notice_ratio = 6;
+    /* Auto-Center page. */
+    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+            table = gtk_table_new(2, 2, FALSE),
+            label = gtk_label_new(_("Auto-Center")));
 
-    /* Get Enable Voice flag.  Default is TRUE. */
-    value = gconf_client_get(gconf_client, GCONF_KEY_ENABLE_VOICE, NULL);
-    if(value)
-    {
-        _enable_voice = gconf_value_get_bool(value);
-        gconf_value_free(value);
-    }
-    else
-        _enable_voice = TRUE;
+    /* Auto-Center Sensitivity. */
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Sensitivity")),
+            0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+            1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_container_add(GTK_CONTAINER(label),
+            num_center_ratio = hildon_controlbar_new());
+    hildon_controlbar_set_range(HILDON_CONTROLBAR(num_center_ratio), 1, 10);
+    force_min_visible_bars(HILDON_CONTROLBAR(num_center_ratio), 1);
 
-    /* Get Voice Speed - Default is 1.0. */
-    value = gconf_client_get(gconf_client, GCONF_KEY_VOICE_SPEED, NULL);
-    if(value)
-    {
-        _voice_speed = gconf_value_get_float(value);
-        gconf_value_free(value);
-    }
-    else
-        _voice_speed = 1.0;
+    /* Lead Amount. */
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Lead Amount")),
+            0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+            1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_container_add(GTK_CONTAINER(label),
+            num_lead_ratio = hildon_controlbar_new());
+    hildon_controlbar_set_range(HILDON_CONTROLBAR(num_lead_ratio), 1, 10);
+    force_min_visible_bars(HILDON_CONTROLBAR(num_lead_ratio), 1);
 
-    /* Get Voice Speed - Default is 0. */
-    value = gconf_client_get(gconf_client, GCONF_KEY_VOICE_PITCH, NULL);
-    if(value)
-    {
-        _voice_pitch = gconf_value_get_int(value);
-        gconf_value_free(value);
-    }
-    else
-        _voice_pitch = 3;
+    /* Announcement. */
+    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+            table = gtk_table_new(2, 3, FALSE),
+            label = gtk_label_new(_("Announce")));
 
-    /* Get Always Keep On flag.  Default is FALSE. */
-    _always_keep_on = gconf_client_get_bool(gconf_client,
-            GCONF_KEY_ALWAYS_KEEP_ON, NULL);
+    /* Announcement Advance Notice. */
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Advance Notice")),
+            0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            num_announce_notice = hildon_controlbar_new(),
+            1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    hildon_controlbar_set_range(HILDON_CONTROLBAR(num_announce_notice), 1, 20);
+    force_min_visible_bars(HILDON_CONTROLBAR(num_announce_notice), 1);
 
-    /* Get Always Keep On flag.  Default is FALSE. */
-    _units = gconf_client_get_string(gconf_client,
-            GCONF_KEY_UNITS, NULL);
-    if(!_units)
-        _units = g_strdup(UNITS_KM);
+    /* Enable Voice. */
+    gtk_table_attach(GTK_TABLE(table),
+            chk_enable_voice = gtk_check_button_new_with_label(
+                _("Enable Voice Synthesis (requires flite)")),
+            0, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_enable_voice),
+            _enable_voice);
 
-    /* Get last saved latitude.  Default is 0. */
-    _pos_lat = gconf_client_get_float(gconf_client, GCONF_KEY_LAT, NULL);
+    /* Voice Speed and Pitch. */
+    gtk_table_attach(GTK_TABLE(table),
+            hbox = gtk_hbox_new(FALSE, 12),
+            0, 2, 2, 3, 0, 0, 2, 6);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            hbox2 = gtk_hbox_new(FALSE, 4),
+            TRUE, TRUE, 4);
+    gtk_box_pack_start(GTK_BOX(hbox2),
+            label = gtk_label_new(_("Speed")),
+            TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox2),
+            num_voice_speed = hildon_controlbar_new(),
+            TRUE, TRUE, 0);
+    hildon_controlbar_set_range(HILDON_CONTROLBAR(num_voice_speed), 1, 10);
+    force_min_visible_bars(HILDON_CONTROLBAR(num_voice_speed), 1);
 
-    /* Get last saved longitude.  Default is somewhere in Midwest. */
-    value = gconf_client_get(gconf_client, GCONF_KEY_LON, NULL);
-    _pos_lon = gconf_client_get_float(gconf_client, GCONF_KEY_LON, NULL);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            hbox2 = gtk_hbox_new(FALSE, 4),
+            TRUE, TRUE, 4);
+    gtk_box_pack_start(GTK_BOX(hbox2),
+            label = gtk_label_new(_("Pitch")),
+            TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox2),
+            num_voice_pitch = hildon_controlbar_new(),
+            TRUE, TRUE, 0);
+    hildon_controlbar_set_range(HILDON_CONTROLBAR(num_voice_pitch), -2, 8);
+    force_min_visible_bars(HILDON_CONTROLBAR(num_voice_pitch), 1);
 
-    /* Get last center point. */
-    {
-        gfloat center_lat, center_lon;
+    /* Misc. page. */
+    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+            table = gtk_table_new(2, 3, FALSE),
+            label = gtk_label_new(_("Misc.")));
 
-        /* Get last saved latitude.  Default is last saved latitude. */
-        value = gconf_client_get(gconf_client, GCONF_KEY_CENTER_LAT, NULL);
-        if(value)
-        {
-            center_lat = gconf_value_get_float(value);
-            gconf_value_free(value);
-        }
-        else
-            center_lat = _pos_lat;
+    /* Line Width. */
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Line Width")),
+            0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            num_draw_line_width = hildon_controlbar_new(),
+            1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    hildon_controlbar_set_range(HILDON_CONTROLBAR(num_draw_line_width), 1, 20);
+    force_min_visible_bars(HILDON_CONTROLBAR(num_draw_line_width), 1);
 
-        /* Get last saved longitude.  Default is last saved longitude. */
-        value = gconf_client_get(gconf_client, GCONF_KEY_CENTER_LON, NULL);
-        if(value)
-        {
-            center_lon = gconf_value_get_float(value);
-            gconf_value_free(value);
-        }
-        else
-            center_lon = _pos_lon;
+    /* Keep Display On Only When Fullscreen. */
+    gtk_table_attach(GTK_TABLE(table),
+            chk_always_keep_on = gtk_check_button_new_with_label(
+                _("Keep Display On Only in Fullscreen Mode")),
+            0, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
 
-        latlon2unit(center_lat, center_lon, _center.unitx, _center.unity);
-    }
+    /* Units. */
+    gtk_table_attach(GTK_TABLE(table),
+            hbox = gtk_hbox_new(FALSE, 4),
+            0, 2, 2, 3, GTK_FILL, 0, 2, 4);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            label = gtk_label_new(_("Units")),
+            FALSE, FALSE, 0);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+            TRUE, TRUE, 0);
+    gtk_container_add(GTK_CONTAINER(label),
+            cmb_units = gtk_combo_box_new_text());
+    gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_units), UNITS_KM_TEXT);
+    gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_units), UNITS_MI_TEXT);
+    gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_units), UNITS_NM_TEXT);
 
-    /* Get last Zoom Level.  Default is 16. */
-    value = gconf_client_get(gconf_client, GCONF_KEY_ZOOM, NULL);
-    if(value)
-    {
-        _zoom = gconf_value_get_int(value);
-        gconf_value_free(value);
-    }
-    else
-        _zoom = 16;
-    BOUND(_zoom, 0, MAX_ZOOM - 1);
-    _world_size_tiles = unit2tile(WORLD_SIZE_UNITS);
+    /* Escape Key. */
+    gtk_box_pack_start(GTK_BOX(hbox),
+            label = gtk_label_new(_("Escape Key")),
+            FALSE, FALSE, 0);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+            TRUE, TRUE, 0);
+    gtk_container_add(GTK_CONTAINER(label),
+            cmb_escape_key = gtk_combo_box_new_text());
+    gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_escape_key),
+            ESCAPE_KEY_TOGGLE_TRACKS_TEXT);
+    gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_escape_key),
+            ESCAPE_KEY_CHANGE_REPO_TEXT);
+    gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_escape_key),
+            ESCAPE_KEY_RESET_BLUETOOTH_TEXT);
+
+    /* POI page */
+    gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
+            table = gtk_table_new(2, 3, FALSE),
+            label = gtk_label_new(_("POI")));
 
-    /* Speed and Heading are always initialized as 0. */
-    _speed = 0.f;
-    _heading = 0.f;
+    /* POI database. */
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("POI database")),
+            0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            hbox = gtk_hbox_new(FALSE, 4),
+            1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            txt_poi_db = gtk_entry_new(),
+            TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            btn_browsepoi = gtk_button_new_with_label(_("Browse...")),
+            FALSE, FALSE, 0);
 
-    /* Get Route Directory.  Default is NULL. */
-    _route_dir_uri = gconf_client_get_string(gconf_client,
-            GCONF_KEY_ROUTEDIR, NULL);
+    /* Show POI below zoom. */
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Show POI below zoom")),
+            0, 1, 2, 3, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+            1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_container_add(GTK_CONTAINER(label),
+            num_poi_zoom = hildon_number_editor_new(0, MAX_ZOOM));
 
-    /* Get Last Track File.  Default is NULL. */
-    _track_file_uri = gconf_client_get_string(gconf_client,
-            GCONF_KEY_TRACKFILE, NULL);
 
-    /* Get Auto-Center Mode.  Default is CENTER_LEAD. */
-    value = gconf_client_get(gconf_client, GCONF_KEY_AUTOCENTER_MODE, NULL);
-    if(value)
-    {
-        _center_mode = gconf_value_get_int(value);
-        gconf_value_free(value);
-    }
-    else
-        _center_mode = CENTER_LEAD;
+    /* Connect signals. */
+    scan_info.settings_dialog = dialog;
+    scan_info.txt_rcvr_mac = txt_rcvr_mac;
+    g_signal_connect(G_OBJECT(btn_scan), "clicked",
+                      G_CALLBACK(scan_bluetooth), &scan_info);
+    g_signal_connect(G_OBJECT(btn_colors), "clicked",
+                      G_CALLBACK(settings_dialog_colors), dialog);
 
-    /* Get Show Tracks flag.  Default is TRUE. */
-    value = gconf_client_get(gconf_client, GCONF_KEY_SHOWTRACKS, NULL);
-    if(value)
-    {
-        _show_tracks |= (gconf_value_get_bool(value) ? TRACKS_MASK : 0);
-        gconf_value_free(value);
-    }
-    else
-        _show_tracks |= TRACKS_MASK;
+    browse_info.dialog = dialog;
+    browse_info.txt = txt_poi_db;
+    g_signal_connect(G_OBJECT(btn_browsepoi), "clicked",
+                      G_CALLBACK(settings_dialog_browse_forfile), &browse_info);
 
-    /* Get Show Routes flag.  Default is TRUE. */
-    value = gconf_client_get(gconf_client, GCONF_KEY_SHOWROUTES, NULL);
-    if(value)
-    {
-        _show_tracks |= (gconf_value_get_bool(value) ? ROUTES_MASK : 0);
-        gconf_value_free(value);
-    }
-    else
-        _show_tracks |= ROUTES_MASK;
+    /* Initialize fields. */
+    if(_rcvr_mac)
+        gtk_entry_set_text(GTK_ENTRY(txt_rcvr_mac), _rcvr_mac);
+    hildon_number_editor_set_value(HILDON_NUMBER_EDITOR(num_rcvr_chan),
+            _rcvr_addr.rc_channel);
+    if(_poi_db)
+        gtk_entry_set_text(GTK_ENTRY(txt_poi_db), _poi_db);
+    hildon_number_editor_set_value(HILDON_NUMBER_EDITOR(num_poi_zoom),
+            _poi_zoom);
+    hildon_controlbar_set_value(HILDON_CONTROLBAR(num_center_ratio),
+            _center_ratio);
+    hildon_controlbar_set_value(HILDON_CONTROLBAR(num_lead_ratio),
+            _lead_ratio);
+    hildon_controlbar_set_value(HILDON_CONTROLBAR(num_announce_notice),
+            _announce_notice_ratio);
+    hildon_controlbar_set_value(HILDON_CONTROLBAR(num_voice_speed),
+            (gint)(_voice_speed * 3 + 0.5));
+    hildon_controlbar_set_value(HILDON_CONTROLBAR(num_voice_pitch),
+            _voice_pitch);
+    hildon_controlbar_set_value(HILDON_CONTROLBAR(num_draw_line_width),
+            _draw_line_width);
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_always_keep_on),
+            !_always_keep_on);
+    gtk_combo_box_set_active(GTK_COMBO_BOX(cmb_units), _units);
+    gtk_combo_box_set_active(GTK_COMBO_BOX(cmb_escape_key), _escape_key);
 
-    /* Get Show Velocity Vector flag.  Default is TRUE. */
-    value = gconf_client_get(gconf_client, GCONF_KEY_SHOWVELVEC, NULL);
-    if(value)
-    {
-        _show_velvec = gconf_value_get_bool(value);
-        gconf_value_free(value);
-    }
-    else
-        _show_velvec = TRUE;
+    gtk_widget_show_all(dialog);
 
-    /* Get Enable GPS flag.  Default is TRUE. */
-    value = gconf_client_get(gconf_client, GCONF_KEY_ENABLE_GPS, NULL);
-    if(value)
+    while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
     {
-        _enable_gps = gconf_value_get_bool(value);
-        gconf_value_free(value);
-    }
-    else
-        _enable_gps = TRUE;
-
-    /* Initialize _conn_state based on _enable_gps. */
-    _conn_state = (_enable_gps ? RCVR_DOWN : RCVR_OFF);
+        /* Set _rcvr_mac if necessary. */
+        if(!*gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac)))
+        {
+            /* User specified no rcvr mac - set _rcvr_mac to NULL. */
+            if(_rcvr_mac)
+            {
+                g_free(_rcvr_mac);
+                _rcvr_mac = NULL;
+                rcvr_changed = TRUE;
+                gtk_widget_set_sensitive(
+                        GTK_WIDGET(_menu_gps_details_item), FALSE);
+            }
+            if(_enable_gps)
+            {
+                gtk_check_menu_item_set_active(
+                        GTK_CHECK_MENU_ITEM(_menu_enable_gps_item), FALSE);
+                popup_error(dialog, _("No GPS Receiver MAC Provided.\n"
+                        "GPS Disabled."));
+                rcvr_changed = TRUE;
+                gtk_widget_set_sensitive(GTK_WIDGET(_menu_gps_details_item),
+                        FALSE);
+                gtk_widget_set_sensitive(GTK_WIDGET(_menu_gps_reset_item),
+                        FALSE);
+            }
+        }
+        else if(!_rcvr_mac || strcmp(_rcvr_mac,
+                      gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac))))
+        {
+            /* User specified a new rcvr mac. */
+            if(_rcvr_mac)
+                g_free(_rcvr_mac);
+            _rcvr_mac = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac)));
+            str2ba(_rcvr_mac, &_rcvr_addr.rc_bdaddr);
+            rcvr_changed = TRUE;
+        }
 
-    /* Load the route locations. */
-    {
-        GSList *curr;
-        _loc_list = gconf_client_get_list(gconf_client,
-            GCONF_KEY_ROUTE_LOCATIONS, GCONF_VALUE_STRING, NULL);
-        _loc_model = gtk_list_store_new(1, G_TYPE_STRING);
-        for(curr = _loc_list; curr != NULL; curr = curr->next)
+        if(_rcvr_addr.rc_channel != hildon_number_editor_get_value(
+                    HILDON_NUMBER_EDITOR(num_rcvr_chan)))
         {
-            GtkTreeIter iter;
-            gtk_list_store_insert_with_values(_loc_model, &iter, INT_MAX,
-                    0, curr->data, -1);
+            _rcvr_addr.rc_channel = hildon_number_editor_get_value(
+                    HILDON_NUMBER_EDITOR(num_rcvr_chan));
+            rcvr_changed = TRUE;
         }
-    }
 
-    /* Initialize colors. */
-    str = gconf_client_get_string(gconf_client,
-            GCONF_KEY_COLOR_MARK, NULL);
-    if(!str || !gdk_color_parse(str, &_color_mark))
-        _color_mark = DEFAULT_COLOR_MARK;
+        _center_ratio = hildon_controlbar_get_value(
+                HILDON_CONTROLBAR(num_center_ratio));
 
-    str = gconf_client_get_string(gconf_client,
-            GCONF_KEY_COLOR_MARK_VELOCITY, NULL);
-    if(!str || !gdk_color_parse(str, &_color_mark_velocity))
-        _color_mark_velocity = DEFAULT_COLOR_MARK_VELOCITY;
+        _lead_ratio = hildon_controlbar_get_value(
+                HILDON_CONTROLBAR(num_lead_ratio));
 
-    str = gconf_client_get_string(gconf_client,
-            GCONF_KEY_COLOR_MARK_OLD, NULL);
-    if(!str || !gdk_color_parse(str, &_color_mark_old))
-        _color_mark_old = DEFAULT_COLOR_MARK_OLD;
+        _draw_line_width = hildon_controlbar_get_value(
+                HILDON_CONTROLBAR(num_draw_line_width));
 
-    str = gconf_client_get_string(gconf_client,
-            GCONF_KEY_COLOR_TRACK, NULL);
-    if(!str || !gdk_color_parse(str, &_color_track))
-        _color_track = DEFAULT_COLOR_TRACK;
+        _always_keep_on = !gtk_toggle_button_get_active(
+                GTK_TOGGLE_BUTTON(chk_always_keep_on));
 
-    str = gconf_client_get_string(gconf_client,
-            GCONF_KEY_COLOR_TRACK_BREAK, NULL);
-    if(!str || !gdk_color_parse(str, &_color_track_break))
-        _color_track_break = DEFAULT_COLOR_TRACK_BREAK;
+        _units = gtk_combo_box_get_active(GTK_COMBO_BOX(cmb_units));
+        _escape_key = gtk_combo_box_get_active(GTK_COMBO_BOX(cmb_escape_key));
 
-    str = gconf_client_get_string(gconf_client,
-            GCONF_KEY_COLOR_ROUTE, NULL);
-    if(!str || !gdk_color_parse(str, &_color_route))
-        _color_route = DEFAULT_COLOR_ROUTE;
+        _announce_notice_ratio = hildon_controlbar_get_value(
+                HILDON_CONTROLBAR(num_announce_notice));
 
-    str = gconf_client_get_string(gconf_client,
-            GCONF_KEY_COLOR_ROUTE_WAY, NULL);
-    if(!str || !gdk_color_parse(str, &_color_route_way))
-        _color_route_way = DEFAULT_COLOR_ROUTE_WAY;
+        _voice_speed = hildon_controlbar_get_value(
+                HILDON_CONTROLBAR(num_voice_speed)) / 3.0;
 
-    str = gconf_client_get_string(gconf_client,
-            GCONF_KEY_COLOR_ROUTE_NEXTWAY, NULL);
-    if(!str || !gdk_color_parse(str, &_color_route_nextway))
-        _color_route_nextway = DEFAULT_COLOR_ROUTE_NEXTWAY;
+        _voice_pitch = hildon_controlbar_get_value(
+                HILDON_CONTROLBAR(num_voice_pitch));
+
+        _enable_voice = gtk_toggle_button_get_active(
+                GTK_TOGGLE_BUTTON(chk_enable_voice));
 
+        if(_dbconn)
+        {
+            sqlite_close(_db);
+            _dbconn = FALSE;
+            gtk_widget_set_sensitive(_cmenu_add_poi, FALSE);
+            gtk_widget_set_sensitive(_cmenu_edit_poi, FALSE);
+            gtk_widget_set_sensitive(_menu_poi_item, FALSE);
+        }
+        if(_poi_db)
+            g_free(_poi_db);
+        if(strlen(gtk_entry_get_text(GTK_ENTRY(txt_poi_db))))
+        {
+            _poi_db = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_poi_db)));
+            db_connect();
+            gtk_widget_set_sensitive(_cmenu_add_poi, _dbconn);
+            gtk_widget_set_sensitive(_cmenu_edit_poi, _dbconn);
+            gtk_widget_set_sensitive(_menu_poi_item, _dbconn);
+        }
+        else
+            _poi_db = NULL;
 
-    g_object_unref(gconf_client);
+        _poi_zoom = hildon_number_editor_get_value(
+        HILDON_NUMBER_EDITOR(num_poi_zoom));
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+        update_gcs();
+
+        config_save();
+        break;
+    }
+
+    gtk_widget_hide(dialog); /* Destroying causes a crash (!?!?!??!) */
+
+    vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, rcvr_changed);
+    return rcvr_changed;
 }
 
 /**
- * Create the menu items needed for the drop down menu.
+ * Initialize all configuration from GCONF.  This should not be called more
+ * than once during execution.
  */
 static void
-menu_init()
+config_init()
 {
-    /* Create needed handles. */
-    GtkMenu *menu;
-    GtkWidget *submenu;
-    GtkWidget *menu_item;
+    GConfValue *value;
+    GConfClient *gconf_client = gconf_client_get_default();
+    gchar *str;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* Get the menu of our view. */
-    menu = GTK_MENU(gtk_menu_new());
-
-    /* Create the menu items. */
+    if(!gconf_client)
+    {
+        popup_error(_window, _("Failed to initialize GConf.  Quitting."));
+        exit(1);
+    }
 
-    /* The "Routes" submenu. */
-    gtk_menu_append(menu, menu_item
-            = gtk_menu_item_new_with_label(_("Route")));
-    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
-            submenu = gtk_menu_new());
-    gtk_menu_append(submenu, _menu_route_open_item
-            = gtk_menu_item_new_with_label(_("Open...")));
-    gtk_menu_append(submenu, _menu_route_download_item
-            = gtk_menu_item_new_with_label(_("Download...")));
-    gtk_menu_append(submenu, _menu_route_save_item
-            = gtk_menu_item_new_with_label(_("Save...")));
-    gtk_menu_append(submenu, _menu_route_reset_item
-        = gtk_menu_item_new_with_label(_("Reset")));
-    gtk_menu_append(submenu, _menu_route_clear_item
-        = gtk_menu_item_new_with_label(_("Clear")));
+    /* Get Receiver MAC from GConf.  Default is scanned via hci_inquiry. */
+    {
+        _rcvr_mac = gconf_client_get_string(
+                gconf_client, GCONF_KEY_RCVR_MAC, NULL);
+        if(_rcvr_mac)
+            str2ba(_rcvr_mac, &_rcvr_addr.rc_bdaddr);
+    }
 
-    /* The "Track" submenu. */
-    gtk_menu_append(menu, menu_item
-            = gtk_menu_item_new_with_label(_("Track")));
-    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
-            submenu = gtk_menu_new());
-    gtk_menu_append(submenu, _menu_track_open_item
-            = gtk_menu_item_new_with_label(_("Open...")));
-    gtk_menu_append(submenu, _menu_track_save_item
-            = gtk_menu_item_new_with_label(_("Save...")));
-    gtk_menu_append(submenu, _menu_track_mark_way_item
-            = gtk_menu_item_new_with_label(_("Insert Breakpoint")));
-    gtk_menu_append(submenu, _menu_track_clear_item
-            = gtk_menu_item_new_with_label(_("Clear")));
+    /* Get Receiver Channel from GConf.  Default is 1. */
+    _rcvr_addr.rc_family = AF_BLUETOOTH;
+    _rcvr_addr.rc_channel = gconf_client_get_int(gconf_client,
+            GCONF_KEY_RCVR_CHAN, NULL);
+    if(_rcvr_addr.rc_channel < 1)
+        _rcvr_addr.rc_channel = 1;
 
-    gtk_menu_append(menu, menu_item
-            = gtk_menu_item_new_with_label(_("Maps")));
-    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
-            submenu = gtk_menu_new());
-    gtk_menu_append(submenu, _menu_maps_dlroute_item
-            = gtk_menu_item_new_with_label(_("Download Along Route")));
-    gtk_menu_append(submenu, _menu_maps_dlarea_item
-            = gtk_menu_item_new_with_label(_("Download Area...")));
-    gtk_menu_append(submenu, _menu_auto_download_item
-            = gtk_check_menu_item_new_with_label(_("Auto-Download")));
-    gtk_check_menu_item_set_active(
-            GTK_CHECK_MENU_ITEM(_menu_auto_download_item), _auto_download);
+    /* Get Auto-Download.  Default is FALSE. */
+    _auto_download = gconf_client_get_bool(gconf_client,
+            GCONF_KEY_AUTO_DOWNLOAD, NULL);
 
-    gtk_menu_append(menu, gtk_separator_menu_item_new());
+    /* Get Center Ratio - Default is 3. */
+    _center_ratio = gconf_client_get_int(gconf_client,
+            GCONF_KEY_CENTER_SENSITIVITY, NULL);
+    if(!_center_ratio)
+        _center_ratio = 7;
 
-    gtk_menu_append(menu, menu_item
-            = gtk_menu_item_new_with_label(_("Show")));
-    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
-            submenu = gtk_menu_new());
-    gtk_menu_append(submenu, _menu_show_routes_item
-            = gtk_check_menu_item_new_with_label(_("Route")));
-    gtk_check_menu_item_set_active(
-            GTK_CHECK_MENU_ITEM(_menu_show_routes_item),
-            _show_tracks & ROUTES_MASK);
-    gtk_menu_append(submenu, _menu_show_tracks_item
-            = gtk_check_menu_item_new_with_label(_("Track")));
-    gtk_check_menu_item_set_active(
-            GTK_CHECK_MENU_ITEM(_menu_show_tracks_item),
-            _show_tracks & TRACKS_MASK);
-    gtk_menu_append(submenu, _menu_show_velvec_item
-            = gtk_check_menu_item_new_with_label(_("Velocity Vector")));
-    gtk_check_menu_item_set_active(
-            GTK_CHECK_MENU_ITEM(_menu_show_velvec_item), _show_velvec);
+    /* Get Lead Ratio - Default is 5. */
+    _lead_ratio = gconf_client_get_int(gconf_client,
+            GCONF_KEY_LEAD_AMOUNT, NULL);
+    if(!_lead_ratio)
+        _lead_ratio = 5;
 
-    gtk_menu_append(menu, menu_item
-            = gtk_menu_item_new_with_label(_("Auto-Center")));
-    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
-            submenu = gtk_menu_new());
-    gtk_menu_append(submenu, _menu_ac_latlon_item
-            = gtk_radio_menu_item_new_with_label(NULL, _("Lat/Lon")));
-    gtk_check_menu_item_set_active(
-            GTK_CHECK_MENU_ITEM(_menu_ac_latlon_item),
-            _center_mode == CENTER_LATLON);
-    gtk_menu_append(submenu, _menu_ac_lead_item
-            = gtk_radio_menu_item_new_with_label_from_widget(
-                GTK_RADIO_MENU_ITEM(_menu_ac_latlon_item), _("Lead")));
-    gtk_check_menu_item_set_active(
-            GTK_CHECK_MENU_ITEM(_menu_ac_lead_item),
-            _center_mode == CENTER_LEAD);
-    gtk_menu_append(submenu, _menu_ac_none_item
-            = gtk_radio_menu_item_new_with_label_from_widget(
-                GTK_RADIO_MENU_ITEM(_menu_ac_latlon_item), _("None")));
-    gtk_check_menu_item_set_active(
-            GTK_CHECK_MENU_ITEM(_menu_ac_none_item),
-            _center_mode < 0);
+    /* Get Draw Line Width- Default is 5. */
+    _draw_line_width = gconf_client_get_int(gconf_client,
+            GCONF_KEY_DRAW_LINE_WIDTH, NULL);
+    if(!_draw_line_width)
+        _draw_line_width = 5;
 
-    gtk_menu_append(menu, _menu_fullscreen_item
-            = gtk_check_menu_item_new_with_label(_("Full Screen")));
-    gtk_check_menu_item_set_active(
-            GTK_CHECK_MENU_ITEM(_menu_fullscreen_item), _fullscreen);
+    /* Get Announce Advance Notice - Default is 30. */
+    value = gconf_client_get(gconf_client, GCONF_KEY_ANNOUNCE_NOTICE, NULL);
+    if(value)
+    {
+        _announce_notice_ratio = gconf_value_get_int(value);
+        gconf_value_free(value);
+    }
+    else
+        _announce_notice_ratio = 8;
 
-    gtk_menu_append(menu, _menu_enable_gps_item
-            = gtk_check_menu_item_new_with_label(_("Enable GPS")));
-    gtk_check_menu_item_set_active(
-            GTK_CHECK_MENU_ITEM(_menu_enable_gps_item), _enable_gps);
+    /* Get Enable Voice flag.  Default is TRUE. */
+    value = gconf_client_get(gconf_client, GCONF_KEY_ENABLE_VOICE, NULL);
+    if(value)
+    {
+        _enable_voice = gconf_value_get_bool(value);
+        gconf_value_free(value);
+    }
+    else
+        _enable_voice = TRUE;
 
-    gtk_menu_append(menu, gtk_separator_menu_item_new());
+    /* Get Voice Speed - Default is 1.0. */
+    value = gconf_client_get(gconf_client, GCONF_KEY_VOICE_SPEED, NULL);
+    if(value)
+    {
+        _voice_speed = gconf_value_get_float(value);
+        gconf_value_free(value);
+    }
+    else
+        _voice_speed = 1.0;
 
-    gtk_menu_append(menu, _menu_settings_item
-        = gtk_menu_item_new_with_label(_("Settings...")));
+    /* Get Voice Speed - Default is 0. */
+    value = gconf_client_get(gconf_client, GCONF_KEY_VOICE_PITCH, NULL);
+    if(value)
+    {
+        _voice_pitch = gconf_value_get_int(value);
+        gconf_value_free(value);
+    }
+    else
+        _voice_pitch = 3;
 
-    gtk_menu_append(menu, gtk_separator_menu_item_new());
+    /* Get Always Keep On flag.  Default is FALSE. */
+    _always_keep_on = gconf_client_get_bool(gconf_client,
+            GCONF_KEY_ALWAYS_KEEP_ON, NULL);
 
-    gtk_menu_append(menu, _menu_help_item
-        = gtk_menu_item_new_with_label(_("Help")));
+    /* Get Units.  Default is UNITS_KM. */
+    {
+        gchar *units_str = gconf_client_get_string(gconf_client,
+                GCONF_KEY_UNITS, NULL);
+        if(units_str == NULL)
+            _units = UNITS_KM;
+        else if(!strcmp(units_str, UNITS_MI_TEXT))
+            _units = UNITS_MI;
+        else if(!strcmp(units_str, UNITS_NM_TEXT))
+            _units = UNITS_NM;
+        else
+            _units = UNITS_KM;
+    }
 
-    gtk_menu_append(menu, _menu_close_item
-        = gtk_menu_item_new_with_label(_("Close")));
+    /* Get Escape Key.  Default is ESCAPE_KEY_TOGGLE_TRACKS. */
+    {
+        gchar *escape_key_str = gconf_client_get_string(gconf_client,
+                GCONF_KEY_ESCAPE_KEY, NULL);
+        if(escape_key_str == NULL)
+            _escape_key = ESCAPE_KEY_TOGGLE_TRACKS;
+        else if(!strcmp(escape_key_str, ESCAPE_KEY_CHANGE_REPO_TEXT))
+            _escape_key = ESCAPE_KEY_CHANGE_REPO;
+        else if(!strcmp(escape_key_str, ESCAPE_KEY_RESET_BLUETOOTH_TEXT))
+            _escape_key = ESCAPE_KEY_RESET_BLUETOOTH;
+        else
+            _escape_key = ESCAPE_KEY_TOGGLE_TRACKS;
+    }
 
-    /* We need to show menu items. */
-    gtk_widget_show_all(GTK_WIDGET(menu));
+    /* Get last saved latitude.  Default is 0. */
+    _pos_lat = gconf_client_get_float(gconf_client, GCONF_KEY_LAT, NULL);
 
-    hildon_window_set_menu(HILDON_WINDOW(_window), menu);
+    /* Get last saved longitude.  Default is somewhere in Midwest. */
+    value = gconf_client_get(gconf_client, GCONF_KEY_LON, NULL);
+    _pos_lon = gconf_client_get_float(gconf_client, GCONF_KEY_LON, NULL);
 
-    /* Connect the signals. */
-    g_signal_connect(G_OBJECT(_menu_route_open_item), "activate",
-                      G_CALLBACK(menu_cb_route_open), NULL);
-    g_signal_connect(G_OBJECT(_menu_route_download_item), "activate",
-                      G_CALLBACK(menu_cb_route_download), NULL);
-    g_signal_connect(G_OBJECT(_menu_route_save_item), "activate",
-                      G_CALLBACK(menu_cb_route_save), NULL);
-    g_signal_connect(G_OBJECT(_menu_route_reset_item), "activate",
-                      G_CALLBACK(menu_cb_route_reset), NULL);
-    g_signal_connect(G_OBJECT(_menu_route_clear_item), "activate",
-                      G_CALLBACK(menu_cb_route_clear), NULL);
-    g_signal_connect(G_OBJECT(_menu_track_open_item), "activate",
-                      G_CALLBACK(menu_cb_track_open), NULL);
-    g_signal_connect(G_OBJECT(_menu_track_save_item), "activate",
-                      G_CALLBACK(menu_cb_track_save), NULL);
-    g_signal_connect(G_OBJECT(_menu_track_mark_way_item), "activate",
-                      G_CALLBACK(menu_cb_track_mark_way), NULL);
-    g_signal_connect(G_OBJECT(_menu_track_clear_item), "activate",
-                      G_CALLBACK(menu_cb_track_clear), NULL);
-    g_signal_connect(G_OBJECT(_menu_show_tracks_item), "toggled",
-                      G_CALLBACK(menu_cb_show_tracks), NULL);
-    g_signal_connect(G_OBJECT(_menu_show_routes_item), "toggled",
-                      G_CALLBACK(menu_cb_show_routes), NULL);
-    g_signal_connect(G_OBJECT(_menu_show_velvec_item), "toggled",
-                      G_CALLBACK(menu_cb_show_velvec), NULL);
-    g_signal_connect(G_OBJECT(_menu_maps_dlroute_item), "activate",
-                      G_CALLBACK(menu_cb_maps_dlroute), NULL);
-    g_signal_connect(G_OBJECT(_menu_maps_dlarea_item), "activate",
-                      G_CALLBACK(menu_cb_maps_dlarea), NULL);
-    g_signal_connect(G_OBJECT(_menu_ac_latlon_item), "toggled",
-                      G_CALLBACK(menu_cb_ac_latlon), NULL);
-    g_signal_connect(G_OBJECT(_menu_ac_lead_item), "toggled",
-                      G_CALLBACK(menu_cb_ac_lead), NULL);
-    g_signal_connect(G_OBJECT(_menu_ac_none_item), "toggled",
-                      G_CALLBACK(menu_cb_ac_none), NULL);
-    g_signal_connect(G_OBJECT(_menu_fullscreen_item), "toggled",
-                      G_CALLBACK(menu_cb_fullscreen), NULL);
-    g_signal_connect(G_OBJECT(_menu_enable_gps_item), "toggled",
-                      G_CALLBACK(menu_cb_enable_gps), NULL);
-    g_signal_connect(G_OBJECT(_menu_auto_download_item), "toggled",
-                      G_CALLBACK(menu_cb_auto_download), NULL);
-    g_signal_connect(G_OBJECT(_menu_settings_item), "activate",
-                      G_CALLBACK(menu_cb_settings), NULL);
-    g_signal_connect(G_OBJECT(_menu_help_item), "activate",
-                      G_CALLBACK(menu_cb_help), NULL);
-    g_signal_connect(G_OBJECT(_menu_close_item), "activate",
-                      G_CALLBACK(gtk_main_quit), NULL);
+    /* Get last center point. */
+    {
+        gfloat center_lat, center_lon;
 
-    /* Setup the context menu. */
-    menu = GTK_MENU(gtk_menu_new());
+        /* Get last saved latitude.  Default is last saved latitude. */
+        value = gconf_client_get(gconf_client, GCONF_KEY_CENTER_LAT, NULL);
+        if(value)
+        {
+            center_lat = gconf_value_get_float(value);
+            gconf_value_free(value);
+        }
+        else
+            center_lat = _pos_lat;
 
-    /* Setup the map context menu. */
-    gtk_menu_append(menu, menu_item
-            = gtk_menu_item_new_with_label(_("Location")));
-    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
-            submenu = gtk_menu_new());
+        /* Get last saved longitude.  Default is last saved longitude. */
+        value = gconf_client_get(gconf_client, GCONF_KEY_CENTER_LON, NULL);
+        if(value)
+        {
+            center_lon = gconf_value_get_float(value);
+            gconf_value_free(value);
+        }
+        else
+            center_lon = _pos_lon;
 
-    /* Setup the map context menu. */
-    gtk_menu_append(submenu, _cmenu_loc_show_latlon_item
-            = gtk_menu_item_new_with_label(_("Show Lat/Lon")));
-    gtk_menu_append(submenu, _cmenu_loc_clip_latlon_item
-            = gtk_menu_item_new_with_label(_("Copy Lat/Lon to Clipboard")));
-    gtk_menu_append(submenu, gtk_separator_menu_item_new());
-    gtk_menu_append(submenu, _cmenu_loc_route_to_item
-            = gtk_menu_item_new_with_label(_("Download Route to...")));
-    gtk_menu_append(submenu, _cmenu_loc_distance_to_item
-            = gtk_menu_item_new_with_label(_("Show Distance to")));
+        latlon2unit(center_lat, center_lon, _center.unitx, _center.unity);
+    }
 
+    /* Load the repositories. */
+    {
+        GSList *curr;
+        guint curr_repo_index = gconf_client_get_int(gconf_client,
+            GCONF_KEY_CURRREPO, NULL);
+        curr = gconf_client_get_list(gconf_client,
+            GCONF_KEY_REPOSITORIES, GCONF_VALUE_STRING, NULL);
+        
+        for(; curr != NULL; curr = curr->next)
+        {
+            /* Parse each part of a repo, delimited by newline characters:
+             * 1. url
+             * 2. cache_dir
+             * 3. dl_zoom_steps
+             * 4. view_zoom_steps
+             */
+            gchar *str = curr->data;
+            RepoData *rd = g_new(RepoData, 1);
+            rd->name = g_strdup(strsep(&str, "\n"));
+            rd->url = g_strdup(strsep(&str, "\n"));
+            rd->cache_dir = g_strdup(strsep(&str, "\n"));
+            rd->dl_zoom_steps = atoi(strsep(&str, "\n"));
+            if(rd->dl_zoom_steps == 0)
+                rd->dl_zoom_steps = 2;
+            rd->view_zoom_steps = atoi(strsep(&str, "\n"));
+            if(rd->view_zoom_steps == 0)
+                rd->view_zoom_steps = 1;
+
+            _repo_list = g_list_append(_repo_list, rd);
+            if(!curr_repo_index--)
+                _curr_repo = rd;
+            g_free(str);
+        }
+        g_slist_free(curr);
+    }
 
-    /* Setup the waypoint context menu. */
-    gtk_menu_append(menu, menu_item
-            = gtk_menu_item_new_with_label(_("Waypoint")));
-    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
-            submenu = gtk_menu_new());
+    if(_repo_list == NULL)
+    {
+        /* We have no repositories - create a default one. */
+        _curr_repo = g_new(RepoData, 1);
 
-    gtk_menu_append(submenu, _cmenu_way_show_latlon_item
-            = gtk_menu_item_new_with_label(_("Show Lat/Lon")));
-    gtk_menu_append(submenu, _cmenu_way_show_desc_item
-            = gtk_menu_item_new_with_label(_("Show Description")));
-    gtk_menu_append(submenu, _cmenu_way_clip_latlon_item
-            = gtk_menu_item_new_with_label(_("Copy Lat/Lon to Clipboard")));
-    gtk_menu_append(submenu, _cmenu_way_clip_desc_item
-            = gtk_menu_item_new_with_label(_("Copy Description to Clipboard")));
-    gtk_menu_append(submenu, gtk_separator_menu_item_new());
-    gtk_menu_append(submenu, _cmenu_way_route_to_item
-            = gtk_menu_item_new_with_label(_("Download Route to...")));
-    gtk_menu_append(submenu, _cmenu_way_distance_to_item
-            = gtk_menu_item_new_with_label(_("Show Distance to")));
-    gtk_menu_append(submenu, _cmenu_way_delete_item
-            = gtk_menu_item_new_with_label(_("Delete")));
+        /* Many fields can be retrieved from the "old" gconf keys. */
 
-    /* Connect signals for context menu. */
-    g_signal_connect(G_OBJECT(_cmenu_loc_show_latlon_item), "activate",
-                      G_CALLBACK(cmenu_cb_loc_show_latlon), NULL);
-    g_signal_connect(G_OBJECT(_cmenu_loc_clip_latlon_item), "activate",
-                      G_CALLBACK(cmenu_cb_loc_clip_latlon), NULL);
-    g_signal_connect(G_OBJECT(_cmenu_loc_route_to_item), "activate",
-                      G_CALLBACK(cmenu_cb_loc_route_to), NULL);
-    g_signal_connect(G_OBJECT(_cmenu_loc_distance_to_item), "activate",
-                      G_CALLBACK(cmenu_cb_loc_distance_to), NULL);
-    g_signal_connect(G_OBJECT(_cmenu_way_show_latlon_item), "activate",
-                      G_CALLBACK(cmenu_cb_way_show_latlon), NULL);
-    g_signal_connect(G_OBJECT(_cmenu_way_show_desc_item), "activate",
-                      G_CALLBACK(cmenu_cb_way_show_desc), NULL);
-    g_signal_connect(G_OBJECT(_cmenu_way_clip_latlon_item), "activate",
-                      G_CALLBACK(cmenu_cb_way_clip_latlon), NULL);
-    g_signal_connect(G_OBJECT(_cmenu_way_clip_desc_item), "activate",
-                      G_CALLBACK(cmenu_cb_way_clip_desc), NULL);
-    g_signal_connect(G_OBJECT(_cmenu_way_route_to_item), "activate",
-                      G_CALLBACK(cmenu_cb_way_route_to), NULL);
-    g_signal_connect(G_OBJECT(_cmenu_way_distance_to_item), "activate",
-                      G_CALLBACK(cmenu_cb_way_distance_to), NULL);
-    g_signal_connect(G_OBJECT(_cmenu_way_delete_item), "activate",
-                      G_CALLBACK(cmenu_cb_way_delete), NULL);
+        /* Get Map Cache Dir.  Default is ~/MyDocs/.documents/Maps. */
+        _curr_repo->cache_dir = gconf_client_get_string(gconf_client,
+                GCONF_KEY_MAP_DIR_NAME, NULL);
 
-    gtk_widget_show_all(GTK_WIDGET(menu));
+        if(!_curr_repo->cache_dir)
+            _curr_repo->cache_dir = gnome_vfs_expand_initial_tilde(
+                    "~/MyDocs/.documents/Maps");
 
-    gtk_widget_tap_and_hold_setup(_map_widget, GTK_WIDGET(menu), NULL, 0);
+        /* Get Map Download URI Format.  Default is "". */
+        _curr_repo->url = gconf_client_get_string(gconf_client,
+                GCONF_KEY_MAP_URI_FORMAT, NULL);
+        if(!_curr_repo->url)
+            _curr_repo->url = g_strdup("");
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
+        /* Get Map Download Zoom Steps.  Default is 2. */
+        _curr_repo->dl_zoom_steps = gconf_client_get_int(gconf_client,
+                GCONF_KEY_MAP_ZOOM_STEPS, NULL);
+        if(!_curr_repo->dl_zoom_steps)
+            _curr_repo->dl_zoom_steps = 2;
 
-/**
- * Call gtk_window_present() on Maemo Mapper.  This also checks the
- * configuration and brings up the Settings dialog if the GPS Receiver is
- * not set up, the first time it is called.
- */
-static gboolean
-window_present()
-{
-    static gint been_here = 0;
-    printf("%s()\n", __PRETTY_FUNCTION__);
+        /* Other fields are brand new. */
+        _curr_repo->name = g_strdup("Default");
+        _curr_repo->view_zoom_steps = 1;
+        _repo_list = g_list_append(_repo_list, _curr_repo);
+    }
 
-    if(!been_here++)
+    /* Get last Zoom Level.  Default is 16. */
+    value = gconf_client_get(gconf_client, GCONF_KEY_ZOOM, NULL);
+    if(value)
     {
-        /* Set connection state first, to avoid going into this if twice. */
-        if(_rcvr_mac || !_enable_gps || settings_dialog())
-        {
-            gtk_widget_show_all(_window);
-
-            /* Connect to receiver. */
-            if(_enable_gps)
-                rcvr_connect_now();
-        }
-        else
-            gtk_main_quit();
+        _zoom = gconf_value_get_int(value) / _curr_repo->view_zoom_steps
+            * _curr_repo->view_zoom_steps;
+        gconf_value_free(value);
     }
-    gtk_window_present(GTK_WINDOW(_window));
+    else
+        _zoom = 16 / _curr_repo->view_zoom_steps
+            * _curr_repo->view_zoom_steps;
+    BOUND(_zoom, 0, MAX_ZOOM - 1);
+    _world_size_tiles = unit2tile(WORLD_SIZE_UNITS);
 
-    /* Re-enable any banners that might have been up. */
+    /* Speed and Heading are always initialized as 0. */
+    _speed = 0.f;
+    _heading = 0.f;
+
+    /* Get Route Directory.  Default is NULL. */
+    _route_dir_uri = gconf_client_get_string(gconf_client,
+            GCONF_KEY_ROUTEDIR, NULL);
+
+    /* Get Last Track File.  Default is NULL. */
+    _track_file_uri = gconf_client_get_string(gconf_client,
+            GCONF_KEY_TRACKFILE, NULL);
+
+    /* Get Auto-Center Mode.  Default is CENTER_LEAD. */
+    value = gconf_client_get(gconf_client, GCONF_KEY_AUTOCENTER_MODE, NULL);
+    if(value)
     {
-        ConnState old_state = _conn_state;
-        set_conn_state(RCVR_OFF);
-        set_conn_state(old_state);
+        _center_mode = gconf_value_get_int(value);
+        gconf_value_free(value);
     }
+    else
+        _center_mode = CENTER_LEAD;
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-    return FALSE;
-}
+    /* Get Show Tracks flag.  Default is TRUE. */
+    value = gconf_client_get(gconf_client, GCONF_KEY_SHOWTRACKS, NULL);
+    if(value)
+    {
+        _show_tracks |= (gconf_value_get_bool(value) ? TRACKS_MASK : 0);
+        gconf_value_free(value);
+    }
+    else
+        _show_tracks |= TRACKS_MASK;
 
-/**
- * Get the hash value of a ProgressUpdateInfo object.  This is trivial, since
- * the hash is generated and stored when the object is created.
- */
-static guint
-download_hashfunc(ProgressUpdateInfo *pui)
-{
-    vprintf("%s()\n", __PRETTY_FUNCTION__);
+    /* Get Show Routes flag.  Default is TRUE. */
+    value = gconf_client_get(gconf_client, GCONF_KEY_SHOWROUTES, NULL);
+    if(value)
+    {
+        _show_tracks |= (gconf_value_get_bool(value) ? ROUTES_MASK : 0);
+        gconf_value_free(value);
+    }
+    else
+        _show_tracks |= ROUTES_MASK;
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-    return pui->hash;
-}
+    /* Get Show Velocity Vector flag.  Default is TRUE. */
+    value = gconf_client_get(gconf_client, GCONF_KEY_SHOWVELVEC, NULL);
+    if(value)
+    {
+        _show_velvec = gconf_value_get_bool(value);
+        gconf_value_free(value);
+    }
+    else
+        _show_velvec = TRUE;
 
-/**
- * Return whether or not two ProgressUpdateInfo objects are equal.  They
- * are equal if they are downloading the same tile.
- */
-static gboolean
-download_equalfunc(
-        ProgressUpdateInfo *pui1, ProgressUpdateInfo *pui2)
-{
-    vprintf("%s()\n", __PRETTY_FUNCTION__);
+    /* Get Enable GPS flag.  Default is TRUE. */
+    value = gconf_client_get(gconf_client, GCONF_KEY_ENABLE_GPS, NULL);
+    if(value)
+    {
+        _enable_gps = gconf_value_get_bool(value);
+        gconf_value_free(value);
+    }
+    else
+        _enable_gps = TRUE;
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-    return pui1->tilex == pui2->tilex && pui1->tiley == pui2->tiley
-        && pui1->zoom == pui2->zoom;
-}
+    /* Initialize _conn_state based on _enable_gps. */
+    _conn_state = (_enable_gps ? RCVR_DOWN : RCVR_OFF);
 
-/**
- * Draw the current mark (representing the current GPS location) onto
- * _map_widget.  This method does not queue the draw area.
- */
-static void
-map_draw_mark()
-{
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    /* Load the route locations. */
+    {
+        GSList *curr;
+        _loc_list = gconf_client_get_list(gconf_client,
+            GCONF_KEY_ROUTE_LOCATIONS, GCONF_VALUE_STRING, NULL);
+        _loc_model = gtk_list_store_new(1, G_TYPE_STRING);
+        for(curr = _loc_list; curr != NULL; curr = curr->next)
+        {
+            GtkTreeIter iter;
+            gtk_list_store_insert_with_values(_loc_model, &iter, INT_MAX,
+                    0, curr->data, -1);
+        }
+    }
 
-    if(_enable_gps)
+    /* Get POI Database.  Default is in ~/MyDocs/.documents/Maps */
+    _poi_db = gconf_client_get_string(gconf_client,
+            GCONF_KEY_POI_DB, NULL);
+    if(_poi_db == NULL)
+        _poi_db = gnome_vfs_make_uri_full_from_relative(
+                _curr_repo->cache_dir, "poi.db");
+    db_connect();
+
+    _poi_zoom = gconf_client_get_int(gconf_client,
+            GCONF_KEY_POI_ZOOM, NULL);
+    if(!_poi_zoom)
+    _poi_zoom = 6;
+
+
+    /* Get GPS Info flag.  Default is FALSE. */
+    value = gconf_client_get(gconf_client, GCONF_KEY_GPS_INFO, NULL);
+    if(value)
     {
-        gdk_draw_arc(
-                _map_widget->window,
-                _conn_state == RCVR_FIXED ? _gc_mark : _gc_mark_old,
-                FALSE, /* not filled. */
-                _mark_x1 - _draw_line_width, _mark_y1 - _draw_line_width,
-                2 * _draw_line_width, 2 * _draw_line_width,
-                0, 360 * 64);
-        gdk_draw_line(
-                _map_widget->window,
-                _conn_state == RCVR_FIXED
-                    ? (_show_velvec ? _gc_mark_velocity : _gc_mark)
-                    : _gc_mark_old,
-                _mark_x1, _mark_y1, _mark_x2, _mark_y2);
+        _gps_info = gconf_value_get_bool(value);
+        gconf_value_free(value);
     }
+    else
+        _gps_info = FALSE;
+
+    /* Initialize colors. */
+    str = gconf_client_get_string(gconf_client,
+            GCONF_KEY_COLOR_MARK, NULL);
+    if(!str || !gdk_color_parse(str, &_color_mark))
+        _color_mark = DEFAULT_COLOR_MARK;
+
+    str = gconf_client_get_string(gconf_client,
+            GCONF_KEY_COLOR_MARK_VELOCITY, NULL);
+    if(!str || !gdk_color_parse(str, &_color_mark_velocity))
+        _color_mark_velocity = DEFAULT_COLOR_MARK_VELOCITY;
+
+    str = gconf_client_get_string(gconf_client,
+            GCONF_KEY_COLOR_MARK_OLD, NULL);
+    if(!str || !gdk_color_parse(str, &_color_mark_old))
+        _color_mark_old = DEFAULT_COLOR_MARK_OLD;
+
+    str = gconf_client_get_string(gconf_client,
+            GCONF_KEY_COLOR_TRACK, NULL);
+    if(!str || !gdk_color_parse(str, &_color_track))
+        _color_track = DEFAULT_COLOR_TRACK;
+
+    str = gconf_client_get_string(gconf_client,
+            GCONF_KEY_COLOR_TRACK_BREAK, NULL);
+    if(!str || !gdk_color_parse(str, &_color_track_break))
+        _color_track_break = DEFAULT_COLOR_TRACK_BREAK;
+
+    str = gconf_client_get_string(gconf_client,
+            GCONF_KEY_COLOR_ROUTE, NULL);
+    if(!str || !gdk_color_parse(str, &_color_route))
+        _color_route = DEFAULT_COLOR_ROUTE;
+
+    str = gconf_client_get_string(gconf_client,
+            GCONF_KEY_COLOR_ROUTE_WAY, NULL);
+    if(!str || !gdk_color_parse(str, &_color_route_way))
+        _color_route_way = DEFAULT_COLOR_ROUTE_WAY;
+
+    str = gconf_client_get_string(gconf_client,
+            GCONF_KEY_COLOR_ROUTE_NEXTWAY, NULL);
+    if(!str || !gdk_color_parse(str, &_color_route_nextway))
+        _color_route_nextway = DEFAULT_COLOR_ROUTE_NEXTWAY;
+
+    str = gconf_client_get_string(gconf_client,
+            GCONF_KEY_COLOR_POI, NULL);
+    if(!str || !gdk_color_parse(str, &_color_poi))
+        _color_poi = DEFAULT_COLOR_POI;
+
+
+    g_object_unref(gconf_client);
+
+    /* GPS data init */
+    _gps.fix = 1;
+    _gps.satinuse = 0;
+    _gps.satinview = 0;
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
-/**
- * "Set" the mark, which translates the current GPS position into on-screen
- * units in preparation for drawing the mark with map_draw_mark().
- */
-static void map_set_mark()
+static void
+menu_maps_remove_repos()
 {
+    GList *curr;
     printf("%s()\n", __PRETTY_FUNCTION__);
-
-    _mark_x1 = unit2x(_pos.unitx);
-    _mark_y1 = unit2y(_pos.unity);
-    _mark_x2 = _mark_x1 + (_show_velvec ? _vel_offsetx : 0);
-    _mark_y2 = _mark_y1 + (_show_velvec ? _vel_offsety : 0);
-    _mark_minx = MIN(_mark_x1, _mark_x2) - (2 * _draw_line_width);
-    _mark_miny = MIN(_mark_y1, _mark_y2) - (2 * _draw_line_width);
-    _mark_width = abs(_mark_x1 - _mark_x2) + (4 * _draw_line_width);
-    _mark_height = abs(_mark_y1 - _mark_y2) + (4 * _draw_line_width);
-
+    
+    /* Delete one menu item for each repo. */
+    for(curr = _repo_list; curr; curr = curr->next)
+    {
+        gtk_widget_destroy(gtk_container_get_children(
+                    GTK_CONTAINER(_menu_maps_submenu))->data);
+    }
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
-/**
- * Do an in-place scaling of a pixbuf's pixels at the given ratio from the
- * given source location.  It would have been nice if gdk_pixbuf provided
- * this method, but I guess it's not general-purpose enough.
- */
 static void
-map_pixbuf_scale_inplace(guchar *pixels, guint ratio_p2,
-        guint src_x, guint src_y)
+menu_maps_add_repos()
 {
-    guint dest_x = 0, dest_y = 0, dest_dim = TILE_SIZE_PIXELS;
-    vprintf("%s(%d, %d, %d)\n", __PRETTY_FUNCTION__, ratio_p2, src_x, src_y);
+    GList *curr;
+    GtkWidget *last_repo = NULL;
+    printf("%s()\n", __PRETTY_FUNCTION__);
+    
+    for(curr = g_list_last(_repo_list); curr; curr = curr->prev)
+    {
+        RepoData *rd = (RepoData*)curr->data;
+        GtkWidget *menu_item;
+        if(last_repo)
+            gtk_menu_prepend(_menu_maps_submenu, menu_item
+                    = gtk_radio_menu_item_new_with_label_from_widget(
+                        GTK_RADIO_MENU_ITEM(last_repo), rd->name));
+        else
+        {
+            gtk_menu_prepend(_menu_maps_submenu, menu_item
+                    = gtk_radio_menu_item_new_with_label(NULL, rd->name));
+            last_repo = menu_item;
+        }
+        gtk_check_menu_item_set_active(
+                GTK_CHECK_MENU_ITEM(menu_item),
+                rd == _curr_repo);
+        rd->menu_item = menu_item;
+    }
 
-    /* Sweep through the entire dest area, copying as necessary, but
-     * DO NOT OVERWRITE THE SOURCE AREA.  We'll copy it afterward. */
-    do {
-        guint src_dim = dest_dim >> ratio_p2;
-        guint src_endx = src_x - dest_x + src_dim;
-        gint x, y;
-        for(y = dest_dim - 1; y >= 0; y--)
+    /* Add signals (must be after entire menu is built). */
+    {
+        GList *currmi = gtk_container_get_children(
+                GTK_CONTAINER(_menu_maps_submenu));
+        for(curr = _repo_list; curr; curr = curr->next, currmi = currmi->next)
         {
-            guint src_offset_y, dest_offset_y;
-            src_offset_y = (src_y + (y >> ratio_p2)) * TILE_PIXBUF_STRIDE;
-            dest_offset_y = (dest_y + y) * TILE_PIXBUF_STRIDE;
-            x = dest_dim - 1;
-            if((unsigned)(dest_y + y - src_y) < src_dim
-                    && (unsigned)(dest_x + x - src_x) < src_dim)
-                x -= src_dim;
-            for(; x >= 0; x--)
-            {
-                guint src_offset, dest_offset;
-                src_offset = src_offset_y + (src_x + (x >> ratio_p2)) * 3;
-                dest_offset = dest_offset_y + (dest_x + x) * 3;
-                pixels[dest_offset + 0] = pixels[src_offset + 0];
-                pixels[dest_offset + 1] = pixels[src_offset + 1];
-                pixels[dest_offset + 2] = pixels[src_offset + 2];
-                if((unsigned)(dest_y + y - src_y) < src_dim && x == src_endx)
-                    x -= src_dim;
-            }
+            g_signal_connect(G_OBJECT(currmi->data), "activate",
+                             G_CALLBACK(menu_cb_maps_select), curr->data);
         }
-        /* Reuse src_dim and src_endx to store new src_x and src_y. */
-        src_dim = src_x + ((src_x - dest_x) >> ratio_p2);
-        src_endx = src_y + ((src_y - dest_y) >> ratio_p2);
-        dest_x = src_x;
-        dest_y = src_y;
-        src_x = src_dim;
-        src_y = src_endx;
     }
-    while((dest_dim >>= ratio_p2) > 1);
 
+    gtk_widget_show_all(_menu_maps_submenu);
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
 /**
- * Free a ProgressUpdateInfo data structure that was allocated during the
- * auto-map-download process.
+ * Create the menu items needed for the drop down menu.
  */
 static void
-progress_update_info_free(ProgressUpdateInfo *pui)
+menu_init()
 {
-    vprintf("%s()\n", __PRETTY_FUNCTION__);
-
-    gnome_vfs_uri_unref((GnomeVFSURI*)pui->src_list->data);
-    g_list_free(pui->src_list);
-    gnome_vfs_uri_unref((GnomeVFSURI*)pui->dest_list->data);
-    g_list_free(pui->dest_list);
-    g_free(pui);
+    /* Create needed handles. */
+    GtkMenu *menu;
+    GtkWidget *submenu;
+    GtkWidget *menu_item;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
+    /* Get the menu of our view. */
+    menu = GTK_MENU(gtk_menu_new());
 
-/**
- * Given the xyz coordinates of our map coordinate system, write the qrst
- * quadtree coordinates to buffer.
- */
-static void
-map_convert_coords_to_quadtree_string(int x, int y, int zoomlevel,gchar *buffer)
-{
-    static const gchar *const quadrant = "qrts";
-    gchar *ptr = buffer;
-    int n;
-    *ptr++ = 't';
-    for (n = 16 - zoomlevel; n >= 0; n--)
-    {
-        int xbit = (x >> n) & 1;
-        int ybit = (y >> n) & 1;
-        *ptr++ = quadrant[xbit + 2 * ybit];
-    }
-    *ptr++ = '\0';
-}
+    /* Create the menu items. */
 
-/**
- * Construct the URL that we should fetch, based on the current URI format.
- * This method works differently depending on if a "%s" string is present in
- * the URI format, since that would indicate a quadtree-based map coordinate
- * system.
- */
-static void
-map_construct_url(gchar *buffer, guint tilex, guint tiley, guint zoom)
-{
-    if(strstr(_map_uri_format, "%s"))
-    {
-        /* This is a satellite-map URI. */
-        gchar location[MAX_ZOOM + 2];
-        map_convert_coords_to_quadtree_string(tilex, tiley, zoom, location);
-        sprintf(buffer, _map_uri_format, location);
-    }
-    else
-        /* This is a street-map URI. */
-        sprintf(buffer, _map_uri_format, tilex, tiley, zoom);
-}
+    /* The "Routes" submenu. */
+    gtk_menu_append(menu, menu_item
+            = gtk_menu_item_new_with_label(_("Route")));
+    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+            submenu = gtk_menu_new());
+    gtk_menu_append(submenu, _menu_route_open_item
+            = gtk_menu_item_new_with_label(_("Open...")));
+    gtk_menu_append(submenu, _menu_route_download_item
+            = gtk_menu_item_new_with_label(_("Download...")));
+    gtk_menu_append(submenu, _menu_route_save_item
+            = gtk_menu_item_new_with_label(_("Save...")));
+    gtk_menu_append(submenu, _menu_route_reset_item
+        = gtk_menu_item_new_with_label(_("Reset")));
+    gtk_menu_append(submenu, _menu_route_clear_item
+        = gtk_menu_item_new_with_label(_("Clear")));
 
+    /* The "Track" submenu. */
+    gtk_menu_append(menu, menu_item
+            = gtk_menu_item_new_with_label(_("Track")));
+    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+            submenu = gtk_menu_new());
+    gtk_menu_append(submenu, _menu_track_open_item
+            = gtk_menu_item_new_with_label(_("Open...")));
+    gtk_menu_append(submenu, _menu_track_save_item
+            = gtk_menu_item_new_with_label(_("Save...")));
+    gtk_menu_append(submenu, _menu_track_mark_way_item
+            = gtk_menu_item_new_with_label(_("Insert Breakpoint")));
+    gtk_menu_append(submenu, _menu_track_clear_item
+            = gtk_menu_item_new_with_label(_("Clear")));
 
-/**
- * Initiate a download of the given xyz coordinates using the given buffer
- * as the URL.  If the map already exists on disk, or if we are already
- * downloading the map, then this method does nothing.
- */
-static gboolean
-map_initiate_download(guint tilex, guint tiley, guint zoom, guint retries)
-{
-    gchar buffer[1024];
-    GnomeVFSURI *src, *dest;
-    GList *src_list, *dest_list;
-    gint priority;
-    ProgressUpdateInfo *pui;
-    vprintf("%s(%u, %u, %u, %u)\n", __PRETTY_FUNCTION__, tilex, tiley, zoom,
-            retries);
+    gtk_menu_append(menu, menu_item
+            = gtk_menu_item_new_with_label(_("Maps")));
+    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+            _menu_maps_submenu = gtk_menu_new());
+    gtk_menu_append(_menu_maps_submenu, gtk_separator_menu_item_new());
+    gtk_menu_append(_menu_maps_submenu, _menu_maps_mapman_item
+            = gtk_menu_item_new_with_label(_("Manage Maps...")));
+    gtk_menu_append(_menu_maps_submenu, _menu_maps_repoman_item
+            = gtk_menu_item_new_with_label(_("Manage Repositories...")));
+    gtk_menu_append(_menu_maps_submenu, _menu_auto_download_item
+            = gtk_check_menu_item_new_with_label(_("Auto-Download")));
+    gtk_check_menu_item_set_active(
+            GTK_CHECK_MENU_ITEM(_menu_auto_download_item), _auto_download);
+    menu_maps_add_repos(_curr_repo);
 
-    pui = g_new(ProgressUpdateInfo, 1);
-    pui->hash = tilex + (tiley << 12) + (zoom << 24);
-    if(g_hash_table_lookup(_downloads_hash, pui))
-    {
-        /* Already downloading - return FALSE. */
-        g_free(pui);
-        return FALSE;
-    }
-    sprintf(buffer, "%s/%u/%u/%u.jpg", _map_dir_name, zoom, tilex, tiley);
-    dest = gnome_vfs_uri_new(buffer);
-    if(gnome_vfs_uri_exists(dest))
-    {
-        /* Already downloaded - return FALSE. */
-        gnome_vfs_uri_unref(dest);
-        g_free(pui);
-        return FALSE;
-    }
+    gtk_menu_append(menu, gtk_separator_menu_item_new());
 
-    /* Priority is based on proximity to _center.unitx - lower number means
-     * higher priority, so the further we are, the higher the number. */
-    priority = GNOME_VFS_PRIORITY_MIN
-        + unit2ptile(abs(tile2punit(tilex, zoom) - _center.unitx)
-                + abs(tile2punit(tiley, zoom) - _center.unity));
-    BOUND(priority, GNOME_VFS_PRIORITY_MIN, GNOME_VFS_PRIORITY_MAX);
+    gtk_menu_append(menu, menu_item
+            = gtk_menu_item_new_with_label(_("View")));
+    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+            submenu = gtk_menu_new());
+    gtk_menu_append(submenu, _menu_fullscreen_item
+            = gtk_check_menu_item_new_with_label(_("Full Screen")));
+    gtk_check_menu_item_set_active(
+            GTK_CHECK_MENU_ITEM(_menu_fullscreen_item), _fullscreen);
+    gtk_menu_append(submenu, _menu_show_routes_item
+            = gtk_check_menu_item_new_with_label(_("Route")));
+    gtk_check_menu_item_set_active(
+            GTK_CHECK_MENU_ITEM(_menu_show_routes_item),
+            _show_tracks & ROUTES_MASK);
+    gtk_menu_append(submenu, _menu_show_tracks_item
+            = gtk_check_menu_item_new_with_label(_("Track")));
+    gtk_check_menu_item_set_active(
+            GTK_CHECK_MENU_ITEM(_menu_show_tracks_item),
+            _show_tracks & TRACKS_MASK);
+    gtk_menu_append(submenu, _menu_show_velvec_item
+            = gtk_check_menu_item_new_with_label(_("Velocity Vector")));
+    gtk_check_menu_item_set_active(
+            GTK_CHECK_MENU_ITEM(_menu_show_velvec_item), _show_velvec);
+    gtk_menu_append(submenu, _menu_poi_item
+            = gtk_menu_item_new_with_label(_("POI Categories...")));
+    gtk_widget_set_sensitive(_menu_poi_item, _dbconn);
 
-    map_construct_url(buffer, tilex, tiley, zoom);
-    src = gnome_vfs_uri_new(buffer);
 
-    src_list = g_list_prepend(src_list = NULL, src);
-    dest_list = g_list_prepend(dest_list = NULL, dest);
+    gtk_menu_append(menu, menu_item
+            = gtk_menu_item_new_with_label(_("Auto-Center")));
+    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+            submenu = gtk_menu_new());
+    gtk_menu_append(submenu, _menu_ac_latlon_item
+            = gtk_radio_menu_item_new_with_label(NULL, _("Lat/Lon")));
+    gtk_check_menu_item_set_active(
+            GTK_CHECK_MENU_ITEM(_menu_ac_latlon_item),
+            _center_mode == CENTER_LATLON);
+    gtk_menu_append(submenu, _menu_ac_lead_item
+            = gtk_radio_menu_item_new_with_label_from_widget(
+                GTK_RADIO_MENU_ITEM(_menu_ac_latlon_item), _("Lead")));
+    gtk_check_menu_item_set_active(
+            GTK_CHECK_MENU_ITEM(_menu_ac_lead_item),
+            _center_mode == CENTER_LEAD);
+    gtk_menu_append(submenu, _menu_ac_none_item
+            = gtk_radio_menu_item_new_with_label_from_widget(
+                GTK_RADIO_MENU_ITEM(_menu_ac_latlon_item), _("None")));
+    gtk_check_menu_item_set_active(
+            GTK_CHECK_MENU_ITEM(_menu_ac_none_item),
+            _center_mode < 0);
 
-    pui->tilex = tilex;
-    pui->tiley = tiley;
-    pui->zoom = zoom;
-    pui->src_list = src_list;
-    pui->dest_list = dest_list;
-    pui->retries_left = retries;
+    gtk_menu_append(menu, menu_item
+            = gtk_menu_item_new_with_label(_("GPS")));
+    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+            submenu = gtk_menu_new());
+    gtk_menu_append(submenu, _menu_enable_gps_item
+            = gtk_check_menu_item_new_with_label(_("Enable GPS")));
+    gtk_check_menu_item_set_active(
+            GTK_CHECK_MENU_ITEM(_menu_enable_gps_item), _enable_gps);
+    gtk_menu_append(submenu, _menu_gps_show_info_item
+            = gtk_check_menu_item_new_with_label(_("Show Information")));
+    gtk_check_menu_item_set_active(
+            GTK_CHECK_MENU_ITEM(_menu_gps_show_info_item), _gps_info);
+    gtk_menu_append(submenu, _menu_gps_details_item
+            = gtk_menu_item_new_with_label(_("Details...")));
+    gtk_widget_set_sensitive(GTK_WIDGET(_menu_gps_details_item), _enable_gps);
+    gtk_menu_append(submenu, _menu_gps_reset_item
+        = gtk_menu_item_new_with_label(_("Reset Bluetooth")));
+    gtk_widget_set_sensitive(GTK_WIDGET(_menu_gps_reset_item), _enable_gps);
 
-    /* Initiate asynchronous download. */
-    if(GNOME_VFS_OK != gnome_vfs_async_xfer(
-                &pui->handle,
-                src_list, dest_list,
-                GNOME_VFS_XFER_USE_UNIQUE_NAMES, /* needed for dupe detect. */
-                GNOME_VFS_XFER_ERROR_MODE_QUERY,
-                GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
-                priority,
-                (GnomeVFSAsyncXferProgressCallback)map_download_cb_async,
-                pui,
-                (GnomeVFSXferProgressCallback)gtk_true,
-                NULL))
-    {
-        progress_update_info_free(pui);
-        return FALSE;
-    }
+    gtk_menu_append(menu, gtk_separator_menu_item_new());
 
-    g_hash_table_insert(_downloads_hash, pui, pui);
-    if(!_num_downloads++ && !_download_banner)
-        _download_banner = hildon_banner_show_progress(
-                _window, NULL, _("Downloading maps"));
+    gtk_menu_append(menu, _menu_settings_item
+        = gtk_menu_item_new_with_label(_("Settings...")));
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-    return TRUE;
-}
+    gtk_menu_append(menu, gtk_separator_menu_item_new());
 
-static void
-map_render_tile(guint tilex, guint tiley, guint destx, guint desty,
-        gboolean fast_fail) {
-    gchar buffer[1024];
-    GdkPixbuf *pixbuf = NULL;
-    GError *error = NULL;
-    guint zoff;
+    gtk_menu_append(menu, _menu_help_item
+        = gtk_menu_item_new_with_label(_("Help")));
 
-    if(tilex < _world_size_tiles && tiley < _world_size_tiles)
-    {
-        /* The tile is possible. */
-        vprintf("%s(%u, %u, %u, %u)\n", __PRETTY_FUNCTION__,
-                tilex, tiley, destx, desty);
-        sprintf(buffer, "%s/%u/%u/%u.jpg",
-            _map_dir_name, _zoom, tilex, tiley);
-        pixbuf = gdk_pixbuf_new_from_file(buffer, &error);
+    gtk_menu_append(menu, _menu_close_item
+        = gtk_menu_item_new_with_label(_("Close")));
 
-        if(error)
-        {
-            pixbuf = NULL;
-            error = NULL;
-        }
+    /* We need to show menu items. */
+    gtk_widget_show_all(GTK_WIDGET(menu));
 
-        if(!pixbuf && !fast_fail && _auto_download && _map_uri_format
-                && !(_zoom % _zoom_steps))
-        {
-            map_initiate_download(tilex, tiley, _zoom,
-                    INITIAL_DOWNLOAD_RETRIES);
-            fast_fail = TRUE;
-        }
+    hildon_window_set_menu(HILDON_WINDOW(_window), menu);
 
-        for(zoff = 1; !pixbuf && (_zoom + zoff) <= MAX_ZOOM; zoff += 1)
-        {
-            /* Attempt to blit a wider map. */
-            sprintf(buffer, "%s/%u/%u/%u.jpg",
-                    _map_dir_name, _zoom + zoff,
-                    (tilex >> zoff), (tiley >> zoff));
-            pixbuf = gdk_pixbuf_new_from_file(buffer, &error);
-            if(error)
-            {
-                pixbuf = NULL;
-                error = NULL;
-            }
-            if(pixbuf)
-            {
-                map_pixbuf_scale_inplace(gdk_pixbuf_get_pixels(pixbuf), zoff,
-                  (tilex - ((tilex >> zoff) << zoff)) << (TILE_SIZE_P2 - zoff),
-                  (tiley - ((tiley >> zoff) << zoff)) << (TILE_SIZE_P2 - zoff));
-            }
-            else
-            {
-                if(_auto_download && _map_uri_format
-                        && !((_zoom + zoff) % _zoom_steps))
-                {
-                    if(!fast_fail)
-                        map_initiate_download(
-                                tilex >> zoff, tiley >> zoff, _zoom + zoff,
-                                INITIAL_DOWNLOAD_RETRIES);
-                    fast_fail = TRUE;
-                }
-            }
-        }
-    }
-    if(!pixbuf)
-        pixbuf = gdk_pixbuf_new(
-                GDK_COLORSPACE_RGB,
-                FALSE, /* no alpha. */
-                8, /* 8 bits per sample. */
-                TILE_SIZE_PIXELS, TILE_SIZE_PIXELS);
-    if(pixbuf)
-    {
-        gdk_draw_pixbuf(
-                _map_pixmap,
-                _gc_mark,
-                pixbuf,
-                0, 0,
-                destx, desty,
-                TILE_SIZE_PIXELS, TILE_SIZE_PIXELS,
-                GDK_RGB_DITHER_NONE, 0, 0);
-        g_object_unref(pixbuf);
-    }
+    /* Connect the signals. */
+    g_signal_connect(G_OBJECT(_menu_route_open_item), "activate",
+                      G_CALLBACK(menu_cb_route_open), NULL);
+    g_signal_connect(G_OBJECT(_menu_route_download_item), "activate",
+                      G_CALLBACK(menu_cb_route_download), NULL);
+    g_signal_connect(G_OBJECT(_menu_route_save_item), "activate",
+                      G_CALLBACK(menu_cb_route_save), NULL);
+    g_signal_connect(G_OBJECT(_menu_route_reset_item), "activate",
+                      G_CALLBACK(menu_cb_route_reset), NULL);
+    g_signal_connect(G_OBJECT(_menu_route_clear_item), "activate",
+                      G_CALLBACK(menu_cb_route_clear), NULL);
+    g_signal_connect(G_OBJECT(_menu_track_open_item), "activate",
+                      G_CALLBACK(menu_cb_track_open), NULL);
+    g_signal_connect(G_OBJECT(_menu_track_save_item), "activate",
+                      G_CALLBACK(menu_cb_track_save), NULL);
+    g_signal_connect(G_OBJECT(_menu_track_mark_way_item), "activate",
+                      G_CALLBACK(menu_cb_track_mark_way), NULL);
+    g_signal_connect(G_OBJECT(_menu_track_clear_item), "activate",
+                      G_CALLBACK(menu_cb_track_clear), NULL);
+    g_signal_connect(G_OBJECT(_menu_show_tracks_item), "toggled",
+                      G_CALLBACK(menu_cb_show_tracks), NULL);
+    g_signal_connect(G_OBJECT(_menu_show_routes_item), "toggled",
+                      G_CALLBACK(menu_cb_show_routes), NULL);
+    g_signal_connect(G_OBJECT(_menu_show_velvec_item), "toggled",
+                      G_CALLBACK(menu_cb_show_velvec), NULL);
+    g_signal_connect(G_OBJECT(_menu_poi_item), "activate",
+                      G_CALLBACK(menu_cb_category), NULL);
+
+    g_signal_connect(G_OBJECT(_menu_maps_repoman_item), "activate",
+                      G_CALLBACK(menu_cb_maps_repoman), NULL);
+    g_signal_connect(G_OBJECT(_menu_maps_mapman_item), "activate",
+                      G_CALLBACK(menu_cb_mapman), NULL);
+    g_signal_connect(G_OBJECT(_menu_ac_latlon_item), "toggled",
+                      G_CALLBACK(menu_cb_ac_latlon), NULL);
+    g_signal_connect(G_OBJECT(_menu_ac_lead_item), "toggled",
+                      G_CALLBACK(menu_cb_ac_lead), NULL);
+    g_signal_connect(G_OBJECT(_menu_ac_none_item), "toggled",
+                      G_CALLBACK(menu_cb_ac_none), NULL);
+    g_signal_connect(G_OBJECT(_menu_fullscreen_item), "toggled",
+                      G_CALLBACK(menu_cb_fullscreen), NULL);
+    g_signal_connect(G_OBJECT(_menu_enable_gps_item), "toggled",
+                      G_CALLBACK(menu_cb_enable_gps), NULL);
+    g_signal_connect(G_OBJECT(_menu_gps_show_info_item), "toggled",
+                      G_CALLBACK(menu_cb_gps_show_info), NULL);
+    g_signal_connect(G_OBJECT(_menu_gps_details_item), "activate",
+                      G_CALLBACK(menu_cb_gps_details), NULL);
+    g_signal_connect(G_OBJECT(_menu_gps_reset_item), "activate",
+                      G_CALLBACK(menu_cb_gps_reset), NULL);
+    g_signal_connect(G_OBJECT(_menu_auto_download_item), "toggled",
+                      G_CALLBACK(menu_cb_auto_download), NULL);
+    g_signal_connect(G_OBJECT(_menu_settings_item), "activate",
+                      G_CALLBACK(menu_cb_settings), NULL);
+    g_signal_connect(G_OBJECT(_menu_help_item), "activate",
+                      G_CALLBACK(menu_cb_help), NULL);
+    g_signal_connect(G_OBJECT(_menu_close_item), "activate",
+                      G_CALLBACK(gtk_main_quit), NULL);
+
+    /* Setup the context menu. */
+    menu = GTK_MENU(gtk_menu_new());
+
+    /* Setup the map context menu. */
+    gtk_menu_append(menu, menu_item
+            = gtk_menu_item_new_with_label(_("Location")));
+    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+            submenu = gtk_menu_new());
+
+    /* Setup the map context menu. */
+    gtk_menu_append(submenu, _cmenu_loc_show_latlon_item
+            = gtk_menu_item_new_with_label(_("Show Lat/Lon")));
+    gtk_menu_append(submenu, _cmenu_loc_clip_latlon_item
+            = gtk_menu_item_new_with_label(_("Copy Lat/Lon to Clipboard")));
+    gtk_menu_append(submenu, gtk_separator_menu_item_new());
+    gtk_menu_append(submenu, _cmenu_loc_route_to_item
+            = gtk_menu_item_new_with_label(_("Download Route to...")));
+    gtk_menu_append(submenu, _cmenu_loc_distance_to_item
+            = gtk_menu_item_new_with_label(_("Show Distance to")));
+    gtk_menu_append(submenu, gtk_separator_menu_item_new());
+    gtk_menu_append(submenu, _cmenu_add_poi
+                = gtk_menu_item_new_with_label(_("Add POI")));
+    gtk_widget_set_sensitive(_cmenu_add_poi, _dbconn);
+    gtk_menu_append(submenu, _cmenu_edit_poi
+                = gtk_menu_item_new_with_label(_("Edit POI")));
+    gtk_widget_set_sensitive(_cmenu_edit_poi, _dbconn);
+
+    /* Setup the waypoint context menu. */
+    gtk_menu_append(menu, menu_item
+            = gtk_menu_item_new_with_label(_("Waypoint")));
+    gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
+            submenu = gtk_menu_new());
+
+    gtk_menu_append(submenu, _cmenu_way_show_latlon_item
+            = gtk_menu_item_new_with_label(_("Show Lat/Lon")));
+    gtk_menu_append(submenu, _cmenu_way_show_desc_item
+            = gtk_menu_item_new_with_label(_("Show Description")));
+    gtk_menu_append(submenu, _cmenu_way_clip_latlon_item
+            = gtk_menu_item_new_with_label(_("Copy Lat/Lon to Clipboard")));
+    gtk_menu_append(submenu, _cmenu_way_clip_desc_item
+            = gtk_menu_item_new_with_label(_("Copy Description to Clipboard")));
+    gtk_menu_append(submenu, gtk_separator_menu_item_new());
+    gtk_menu_append(submenu, _cmenu_way_route_to_item
+            = gtk_menu_item_new_with_label(_("Download Route to...")));
+    gtk_menu_append(submenu, _cmenu_way_distance_to_item
+            = gtk_menu_item_new_with_label(_("Show Distance to")));
+    gtk_menu_append(submenu, _cmenu_way_delete_item
+            = gtk_menu_item_new_with_label(_("Delete")));
+
+    /* Connect signals for context menu. */
+    g_signal_connect(G_OBJECT(_cmenu_loc_show_latlon_item), "activate",
+                      G_CALLBACK(cmenu_cb_loc_show_latlon), NULL);
+    g_signal_connect(G_OBJECT(_cmenu_loc_clip_latlon_item), "activate",
+                      G_CALLBACK(cmenu_cb_loc_clip_latlon), NULL);
+    g_signal_connect(G_OBJECT(_cmenu_loc_route_to_item), "activate",
+                      G_CALLBACK(cmenu_cb_loc_route_to), NULL);
+    g_signal_connect(G_OBJECT(_cmenu_loc_distance_to_item), "activate",
+                      G_CALLBACK(cmenu_cb_loc_distance_to), NULL);
+    g_signal_connect(G_OBJECT(_cmenu_add_poi), "activate",
+                        G_CALLBACK(cmenu_cb_add_poi), NULL);
+    g_signal_connect(G_OBJECT(_cmenu_edit_poi), "activate",
+                        G_CALLBACK(cmenu_cb_edit_poi), NULL);
+    g_signal_connect(G_OBJECT(_cmenu_way_show_latlon_item), "activate",
+                      G_CALLBACK(cmenu_cb_way_show_latlon), NULL);
+    g_signal_connect(G_OBJECT(_cmenu_way_show_desc_item), "activate",
+                      G_CALLBACK(cmenu_cb_way_show_desc), NULL);
+    g_signal_connect(G_OBJECT(_cmenu_way_clip_latlon_item), "activate",
+                      G_CALLBACK(cmenu_cb_way_clip_latlon), NULL);
+    g_signal_connect(G_OBJECT(_cmenu_way_clip_desc_item), "activate",
+                      G_CALLBACK(cmenu_cb_way_clip_desc), NULL);
+    g_signal_connect(G_OBJECT(_cmenu_way_route_to_item), "activate",
+                      G_CALLBACK(cmenu_cb_way_route_to), NULL);
+    g_signal_connect(G_OBJECT(_cmenu_way_distance_to_item), "activate",
+                      G_CALLBACK(cmenu_cb_way_distance_to), NULL);
+    g_signal_connect(G_OBJECT(_cmenu_way_delete_item), "activate",
+                      G_CALLBACK(cmenu_cb_way_delete), NULL);
+
+    gtk_widget_show_all(GTK_WIDGET(menu));
+
+    gtk_widget_tap_and_hold_setup(_map_widget, GTK_WIDGET(menu), NULL, 0);
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
 /**
- * Force a redraw of the entire _map_pixmap, including fetching the
- * background maps from disk and redrawing the tracks on top of them.
+ * Call gtk_window_present() on Maemo Mapper.  This also checks the
+ * configuration and brings up the Settings dialog if the GPS Receiver is
+ * not set up, the first time it is called.
  */
-void
-map_force_redraw()
+static gboolean
+window_present()
 {
-    guint new_x, new_y;
+    static gint been_here = 0;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    for(new_y = 0; new_y < BUF_HEIGHT_TILES; ++new_y)
-        for(new_x = 0; new_x < BUF_WIDTH_TILES; ++new_x)
+    if(!been_here++)
+    {
+        /* Set connection state first, to avoid going into this if twice. */
+        if(_rcvr_mac || !_enable_gps || settings_dialog())
         {
-            map_render_tile(
-                    _base_tilex + new_x,
-                    _base_tiley + new_y,
-                    new_x * TILE_SIZE_PIXELS,
-                    new_y * TILE_SIZE_PIXELS,
-                    FALSE);
+            gtk_widget_show_all(_window);
+            gps_show_info();
+
+            /* Connect to receiver. */
+            if(_enable_gps)
+                rcvr_connect_now();
         }
-    map_render_paths();
-    MACRO_QUEUE_DRAW_AREA();
+        else
+            gtk_main_quit();
+    }
+    gtk_window_present(GTK_WINDOW(_window));
+
+    /* Re-enable any banners that might have been up. */
+    {
+        ConnState old_state = _conn_state;
+        set_conn_state(RCVR_OFF);
+        set_conn_state(old_state);
+    }
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return FALSE;
 }
 
 /**
- * Set the current zoom level.  If the given zoom level is the same as the
- * current zoom level, or if the new zoom is invalid
- * (not MIN_ZOOM <= new_zoom < MAX_ZOOM), then this method does nothing.
+ * Get the hash value of a ProgressUpdateInfo object.  This is trivial, since
+ * the hash is generated and stored when the object is created.
  */
-void
-map_set_zoom(guint new_zoom)
+static guint
+download_hashfunc(ProgressUpdateInfo *pui)
 {
-    printf("%s(%d)\n", __PRETTY_FUNCTION__, _zoom);
-
-    /* Note that, since new_zoom is a guint and MIN_ZOOM is 0, this if
-     * condition also checks for new_zoom >= MIN_ZOOM. */
-    if(new_zoom > (MAX_ZOOM - 1) || new_zoom == _zoom)
-        return;
-    _zoom = new_zoom;
-    _world_size_tiles = unit2tile(WORLD_SIZE_UNITS);
-
-    /* If we're leading, update the center to reflect new zoom level. */
-    MACRO_RECALC_CENTER(_center.unitx, _center.unity);
-
-    /* Update center bounds to reflect new zoom level. */
-    _min_center.unitx = pixel2unit(grid2pixel(_screen_grids_halfwidth));
-    _min_center.unity = pixel2unit(grid2pixel(_screen_grids_halfheight));
-    _max_center.unitx = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfwidth) - 1;
-    _max_center.unity = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfheight)- 1;
-
-    BOUND(_center.unitx, _min_center.unitx, _max_center.unitx);
-    BOUND(_center.unity, _min_center.unity, _max_center.unity);
+    vprintf("%s()\n", __PRETTY_FUNCTION__);
 
-    _base_tilex = grid2tile((gint)pixel2grid(
-                (gint)unit2pixel((gint)_center.unitx))
-            - (gint)_screen_grids_halfwidth);
-    _base_tiley = grid2tile(pixel2grid(
-                unit2pixel(_center.unity))
-            - _screen_grids_halfheight);
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return pui->hash;
+}
 
-    /* New zoom level, so we can't reuse the old buffer's pixels. */
+/**
+ * Return whether or not two ProgressUpdateInfo objects are equal.  They
+ * are equal if they are downloading the same tile.
+ */
+static gboolean
+download_equalfunc(
+        ProgressUpdateInfo *pui1, ProgressUpdateInfo *pui2)
+{
+    vprintf("%s()\n", __PRETTY_FUNCTION__);
 
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return pui1->tilex == pui2->tilex && pui1->tiley == pui2->tiley
+        && pui1->zoom == pui2->zoom;
+}
 
-    /* Update state variables. */
-    MACRO_RECALC_OFFSET();
-    MACRO_RECALC_FOCUS_BASE();
-    MACRO_RECALC_FOCUS_SIZE();
+/**
+ * Draw the current mark (representing the current GPS location) onto
+ * _map_widget.  This method does not queue the draw area.
+ */
+static void
+map_draw_mark()
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    map_set_mark();
-    map_force_redraw();
+    if(_enable_gps)
+    {
+        gdk_draw_arc(
+                _map_widget->window,
+                _conn_state == RCVR_FIXED ? _gc_mark : _gc_mark_old,
+                FALSE, /* not filled. */
+                _mark_x1 - _draw_line_width, _mark_y1 - _draw_line_width,
+                2 * _draw_line_width, 2 * _draw_line_width,
+                0, 360 * 64);
+        gdk_draw_line(
+                _map_widget->window,
+                _conn_state == RCVR_FIXED
+                    ? (_show_velvec ? _gc_mark_velocity : _gc_mark)
+                    : _gc_mark_old,
+                _mark_x1, _mark_y1, _mark_x2, _mark_y2);
+    }
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
 /**
- * Center the view on the given unitx/unity.
+ * "Set" the mark, which translates the current GPS position into on-screen
+ * units in preparation for drawing the mark with map_draw_mark().
  */
-static void
-map_center_unit(guint new_center_unitx, guint new_center_unity)
+static void map_set_mark()
 {
-    gint new_base_tilex, new_base_tiley;
-    guint new_x, new_y;
-    guint j, k, base_new_x, base_old_x, old_x, old_y, iox, ioy;
-    printf("%s(%d, %d)\n", __PRETTY_FUNCTION__,
-            new_center_unitx, new_center_unity);
-
-    /* Assure that _center.unitx/y are bounded. */
-    BOUND(new_center_unitx, _min_center.unitx, _max_center.unitx);
-    BOUND(new_center_unity, _min_center.unity, _max_center.unity);
-
-    _center.unitx = new_center_unitx;
-    _center.unity = new_center_unity;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    new_base_tilex = grid2tile((gint)pixel2grid(
-                (gint)unit2pixel((gint)_center.unitx))
-            - (gint)_screen_grids_halfwidth);
-    new_base_tiley = grid2tile(pixel2grid(
-                unit2pixel(_center.unity))
-            - _screen_grids_halfheight);
+    _mark_x1 = unit2x(_pos.unitx);
+    _mark_y1 = unit2y(_pos.unity);
+    _mark_x2 = _mark_x1 + (_show_velvec ? _vel_offsetx : 0);
+    _mark_y2 = _mark_y1 + (_show_velvec ? _vel_offsety : 0);
+    _mark_minx = MIN(_mark_x1, _mark_x2) - (2 * _draw_line_width);
+    _mark_miny = MIN(_mark_y1, _mark_y2) - (2 * _draw_line_width);
+    _mark_width = abs(_mark_x1 - _mark_x2) + (4 * _draw_line_width);
+    _mark_height = abs(_mark_y1 - _mark_y2) + (4 * _draw_line_width);
 
-    /* Same zoom level, so it's likely that we can reuse some of the old
-     * buffer's pixels. */
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
 
-    if(new_base_tilex != _base_tilex
-            || new_base_tiley != _base_tiley)
-    {
-        /* If copying from old parts to new parts, we need to make sure we
-         * don't overwrite the old parts when copying, so set up new_x,
-         * new_y, old_x, old_y, iox, and ioy with that in mind. */
-        if(new_base_tiley < _base_tiley)
-        {
-            /* New is lower than old - start at bottom and go up. */
-            new_y = BUF_HEIGHT_TILES - 1;
-            ioy = -1;
-        }
-        else
-        {
-            /* New is higher than old - start at top and go down. */
-            new_y = 0;
-            ioy = 1;
-        }
-        if(new_base_tilex < _base_tilex)
-        {
-            /* New is righter than old - start at right and go left. */
-            base_new_x = BUF_WIDTH_TILES - 1;
-            iox = -1;
-        }
-        else
-        {
-            /* New is lefter than old - start at left and go right. */
-            base_new_x = 0;
-            iox = 1;
-        }
+/**
+ * Do an in-place scaling of a pixbuf's pixels at the given ratio from the
+ * given source location.  It would have been nice if gdk_pixbuf provided
+ * this method, but I guess it's not general-purpose enough.
+ */
+static void
+map_pixbuf_scale_inplace(guchar *pixels, guint ratio_p2,
+        guint src_x, guint src_y)
+{
+    guint dest_x = 0, dest_y = 0, dest_dim = TILE_SIZE_PIXELS;
+    vprintf("%s(%d, %d, %d)\n", __PRETTY_FUNCTION__, ratio_p2, src_x, src_y);
 
-        /* Iterate over the y tile values. */
-        old_y = new_y + new_base_tiley - _base_tiley;
-        base_old_x = base_new_x + new_base_tilex - _base_tilex;
-        _base_tilex = new_base_tilex;
-        _base_tiley = new_base_tiley;
-        for(j = 0; j < BUF_HEIGHT_TILES; ++j, new_y += ioy, old_y += ioy)
+    /* Sweep through the entire dest area, copying as necessary, but
+     * DO NOT OVERWRITE THE SOURCE AREA.  We'll copy it afterward. */
+    do {
+        guint src_dim = dest_dim >> ratio_p2;
+        guint src_endx = src_x - dest_x + src_dim;
+        gint x, y;
+        for(y = dest_dim - 1; y >= 0; y--)
         {
-            new_x = base_new_x;
-            old_x = base_old_x;
-            /* Iterate over the x tile values. */
-            for(k = 0; k < BUF_WIDTH_TILES; ++k, new_x += iox, old_x += iox)
+            guint src_offset_y, dest_offset_y;
+            src_offset_y = (src_y + (y >> ratio_p2)) * TILE_PIXBUF_STRIDE;
+            dest_offset_y = (dest_y + y) * TILE_PIXBUF_STRIDE;
+            x = dest_dim - 1;
+            if((unsigned)(dest_y + y - src_y) < src_dim
+                    && (unsigned)(dest_x + x - src_x) < src_dim)
+                x -= src_dim;
+            for(; x >= 0; x--)
             {
-                /* Can we get this grid block from the old buffer?. */
-                if(old_x >= 0 && old_x < BUF_WIDTH_TILES
-                        && old_y >= 0 && old_y < BUF_HEIGHT_TILES)
-                {
-                    /* Copy from old buffer to new buffer. */
-                    gdk_draw_drawable(
-                            _map_pixmap,
-                            _gc_mark,
-                            _map_pixmap,
-                            old_x * TILE_SIZE_PIXELS,
-                            old_y * TILE_SIZE_PIXELS,
-                            new_x * TILE_SIZE_PIXELS,
-                            new_y * TILE_SIZE_PIXELS,
-                            TILE_SIZE_PIXELS, TILE_SIZE_PIXELS);
-                }
-                else
-                {
-                    map_render_tile(
-                            new_base_tilex + new_x,
-                            new_base_tiley + new_y,
-                            new_x * TILE_SIZE_PIXELS,
-                            new_y * TILE_SIZE_PIXELS,
-                            FALSE);
-                }
+                guint src_offset, dest_offset;
+                src_offset = src_offset_y + (src_x + (x >> ratio_p2)) * 3;
+                dest_offset = dest_offset_y + (dest_x + x) * 3;
+                pixels[dest_offset + 0] = pixels[src_offset + 0];
+                pixels[dest_offset + 1] = pixels[src_offset + 1];
+                pixels[dest_offset + 2] = pixels[src_offset + 2];
+                if((unsigned)(dest_y + y - src_y) < src_dim && x == src_endx)
+                    x -= src_dim;
             }
         }
-        map_render_paths();
+        /* Reuse src_dim and src_endx to store new src_x and src_y. */
+        src_dim = src_x + ((src_x - dest_x) >> ratio_p2);
+        src_endx = src_y + ((src_y - dest_y) >> ratio_p2);
+        dest_x = src_x;
+        dest_y = src_y;
+        src_x = src_dim;
+        src_y = src_endx;
     }
-
-    MACRO_RECALC_OFFSET();
-    MACRO_RECALC_FOCUS_BASE();
-
-    map_set_mark();
-    MACRO_QUEUE_DRAW_AREA();
+    while((dest_dim >>= ratio_p2) > 1);
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
 /**
- * Pan the view by the given number of units in the X and Y directions.
+ * Free a ProgressUpdateInfo data structure that was allocated during the
+ * auto-map-download process.
  */
-void
-map_pan(gint delta_unitx, gint delta_unity)
+static void
+progress_update_info_free(ProgressUpdateInfo *pui)
 {
-    printf("%s(%d, %d)\n", __PRETTY_FUNCTION__, delta_unitx, delta_unity);
+    vprintf("%s()\n", __PRETTY_FUNCTION__);
 
-    if(_center_mode > 0)
-        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
-                    _menu_ac_none_item), TRUE);
-    map_center_unit(
-            _center.unitx + delta_unitx,
-            _center.unity + delta_unity);
+    gnome_vfs_uri_unref((GnomeVFSURI*)pui->src_list->data);
+    g_list_free(pui->src_list);
+    gnome_vfs_uri_unref((GnomeVFSURI*)pui->dest_list->data);
+    g_list_free(pui->dest_list);
+    g_free(pui);
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
 /**
- * Initiate a move of the mark from the old location to the current
- * location.  This function queues the draw area of the old mark (to force
- * drawing of the background map), then updates the mark, then queus the
- * draw area of the new mark.
+ * Given the xyz coordinates of our map coordinate system, write the qrst
+ * quadtree coordinates to buffer.
  */
 static void
-map_move_mark()
+map_convert_coords_to_quadtree_string(int x, int y, int zoomlevel,gchar *buffer)
 {
-    printf("%s()\n", __PRETTY_FUNCTION__);
-
-    /* Just queue the old and new draw areas. */
-    gtk_widget_queue_draw_area(_map_widget,
-            _mark_minx,
-            _mark_miny,
-            _mark_width,
-            _mark_height);
-    map_set_mark();
-    gtk_widget_queue_draw_area(_map_widget,
-            _mark_minx,
-            _mark_miny,
-            _mark_width,
-            _mark_height);
-
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    static const gchar *const quadrant = "qrts";
+    gchar *ptr = buffer;
+    int n;
+    *ptr++ = 't';
+    for(n = 16 - zoomlevel; n >= 0; n--)
+    {
+        int xbit = (x >> n) & 1;
+        int ybit = (y >> n) & 1;
+        *ptr++ = quadrant[xbit + 2 * ybit];
+    }
+    *ptr++ = '\0';
 }
 
 /**
- * Make sure the mark is up-to-date.  This function triggers a panning of
- * the view if the mark is appropriately close to the edge of the view.
+ * Construct the URL that we should fetch, based on the current URI format.
+ * This method works differently depending on if a "%s" string is present in
+ * the URI format, since that would indicate a quadtree-based map coordinate
+ * system.
  */
 static void
-refresh_mark()
+map_construct_url(gchar *buffer, guint tilex, guint tiley, guint zoom)
 {
-    printf("%s()\n", __PRETTY_FUNCTION__);
-
-    guint new_center_unitx;
-    guint new_center_unity;
-
-    MACRO_RECALC_CENTER(new_center_unitx, new_center_unity);
-
-    if((new_center_unitx - _focus.unitx) < _focus_unitwidth
-            && (new_center_unity - _focus.unity) < _focus_unitheight)
-        /* We're not changing the view - just move the mark. */
-        map_move_mark();
+    if(strstr(_curr_repo->url, "%s"))
+    {
+        /* This is a satellite-map URI. */
+        gchar location[MAX_ZOOM + 2];
+        map_convert_coords_to_quadtree_string(tilex, tiley, zoom, location);
+        sprintf(buffer, _curr_repo->url, location);
+    }
     else
-        map_center_unit(new_center_unitx, new_center_unity);
-
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+        /* This is a street-map URI. */
+        sprintf(buffer, _curr_repo->url, tilex, tiley, zoom);
 }
 
+
 /**
- * Handle a start tag in the parsing of a GPX file.
+ * Initiate a download of the given xyz coordinates using the given buffer
+ * as the URL.  If the map already exists on disk, or if we are already
+ * downloading the map, then this method does nothing.
  */
-#define MACRO_SET_UNKNOWN() { \
-    data->prev_state = data->state; \
-    data->state = UNKNOWN; \
-    data->unknown_depth = 1; \
-}
-static void
-gpx_start_element(SaxData *data, const xmlChar *name, const xmlChar **attrs)
+static gboolean
+map_initiate_download(guint tilex, guint tiley, guint zoom, gint retries)
 {
-    vprintf("%s(%s)\n", __PRETTY_FUNCTION__, name);
+    gchar buffer[1024];
+    GnomeVFSURI *src, *dest;
+    GList *src_list, *dest_list;
+    gint priority;
+    ProgressUpdateInfo *pui;
+    vprintf("%s(%u, %u, %u, %d)\n", __PRETTY_FUNCTION__, tilex, tiley, zoom,
+            retries);
 
-    switch(data->state)
+    pui = g_new(ProgressUpdateInfo, 1);
+    pui->hash = tilex + (tiley << 12) + (zoom << 24);
+    pui->tilex = tilex;
+    pui->tiley = tiley;
+    pui->zoom = zoom;
+    if(g_hash_table_lookup(_downloads_hash, pui))
     {
-        case ERROR:
-            break;
-        case START:
-            if(!strcmp((gchar*)name, "gpx"))
-                data->state = INSIDE_GPX;
-            else
-                MACRO_SET_UNKNOWN();
-            break;
-        case INSIDE_GPX:
-            if(!strcmp((gchar*)name, "trk"))
-                data->state = INSIDE_PATH;
-            else
-                MACRO_SET_UNKNOWN();
-            break;
-        case INSIDE_PATH:
-            if(!strcmp((gchar*)name, "trkseg"))
-            {
-                data->state = INSIDE_PATH_SEGMENT;
-                data->at_least_one_trkpt = FALSE;
-            }
-            else
-                MACRO_SET_UNKNOWN();
-            break;
-        case INSIDE_PATH_SEGMENT:
-            if(!strcmp((gchar*)name, "trkpt"))
+        /* Already downloading - return FALSE. */
+        g_free(pui);
+        return FALSE;
+    }
+    sprintf(buffer, "%s/%u/%u/%u.jpg", _curr_repo->cache_dir,
+            zoom, tilex, tiley);
+    dest = gnome_vfs_uri_new(buffer);
+    if(retries > 0 && gnome_vfs_uri_exists(dest))
+    {
+        /* Already downloaded and not overwriting - return FALSE. */
+        gnome_vfs_uri_unref(dest);
+        g_free(pui);
+        return FALSE;
+    }
+
+    /* Priority is based on proximity to _center.unitx - lower number means
+     * higher priority, so the further we are, the higher the number. */
+    priority = GNOME_VFS_PRIORITY_MIN
+        + unit2ptile(abs(tile2punit(tilex, zoom) - _center.unitx)
+                + abs(tile2punit(tiley, zoom) - _center.unity));
+    BOUND(priority, GNOME_VFS_PRIORITY_MIN, GNOME_VFS_PRIORITY_MAX);
+
+    map_construct_url(buffer, tilex, tiley, zoom);
+    src = gnome_vfs_uri_new(buffer);
+
+    src_list = g_list_prepend(src_list = NULL, src);
+    dest_list = g_list_prepend(dest_list = NULL, dest);
+
+    pui->src_list = src_list;
+    pui->dest_list = dest_list;
+    pui->retries_left = retries;
+
+    /* Initiate asynchronous download. */
+    if(retries)
+    {
+        /* This is a download; if retries < 0, then this is an overwrite */
+        if(GNOME_VFS_OK != gnome_vfs_async_xfer(
+                    &pui->handle,
+                    src_list, dest_list,
+                    retries < 0 ? GNOME_VFS_XFER_DEFAULT
+                                : GNOME_VFS_XFER_USE_UNIQUE_NAMES,
+                    GNOME_VFS_XFER_ERROR_MODE_QUERY,
+                    retries < 0 ? GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE
+                                : GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
+                    priority,
+                    (GnomeVFSAsyncXferProgressCallback)map_download_cb_async,
+                    pui,
+                    (GnomeVFSXferProgressCallback)gtk_true,
+                    NULL))
+        {
+            progress_update_info_free(pui);
+            return FALSE;
+        }
+    }
+    else
+    {
+        /* This is a deletion. */
+        if(GNOME_VFS_OK != gnome_vfs_async_xfer(
+                    &pui->handle,
+                    dest_list, NULL,
+                    GNOME_VFS_XFER_DELETE_ITEMS,
+                    GNOME_VFS_XFER_ERROR_MODE_QUERY,
+                    GNOME_VFS_XFER_OVERWRITE_MODE_QUERY,
+                    priority,
+                    (GnomeVFSAsyncXferProgressCallback)map_download_cb_async,
+                    pui,
+                    (GnomeVFSXferProgressCallback)gtk_true,
+                    NULL))
+        {
+            progress_update_info_free(pui);
+            return FALSE;
+        }
+    }
+
+    g_hash_table_insert(_downloads_hash, pui, pui);
+    if(!_num_downloads++ && !_download_banner)
+        _download_banner = hildon_banner_show_progress(
+                _window, NULL, _("Downloading maps"));
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
+
+static void
+map_render_poi()
+{
+    guint unitx, unity;
+    gfloat lat1, lat2, lon1, lon2, tmp;
+    gchar slat1[10], slat2[10], slon1[10], slon2[10];
+    gchar buffer[100], *sql;
+    gchar **pszResult;
+    gint nRow, nColumn, row, poix, poiy;
+    GdkPixbuf *pixbuf = NULL;
+    GError *error = NULL;
+
+    if(_db && _poi_zoom > _zoom)
+    {
+        unitx = x2unit(1);
+        unity = y2unit(1);
+        unit2latlon(unitx, unity, lat1, lon1);
+        unitx = x2unit(BUF_WIDTH_PIXELS);
+        unity = y2unit(BUF_HEIGHT_PIXELS);
+        unit2latlon(unitx, unity, lat2, lon2);
+        if(lat1 > lat2)
+        {
+            tmp = lat2;
+            lat2 = lat1;
+            lat1 = tmp;
+        }
+        if(lon1 > lon2)
+        {
+            tmp = lon2;
+            lon2 = lon1;
+            lon1 = tmp;
+        }
+
+        g_ascii_dtostr(slat1, sizeof(slat1), lat1);
+        g_ascii_dtostr(slat2, sizeof(slat2), lat2);
+        g_ascii_dtostr(slon1, sizeof(slon1), lon1);
+        g_ascii_dtostr(slon2, sizeof(slon2), lon2);
+
+        sql = g_strdup_printf(
+                "select p.lat, p.lon, lower(p.label), lower(c.label)"
+                " from poi p, category c "
+                " where p.lat between %s and %s "
+                " and p.lon  between %s and %s "
+                " and c.enabled = 1 and p.cat_id = c.cat_id",
+                slat1, slat2, slon1, slon2);
+
+        if(sqlite_get_table(_db, sql, &pszResult, &nRow, &nColumn, NULL)
+            == SQLITE_OK)
+        {
+            for(row=1; row<nRow+1; row++)
             {
-                const xmlChar **curr_attr;
-                gchar *error_check;
-                gfloat lat = 0.f, lon = 0.f;
-                gboolean has_lat, has_lon;
-                has_lat = FALSE;
-                has_lon = FALSE;
-                for(curr_attr = attrs; *curr_attr != NULL; )
+                lat1 = g_ascii_strtod(pszResult[row*nColumn+0], NULL);
+                lon1 = g_ascii_strtod(pszResult[row*nColumn+1], NULL);
+                latlon2unit(lat1, lon1, unitx, unity);
+                poix = unit2bufx(unitx);
+                poiy = unit2bufy(unity);
+
+                /* Try to get icon for specific POI first. */
+                sprintf(buffer, "%s/poi/%s.jpg", _curr_repo->cache_dir,
+                    pszResult[row*nColumn+2]);
+                pixbuf = gdk_pixbuf_new_from_file(buffer, &error);
+                if(error)
                 {
-                    const gchar *attr_name = *curr_attr++;
-                    const gchar *attr_val = *curr_attr++;
-                    if(!strcmp(attr_name, "lat"))
-                    {
-                        lat = g_ascii_strtod(attr_val, &error_check);
-                        if(error_check != attr_val)
-                            has_lat = TRUE;
-                    }
-                    else if(!strcmp(attr_name, "lon"))
-                    {
-                        lon = g_ascii_strtod(attr_val, &error_check);
-                        if(error_check != attr_val)
-                            has_lon = TRUE;
-                    }
+                    /* No icon for specific POI - try for category. */
+                    error = NULL;
+                    sprintf(buffer, "%s/poi/%s.jpg", _curr_repo->cache_dir,
+                        pszResult[row*nColumn+3]);
+                    pixbuf = gdk_pixbuf_new_from_file(buffer, &error);
                 }
-                if(has_lat && has_lon)
+                if(error)
                 {
-                    if(data->path.path_type == TRACK)
-                    {
-                        MACRO_TRACK_INCREMENT_TAIL(data->path.path.track);
-                        latlon2unit(lat, lon,
-                                data->path.path.track.tail->point.unitx,
-                                data->path.path.track.tail->point.unity);
-                        data->path.path.track.tail->time = 0;
-                    }
-                    else
-                    {
-                        MACRO_ROUTE_INCREMENT_TAIL(data->path.path.route);
-                        latlon2unit(lat, lon,
-                                data->path.path.route.tail->unitx,
-                                data->path.path.route.tail->unity);
-                    }
-                    data->state = INSIDE_PATH_POINT;
+                    /* No icon for POI or for category - draw default. */
+                    error = NULL;
+                    gdk_draw_rectangle(_map_pixmap, _gc_poi, TRUE,
+                        poix - (int)(0.5f * _draw_line_width),
+                        poiy - (int)(0.5f * _draw_line_width),
+                        3 * _draw_line_width,
+                        3 * _draw_line_width);
                 }
                 else
-                    data->state = ERROR;
-            }
-            else
-                MACRO_SET_UNKNOWN();
-            break;
-        case INSIDE_PATH_POINT:
-            /* only parse time for tracks */
-            if(data->path.path_type == TRACK
-                    && !strcmp((gchar*)name, "time"))
-                data->state = INSIDE_PATH_POINT_TIME;
-
-            /* only parse description for routes */
-            else if(data->path.path_type == ROUTE
-                    && !strcmp((gchar*)name, "desc"))
-                data->state = INSIDE_PATH_POINT_DESC;
-
-            else
-                MACRO_SET_UNKNOWN();
-            break;
-        case UNKNOWN:
-            data->unknown_depth++;
-            break;
-        default:
-            ;
+                {
+                    gdk_draw_pixbuf(
+                            _map_pixmap,
+                            _gc_poi,
+                            pixbuf,
+                            0, 0,
+                            poix - gdk_pixbuf_get_width(pixbuf) / 2,
+                            poix - gdk_pixbuf_get_height(pixbuf) / 2,
+                            -1,-1,
+                            GDK_RGB_DITHER_NONE, 0, 0);
+                    g_object_unref(pixbuf);
+                }
+             }
+            sqlite_free_table(pszResult);
+        }
+        g_free(sql);
     }
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
-/**
- * Handle an end tag in the parsing of a GPX file.
- */
 static void
-gpx_end_element(SaxData *data, const xmlChar *name)
-{
-    vprintf("%s(%s)\n", __PRETTY_FUNCTION__, name);
+map_render_tile(guint tilex, guint tiley, guint destx, guint desty,
+        gboolean fast_fail) {
+    gchar buffer[1024];
+    GdkPixbuf *pixbuf = NULL;
+    GError *error = NULL;
+    guint zoff;
 
-    switch(data->state)
+    if(tilex < _world_size_tiles && tiley < _world_size_tiles)
     {
-        case ERROR:
-            break;
-        case START:
-            data->state = ERROR;
-            break;
-        case INSIDE_GPX:
-            if(!strcmp((gchar*)name, "gpx"))
-                data->state = FINISH;
-            else
-                data->state = ERROR;
-            break;
-        case INSIDE_PATH:
-            if(!strcmp((gchar*)name, "trk"))
-                data->state = INSIDE_GPX;
-            else
-                data->state = ERROR;
-            break;
-        case INSIDE_PATH_SEGMENT:
-            if(!strcmp((gchar*)name, "trkseg"))
+        /* The tile is possible. */
+        vprintf("%s(%u, %u, %u, %u)\n", __PRETTY_FUNCTION__,
+                tilex, tiley, destx, desty);
+        sprintf(buffer, "%s/%u/%u/%u.jpg",
+            _curr_repo->cache_dir, _zoom, tilex, tiley);
+        pixbuf = gdk_pixbuf_new_from_file(buffer, &error);
+
+        if(error)
+        {
+            pixbuf = NULL;
+            error = NULL;
+        }
+
+        if(!pixbuf && !fast_fail && _auto_download && *_curr_repo->url
+                && !(_zoom % _curr_repo->dl_zoom_steps))
+        {
+            map_initiate_download(tilex, tiley, _zoom,
+                    INITIAL_DOWNLOAD_RETRIES);
+            fast_fail = TRUE;
+        }
+
+        for(zoff = 1; !pixbuf && (_zoom + zoff) <= MAX_ZOOM
+                && zoff <= TILE_SIZE_P2; zoff += 1)
+        {
+            /* Attempt to blit a wider map. */
+            sprintf(buffer, "%s/%u/%u/%u.jpg",
+                    _curr_repo->cache_dir, _zoom + zoff,
+                    (tilex >> zoff), (tiley >> zoff));
+            pixbuf = gdk_pixbuf_new_from_file(buffer, &error);
+            if(error)
             {
-                if(data->at_least_one_trkpt)
-                {
-                    if(data->path.path_type == TRACK)
-                    {
-                        MACRO_TRACK_INCREMENT_TAIL(data->path.path.track);
-                        *data->path.path.track.tail = _track_null;
-                    }
-                    else
-                    {
-                        MACRO_ROUTE_INCREMENT_TAIL(data->path.path.route);
-                        *data->path.path.route.tail = _pos_null;
-                    }
-                }
-                data->state = INSIDE_PATH;
+                pixbuf = NULL;
+                error = NULL;
             }
-            else
-                data->state = ERROR;
-            break;
-        case INSIDE_PATH_POINT:
-            if(!strcmp((gchar*)name, "trkpt"))
+            if(pixbuf)
             {
-                data->state = INSIDE_PATH_SEGMENT;
-                data->at_least_one_trkpt = TRUE;
+                map_pixbuf_scale_inplace(gdk_pixbuf_get_pixels(pixbuf), zoff,
+                  (tilex - ((tilex >> zoff) << zoff)) << (TILE_SIZE_P2 - zoff),
+                  (tiley - ((tiley >> zoff) << zoff)) << (TILE_SIZE_P2 - zoff));
             }
             else
-                data->state = ERROR;
-            break;
-        case INSIDE_PATH_POINT_TIME:
-            /* only parse time for tracks */
-            if(!strcmp((gchar*)name, "time"))
             {
-                struct tm time;
-                gchar *ptr;
-
-                if(NULL == (ptr = strptime(data->chars->str,
-                            XML_DATE_FORMAT, &time)))
-                    /* Failed to parse dateTime format. */
-                    data->state = ERROR;
-                else
+                if(_auto_download && *_curr_repo->url
+                        && !((_zoom + zoff) % _curr_repo->dl_zoom_steps))
                 {
-                    /* Parse was successful. Now we have to parse timezone.
-                     * From here on, if there is an error, I just assume local
-                     * timezone.  Yes, this is not proper XML, but I don't
-                     * care. */
-                    gchar *error_check;
-
-                    /* First, set time in "local" time zone. */
-                    data->path.path.track.tail->time = (mktime(&time));
+                    if(!fast_fail)
+                        map_initiate_download(
+                                tilex >> zoff, tiley >> zoff, _zoom + zoff,
+                                INITIAL_DOWNLOAD_RETRIES);
+                    fast_fail = TRUE;
+                }
+            }
+        }
+    }
+    if(!pixbuf)
+        pixbuf = gdk_pixbuf_new(
+                GDK_COLORSPACE_RGB,
+                FALSE, /* no alpha. */
+                8, /* 8 bits per sample. */
+                TILE_SIZE_PIXELS, TILE_SIZE_PIXELS);
+    if(pixbuf)
+    {
+        gdk_draw_pixbuf(
+                _map_pixmap,
+                _gc_mark,
+                pixbuf,
+                0, 0,
+                destx, desty,
+                TILE_SIZE_PIXELS, TILE_SIZE_PIXELS,
+                GDK_RGB_DITHER_NONE, 0, 0);
+        g_object_unref(pixbuf);
+    }
 
-                    /* Now, skip inconsequential characters */
-                    while(*ptr && *ptr != 'Z' && *ptr != '-' && *ptr != '+')
-                        ptr++;
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
 
-                    /* Check if we ran to the end of the string. */
-                    if(*ptr)
-                    {
-                        /* Next character is either 'Z', '-', or '+' */
-                        if(*ptr == 'Z')
-                            /* Zulu (UTC) time. Undo the local time zone's
-                             * offset. */
-                            data->path.path.track.tail->time += time.tm_gmtoff;
-                        else
-                        {
-                            /* Not Zulu (UTC). Must parse hours and minutes. */
-                            gint offhours = strtol(ptr, &error_check, 10);
-                            if(error_check != ptr
-                                    && *(ptr = error_check) == ':')
-                            {
-                                /* Parse of hours worked. Check minutes. */
-                                gint offmins = strtol(ptr + 1,
-                                        &error_check, 10);
-                                if(error_check != (ptr + 1))
-                                {
-                                    /* Parse of minutes worked. Calculate. */
-                                    data->path.path.track.tail->time
-                                        += (time.tm_gmtoff
-                                                - (offhours * 60 * 60
-                                                    + offmins * 60));
-                                }
-                            }
-                        }
-                    }
-                    /* Successfully parsed dateTime. */
-                    data->state = INSIDE_PATH_POINT;
-                }
+/**
+ * Force a redraw of the entire _map_pixmap, including fetching the
+ * background maps from disk and redrawing the tracks on top of them.
+ */
+void
+map_force_redraw()
+{
+    guint new_x, new_y;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-                g_string_free(data->chars, TRUE);
-                data->chars = g_string_new("");
-            }
-            else
-                data->state = ERROR;
-            break;
-        case INSIDE_PATH_POINT_DESC:
-            /* only parse description for routes */
-            if(!strcmp((gchar*)name, "desc"))
+    for(new_y = 0; new_y < BUF_HEIGHT_TILES; ++new_y)
+        for(new_x = 0; new_x < BUF_WIDTH_TILES; ++new_x)
+        {
+            map_render_tile(
+                    _base_tilex + new_x,
+                    _base_tiley + new_y,
+                    new_x * TILE_SIZE_PIXELS,
+                    new_y * TILE_SIZE_PIXELS,
+                    FALSE);
+        }
+    map_render_paths();
+    map_render_poi();
+    MACRO_QUEUE_DRAW_AREA();
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Set the current zoom level.  If the given zoom level is the same as the
+ * current zoom level, or if the new zoom is invalid
+ * (not MIN_ZOOM <= new_zoom < MAX_ZOOM), then this method does nothing.
+ */
+void
+map_set_zoom(guint new_zoom)
+{
+    printf("%s(%d)\n", __PRETTY_FUNCTION__, _zoom);
+
+    /* Note that, since new_zoom is a guint and MIN_ZOOM is 0, this if
+     * condition also checks for new_zoom >= MIN_ZOOM. */
+    if(new_zoom > (MAX_ZOOM - 1))
+        return;
+    _zoom = new_zoom / _curr_repo->view_zoom_steps
+                     * _curr_repo->view_zoom_steps;
+    _world_size_tiles = unit2tile(WORLD_SIZE_UNITS);
+
+    /* If we're leading, update the center to reflect new zoom level. */
+    MACRO_RECALC_CENTER(_center.unitx, _center.unity);
+
+    /* Update center bounds to reflect new zoom level. */
+    _min_center.unitx = pixel2unit(grid2pixel(_screen_grids_halfwidth));
+    _min_center.unity = pixel2unit(grid2pixel(_screen_grids_halfheight));
+    _max_center.unitx = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfwidth) - 1;
+    _max_center.unity = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfheight)- 1;
+
+    BOUND(_center.unitx, _min_center.unitx, _max_center.unitx);
+    BOUND(_center.unity, _min_center.unity, _max_center.unity);
+
+    _base_tilex = grid2tile((gint)pixel2grid(
+                (gint)unit2pixel((gint)_center.unitx))
+            - (gint)_screen_grids_halfwidth);
+    _base_tiley = grid2tile(pixel2grid(
+                unit2pixel(_center.unity))
+            - _screen_grids_halfheight);
+
+    /* New zoom level, so we can't reuse the old buffer's pixels. */
+
+
+    /* Update state variables. */
+    MACRO_RECALC_OFFSET();
+    MACRO_RECALC_FOCUS_BASE();
+    MACRO_RECALC_FOCUS_SIZE();
+
+    map_set_mark();
+    map_force_redraw();
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Center the view on the given unitx/unity.
+ */
+static void
+map_center_unit(guint new_center_unitx, guint new_center_unity)
+{
+    gint new_base_tilex, new_base_tiley;
+    guint new_x, new_y;
+    guint j, k, base_new_x, base_old_x, old_x, old_y, iox, ioy;
+    printf("%s(%d, %d)\n", __PRETTY_FUNCTION__,
+            new_center_unitx, new_center_unity);
+
+    /* Assure that _center.unitx/y are bounded. */
+    BOUND(new_center_unitx, _min_center.unitx, _max_center.unitx);
+    BOUND(new_center_unity, _min_center.unity, _max_center.unity);
+
+    _center.unitx = new_center_unitx;
+    _center.unity = new_center_unity;
+
+    new_base_tilex = grid2tile((gint)pixel2grid(
+                (gint)unit2pixel((gint)_center.unitx))
+            - (gint)_screen_grids_halfwidth);
+    new_base_tiley = grid2tile(pixel2grid(
+                unit2pixel(_center.unity))
+            - _screen_grids_halfheight);
+
+    /* Same zoom level, so it's likely that we can reuse some of the old
+     * buffer's pixels. */
+
+    if(new_base_tilex != _base_tilex
+            || new_base_tiley != _base_tiley)
+    {
+        /* If copying from old parts to new parts, we need to make sure we
+         * don't overwrite the old parts when copying, so set up new_x,
+         * new_y, old_x, old_y, iox, and ioy with that in mind. */
+        if(new_base_tiley < _base_tiley)
+        {
+            /* New is lower than old - start at bottom and go up. */
+            new_y = BUF_HEIGHT_TILES - 1;
+            ioy = -1;
+        }
+        else
+        {
+            /* New is higher than old - start at top and go down. */
+            new_y = 0;
+            ioy = 1;
+        }
+        if(new_base_tilex < _base_tilex)
+        {
+            /* New is righter than old - start at right and go left. */
+            base_new_x = BUF_WIDTH_TILES - 1;
+            iox = -1;
+        }
+        else
+        {
+            /* New is lefter than old - start at left and go right. */
+            base_new_x = 0;
+            iox = 1;
+        }
+
+        /* Iterate over the y tile values. */
+        old_y = new_y + new_base_tiley - _base_tiley;
+        base_old_x = base_new_x + new_base_tilex - _base_tilex;
+        _base_tilex = new_base_tilex;
+        _base_tiley = new_base_tiley;
+        for(j = 0; j < BUF_HEIGHT_TILES; ++j, new_y += ioy, old_y += ioy)
+        {
+            new_x = base_new_x;
+            old_x = base_old_x;
+            /* Iterate over the x tile values. */
+            for(k = 0; k < BUF_WIDTH_TILES; ++k, new_x += iox, old_x += iox)
             {
-                MACRO_ROUTE_INCREMENT_WTAIL(data->path.path.route);
-                data->path.path.route.wtail->point = data->path.path.route.tail;
-                data->path.path.route.wtail->desc
-                    = g_string_free(data->chars, FALSE);
-                data->chars = g_string_new("");
-                data->state = INSIDE_PATH_POINT;
+                /* Can we get this grid block from the old buffer?. */
+                if(old_x >= 0 && old_x < BUF_WIDTH_TILES
+                        && old_y >= 0 && old_y < BUF_HEIGHT_TILES)
+                {
+                    /* Copy from old buffer to new buffer. */
+                    gdk_draw_drawable(
+                            _map_pixmap,
+                            _gc_mark,
+                            _map_pixmap,
+                            old_x * TILE_SIZE_PIXELS,
+                            old_y * TILE_SIZE_PIXELS,
+                            new_x * TILE_SIZE_PIXELS,
+                            new_y * TILE_SIZE_PIXELS,
+                            TILE_SIZE_PIXELS, TILE_SIZE_PIXELS);
+                }
+                else
+                {
+                    map_render_tile(
+                            new_base_tilex + new_x,
+                            new_base_tiley + new_y,
+                            new_x * TILE_SIZE_PIXELS,
+                            new_y * TILE_SIZE_PIXELS,
+                            FALSE);
+                }
             }
-            else
-                data->state = ERROR;
-            break;
-        case UNKNOWN:
-            if(!--data->unknown_depth)
-                data->state = data->prev_state;
-            else
-                data->state = ERROR;
-            break;
+        }
+        map_render_paths();
+        map_render_poi();
+    }
+
+    MACRO_RECALC_OFFSET();
+    MACRO_RECALC_FOCUS_BASE();
+
+    map_set_mark();
+    MACRO_QUEUE_DRAW_AREA();
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Pan the view by the given number of units in the X and Y directions.
+ */
+void
+map_pan(gint delta_unitx, gint delta_unity)
+{
+    printf("%s(%d, %d)\n", __PRETTY_FUNCTION__, delta_unitx, delta_unity);
+
+    if(_center_mode > 0)
+        gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+                    _menu_ac_none_item), TRUE);
+    map_center_unit(
+            _center.unitx + delta_unitx,
+            _center.unity + delta_unity);
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Initiate a move of the mark from the old location to the current
+ * location.  This function queues the draw area of the old mark (to force
+ * drawing of the background map), then updates the mark, then queus the
+ * draw area of the new mark.
+ */
+static void
+map_move_mark()
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    /* Just queue the old and new draw areas. */
+    gtk_widget_queue_draw_area(_map_widget,
+            _mark_minx,
+            _mark_miny,
+            _mark_width,
+            _mark_height);
+    map_set_mark();
+    gtk_widget_queue_draw_area(_map_widget,
+            _mark_minx,
+            _mark_miny,
+            _mark_width,
+            _mark_height);
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Make sure the mark is up-to-date.  This function triggers a panning of
+ * the view if the mark is appropriately close to the edge of the view.
+ */
+static void
+refresh_mark()
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    guint new_center_unitx;
+    guint new_center_unity;
+
+    MACRO_RECALC_CENTER(new_center_unitx, new_center_unity);
+
+    if((new_center_unitx - _focus.unitx) < _focus_unitwidth
+            && (new_center_unity - _focus.unity) < _focus_unitheight)
+        /* We're not changing the view - just move the mark. */
+        map_move_mark();
+    else
+        map_center_unit(new_center_unitx, new_center_unity);
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Handle a start tag in the parsing of a GPX file.
+ */
+#define MACRO_SET_UNKNOWN() { \
+    data->prev_state = data->state; \
+    data->state = UNKNOWN; \
+    data->unknown_depth = 1; \
+}
+static void
+gpx_start_element(SaxData *data, const xmlChar *name, const xmlChar **attrs)
+{
+    vprintf("%s(%s)\n", __PRETTY_FUNCTION__, name);
+
+    switch(data->state)
+    {
+        case ERROR:
+            break;
+        case START:
+            if(!strcmp((gchar*)name, "gpx"))
+                data->state = INSIDE_GPX;
+            else
+                MACRO_SET_UNKNOWN();
+            break;
+        case INSIDE_GPX:
+            if(!strcmp((gchar*)name, "trk"))
+                data->state = INSIDE_PATH;
+            else
+                MACRO_SET_UNKNOWN();
+            break;
+        case INSIDE_PATH:
+            if(!strcmp((gchar*)name, "trkseg"))
+            {
+                data->state = INSIDE_PATH_SEGMENT;
+                data->at_least_one_trkpt = FALSE;
+            }
+            else
+                MACRO_SET_UNKNOWN();
+            break;
+        case INSIDE_PATH_SEGMENT:
+            if(!strcmp((gchar*)name, "trkpt"))
+            {
+                const xmlChar **curr_attr;
+                gchar *error_check;
+                gfloat lat = 0.f, lon = 0.f;
+                gboolean has_lat, has_lon;
+                has_lat = FALSE;
+                has_lon = FALSE;
+                for(curr_attr = attrs; *curr_attr != NULL; )
+                {
+                    const gchar *attr_name = *curr_attr++;
+                    const gchar *attr_val = *curr_attr++;
+                    if(!strcmp(attr_name, "lat"))
+                    {
+                        lat = g_ascii_strtod(attr_val, &error_check);
+                        if(error_check != attr_val)
+                            has_lat = TRUE;
+                    }
+                    else if(!strcmp(attr_name, "lon"))
+                    {
+                        lon = g_ascii_strtod(attr_val, &error_check);
+                        if(error_check != attr_val)
+                            has_lon = TRUE;
+                    }
+                }
+                if(has_lat && has_lon)
+                {
+                    if(data->path.path_type == TRACK)
+                    {
+                        MACRO_TRACK_INCREMENT_TAIL(data->path.path.track);
+                        latlon2unit(lat, lon,
+                                data->path.path.track.tail->point.unitx,
+                                data->path.path.track.tail->point.unity);
+                        data->path.path.track.tail->time = 0;
+                    }
+                    else
+                    {
+                        MACRO_ROUTE_INCREMENT_TAIL(data->path.path.route);
+                        latlon2unit(lat, lon,
+                                data->path.path.route.tail->unitx,
+                                data->path.path.route.tail->unity);
+                    }
+                    data->state = INSIDE_PATH_POINT;
+                }
+                else
+                    data->state = ERROR;
+            }
+            else
+                MACRO_SET_UNKNOWN();
+            break;
+        case INSIDE_PATH_POINT:
+            /* only parse time for tracks */
+            if(data->path.path_type == TRACK
+                    && !strcmp((gchar*)name, "time"))
+                data->state = INSIDE_PATH_POINT_TIME;
+
+            /* only parse description for routes */
+            else if(data->path.path_type == ROUTE
+                    && !strcmp((gchar*)name, "desc"))
+                data->state = INSIDE_PATH_POINT_DESC;
+
+            else
+                MACRO_SET_UNKNOWN();
+            break;
+        case UNKNOWN:
+            data->unknown_depth++;
+            break;
         default:
             ;
     }
@@ -4107,1766 +5371,3597 @@ gpx_end_element(SaxData *data, const xmlChar *name)
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
-/**
- * Handle char data in the parsing of a GPX file.
- */
+/**
+ * Handle an end tag in the parsing of a GPX file.
+ */
+static void
+gpx_end_element(SaxData *data, const xmlChar *name)
+{
+    vprintf("%s(%s)\n", __PRETTY_FUNCTION__, name);
+
+    switch(data->state)
+    {
+        case ERROR:
+            break;
+        case START:
+            data->state = ERROR;
+            break;
+        case INSIDE_GPX:
+            if(!strcmp((gchar*)name, "gpx"))
+                data->state = FINISH;
+            else
+                data->state = ERROR;
+            break;
+        case INSIDE_PATH:
+            if(!strcmp((gchar*)name, "trk"))
+                data->state = INSIDE_GPX;
+            else
+                data->state = ERROR;
+            break;
+        case INSIDE_PATH_SEGMENT:
+            if(!strcmp((gchar*)name, "trkseg"))
+            {
+                if(data->at_least_one_trkpt)
+                {
+                    if(data->path.path_type == TRACK)
+                    {
+                        MACRO_TRACK_INCREMENT_TAIL(data->path.path.track);
+                        *data->path.path.track.tail = _track_null;
+                    }
+                    else
+                    {
+                        MACRO_ROUTE_INCREMENT_TAIL(data->path.path.route);
+                        *data->path.path.route.tail = _pos_null;
+                    }
+                }
+                data->state = INSIDE_PATH;
+            }
+            else
+                data->state = ERROR;
+            break;
+        case INSIDE_PATH_POINT:
+            if(!strcmp((gchar*)name, "trkpt"))
+            {
+                data->state = INSIDE_PATH_SEGMENT;
+                data->at_least_one_trkpt = TRUE;
+            }
+            else
+                data->state = ERROR;
+            break;
+        case INSIDE_PATH_POINT_TIME:
+            /* only parse time for tracks */
+            if(!strcmp((gchar*)name, "time"))
+            {
+                struct tm time;
+                gchar *ptr;
+
+                if(NULL == (ptr = strptime(data->chars->str,
+                            XML_DATE_FORMAT, &time)))
+                    /* Failed to parse dateTime format. */
+                    data->state = ERROR;
+                else
+                {
+                    /* Parse was successful. Now we have to parse timezone.
+                     * From here on, if there is an error, I just assume local
+                     * timezone.  Yes, this is not proper XML, but I don't
+                     * care. */
+                    gchar *error_check;
+
+                    /* First, set time in "local" time zone. */
+                    data->path.path.track.tail->time = (mktime(&time));
+
+                    /* Now, skip inconsequential characters */
+                    while(*ptr && *ptr != 'Z' && *ptr != '-' && *ptr != '+')
+                        ptr++;
+
+                    /* Check if we ran to the end of the string. */
+                    if(*ptr)
+                    {
+                        /* Next character is either 'Z', '-', or '+' */
+                        if(*ptr == 'Z')
+                            /* Zulu (UTC) time. Undo the local time zone's
+                             * offset. */
+                            data->path.path.track.tail->time += time.tm_gmtoff;
+                        else
+                        {
+                            /* Not Zulu (UTC). Must parse hours and minutes. */
+                            gint offhours = strtol(ptr, &error_check, 10);
+                            if(error_check != ptr
+                                    && *(ptr = error_check) == ':')
+                            {
+                                /* Parse of hours worked. Check minutes. */
+                                gint offmins = strtol(ptr + 1,
+                                        &error_check, 10);
+                                if(error_check != (ptr + 1))
+                                {
+                                    /* Parse of minutes worked. Calculate. */
+                                    data->path.path.track.tail->time
+                                        += (time.tm_gmtoff
+                                                - (offhours * 60 * 60
+                                                    + offmins * 60));
+                                }
+                            }
+                        }
+                    }
+                    /* Successfully parsed dateTime. */
+                    data->state = INSIDE_PATH_POINT;
+                }
+
+                g_string_free(data->chars, TRUE);
+                data->chars = g_string_new("");
+            }
+            else
+                data->state = ERROR;
+            break;
+        case INSIDE_PATH_POINT_DESC:
+            /* only parse description for routes */
+            if(!strcmp((gchar*)name, "desc"))
+            {
+                MACRO_ROUTE_INCREMENT_WTAIL(data->path.path.route);
+                data->path.path.route.wtail->point = data->path.path.route.tail;
+                data->path.path.route.wtail->desc
+                    = g_string_free(data->chars, FALSE);
+                data->chars = g_string_new("");
+                data->state = INSIDE_PATH_POINT;
+            }
+            else
+                data->state = ERROR;
+            break;
+        case UNKNOWN:
+            if(!--data->unknown_depth)
+                data->state = data->prev_state;
+            else
+                data->state = ERROR;
+            break;
+        default:
+            ;
+    }
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Handle char data in the parsing of a GPX file.
+ */
+static void
+gpx_chars(SaxData *data, const xmlChar *ch, int len)
+{
+    guint i;
+    vprintf("%s()\n", __PRETTY_FUNCTION__);
+
+    switch(data->state)
+    {
+        case ERROR:
+        case UNKNOWN:
+            break;
+        case INSIDE_PATH_POINT_TIME:
+        case INSIDE_PATH_POINT_DESC:
+            for(i = 0; i < len; i++)
+                data->chars = g_string_append_c(data->chars, ch[i]);
+            vprintf("%s\n", data->chars->str);
+            break;
+        default:
+            break;
+    }
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Handle an entity in the parsing of a GPX file.  We don't do anything
+ * special here.
+ */
+static xmlEntityPtr
+gpx_get_entity(SaxData *data, const xmlChar *name)
+{
+    vprintf("%s()\n", __PRETTY_FUNCTION__);
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return xmlGetPredefinedEntity(name);
+}
+
+/**
+ * Handle an error in the parsing of a GPX file.
+ */
+static void
+gpx_error(SaxData *data, const gchar *msg, ...)
+{
+    vprintf("%s()\n", __PRETTY_FUNCTION__);
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    data->state = ERROR;
+}
+
+/**
+ * Parse the given character buffer of the given size, replacing the given
+ * Track's pointers with pointers to new arrays depending on the given
+ * policy, adding extra_bins slots in the arrays for new data.
+ *
+ * policy_old should be negative to indicate that the existing data should
+ * be prepended to the new GPX data, positive to indicate the opposite, and
+ * zero to indicate that we should throw away the old data.
+ *
+ * When importing tracks, we *prepend* the GPX data and provide extra_bins.
+ * When importing routes, we *append* in the case of regular routes, and we
+ * *replace* in the case of automatic routing.  Routes get no extra bins.
+ */
+static gboolean
+parse_track_gpx(gchar *buffer, gint size, gint policy_old)
+{
+    SaxData data;
+    xmlSAXHandler sax_handler;
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    data.path.path_type = TRACK;
+    MACRO_INIT_TRACK(data.path.path.track);
+    data.state = START;
+    data.chars = g_string_new("");
+
+    memset(&sax_handler, 0, sizeof(sax_handler));
+    sax_handler.characters = (charactersSAXFunc)gpx_chars;
+    sax_handler.startElement = (startElementSAXFunc)gpx_start_element;
+    sax_handler.endElement = (endElementSAXFunc)gpx_end_element;
+    sax_handler.entityDecl = (entityDeclSAXFunc)gpx_get_entity;
+    sax_handler.warning = (warningSAXFunc)gpx_error;
+    sax_handler.error = (errorSAXFunc)gpx_error;
+    sax_handler.fatalError = (fatalErrorSAXFunc)gpx_error;
+
+    xmlSAXUserParseMemory(&sax_handler, &data, buffer, size);
+    g_string_free(data.chars, TRUE);
+
+    if(data.state != FINISH)
+    {
+        vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+        return FALSE;
+    }
+    
+    /* Successful parsing - replace given Track structure. */
+    if(policy_old && _track.head)
+    {
+        TrackPoint *src_first;
+        Track *src, *dest;
+
+        if(policy_old > 0)
+        {
+            /* Append to current track. */
+            src = &data.path.path.track;
+            dest = &_track;
+        }
+        else
+        {
+            /* Prepend to current track. */
+            src = &_track;
+            dest = &data.path.path.track;
+        }
+
+        /* Find src_first non-zero point. */
+        for(src_first = src->head - 1; src_first++ != src->tail; )
+            if(src_first->point.unity)
+                break;
+
+        /* Append track points from src to dest. */
+        if(src->tail >= src_first)
+        {
+            guint num_dest_points = dest->tail - dest->head + 1;
+            guint num_src_points = src->tail - src_first + 1;
+
+            /* Adjust dest->tail to be able to fit src track data
+             * plus room for more track data. */
+            track_resize(dest,
+                    num_dest_points + num_src_points + ARRAY_CHUNK_SIZE);
+
+            memcpy(dest->tail + 1, src_first,
+                    num_src_points * sizeof(TrackPoint));
+
+            dest->tail += num_src_points;
+        }
+
+        MACRO_CLEAR_TRACK(*src);
+        if(policy_old < 0)
+            _track = *dest;
+    }
+    else
+    {
+        MACRO_CLEAR_TRACK(_track);
+        /* Overwrite with data.track. */
+        _track = data.path.path.track;
+        track_resize(&_track,
+                _track.tail - _track.head + 1 + ARRAY_CHUNK_SIZE);
+    }
+
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
+
+static gboolean
+parse_route_gpx(gchar *buffer, gint size, gint policy_old)
+{
+    SaxData data;
+    xmlSAXHandler sax_handler;
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    data.path.path_type = ROUTE;
+    MACRO_INIT_ROUTE(data.path.path.route);
+    data.state = START;
+    data.chars = g_string_new("");
+
+    memset(&sax_handler, 0, sizeof(sax_handler));
+    sax_handler.characters = (charactersSAXFunc)gpx_chars;
+    sax_handler.startElement = (startElementSAXFunc)gpx_start_element;
+    sax_handler.endElement = (endElementSAXFunc)gpx_end_element;
+    sax_handler.entityDecl = (entityDeclSAXFunc)gpx_get_entity;
+    sax_handler.warning = (warningSAXFunc)gpx_error;
+    sax_handler.error = (errorSAXFunc)gpx_error;
+    sax_handler.fatalError = (fatalErrorSAXFunc)gpx_error;
+
+    xmlSAXUserParseMemory(&sax_handler, &data, buffer, size);
+    g_string_free(data.chars, TRUE);
+
+    if(data.state != FINISH)
+    {
+        vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+        return FALSE;
+    }
+    
+    if(policy_old && _route.head)
+    {
+        Point *src_first;
+        Route *src, *dest;
+
+        if(policy_old > 0)
+        {
+            /* Append to current route. */
+            src = &data.path.path.route;
+            dest = &_route;
+        }
+        else
+        {
+            /* Prepend to current route. */
+            src = &_route;
+            dest = &data.path.path.route;
+        }
+
+        /* Find src_first non-zero point. */
+        for(src_first = src->head - 1; src_first++ != src->tail; )
+            if(src_first->unity)
+                break;
+
+        /* Append route points from src to dest. */
+        if(src->tail >= src_first)
+        {
+            WayPoint *curr;
+            guint num_dest_points = dest->tail - dest->head + 1;
+            guint num_src_points = src->tail - src_first + 1;
+
+            /* Adjust dest->tail to be able to fit src route data
+             * plus room for more route data. */
+            route_resize(dest, num_dest_points + num_src_points);
+
+            memcpy(dest->tail + 1, src_first,
+                    num_src_points * sizeof(Point));
+
+            dest->tail += num_src_points;
+
+            /* Append waypoints from src to dest->. */
+            route_wresize(dest, (dest->wtail - dest->whead)
+                    + (src->wtail - src->whead) + 2);
+            for(curr = src->whead - 1; curr++ != src->wtail; )
+            {
+                (++(dest->wtail))->point = dest->head + num_dest_points
+                    + (curr->point - src_first);
+                dest->wtail->desc = curr->desc;
+            }
+
+        }
+
+        /* Kill old route - don't use MACRO_CLEAR_ROUTE(), because that
+         * would free the string desc's that we just moved to data.route. */
+        g_free(src->head);
+        g_free(src->whead);
+        if(policy_old < 0)
+            _route = *dest;
+    }
+    else
+    {
+        MACRO_CLEAR_ROUTE(_route);
+        /* Overwrite with data.route. */
+        _route = data.path.path.route;
+        route_resize(&_route, _route.tail - _route.head + 1);
+    }
+
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
+
+/**
+ * This is a multi-purpose function for allowing the user to select a file
+ * for either reading or writing.  If chooser_action is
+ * GTK_FILE_CHOOSER_ACTION_OPEN, then bytes_out and size_out must be
+ * non-NULL.  If chooser_action is GTK_FILE_CHOOSER_ACTION_SAVE, then
+ * handle_out must be non-NULL.  Either dir or file (or both) can be NULL.
+ * This function returns TRUE if a file was successfully opened.
+ */
+static gboolean
+open_file(gchar **bytes_out, GnomeVFSHandle **handle_out, gint *size_out,
+        gchar **dir, gchar **file, GtkFileChooserAction chooser_action)
+{
+    GtkWidget *dialog;
+    gboolean success = FALSE;
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    dialog = hildon_file_chooser_dialog_new(GTK_WINDOW(_window),chooser_action);
+
+    if(dir && *dir)
+        gtk_file_chooser_set_current_folder_uri(
+                GTK_FILE_CHOOSER(dialog), *dir);
+    if(file && *file)
+    {
+        GValue val;
+        gtk_file_chooser_set_uri(
+                GTK_FILE_CHOOSER(dialog), *file);
+        if(chooser_action == GTK_FILE_CHOOSER_ACTION_SAVE)
+        {
+            /* Work around a bug in HildonFileChooserDialog. */
+            memset(&val, 0, sizeof(val));
+            g_value_init(&val, G_TYPE_BOOLEAN);
+            g_value_set_boolean(&val, FALSE);
+            g_object_set_property(G_OBJECT(dialog), "autonaming", &val);
+            gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),
+                    strrchr(*file, '/') + 1);
+        }
+    }
+
+    gtk_widget_show_all(GTK_WIDGET(dialog));
+
+    while(!success && gtk_dialog_run(GTK_DIALOG(dialog))==GTK_RESPONSE_OK)
+    {
+        gchar *file_uri_str;
+        GnomeVFSResult vfs_result;
+
+        /* Get the selected filename. */
+        file_uri_str = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
+
+        if((chooser_action == GTK_FILE_CHOOSER_ACTION_OPEN
+                && (GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
+                        file_uri_str, size_out, bytes_out))))
+                || (chooser_action == GTK_FILE_CHOOSER_ACTION_SAVE
+                    && GNOME_VFS_OK != (vfs_result = gnome_vfs_create(
+                            handle_out, file_uri_str,
+                            GNOME_VFS_OPEN_WRITE, FALSE, 0664))))
+        {
+            gchar buffer[1024];
+            sprintf(buffer, "%s %s:\n%s", _("Failed to open file for"),
+                    chooser_action == GTK_FILE_CHOOSER_ACTION_OPEN
+                    ? _("reading") : _("writing"),
+                    gnome_vfs_result_to_string(vfs_result));
+            popup_error(dialog, buffer);
+        }
+        else
+            success = TRUE;
+
+        g_free(file_uri_str);
+    }
+
+    if(success)
+    {
+        /* Success!. */
+        if(dir)
+        {
+            if(*dir)
+                g_free(*dir);
+            *dir = gtk_file_chooser_get_current_folder_uri(
+                    GTK_FILE_CHOOSER(dialog));
+        }
+
+        /* If desired, save the file for later. */
+        if(file)
+        {
+            if(*file)
+                g_free(*file);
+            *file = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
+        }
+    }
+
+    gtk_widget_destroy(dialog);
+
+    vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, success);
+    return success;
+}
+
+/**
+ * Refresh the view based on the fact that the route has been automatically
+ * updated.
+ */
+static gboolean
+auto_route_dl_idle_refresh()
+{
+    /* Make sure we're still supposed to do work. */
+    vprintf("%s()\n", __PRETTY_FUNCTION__);
+
+    if(!_autoroute_data.enabled)
+        _autoroute_data.handle = NULL;
+    else
+    {
+        if(parse_route_gpx(_autoroute_data.bytes, _autoroute_data.bytes_read,0))
+        {
+            /* Find the nearest route point, if we're connected. */
+            route_find_nearest_point();
+
+            map_force_redraw();
+        }
+    }
+
+    _autoroute_data.in_progress = FALSE;
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return FALSE;
+}
+
+/**
+ * Read the data provided by the given handle as GPX data, updating the
+ * auto-route with that data.
+ */
+static void
+auto_route_dl_cb_read(GnomeVFSAsyncHandle *handle,
+        GnomeVFSResult result,
+        gpointer bytes,
+        GnomeVFSFileSize bytes_requested,
+        GnomeVFSFileSize bytes_read)
+{
+    vprintf("%s(%s)\n", __PRETTY_FUNCTION__,gnome_vfs_result_to_string(result));
+
+    _autoroute_data.bytes_read += bytes_read;
+    if(result == GNOME_VFS_OK)
+    {
+        /* Expand bytes and continue reading. */
+        if(_autoroute_data.bytes_read * 2 > _autoroute_data.bytes_maxsize)
+        {
+            _autoroute_data.bytes = g_renew(gchar, _autoroute_data.bytes,
+                    2 * _autoroute_data.bytes_read);
+            _autoroute_data.bytes_maxsize = 2 * _autoroute_data.bytes_read;
+        }
+        gnome_vfs_async_read(_autoroute_data.handle,
+                _autoroute_data.bytes + _autoroute_data.bytes_read,
+                _autoroute_data.bytes_maxsize - _autoroute_data.bytes_read,
+                (GnomeVFSAsyncReadCallback)auto_route_dl_cb_read, NULL);
+    }
+    else
+        g_idle_add((GSourceFunc)auto_route_dl_idle_refresh, NULL);
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Open the given handle in preparation for reading GPX data.
+ */
+static void
+auto_route_dl_cb_open(GnomeVFSAsyncHandle *handle, GnomeVFSResult result)
+{
+    vprintf("%s()\n", __PRETTY_FUNCTION__);
+
+    if(result == GNOME_VFS_OK)
+        gnome_vfs_async_read(_autoroute_data.handle,
+                _autoroute_data.bytes,
+                _autoroute_data.bytes_maxsize,
+                (GnomeVFSAsyncReadCallback)auto_route_dl_cb_read, NULL);
+    else
+    {
+        _autoroute_data.in_progress = FALSE;
+        _autoroute_data.handle = NULL;
+    }
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * This function is periodically run to download updated auto-route data
+ * from the route source.
+ */
+static gboolean
+auto_route_dl_idle()
+{
+    gchar buffer[1024], latstr[32], lonstr[32];
+    vprintf("%s(%f, %f, %s)\n", __PRETTY_FUNCTION__,
+            _pos_lat, _pos_lon, _autoroute_data.dest);
+
+
+    g_ascii_dtostr(latstr, 32, _pos_lat);
+    g_ascii_dtostr(lonstr, 32, _pos_lon);
+    sprintf(buffer,"http://www.gnuite.com/cgi-bin/gpx.cgi?saddr=%s,%s&daddr=%s",
+            latstr, lonstr, _autoroute_data.dest);
+    _autoroute_data.bytes_read = 0;
+
+    gnome_vfs_async_open(&_autoroute_data.handle,
+            buffer, GNOME_VFS_OPEN_READ,
+            GNOME_VFS_PRIORITY_DEFAULT,
+            (GnomeVFSAsyncOpenCallback)auto_route_dl_cb_open, NULL);
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return FALSE;
+}
+
+/**
+ * Cancel the current auto-route.
+ */
+static void
+cancel_autoroute()
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    if(_autoroute_data.enabled)
+    {
+        _autoroute_data.enabled = FALSE;
+        if(_autoroute_data.dest)
+        {
+            g_free(_autoroute_data.dest);
+            _autoroute_data.dest = NULL;
+        }
+        if(_autoroute_data.handle)
+        {
+            gnome_vfs_async_cancel(_autoroute_data.handle);
+            _autoroute_data.handle = NULL;
+        }
+        if(_autoroute_data.bytes)
+        {
+            g_free(_autoroute_data.bytes);
+            _autoroute_data.bytes = NULL;
+        }
+        _autoroute_data.in_progress = FALSE;
+    }
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Save state and destroy all non-UI elements created by this program in
+ * preparation for exiting.
+ */
+static void
+maemo_mapper_destroy(void)
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    config_save();
+    rcvr_disconnect();
+    /* _program and widgets have already been destroyed. */
+
+    if(_dbconn)
+        sqlite_close(_db);
+
+    MACRO_CLEAR_TRACK(_track);
+    if(_route.head)
+        MACRO_CLEAR_TRACK(_route);
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/**
+ * Initialize everything required in preparation for calling gtk_main().
+ */
+static void
+maemo_mapper_init(gint argc, gchar **argv)
+{
+    GtkWidget *hbox, *label, *vbox;
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    config_init();
+
+    /* Initialize _program. */
+    _program = HILDON_PROGRAM(hildon_program_get_instance());
+    g_set_application_name("Maemo Mapper");
+
+    /* Initialize _window. */
+    _window = GTK_WIDGET(hildon_window_new());
+    hildon_program_add_window(_program, HILDON_WINDOW(_window));
+
+    /* Create and add widgets and supporting data. */
+    hbox = gtk_hbox_new(FALSE, 0);
+    gtk_container_add(GTK_CONTAINER(_window), hbox);
+
+    _gps_widget = gtk_frame_new("GPS Info");
+    gtk_container_add(GTK_CONTAINER(_gps_widget),
+            vbox = gtk_vbox_new(FALSE, 0));
+    gtk_widget_set_size_request(GTK_WIDGET(_gps_widget), 180, 0);
+    gtk_box_pack_start(GTK_BOX(hbox), _gps_widget, FALSE, TRUE, 0);
+
+    label = gtk_label_new(" ");
+    gtk_widget_set_size_request(GTK_WIDGET(label), -1, 10);
+    gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
+
+    _text_lat = gtk_label_new(" --- ");
+    gtk_widget_set_size_request(GTK_WIDGET(_text_lat), -1, 30);
+    gtk_box_pack_start(GTK_BOX(vbox), _text_lat, FALSE, TRUE, 0);
+
+    _text_lon = gtk_label_new(" --- ");
+    gtk_widget_set_size_request(GTK_WIDGET(_text_lon), -1, 30);
+    gtk_box_pack_start(GTK_BOX(vbox), _text_lon, FALSE, TRUE, 0);
+
+    _text_speed = gtk_label_new(" --- ");
+    gtk_widget_set_size_request(GTK_WIDGET(_text_speed), -1, 30);
+    gtk_box_pack_start(GTK_BOX(vbox), _text_speed, FALSE, TRUE, 0);
+
+    _text_alt = gtk_label_new(" --- ");
+    gtk_widget_set_size_request(GTK_WIDGET(_text_alt), -1, 30);
+    gtk_box_pack_start(GTK_BOX(vbox), _text_alt, FALSE, TRUE, 0);
+
+    label = gtk_label_new(" ");
+    gtk_widget_set_size_request(GTK_WIDGET(label), -1, 10);
+    gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
+
+    _sat_panel = gtk_drawing_area_new ();
+    gtk_widget_set_size_request (_sat_panel, -1, 100);
+    gtk_box_pack_start(GTK_BOX(vbox), _sat_panel, TRUE, TRUE, 0);
+
+    label = gtk_label_new(" ");
+    gtk_widget_set_size_request(GTK_WIDGET(label), -1, 10);
+    gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
+
+    _text_time = gtk_label_new("--:--:--");
+    gtk_widget_set_size_request(GTK_WIDGET(_text_time), -1, 30);
+    gtk_box_pack_start(GTK_BOX(vbox), _text_time, FALSE, TRUE, 0);
+
+    _heading_panel = gtk_drawing_area_new ();
+    gtk_widget_set_size_request (_heading_panel, -1, 100);
+    gtk_box_pack_start(GTK_BOX(vbox), _heading_panel, TRUE, TRUE, 0);
+
+    _map_widget = gtk_drawing_area_new();
+    gtk_box_pack_start(GTK_BOX(hbox), _map_widget, TRUE, TRUE, 0);
+
+    gtk_widget_realize(_map_widget);
+
+    _map_pixmap = gdk_pixmap_new(
+                _map_widget->window,
+                BUF_WIDTH_PIXELS, BUF_HEIGHT_PIXELS,
+                -1); /* -1: use bit depth of widget->window. */
+
+    /* Connect signals. */
+    g_signal_connect(G_OBJECT(_sat_panel), "expose_event",
+            G_CALLBACK(sat_panel_expose), NULL);
+    g_signal_connect(G_OBJECT(_heading_panel), "expose_event",
+            G_CALLBACK(heading_panel_expose), NULL);
+    g_signal_connect(G_OBJECT(_window), "destroy",
+            G_CALLBACK(gtk_main_quit), NULL);
+
+    g_signal_connect(G_OBJECT(_window), "key_press_event",
+            G_CALLBACK(window_cb_key_press), NULL);
+
+    g_signal_connect(G_OBJECT(_window), "key_release_event",
+            G_CALLBACK(window_cb_key_release), NULL);
+
+    g_signal_connect(G_OBJECT(_map_widget), "configure_event",
+            G_CALLBACK(map_cb_configure), NULL);
+
+    g_signal_connect(G_OBJECT(_map_widget), "expose_event",
+            G_CALLBACK(map_cb_expose), NULL);
+
+    g_signal_connect(G_OBJECT(_map_widget), "button_press_event",
+            G_CALLBACK(map_cb_button_press), NULL);
+
+    g_signal_connect(G_OBJECT(_map_widget), "button_release_event",
+            G_CALLBACK(map_cb_button_release), NULL);
+
+    gtk_widget_add_events(_map_widget,
+            GDK_EXPOSURE_MASK
+            | GDK_BUTTON_PRESS_MASK
+            | GDK_BUTTON_RELEASE_MASK);
+
+    osso_hw_set_event_cb(_osso, NULL, osso_cb_hw_state, NULL);
+
+    gnome_vfs_async_set_job_limit(24);
+
+    /* Initialize data. */
+
+    UNITS_TEXT[UNITS_KM] = UNITS_KM_TEXT;
+    UNITS_TEXT[UNITS_MI] = UNITS_MI_TEXT;
+    UNITS_TEXT[UNITS_NM] = UNITS_NM_TEXT;
+
+    ESCAPE_KEY_TEXT[ESCAPE_KEY_TOGGLE_TRACKS] = ESCAPE_KEY_TOGGLE_TRACKS_TEXT;
+    ESCAPE_KEY_TEXT[ESCAPE_KEY_CHANGE_REPO] = ESCAPE_KEY_CHANGE_REPO_TEXT;
+    ESCAPE_KEY_TEXT[ESCAPE_KEY_RESET_BLUETOOTH]=ESCAPE_KEY_RESET_BLUETOOTH_TEXT;
+
+    /* set XML_TZONE */
+    {
+        time_t time1;
+        struct tm time2;
+        time1 = time(NULL);
+        localtime_r(&time1, &time2);
+        sprintf(XML_TZONE, "%+03ld:%02ld",
+                (time2.tm_gmtoff / 60 / 60), (time2.tm_gmtoff / 60) % 60);
+        _gmtoffset = time2.tm_gmtoff;
+    }
+
+    memset(&_track, 0, sizeof(_track));
+    memset(&_route, 0, sizeof(_route));
+    _last_spoken_phrase = g_strdup("");
+
+    /* Set up track array. */
+    MACRO_INIT_TRACK(_track);
+
+    _downloads_hash = g_hash_table_new((GHashFunc)download_hashfunc,
+            (GEqualFunc)download_equalfunc);
+    memset(&_autoroute_data, 0, sizeof(_autoroute_data));
+
+    integerize_data();
+
+    /* Initialize our line styles. */
+    update_gcs();
+
+    menu_init();
+
+    /* If present, attempt to load the file specified on the command line. */
+    if(argc > 1)
+    {
+        GnomeVFSResult vfs_result;
+        gint size;
+        gchar *buffer;
+        gchar *file_uri;
+
+        /* Get the selected filename. */
+        file_uri = gnome_vfs_make_uri_from_shell_arg(argv[1]);
+
+        if(GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
+                        file_uri, &size, &buffer)))
+        {
+            gchar buffer[1024];
+            sprintf(buffer, "%s %s:\n%s", _("Failed to open file for"),
+                    _("reading"), gnome_vfs_result_to_string(vfs_result));
+            popup_error(_window, buffer);
+        }
+        else
+        {
+            /* If auto is enabled, append the route, otherwise replace it. */
+            if(parse_route_gpx(buffer, size, 0))
+                hildon_banner_show_information(
+                        _window, NULL, _("Route Opened"));
+            else
+                popup_error(_window, _("Error parsing GPX file."));
+            g_free(buffer);
+        }
+        g_free(file_uri);
+    }
+
+    gtk_idle_add((GSourceFunc)window_present, NULL);
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+/****************************************************************************
+ * ABOVE: ROUTINES **********************************************************
+ ****************************************************************************/
+
+
+
+/****************************************************************************
+ * BELOW: MAIN **************************************************************
+ ****************************************************************************/
+
+gint
+main(gint argc, gchar *argv[])
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    g_thread_init(NULL);
+
+    /* Initialize _osso. */
+    _osso = osso_initialize("com.gnuite.maemo_mapper", VERSION, TRUE, NULL);
+    if(!_osso)
+    {
+        fprintf(stderr, "osso_initialize failed.\n");
+        return 1;
+    }
+
+    gtk_init(&argc, &argv);
+
+    /* Init gconf. */
+    g_type_init();
+    gconf_init(argc, argv, NULL);
+
+    gnome_vfs_init();
+
+    maemo_mapper_init(argc, argv);
+
+    if(OSSO_OK != osso_rpc_set_default_cb_f(_osso, dbus_cb_default, NULL))
+    {
+        fprintf(stderr, "osso_rpc_set_default_cb_f failed.\n");
+        return 1;
+    }
+
+    gtk_main();
+
+    maemo_mapper_destroy();
+
+    osso_deinitialize(_osso);
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return 0;
+}
+
+/****************************************************************************
+ * ABOVE: MAIN **************************************************************
+ ****************************************************************************/
+
+
+
+/****************************************************************************
+ * BELOW: CALLBACKS *********************************************************
+ ****************************************************************************/
+
+static gint
+dbus_cb_default(const gchar *interface, const gchar *method,
+        GArray *arguments, gpointer data, osso_rpc_t *retval)
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    if(!strcmp(method, "top_application"))
+        gtk_idle_add((GSourceFunc)window_present, NULL);
+
+    retval->type = DBUS_TYPE_INVALID;
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return OSSO_OK;
+}
+
 static void
-gpx_chars(SaxData *data, const xmlChar *ch, int len)
+osso_cb_hw_state(osso_hw_state_t *state, gpointer data)
 {
-    guint i;
-    vprintf("%s()\n", __PRETTY_FUNCTION__);
+    static gboolean _must_save_data = FALSE;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    switch(data->state)
+    if(state->system_inactivity_ind)
     {
-        case ERROR:
-        case UNKNOWN:
-            break;
-        case INSIDE_PATH_POINT_TIME:
-        case INSIDE_PATH_POINT_DESC:
-            for (i = 0; i < len; i++)
-                data->chars = g_string_append_c(data->chars, ch[i]);
-            vprintf("%s\n", data->chars->str);
-            break;
-        default:
-            break;
+        if(_must_save_data)
+            _must_save_data = FALSE;
+        else if(_conn_state > RCVR_OFF)
+        {
+            set_conn_state(RCVR_OFF);
+            rcvr_disconnect();
+            track_add(0, FALSE);
+            /* Pretend the autoroute is in progress to avoid download. */
+            if(_autoroute_data.enabled)
+                _autoroute_data.in_progress = TRUE;
+        }
+    }
+    else if(state->save_unsaved_data_ind)
+    {
+        config_save();
+        _must_save_data = TRUE;
+    }
+    else if(_conn_state == RCVR_OFF && _enable_gps)
+    {
+        set_conn_state(RCVR_DOWN);
+        rcvr_connect_later();
+        if(_autoroute_data.enabled)
+            _autoroute_data.in_progress = TRUE;
     }
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
-/**
- * Handle an entity in the parsing of a GPX file.  We don't do anything
- * special here.
- */
-static xmlEntityPtr
-gpx_get_entity(SaxData *data, const xmlChar *name)
+static gboolean
+key_zoom_timeout()
 {
-    vprintf("%s()\n", __PRETTY_FUNCTION__);
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-    return xmlGetPredefinedEntity(name);
+    if(_key_zoom_new < _zoom)
+    {
+        /* We're currently zooming in (_zoom is decreasing). */
+        guint test = _key_zoom_new - _curr_repo->view_zoom_steps;
+        if(test < MAX_ZOOM)
+            /* We can zoom some more.  Hurray! */
+            _key_zoom_new = test;
+        else
+            /* We can't zoom anymore.  Booooo! */
+            return FALSE;
+    }
+    else
+    {
+        /* We're currently zooming out (_zoom is increasing). */
+        guint test = _key_zoom_new + _curr_repo->view_zoom_steps;
+        if(test < MAX_ZOOM)
+            /* We can zoom some more.  Hurray! */
+            _key_zoom_new = test;
+        else
+            /* We can't zoom anymore.  Booooo! */
+            return FALSE;
+    }
+
+    /* We can zoom more - tell them how much they're zooming. */
+    {
+        gchar buffer[32];
+        sprintf(buffer, "%s %d", _("Zoom to Level"), _key_zoom_new);
+        hildon_banner_show_information(_window, NULL, buffer);
+    }
+    return TRUE;
 }
 
-/**
- * Handle an error in the parsing of a GPX file.
- */
 static void
-gpx_error(SaxData *data, const gchar *msg, ...)
+reset_bluetooth()
 {
-    vprintf("%s()\n", __PRETTY_FUNCTION__);
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-    data->state = ERROR;
+    if(system("/usr/bin/sudo -l | grep -q '/usr/sbin/hciconfig  *hci0  *reset'"
+            " && sudo /usr/sbin/hciconfig hci0 reset"))
+        popup_error(_window,
+                _("An error occurred while trying to reset the bluetooth "
+                "radio.\n\n"
+                "Did you make sure to modify\nthe /etc/sudoers file?"));
+    else if(_conn_state > RCVR_OFF)
+    {
+        set_conn_state(RCVR_DOWN);
+        rcvr_connect_now();
+    }
 }
 
-/**
- * Parse the given character buffer of the given size, replacing the given
- * Track's pointers with pointers to new arrays depending on the given
- * policy, adding extra_bins slots in the arrays for new data.
- *
- * policy_old should be negative to indicate that the existing data should
- * be prepended to the new GPX data, positive to indicate the opposite, and
- * zero to indicate that we should throw away the old data.
- *
- * When importing tracks, we *prepend* the GPX data and provide extra_bins.
- * When importing routes, we *append* in the case of regular routes, and we
- * *replace* in the case of automatic routing.  Routes get no extra bins.
- */
 static gboolean
-parse_track_gpx(gchar *buffer, gint size, gint policy_old)
+window_cb_key_press(GtkWidget* widget, GdkEventKey *event)
 {
-    SaxData data;
-    xmlSAXHandler sax_handler;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    data.path.path_type = TRACK;
-    MACRO_INIT_TRACK(data.path.path.track);
-    data.state = START;
-    data.chars = g_string_new("");
-
-    memset(&sax_handler, 0, sizeof(sax_handler));
-    sax_handler.characters = (charactersSAXFunc)gpx_chars;
-    sax_handler.startElement = (startElementSAXFunc)gpx_start_element;
-    sax_handler.endElement = (endElementSAXFunc)gpx_end_element;
-    sax_handler.entityDecl = (entityDeclSAXFunc)gpx_get_entity;
-    sax_handler.warning = (warningSAXFunc)gpx_error;
-    sax_handler.error = (errorSAXFunc)gpx_error;
-    sax_handler.fatalError = (fatalErrorSAXFunc)gpx_error;
+    switch(event->keyval)
+    {
+        case HILDON_HARDKEY_UP:
+            map_pan(0, -PAN_UNITS);
+            return TRUE;
 
-    xmlSAXUserParseMemory(&sax_handler, &data, buffer, size);
-    g_string_free(data.chars, TRUE);
+        case HILDON_HARDKEY_DOWN:
+            map_pan(0, PAN_UNITS);
+            return TRUE;
 
-    if(data.state != FINISH)
-    {
-        vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
-        return FALSE;
-    }
-    
-    /* Successful parsing - replace given Track structure. */
-    if(policy_old && _track.head)
-    {
-        TrackPoint *src_first;
-        Track *src, *dest;
+        case HILDON_HARDKEY_LEFT:
+            map_pan(-PAN_UNITS, 0);
+            return TRUE;
 
-        if(policy_old > 0)
-        {
-            /* Append to current track. */
-            src = &data.path.path.track;
-            dest = &_track;
-        }
-        else
-        {
-            /* Prepend to current track. */
-            src = &_track;
-            dest = &data.path.path.track;
-        }
+        case HILDON_HARDKEY_RIGHT:
+            map_pan(PAN_UNITS, 0);
+            return TRUE;
 
-        /* Find src_first non-zero point. */
-        for(src_first = src->head - 1; src_first++ != src->tail; )
-            if(src_first->point.unity)
-                break;
+        case HILDON_HARDKEY_SELECT:
+            switch(_center_mode)
+            {
+                case CENTER_LATLON:
+                case CENTER_WAS_LEAD:
+                    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+                                _menu_ac_lead_item), TRUE);
+                    break;
+                case CENTER_LEAD:
+                case CENTER_WAS_LATLON:
+                    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+                                _menu_ac_latlon_item), TRUE);
+                    break;
+            }
+            return TRUE;
 
-        /* Append track points from src to dest. */
-        if(src->tail >= src_first)
-        {
-            guint num_dest_points = dest->tail - dest->head + 1;
-            guint num_src_points = src->tail - src_first + 1;
+        case HILDON_HARDKEY_FULLSCREEN:
+            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+                        _menu_fullscreen_item), !_fullscreen);
+            return TRUE;
 
-            /* Adjust dest->tail to be able to fit src track data
-             * plus room for more track data. */
-            track_resize(dest,
-                    num_dest_points + num_src_points + ARRAY_CHUNK_SIZE);
+        case HILDON_HARDKEY_INCREASE:
+        case HILDON_HARDKEY_DECREASE:
+            if(!_key_zoom_timeout_sid)
+            {
+                _key_zoom_new = _zoom
+                    + (event->keyval == HILDON_HARDKEY_INCREASE
+                            ? -_curr_repo->view_zoom_steps
+                            : _curr_repo->view_zoom_steps);
+                /* Remember, _key_zoom_new is unsigned. */
+                if(_key_zoom_new < MAX_ZOOM)
+                {
+                    gchar buffer[80];
+                    sprintf(buffer, "%s %d", _("Zoom to Level"), _key_zoom_new);
+                    hildon_banner_show_information(_window, NULL, buffer);
+                    _key_zoom_timeout_sid = g_timeout_add(
+                        500, key_zoom_timeout, NULL);
+                }
+            }
+            return TRUE;
 
-            memcpy(dest->tail + 1, src_first,
-                    num_src_points * sizeof(TrackPoint));
+        case HILDON_HARDKEY_ESC:
+            switch(_escape_key)
+            {
+                case ESCAPE_KEY_CHANGE_REPO:
+                    {
+                        GList *curr = g_list_find(_repo_list, _curr_repo);
+                        if(curr && curr->next)
+                            curr = curr->next;
+                        else
+                            curr = _repo_list;
+                        _curr_repo = curr->data;
+                        gtk_check_menu_item_set_active(
+                                GTK_CHECK_MENU_ITEM(_curr_repo->menu_item),
+                                TRUE);
+                    }
+                    break;
+                case ESCAPE_KEY_RESET_BLUETOOTH:
+                    reset_bluetooth();
+                    break;
+                default:
+                    switch(_show_tracks)
+                    {
+                        case 0:
+                            /* Nothing shown, nothing saved; just set both. */
+                            _show_tracks = TRACKS_MASK | ROUTES_MASK;
+                            break;
+                        case TRACKS_MASK << 16:
+                        case ROUTES_MASK << 16:
+                        case (ROUTES_MASK | TRACKS_MASK) << 16:
+                            /* Something was saved and nothing changed since.
+                             * Restore saved. */
+                            _show_tracks = _show_tracks >> 16;
+                            break;
+                        default:
+                            /* There is no history, or they changed something
+                             * since the last historical change. Save and
+                             * clear. */
+                            _show_tracks = _show_tracks << 16;
+                    }
+                    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+                                _menu_show_routes_item),
+                            _show_tracks & ROUTES_MASK);
 
-            dest->tail += num_src_points;
-        }
+                    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+                                _menu_show_tracks_item),
+                            _show_tracks & TRACKS_MASK);
+            }
+            return TRUE;
 
-        MACRO_CLEAR_TRACK(*src);
-        if(policy_old < 0)
-            _track = *dest;
-    }
-    else
-    {
-        MACRO_CLEAR_TRACK(_track);
-        /* Overwrite with data.track. */
-        _track = data.path.path.track;
-        track_resize(&_track,
-                _track.tail - _track.head + 1 + ARRAY_CHUNK_SIZE);
+        default:
+            return FALSE;
     }
-
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
 }
 
 static gboolean
-parse_route_gpx(gchar *buffer, gint size, gint policy_old)
+window_cb_key_release(GtkWidget* widget, GdkEventKey *event)
 {
-    SaxData data;
-    xmlSAXHandler sax_handler;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    data.path.path_type = ROUTE;
-    MACRO_INIT_ROUTE(data.path.path.route);
-    data.state = START;
-    data.chars = g_string_new("");
-
-    memset(&sax_handler, 0, sizeof(sax_handler));
-    sax_handler.characters = (charactersSAXFunc)gpx_chars;
-    sax_handler.startElement = (startElementSAXFunc)gpx_start_element;
-    sax_handler.endElement = (endElementSAXFunc)gpx_end_element;
-    sax_handler.entityDecl = (entityDeclSAXFunc)gpx_get_entity;
-    sax_handler.warning = (warningSAXFunc)gpx_error;
-    sax_handler.error = (errorSAXFunc)gpx_error;
-    sax_handler.fatalError = (fatalErrorSAXFunc)gpx_error;
-
-    xmlSAXUserParseMemory(&sax_handler, &data, buffer, size);
-    g_string_free(data.chars, TRUE);
-
-    if(data.state != FINISH)
+    switch(event->keyval)
     {
-        vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
-        return FALSE;
-    }
-    
-    if(policy_old && _route.head)
-    {
-        Point *src_first;
-        Route *src, *dest;
-
-        if(policy_old > 0)
-        {
-            /* Append to current route. */
-            src = &data.path.path.route;
-            dest = &_route;
-        }
-        else
-        {
-            /* Prepend to current route. */
-            src = &_route;
-            dest = &data.path.path.route;
-        }
+        case HILDON_HARDKEY_INCREASE:
+        case HILDON_HARDKEY_DECREASE:
+            if(_key_zoom_timeout_sid)
+            {
+                g_source_remove(_key_zoom_timeout_sid);
+                _key_zoom_timeout_sid = 0;
+                map_set_zoom(_key_zoom_new);
+            }
+            return TRUE;
 
-        /* Find src_first non-zero point. */
-        for(src_first = src->head - 1; src_first++ != src->tail; )
-            if(src_first->unity)
-                break;
+        default:
+            return FALSE;
+    }
+}
 
-        /* Append route points from src to dest. */
-        if(src->tail >= src_first)
-        {
-            WayPoint *curr;
-            guint num_dest_points = dest->tail - dest->head + 1;
-            guint num_src_points = src->tail - src_first + 1;
+static gboolean
+map_cb_configure(GtkWidget *widget, GdkEventConfigure *event)
+{
+    printf("%s(%d, %d)\n", __PRETTY_FUNCTION__,
+            _map_widget->allocation.width, _map_widget->allocation.height);
 
-            /* Adjust dest->tail to be able to fit src route data
-             * plus room for more route data. */
-            route_resize(dest, num_dest_points + num_src_points);
+    _screen_width_pixels = _map_widget->allocation.width;
+    _screen_height_pixels = _map_widget->allocation.height;
+    _screen_grids_halfwidth = pixel2grid(_screen_width_pixels) / 2;
+    _screen_grids_halfheight = pixel2grid(_screen_height_pixels) / 2;
 
-            memcpy(dest->tail + 1, src_first,
-                    num_src_points * sizeof(Point));
+    MACRO_RECALC_FOCUS_BASE();
+    MACRO_RECALC_FOCUS_SIZE();
 
-            dest->tail += num_src_points;
+    _min_center.unitx = pixel2unit(grid2pixel(_screen_grids_halfwidth));
+    _min_center.unity = pixel2unit(grid2pixel(_screen_grids_halfheight));
+    _max_center.unitx = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfwidth) - 1;
+    _max_center.unity = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfheight)- 1;
 
-            /* Append waypoints from src to dest->. */
-            route_wresize(dest, (dest->wtail - dest->whead)
-                    + (src->wtail - src->whead) + 2);
-            for(curr = src->whead - 1; curr++ != src->wtail; )
-            {
-                (++(dest->wtail))->point = dest->head + num_dest_points
-                    + (curr->point - src_first);
-                dest->wtail->desc = curr->desc;
-            }
+    map_center_unit(_center.unitx, _center.unity);
 
-        }
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-        /* Kill old route - don't use MACRO_CLEAR_ROUTE(), because that
-         * would free the string desc's that we just moved to data.route. */
-        g_free(src->head);
-        g_free(src->whead);
-        if(policy_old < 0)
-            _route = *dest;
-    }
-    else
+static gboolean
+sat_panel_expose(GtkWidget *widget, GdkEventExpose *event)
+{
+    PangoContext *context = NULL;
+    PangoLayout *layout = NULL;
+    PangoFontDescription *fontdesc = NULL;
+    gchar *tmp = NULL;
+    guint x, y;
+
+    draw_sat_info(widget,
+        0, 0,
+        widget->allocation.width,
+        widget->allocation.height,
+        FALSE);
+
+    context = gtk_widget_get_pango_context(widget);
+    layout = pango_layout_new(context);
+    fontdesc =  pango_font_description_new();
+
+    pango_font_description_set_family(fontdesc,"Sans Serif");
+    pango_font_description_set_size(fontdesc, 14*PANGO_SCALE);
+
+    /* Sat View/In Use */
+    tmp = g_strdup_printf("%d/%d", _gps.satinuse, _gps.satinview);
+    pango_layout_set_font_description (layout, fontdesc);
+    pango_layout_set_text(layout, tmp, strlen(tmp));
+    gdk_draw_layout(widget->window,
+        widget->style->fg_gc[GTK_STATE_NORMAL],
+        20, 2,
+        layout);
+    g_free(tmp);
+
+    switch(_gps.fix)
     {
-        MACRO_CLEAR_ROUTE(_route);
-        /* Overwrite with data.route. */
-        _route = data.path.path.route;
-        route_resize(&_route, _route.tail - _route.head + 1);
-    }
+        case 2:
+        case 3: tmp = g_strdup_printf("%dD fix", _gps.fix); break;
+        default: tmp = g_strdup_printf("nofix"); break;
+    }
+    pango_layout_set_text(layout, tmp, strlen(tmp));
+    pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
+    pango_layout_get_pixel_size(layout, &x, &y);
+    gdk_draw_layout(widget->window,
+        widget->style->fg_gc[GTK_STATE_NORMAL],
+        widget->allocation.width - 20 - x, 2,
+        layout);
+    g_free(tmp);
+
+    pango_font_description_free (fontdesc);
+    g_object_unref (layout);
 
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
-/**
- * This is a multi-purpose function for allowing the user to select a file
- * for either reading or writing.  If chooser_action is
- * GTK_FILE_CHOOSER_ACTION_OPEN, then bytes_out and size_out must be
- * non-NULL.  If chooser_action is GTK_FILE_CHOOSER_ACTION_SAVE, then
- * handle_out must be non-NULL.  Either dir or file (or both) can be NULL.
- * This function returns TRUE if a file was successfully opened.
- */
 static gboolean
-open_file(gchar **bytes_out, GnomeVFSHandle **handle_out, gint *size_out,
-        gchar **dir, gchar **file, GtkFileChooserAction chooser_action)
+heading_panel_expose(GtkWidget *widget, GdkEventExpose *event)
 {
-    GtkWidget *dialog;
-    gboolean success = FALSE;
-    printf("%s()\n", __PRETTY_FUNCTION__);
-
-    dialog = hildon_file_chooser_dialog_new(GTK_WINDOW(_window),chooser_action);
+    guint size, xoffset, yoffset, i, x, y;
+    gint dir;
+    gfloat tmp;
+    gchar *text;
+    PangoContext            *context=NULL;
+    PangoLayout             *layout=NULL;
+    PangoFontDescription    *fontdesc=NULL;
 
-    if(dir && *dir)
-        gtk_file_chooser_set_current_folder_uri(
-                GTK_FILE_CHOOSER(dialog), *dir);
-    if(file && *file)
+    size = MIN(widget->allocation.width, widget->allocation.height);
+    if(widget->allocation.width > widget->allocation.height)
     {
-        GValue val;
-        gtk_file_chooser_set_uri(
-                GTK_FILE_CHOOSER(dialog), *file);
-        if(chooser_action == GTK_FILE_CHOOSER_ACTION_SAVE)
-        {
-            /* Work around a bug in HildonFileChooserDialog. */
-            memset(&val, 0, sizeof(val));
-            g_value_init(&val, G_TYPE_BOOLEAN);
-            g_value_set_boolean(&val, FALSE);
-            g_object_set_property(G_OBJECT(dialog), "autonaming", &val);
-            gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog),
-                    strrchr(*file, '/') + 1);
-        }
+        xoffset = (widget->allocation.width - widget->allocation.height) / 2;
+        yoffset = 0;
     }
-
-    gtk_widget_show_all(GTK_WIDGET(dialog));
-
-    while(!success && gtk_dialog_run(GTK_DIALOG(dialog))==GTK_RESPONSE_OK)
+    else
     {
-        gchar *file_uri_str;
-        GnomeVFSResult vfs_result;
-
-        /* Get the selected filename. */
-        file_uri_str = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
+        xoffset = 0;
+        yoffset = (widget->allocation.height - widget->allocation.width) / 2;
+    }
+    context = gtk_widget_get_pango_context(widget);
+    layout = pango_layout_new(context);
+    fontdesc =  pango_font_description_new();
+    pango_font_description_set_family(fontdesc,"Sans Serif");
+    pango_font_description_set_size(fontdesc,12*PANGO_SCALE);
+    pango_layout_set_font_description (layout, fontdesc);
+    pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
+
+    text = g_strdup_printf("%3d°", (guint)_gps.heading);
+    pango_layout_set_text(layout, text, -1);
+    pango_layout_get_pixel_size(layout, &x, &y);
+
+    gdk_draw_layout(widget->window,
+        widget->style->fg_gc[GTK_STATE_NORMAL],
+        xoffset + size/2 - x/2,
+        yoffset + size - y - 2, layout);
+    g_free(text);
+
+    gdk_draw_arc (widget->window,
+        widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+        FALSE,
+        xoffset, yoffset + size/2,
+        size, size,
+        0, 64 * 180);
+
+    /* Simple arrow for heading*/
+    gdk_draw_line(widget->window,
+        widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+        xoffset + size/2 + 3,
+        yoffset + size - y - 5,
+        xoffset + size/2,
+        yoffset + size/2 + 5);
+
+    gdk_draw_line(widget->window,
+        widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+        xoffset + size/2 - 3,
+        yoffset + size - y - 5,
+        xoffset + size/2,
+        yoffset + size/2 + 5);
+
+    gdk_draw_line(widget->window,
+        widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+        xoffset + size/2 - 3,
+        yoffset + size - y - 5,
+        xoffset + size/2,
+        yoffset + size - y - 8);
+
+    gdk_draw_line(widget->window,
+        widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+        xoffset + size/2 + 3,
+        yoffset + size - y - 5,
+        xoffset + size/2,
+        yoffset + size - y - 8);
+
+    gint angle[5] = {-90,-45,0,45,90};
+    gint fsize[5] = {0,4,10,4,0};
+    for(i = 0; i < 5; i++)
+    {
+        dir = (gint)(_gps.heading/45)*45 + angle[i];
 
-        if((chooser_action == GTK_FILE_CHOOSER_ACTION_OPEN
-                && (GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
-                        file_uri_str, size_out, bytes_out))))
-                || (chooser_action == GTK_FILE_CHOOSER_ACTION_SAVE
-                    && GNOME_VFS_OK != (vfs_result = gnome_vfs_create(
-                            handle_out, file_uri_str,
-                            GNOME_VFS_OPEN_WRITE, FALSE, 0664))))
+        switch(dir)
         {
-            gchar buffer[1024];
-            sprintf(buffer, "%s %s:\n%s", _("Failed to open file for"),
-                    chooser_action == GTK_FILE_CHOOSER_ACTION_OPEN
-                    ? _("reading") : _("writing"),
-                    gnome_vfs_result_to_string(vfs_result));
-            popup_error(dialog, buffer);
+            case   0:
+            case 360: text = g_strdup("N"); break;
+            case  45:
+            case 405:
+                text = g_strdup("NE"); break;
+            case  90:
+                text = g_strdup("E"); break;
+            case 135:
+                text = g_strdup("SE"); break;
+            case 180:
+                text = g_strdup("S"); break;
+            case 225:
+                text = g_strdup("SW"); break;
+            case 270:
+            case -90:
+                text = g_strdup("W"); break;
+            case 315:
+            case -45:
+                text = g_strdup("NW"); break;
+            default :
+                text = g_strdup("??");
+                break;
         }
-        else
-            success = TRUE;
 
-        g_free(file_uri_str);
+        tmp = ((dir - _gps.heading) * (1.f / 180.f)) * PI;
+        gdk_draw_line(widget->window,
+            widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
+            xoffset + size/2 + ((size/2 - 5) * sinf(tmp)),
+            yoffset + size - ((size/2 - 5) * cosf(tmp)),
+            xoffset + size/2 + ((size/2 + 5) * sinf(tmp)),
+            yoffset + size - ((size/2 + 5) * cosf(tmp)));
+
+        x = fsize[i];
+        if(abs((guint)(_gps.heading/45)*45 - _gps.heading)
+                > abs((guint)(_gps.heading/45)*45 + 45 - _gps.heading)
+                && (i > 0))
+            x = fsize[i - 1];
+
+        pango_font_description_set_size(fontdesc,(10 + x)*PANGO_SCALE);
+        pango_layout_set_font_description (layout, fontdesc);
+        pango_layout_set_text(layout, text, -1);
+        pango_layout_get_pixel_size(layout, &x, &y);
+        x = xoffset + size/2 + ((size/2 + 15) * sinf(tmp)) - x/2,
+        y = yoffset + size - ((size/2 + 15) * cosf(tmp)) - y/2,
+
+        gdk_draw_layout(widget->window,
+            widget->style->fg_gc[GTK_STATE_NORMAL],
+            x, y, layout);
+        g_free(text);
     }
 
-    if(success)
-    {
-        /* Success!. */
-        if(dir)
-        {
-            if(*dir)
-                g_free(*dir);
-            *dir = gtk_file_chooser_get_current_folder_uri(
-                    GTK_FILE_CHOOSER(dialog));
-        }
+    pango_font_description_free (fontdesc);
+    g_object_unref (layout);
+
+    return TRUE;
+}
+
+static gboolean
+map_cb_expose(GtkWidget *widget, GdkEventExpose *event)
+{
+    printf("%s(%d, %d, %d, %d)\n", __PRETTY_FUNCTION__,
+            event->area.x, event->area.y,
+            event->area.width, event->area.height);
+
+    gdk_draw_drawable(
+            _map_widget->window,
+            _gc_mark,
+            _map_pixmap,
+            event->area.x + _offsetx, event->area.y + _offsety,
+            event->area.x, event->area.y,
+            event->area.width, event->area.height);
+    map_draw_mark();
+
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-        /* If desired, save the file for later. */
-        if(file)
-        {
-            if(*file)
-                g_free(*file);
-            *file = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
-        }
-    }
+static gboolean
+map_cb_button_press(GtkWidget *widget, GdkEventButton *event)
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    gtk_widget_destroy(dialog);
+    _cmenu_position_x = event->x + 0.5;
+    _cmenu_position_y = event->y + 0.5;
 
-    vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, success);
-    return success;
+    /* Return FALSE to allow context menu to work. */
+    vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+    return FALSE;
 }
 
-/**
- * Refresh the view based on the fact that the route has been automatically
- * updated.
- */
 static gboolean
-auto_route_dl_idle_refresh()
+map_cb_button_release(GtkWidget *widget, GdkEventButton *event)
 {
-    /* Make sure we're still supposed to do work. */
-    vprintf("%s()\n", __PRETTY_FUNCTION__);
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    if(!_autoroute_data.enabled)
-        _autoroute_data.handle = NULL;
+#ifdef DEBUG
+    if(event->button != 1)
+    {
+        _pos.unitx = x2unit((gint)(event->x + 0.5));
+        _pos.unity = y2unit((gint)(event->y + 0.5));
+        unit2latlon(_pos.unitx, _pos.unity, _pos_lat, _pos_lon);
+        _speed = 20.f;
+        integerize_data();
+        track_add(time(NULL), FALSE);
+        refresh_mark();
+    }
     else
+#endif
     {
-        if(parse_route_gpx(_autoroute_data.bytes, _autoroute_data.bytes_read,0))
-        {
-            /* Find the nearest route point, if we're connected. */
-            route_find_nearest_point();
-
-            map_force_redraw();
-        }
+        if(_center_mode > 0)
+            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
+                        _menu_ac_none_item), TRUE);
+        map_center_unit(
+                x2unit((gint)(event->x + 0.5)),
+                y2unit((gint)(event->y + 0.5)));
     }
 
-    _autoroute_data.in_progress = FALSE;
+    /* Return FALSE to avoid context menu (if it hasn't popped up already). */
+    vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+    return FALSE;
+}
+
+static gboolean
+channel_cb_error(GIOChannel *src, GIOCondition condition, gpointer data)
+{
+    printf("%s(%d)\n", __PRETTY_FUNCTION__, condition);
+
+    /* An error has occurred - re-connect(). */
+    rcvr_disconnect();
+    track_add(0, FALSE);
+
+    if(_conn_state > RCVR_OFF)
+    {
+        set_conn_state(RCVR_DOWN);
+        gps_hide_text();
+        rcvr_connect_now();
+    }
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
     return FALSE;
 }
 
-/**
- * Read the data provided by the given handle as GPX data, updating the
- * auto-route with that data.
- */
-static void
-auto_route_dl_cb_read(GnomeVFSAsyncHandle *handle,
-        GnomeVFSResult result,
-        gpointer bytes,
-        GnomeVFSFileSize bytes_requested,
-        GnomeVFSFileSize bytes_read)
+static gboolean
+channel_cb_connect(GIOChannel *src, GIOCondition condition, gpointer data)
 {
-    vprintf("%s(%s)\n", __PRETTY_FUNCTION__,gnome_vfs_result_to_string(result));
+    int error, size = sizeof(error);
+    printf("%s(%d)\n", __PRETTY_FUNCTION__, condition);
 
-    _autoroute_data.bytes_read += bytes_read;
-    if(result == GNOME_VFS_OK)
+    if(*_rcvr_mac != '/'
+            && (getsockopt(_fd, SOL_SOCKET, SO_ERROR, &error, &size) || error))
     {
-        /* Expand bytes and continue reading. */
-        if(_autoroute_data.bytes_read * 2 > _autoroute_data.bytes_maxsize)
-        {
-            _autoroute_data.bytes = g_renew(gchar, _autoroute_data.bytes,
-                    2 * _autoroute_data.bytes_read);
-            _autoroute_data.bytes_maxsize = 2 * _autoroute_data.bytes_read;
-        }
-        gnome_vfs_async_read(_autoroute_data.handle,
-                _autoroute_data.bytes + _autoroute_data.bytes_read,
-                _autoroute_data.bytes_maxsize - _autoroute_data.bytes_read,
-                (GnomeVFSAsyncReadCallback)auto_route_dl_cb_read, NULL);
+        printf("%s(): Error connecting to receiver; retrying...\n",
+                __PRETTY_FUNCTION__);
+        /* Try again. */
+        rcvr_disconnect();
+        rcvr_connect_later();
     }
     else
-        g_idle_add((GSourceFunc)auto_route_dl_idle_refresh, NULL);
+    {
+        printf("%s(): Connected to receiver!\n",
+                __PRETTY_FUNCTION__);
+        set_conn_state(RCVR_UP);
+        _input_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE,
+                G_IO_IN | G_IO_PRI, channel_cb_input, NULL, NULL);
+    }
 
+    _connect_sid = 0;
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return FALSE;
 }
 
-/**
- * Open the given handle in preparation for reading GPX data.
- */
+#define MACRO_PARSE_INT(tofill, str) { \
+    gchar *error_check; \
+    (tofill) = strtol((str), &error_check, 10); \
+    if(error_check == (str)) \
+    { \
+        fprintf(stderr, "Line %d: Failed to parse string as int: %s\n", \
+                __LINE__, str); \
+        hildon_banner_show_information(_window, NULL, \
+                _("Invalid NMEA input from receiver!")); \
+        return; \
+    } \
+}
+#define MACRO_PARSE_FLOAT(tofill, str) { \
+    gchar *error_check; \
+    (tofill) = g_ascii_strtod((str), &error_check); \
+    if(error_check == (str)) \
+    { \
+        fprintf(stderr, "Failed to parse string as float: %s\n", str); \
+        hildon_banner_show_information(_window, NULL, \
+                _("Invalid NMEA input from receiver!")); \
+        return; \
+    } \
+}
 static void
-auto_route_dl_cb_open(GnomeVFSAsyncHandle *handle, GnomeVFSResult result)
+channel_parse_rmc(gchar *sentence)
 {
-    vprintf("%s()\n", __PRETTY_FUNCTION__);
+    /* Recommended Minimum Navigation Information C
+     *  1) UTC Time
+     *  2) Status, V=Navigation receiver warning A=Valid
+     *  3) Latitude
+     *  4) N or S
+     *  5) Longitude
+     *  6) E or W
+     *  7) Speed over ground, knots
+     *  8) Track made good, degrees true
+     *  9) Date, ddmmyy
+     * 10) Magnetic Variation, degrees
+     * 11) E or W
+     * 12) FAA mode indicator (NMEA 2.3 and later)
+     * 13) Checksum
+     */
+    gchar *token, *dpoint, *gpstime, *gpsdate;
+    gdouble tmpd = 0.f;
+    guint tmpi = 0;
+    gboolean newly_fixed = FALSE;
+    vprintf("%s(): %s", __PRETTY_FUNCTION__, sentence);
 
-    if(result == GNOME_VFS_OK)
-        gnome_vfs_async_read(_autoroute_data.handle,
-                _autoroute_data.bytes,
-                _autoroute_data.bytes_maxsize,
-                (GnomeVFSAsyncReadCallback)auto_route_dl_cb_read, NULL);
+#define DELIM ","
+
+    /* Parse time. */
+    token = strsep(&sentence, DELIM);
+    gpstime = g_strdup(token);
+
+    token = strsep(&sentence, DELIM);
+    /* Token is now Status. */
+    if(*token != 'A')
+    {
+        /* Data is invalid - not enough satellites?. */
+        if(_conn_state != RCVR_UP)
+        {
+            set_conn_state(RCVR_UP);
+            track_add(0, FALSE);
+        }
+    }
     else
     {
-        _autoroute_data.in_progress = FALSE;
-        _autoroute_data.handle = NULL;
+        /* Data is valid. */
+        if(_conn_state != RCVR_FIXED)
+        {
+            newly_fixed = TRUE;
+            set_conn_state(RCVR_FIXED);
+        }
     }
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
+    /* Parse the latitude. */
+    token = strsep(&sentence, DELIM);
+    if(*token)
+    {
+        dpoint = strchr(token, '.');
+        MACRO_PARSE_FLOAT(tmpd, dpoint - 2);
+        dpoint[-2] = '\0';
+        MACRO_PARSE_INT(tmpi, token);
+        _pos_lat = tmpi + (tmpd * (1.0 / 60.0));
+        _gps.latitude = _pos_lat;
+    }
 
-/**
- * This function is periodically run to download updated auto-route data
- * from the route source.
- */
-static gboolean
-auto_route_dl_idle()
-{
-    gchar buffer[1024];
-    vprintf("%s(%f, %f, %s)\n", __PRETTY_FUNCTION__,
-            _pos_lat, _pos_lon, _autoroute_data.dest);
+    /* Parse N or S. */
+    token = strsep(&sentence, DELIM);
+    if(*token)
+        sprintf(_gps.slatitude, "%c %u°%07.04f", token[0], tmpi, tmpd);
 
-    sprintf(buffer,"http://www.gnuite.com/cgi-bin/gpx.cgi?saddr=%f,%f&daddr=%s",
-            _pos_lat, _pos_lon, _autoroute_data.dest);
-    _autoroute_data.bytes_read = 0;
+    if(*token && token[0] == 'S')
+        _pos_lat = -_pos_lat;
 
-    gnome_vfs_async_open(&_autoroute_data.handle,
-            buffer, GNOME_VFS_OPEN_READ,
-            GNOME_VFS_PRIORITY_DEFAULT,
-            (GnomeVFSAsyncOpenCallback)auto_route_dl_cb_open, NULL);
+    /* Parse the longitude. */
+    token = strsep(&sentence, DELIM);
+    if(*token)
+    {
+        dpoint = strchr(token, '.');
+        MACRO_PARSE_FLOAT(tmpd, dpoint - 2);
+        dpoint[-2] = '\0';
+        MACRO_PARSE_INT(tmpi, token);
+        _pos_lon = tmpi + (tmpd * (1.0 / 60.0));
+        _gps.longitude = _pos_lon;
+    }
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-    return FALSE;
-}
+    /* Parse E or W. */
+    token = strsep(&sentence, DELIM);
+    if(*token)
+        sprintf(_gps.slongitude, "%c %u°%07.04f", token[0], tmpi, tmpd);
 
-/**
- * Cancel the current auto-route.
- */
-static void
-cancel_autoroute()
-{
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    if(*token && token[0] == 'W')
+        _pos_lon = -_pos_lon;
+
+    /* Parse speed over ground, knots. */
+    token = strsep(&sentence, DELIM);
+    if(*token)
+    {
+        MACRO_PARSE_FLOAT(_speed, token);
+        _gps.speed = _speed;
+        if(_gps.fix > 1)
+            _gps.maxspeed = MAX(_gps.maxspeed, _speed);
+    }
 
-    if(_autoroute_data.enabled)
+    /* Parse heading, degrees from true north. */
+    token = strsep(&sentence, DELIM);
+    if(*token)
     {
-        _autoroute_data.enabled = FALSE;
-        if(_autoroute_data.dest)
-        {
-            g_free(_autoroute_data.dest);
-            _autoroute_data.dest = NULL;
-        }
-        if(_autoroute_data.handle)
-        {
-            gnome_vfs_async_cancel(_autoroute_data.handle);
-            _autoroute_data.handle = NULL;
-        }
-        if(_autoroute_data.bytes)
-        {
-            g_free(_autoroute_data.bytes);
-            _autoroute_data.bytes = NULL;
-        }
-        _autoroute_data.in_progress = FALSE;
+        MACRO_PARSE_FLOAT(_heading, token);
+        _gps.heading = _heading;
     }
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
+    /* Parse date. */
+    token = strsep(&sentence, DELIM);
+    if(*token)
+    {
+        time_t timeloc;
+        gpsdate = g_strdup_printf("%s%s", token, gpstime);
+        strptime(gpsdate, "%d%m%y%H%M%S", &_gps.time);
+        if(_gps.time.tm_year >= 0 && _gps.time.tm_year <= 68)
+            _gps.time.tm_year += 100; /* year 2000 */
+        _gps.time.tm_mon -= 1;
+        timeloc = mktime(&_gps.time);
+        timeloc += _gmtoffset;
+        localtime_r(&timeloc, &_gps.timeloc);
+        g_free(gpstime);
+        g_free(gpsdate);
+    }
 
-/**
- * Save state and destroy all non-UI elements created by this program in
- * preparation for exiting.
- */
-static void
-maemo_mapper_destroy(void)
-{
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    /* Translate data into integers. */
+    integerize_data();
 
-    config_save();
-    rcvr_disconnect();
-    /* _program and widgets have already been destroyed. */
+    /* Add new data to track. */
+    if(_conn_state == RCVR_FIXED)
+        track_add(time(NULL), newly_fixed);
 
-    MACRO_CLEAR_TRACK(_track);
-    if(_route.head)
-        MACRO_CLEAR_TRACK(_route);
+    /* Move mark to new location. */
+    refresh_mark();
 
     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
-/**
- * Initialize everything required in preparation for calling gtk_main().
- */
-static void
-maemo_mapper_init(gint argc, gchar **argv)
+ static void
+channel_parse_gga(gchar *sentence)
 {
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    /* GGA          Global Positioning System Fix Data
+     1. Fix Time
+     2. Latitude
+     3. N or S
+     4. Longitude
+     5. E or W
+     6. Fix quality
+                   0 = invalid
+                   1 = GPS fix (SPS)
+                   2 = DGPS fix
+                   3 = PPS fix
+                   4 = Real Time Kinematic
+                   5 = Float RTK
+                   6 = estimated (dead reckoning) (2.3 feature)
+                   7 = Manual input mode
+                   8 = Simulation mode
+     7. Number of satellites being tracked
+     8. Horizontal dilution of position
+     9. Altitude, Meters, above mean sea level
+     10. Alt unit (meters)
+     11. Height of geoid (mean sea level) above WGS84 ellipsoid
+     12. unit
+     13. (empty field) time in seconds since last DGPS update
+     14. (empty field) DGPS station ID number
+     15. the checksum data
+     */
+    gchar *token;
+    vprintf("%s(): %s", __PRETTY_FUNCTION__, sentence);
 
-    config_init();
+#define DELIM ","
 
-    /* Initialize _program. */
-    _program = HILDON_PROGRAM(hildon_program_get_instance());
-    g_set_application_name("Maemo Mapper");
+    /* Skip Fix time */
+    token = strsep(&sentence, DELIM);
+    /* Skip latitude */
+    token = strsep(&sentence, DELIM);
+    /* Skip N or S */
+    token = strsep(&sentence, DELIM);
+    /* Skip longitude */
+    token = strsep(&sentence, DELIM);
+    /* Skip S or W */
+    token = strsep(&sentence, DELIM);
 
-    /* Initialize _window. */
-    _window = GTK_WIDGET(hildon_window_new());
-    hildon_program_add_window(_program, HILDON_WINDOW(_window));
+    /* Parse Fix quality */
+    token = strsep(&sentence, DELIM);
 
-    /* Create and add widgets and supporting data. */
-    _map_widget = gtk_drawing_area_new();
-    gtk_container_add(GTK_CONTAINER(_window), _map_widget);
+    /* Parse number of satellites */
+    token = strsep(&sentence, DELIM);
+    if(*token)
+        MACRO_PARSE_INT(_gps.satinuse, token);
 
-    gtk_widget_realize(_map_widget);
+    /* Parse Horizontal dilution of position */
+    token = strsep(&sentence, DELIM);
+    if(*token)
+        MACRO_PARSE_INT(_gps.hdop, token);
 
-    _map_pixmap = gdk_pixmap_new(
-                _map_widget->window,
-                BUF_WIDTH_PIXELS, BUF_HEIGHT_PIXELS,
-                -1); /* -1: use bit depth of widget->window. */
+    /* Altitude */
+    token = strsep(&sentence, DELIM);
+    if(!sentence)
+        return; /* because this is an invalid sentence. */
+    if(*token)
+        MACRO_PARSE_INT(_gps.altitude, token);
 
-    /* Connect signals. */
-    g_signal_connect(G_OBJECT(_window), "destroy",
-            G_CALLBACK(gtk_main_quit), NULL);
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
 
-    g_signal_connect(G_OBJECT(_window), "key_press_event",
-            G_CALLBACK(window_cb_key_press), NULL);
+static void
+channel_parse_gsa(gchar *sentence)
+{
+    /* GPS DOP and active satellites
+     *  1) Auto selection of 2D or 3D fix (M = manual)
+     *  2) 3D fix - values include: 1 = no fix, 2 = 2D, 3 = 2D
+     *  3) PRNs of satellites used for fix
+     *     (space for 12)
+     *  4) PDOP (dilution of precision)
+     *  5) Horizontal dilution of precision (HDOP)
+     *  6) Vertical dilution of precision (VDOP)
+     *  7) Checksum
+     */
+    gchar *token;
+    guint i, sat;
+    vprintf("%s(): %s", __PRETTY_FUNCTION__, sentence);
 
-    g_signal_connect(G_OBJECT(_window), "key_release_event",
-            G_CALLBACK(window_cb_key_release), NULL);
+#define DELIM ","
 
-    g_signal_connect(G_OBJECT(_map_widget), "configure_event",
-            G_CALLBACK(map_cb_configure), NULL);
+    /* Skip Auto selection. */
+    token = strsep(&sentence, DELIM);
 
-    g_signal_connect(G_OBJECT(_map_widget), "expose_event",
-            G_CALLBACK(map_cb_expose), NULL);
+    /* 3D fix. */
+    token = strsep(&sentence, DELIM);
+    if(!sentence)
+        return; /* because this is an invalid sentence. */
+    MACRO_PARSE_INT(_gps.fix, token);
 
-    g_signal_connect(G_OBJECT(_map_widget), "button_press_event",
-            G_CALLBACK(map_cb_button_press), NULL);
+    _gps.satinuse = 0;
+    for(i = 0; i < 12; i++)
+    {
+        token = strsep(&sentence, DELIM);
+        if((sat = atoi(token)))
+            _gps.satforfix[_gps.satinuse++] = sat;
+    }
 
-    g_signal_connect(G_OBJECT(_map_widget), "button_release_event",
-            G_CALLBACK(map_cb_button_release), NULL);
+    /* PDOP */
+    token = strsep(&sentence, DELIM);
+    if(*token)
+        MACRO_PARSE_FLOAT(_gps.pdop, token);
 
-    gtk_widget_add_events(_map_widget,
-            GDK_EXPOSURE_MASK
-            | GDK_BUTTON_PRESS_MASK
-            | GDK_BUTTON_RELEASE_MASK);
+    /* HDOP */
+    token = strsep(&sentence, DELIM);
+    if(*token)
+        MACRO_PARSE_FLOAT(_gps.hdop, token);
 
-    osso_hw_set_event_cb(_osso, NULL, osso_cb_hw_state, NULL);
+    /* VDOP */
+    token = strsep(&sentence, DELIM);
+    if(*token)
+        MACRO_PARSE_FLOAT(_gps.vdop, token);
 
-    gnome_vfs_async_set_job_limit(24);
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
 
-    /* Initialize data. */
+static void
+channel_parse_gsv(gchar *sentence)
+{
+    /* Must be GSV - Satellites in view
+     *  1) total number of messages
+     *  2) message number
+     *  3) satellites in view
+     *  4) satellite number
+     *  5) elevation in degrees (0-90)
+     *  6) azimuth in degrees to true north (0-359)
+     *  7) SNR in dB (0-99)
+     *  more satellite infos like 4)-7)
+     *  n) checksum
+     */
+    gchar *token;
+    guint msgcnt, nummsgs;
+    static guint running_total = 0;
+    static guint num_sats_used = 0;
+    static guint satcnt = 0;
+    vprintf("%s(): %s", __PRETTY_FUNCTION__, sentence);
 
-    /* set XML_TZONE */
-    {
-        time_t time1;
-        struct tm time2;
-        time1 = time(NULL);
-        localtime_r(&time1, &time2);
-        sprintf(XML_TZONE, "%+03ld:%02ld",
-                (time2.tm_gmtoff / 60 / 60), (time2.tm_gmtoff / 60) % 60);
-    }
+    /* Parse number of messages. */
+    token = strsep(&sentence, DELIM);
+    if(!sentence)
+        return; /* because this is an invalid sentence. */
+    MACRO_PARSE_INT(nummsgs, token);
 
-    memset(&_track, 0, sizeof(_track));
-    memset(&_route, 0, sizeof(_route));
-    _last_spoken_phrase = g_strdup("");
+    /* Parse message number. */
+    token = strsep(&sentence, DELIM);
+    if(!sentence)
+        return; /* because this is an invalid sentence. */
+    MACRO_PARSE_INT(msgcnt, token);
 
-    /* Set up track array. */
-    MACRO_INIT_TRACK(_track);
+    /* Parse number of satellites in view. */
+    token = strsep(&sentence, DELIM);
+    if(!sentence)
+        return; /* because this is an invalid sentence. */
+    MACRO_PARSE_INT(_gps.satinview, token);
 
-    _downloads_hash = g_hash_table_new((GHashFunc)download_hashfunc,
-            (GEqualFunc)download_equalfunc);
-    memset(&_autoroute_data, 0, sizeof(_autoroute_data));
+    /* Loop until there are no more satellites to parse. */
+    while(sentence)
+    {
+        /* Get token for Satellite Number. */
+        token = strsep(&sentence, DELIM);
+        if(!sentence)
+            break; /* because this is an invalid sentence. */
+        _gps_sat[satcnt].prn = atoi(token);
 
-    integerize_data();
+        /* Get token for elevation in degrees (0-90). */
+        token = strsep(&sentence, DELIM);
+        if(!sentence)
+            break; /* because this is an invalid sentence. */
+        _gps_sat[satcnt].elevation = atoi(token);
 
-    /* Initialize our line styles. */
-    update_gcs();
+        /* Get token for azimuth in degrees to true north (0-359). */
+        token = strsep(&sentence, DELIM);
+        if(!sentence)
+            break; /* because this is an invalid sentence. */
+        _gps_sat[satcnt].azimuth = atoi(token);
 
-    menu_init();
+        /* Get token for SNR. */
+        token = strsep(&sentence, DELIM);
+        _gps_sat[satcnt].snr = atoi(token);
+        if(_gps_sat[satcnt].snr)
+        {
+            /* Snr is non-zero - add to total and count as used. */
+            running_total += _gps_sat[satcnt].snr;
+            num_sats_used++;
+        }
+        satcnt++;
+    }
 
-    /* If present, attempt to load the file specified on the command line. */
-    if(argc > 1)
+    if(msgcnt == nummsgs)
     {
-        GnomeVFSResult vfs_result;
-        gint size;
-        gchar *buffer;
-        gchar *file_uri;
-
-        /* Get the selected filename. */
-        file_uri = gnome_vfs_make_uri_from_shell_arg(argv[1]);
-
-        if(GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
-                        file_uri, &size, &buffer)))
+        /*  This is the last message. Calculate signal strength. */
+        if(num_sats_used)
         {
-            gchar buffer[1024];
-            sprintf(buffer, "%s %s:\n%s", _("Failed to open file for"),
-                    _("reading"), gnome_vfs_result_to_string(vfs_result));
-            popup_error(_window, buffer);
+            if(_conn_state == RCVR_UP)
+            {
+                gdouble fraction = running_total * sqrt(num_sats_used)
+                    / num_sats_used / 100.0;
+                BOUND(fraction, 0.0, 1.0);
+                hildon_banner_set_fraction(
+                        HILDON_BANNER(_fix_banner), fraction);
+            }
+            running_total = 0;
+            num_sats_used = 0;
         }
-        else
+        satcnt = 0;
+
+        /* Keep awake while they watch the progress bar. */
+        KEEP_DISPLAY_ON();
+    }
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+}
+
+static gboolean
+channel_cb_input(GIOChannel *src, GIOCondition condition, gpointer data)
+{
+    gchar *sentence = _gps_read_buf;
+    gsize bytes_read;
+    vprintf("%s(%d)\n", __PRETTY_FUNCTION__, condition);
+
+    if(G_IO_STATUS_NORMAL == g_io_channel_read_chars(
+                _channel,
+                _gps_read_buf + _gps_read_buf_pos,
+                sizeof(_gps_read_buf) - _gps_read_buf_pos -1,
+                &bytes_read,
+                NULL))
+    {
+        gchar *eol;
+        _gps_read_buf_pos += bytes_read;
+        _gps_read_buf[_gps_read_buf_pos] = '\0';
+        eol = strchr(_gps_read_buf, '\n');
+        while(eol)
         {
-            /* If auto is enabled, append the route, otherwise replace it. */
-            if(parse_route_gpx(buffer, size, 0))
-                hildon_banner_show_information(
-                        _window, NULL, _("Route Opened"));
+            gchar *sptr = sentence + 1;
+            guint csum = 0;
+            gint leftover = _gps_read_buf + _gps_read_buf_pos - eol - 1;
+            *eol = '\0';
+            while(*sptr && *sptr != '*')
+                csum ^= *sptr++;
+            if(!*sptr || csum == strtol(sptr + 1, NULL, 16))
+            {
+                if(*sptr)
+                    *sptr = '\0'; /* take checksum out of the sentence. */
+                if(!strncmp(sentence + 3, "GSV", 3))
+                    channel_parse_gsv(sentence + 7);
+                else if(!strncmp(sentence + 3, "RMC", 3))
+                    channel_parse_rmc(sentence + 7);
+                else if(!strncmp(sentence + 3, "GGA", 3))
+                    channel_parse_gga(sentence + 7);
+                else if(!strncmp(sentence + 3, "GSA", 3))
+                    channel_parse_gsa(sentence + 7);
+
+                if(_gps_info)
+                    gps_display_data();
+                if(_satdetails_on)
+                    gps_display_details();
+            }
+            else
+            {
+                fprintf(stderr, "%s: Bad checksum in NMEA sentence:\n%s\n",
+                        __PRETTY_FUNCTION__, sentence);
+            }
+            if(leftover <= 0)
+            {
+                /* last read was a newline */
+                _gps_read_buf_pos = 0;
+                eol = 0;
+            }
             else
-                popup_error(_window, _("Error parsing GPX file."));
-            g_free(buffer);
+            {
+                memmove(_gps_read_buf, eol+1, leftover+1); /* incl term. 0 */
+                _gps_read_buf_pos = leftover;
+                eol = strchr(_gps_read_buf, '\n');
+            }
         }
-        g_free(file_uri);
     }
 
-    gtk_idle_add((GSourceFunc)window_present, NULL);
-
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
 }
 
-/****************************************************************************
- * ABOVE: ROUTINES **********************************************************
- ****************************************************************************/
+static gboolean
+gps_toggled_from(GtkToggleButton *chk_gps,
+        GtkWidget *txt_from)
+{
+    gchar buffer[80];
+    gchar strlat[32];
+    gchar strlon[32];
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
+    g_ascii_formatd(strlat, 80, "%.06f", _pos_lat);
+    g_ascii_formatd(strlon, 80, "%.06f", _pos_lon);
+    sprintf(buffer, "%s, %s", strlat, strlon);
+    gtk_widget_set_sensitive(txt_from, !gtk_toggle_button_get_active(chk_gps));
+    gtk_entry_set_text(GTK_ENTRY(txt_from), buffer);
 
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-/****************************************************************************
- * BELOW: MAIN **************************************************************
- ****************************************************************************/
+static gboolean
+gps_toggled_auto(GtkToggleButton *chk_gps,
+        GtkWidget *chk_auto)
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-gint
-main(gint argc, gchar *argv[])
+    gtk_widget_set_sensitive(chk_auto, gtk_toggle_button_get_active(chk_gps));
+
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
+
+/**
+ * Display a dialog box to the user asking them to download a route.  The
+ * "From" and "To" textfields may be initialized using the first two
+ * parameters.  The third parameter, if set to TRUE, will cause the "Use GPS
+ * Location" checkbox to be enabled, which automatically sets the "From" to the
+ * current GPS position (this overrides any value that may have been passed as
+ * the "To" initializer).
+ * None of the passed strings are freed - that is left to the caller, and it is
+ * safe to free either string as soon as this function returns.
+ */
+static gboolean
+route_download(gchar *from, gchar *to, gboolean from_here)
 {
+    GtkWidget *dialog;
+    GtkWidget *table;
+    GtkWidget *label;
+    GtkWidget *chk_gps;
+    GtkWidget *chk_auto;
+    GtkWidget *txt_from;
+    GtkWidget *txt_to;
+    GtkWidget *hbox;
+    GtkEntryCompletion *from_comp;
+    GtkEntryCompletion *to_comp;
+    gchar *bytes = NULL;
+    gint size;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    g_thread_init(NULL);
+    dialog = gtk_dialog_new_with_buttons(_("Download Route"),
+            GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+            NULL);
 
-    /* Initialize _osso. */
-    _osso = osso_initialize("com.gnuite.maemo_mapper", VERSION, TRUE, NULL);
-    if(!_osso)
-    {
-        fprintf(stderr, "osso_initialize failed.\n");
-        return 1;
-    }
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+            table = gtk_table_new(2, 4, FALSE), TRUE, TRUE, 0);
 
-    gtk_init(&argc, &argv);
+    from_comp = gtk_entry_completion_new();
+    gtk_entry_completion_set_model(from_comp, GTK_TREE_MODEL(_loc_model));
+    gtk_entry_completion_set_text_column(from_comp, 0);
+    to_comp = gtk_entry_completion_new();
+    gtk_entry_completion_set_model(to_comp, GTK_TREE_MODEL(_loc_model));
+    gtk_entry_completion_set_text_column(to_comp, 0);
 
-    /* Init gconf. */
-    g_type_init();
-    gconf_init(argc, argv, NULL);
+    /* Auto. */
+    gtk_table_attach(GTK_TABLE(table),
+            hbox = gtk_hbox_new(FALSE, 6),
+            0, 2, 0, 1, 0, 0, 2, 4);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            chk_gps = gtk_check_button_new_with_label(
+                _("Use GPS Location")),
+            TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            chk_auto = gtk_check_button_new_with_label(
+                _("Auto-Update")),
+            TRUE, TRUE, 0);
+    gtk_widget_set_sensitive(chk_auto, FALSE);
 
-    gnome_vfs_init();
+    /* Origin. */
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Origin")),
+            0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            txt_from = gtk_entry_new(),
+            1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_entry_set_completion(GTK_ENTRY(txt_from), from_comp);
+    gtk_entry_set_width_chars(GTK_ENTRY(txt_from), 25);
 
-    maemo_mapper_init(argc, argv);
+    /* Destination. */
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Destination")),
+            0, 1, 2, 3, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            txt_to = gtk_entry_new(),
+            1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_entry_set_completion(GTK_ENTRY(txt_to), to_comp);
+    gtk_entry_set_width_chars(GTK_ENTRY(txt_to), 25);
 
-    if(OSSO_OK != osso_rpc_set_default_cb_f(_osso, dbus_cb_default, NULL))
+    g_signal_connect(G_OBJECT(chk_gps), _("toggled"),
+                      G_CALLBACK(gps_toggled_from), txt_from);
+    g_signal_connect(G_OBJECT(chk_gps), _("toggled"),
+                      G_CALLBACK(gps_toggled_auto), chk_auto);
+
+    /* Initialize fields. */
+    gtk_entry_set_text(GTK_ENTRY(txt_from), (from ? from : ""));
+    gtk_entry_set_text(GTK_ENTRY(txt_to), (to ? to : ""));
+
+    if(from_here)
+        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_gps), TRUE);
+
+    gtk_widget_show_all(dialog);
+
+    while(!bytes
+            && GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
     {
-        fprintf(stderr, "osso_rpc_set_default_cb_f failed.\n");
-        return 1;
-    }
+        GnomeVFSResult vfs_result;
+        gchar buffer[1024];
+        const gchar *from, *to;
+        gchar *from_escaped, *to_escaped;
 
-    gtk_main();
+        from = gtk_entry_get_text(GTK_ENTRY(txt_from));
+        if(!strlen(from))
+        {
+            popup_error(dialog, _("Please specify a start location."));
+            continue;
+        }
 
-    maemo_mapper_destroy();
+        to = gtk_entry_get_text(GTK_ENTRY(txt_to));
+        if(!strlen(to))
+        {
+            popup_error(dialog, _("Please specify an end location."));
+            continue;
+        }
 
-    osso_deinitialize(_osso);
+        from_escaped = gnome_vfs_escape_string(from);
+        to_escaped = gnome_vfs_escape_string(to);
+        sprintf(buffer, "http://www.gnuite.com/cgi-bin/gpx.cgi?"
+                "saddr=%s&daddr=%s",
+                from_escaped, to_escaped);
+        g_free(from_escaped);
+        g_free(to_escaped);
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-    return 0;
-}
+        if(GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
+                        buffer, &size, &bytes)))
+        {
+            gchar buffer[1024];
+            sprintf(buffer, "%s:\n%s",
+                    _("Failed to connect to GPX Directions server"),
+                    gnome_vfs_result_to_string(vfs_result));
+            popup_error(dialog, buffer);
+        }
+        else if(strncmp(bytes, "<?xml", strlen("<?xml")))
+        {
+            /* Not an XML document - must be bad locations. */
+            popup_error(dialog,
+                    _("Could not generate directions. Make sure your "
+                    "source and destination are valid."));
+            g_free(bytes);
+            bytes = NULL;
+        }
+        else
+        {
+            /* If GPS is enabled, append the route, otherwise replace it. */
+            if(parse_route_gpx(bytes, size,
+                    (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chk_gps))
+                        ? 0 : 1)))
+            {
+                GtkTreeIter iter;
 
-/****************************************************************************
- * ABOVE: MAIN **************************************************************
- ****************************************************************************/
+                /* Find the nearest route point, if we're connected. */
+                route_find_nearest_point();
 
+                /* Cancel any autoroute that might be occurring. */
+                cancel_autoroute();
 
+                map_force_redraw();
 
-/****************************************************************************
- * BELOW: CALLBACKS *********************************************************
- ****************************************************************************/
+                if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chk_auto)))
+                {
+                    /* Kick off a timeout to start the first update. */
+                    _autoroute_data.dest = gnome_vfs_escape_string(to);
+                    _autoroute_data.enabled = TRUE;
+                    _autoroute_data.bytes_maxsize = 2 * size;
+                    _autoroute_data.bytes = g_new(gchar, 2 * size);
+                }
 
-static gint
-dbus_cb_default(const gchar *interface, const gchar *method,
-        GArray *arguments, gpointer data, osso_rpc_t *retval)
-{
-    printf("%s()\n", __PRETTY_FUNCTION__);
+                /* Save Origin in Route Locations list if not from GPS. */
+                if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chk_gps))
+                    && !g_slist_find_custom(_loc_list, from,
+                                (GCompareFunc)strcmp))
+                {
+                    _loc_list = g_slist_prepend(_loc_list, g_strdup(from));
+                    gtk_list_store_insert_with_values(_loc_model, &iter,
+                            INT_MAX, 0, from, -1);
+                }
+
+                /* Save Destination in Route Locations list. */
+                if(!g_slist_find_custom(_loc_list, to,
+                            (GCompareFunc)strcmp))
+                {
+                    _loc_list = g_slist_prepend(_loc_list, g_strdup(to));
+                    gtk_list_store_insert_with_values(_loc_model, &iter,
+                            INT_MAX, 0, to, -1);
+                }
+
+                hildon_banner_show_information(_window, NULL,
+                        _("Route Downloaded"));
+                g_free(bytes);
+            }
+            else
+            {
+                popup_error(dialog, _("Error parsing GPX file."));
+                g_free(bytes);
+                bytes = NULL; /* Let them try again. */
+            }
+        }
+    }
 
-    if(!strcmp(method, "top_application"))
-        gtk_idle_add((GSourceFunc)window_present, NULL);
+    gtk_widget_destroy(dialog);
 
-    retval->type = DBUS_TYPE_INVALID;
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-    return OSSO_OK;
+static gboolean
+menu_cb_route_download(GtkAction *action)
+{
+    route_download(NULL, NULL, FALSE);
+    return TRUE;
 }
 
-static void
-osso_cb_hw_state(osso_hw_state_t *state, gpointer data)
+static gboolean
+menu_cb_route_open(GtkAction *action)
 {
-    static gboolean _must_save_data = FALSE;
+    gchar *buffer;
+    gint size;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    if(state->system_inactivity_ind)
+    if(open_file(&buffer, NULL, &size, &_route_dir_uri, NULL,
+                    GTK_FILE_CHOOSER_ACTION_OPEN))
     {
-        if(_must_save_data)
-            _must_save_data = FALSE;
-        else if(_conn_state > RCVR_OFF)
+        /* If auto is enabled, append the route, otherwise replace it. */
+        if(parse_route_gpx(buffer, size, _autoroute_data.enabled ? 0 : 1))
         {
-            set_conn_state(RCVR_OFF);
-            rcvr_disconnect();
-            track_add(0, FALSE);
-            /* Pretend the autoroute is in progress to avoid download. */
-            if(_autoroute_data.enabled)
-                _autoroute_data.in_progress = TRUE;
-        }
-    }
-    else if(state->save_unsaved_data_ind)
-    {
-        config_save();
-        _must_save_data = TRUE;
-    }
-    else if(_conn_state == RCVR_OFF && _enable_gps)
-    {
-        set_conn_state(RCVR_DOWN);
-        rcvr_connect_later();
-        if(_autoroute_data.enabled)
-            _autoroute_data.in_progress = TRUE;
-    }
+            cancel_autoroute();
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-}
+            /* Find the nearest route point, if we're connected. */
+            route_find_nearest_point();
 
-static gboolean
-key_zoom_timeout()
-{
-    if(_key_zoom_new < _zoom)
-    {
-        /* We're currently zooming in (_zoom is decreasing). */
-        if(_key_zoom_new)
-            /* We can zoom some more.  Hurray! */
-            _key_zoom_new--;
-        else
-            /* We can't zoom anymore.  Booooo! */
-            return FALSE;
-    }
-    else
-    {
-        /* We're currently zooming out (_zoom is increasing). */
-        if(_key_zoom_new < (MAX_ZOOM - 1))
-            /* We can zoom some more.  Hurray! */
-            _key_zoom_new++;
+            map_force_redraw();
+            hildon_banner_show_information(_window, NULL,
+                    _("Route Opened"));
+        }
         else
-            /* We can't zoom anymore.  Booooo! */
-            return FALSE;
+            popup_error(_window, _("Error parsing GPX file."));
+        g_free(buffer);
     }
 
-    /* We can zoom more - tell them how much they're zooming. */
-    {
-        gchar buffer[32];
-        sprintf(buffer, "%s %d", _("Zoom to Level"), _key_zoom_new);
-        hildon_banner_show_information(_window, NULL, buffer);
-    }
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-window_cb_key_press(GtkWidget* widget, GdkEventKey *event)
+menu_cb_route_reset(GtkAction *action)
 {
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    switch (event->keyval)
-    {
-        case HILDON_HARDKEY_UP:
-            map_pan(0, -PAN_UNITS);
-            return TRUE;
-
-        case HILDON_HARDKEY_DOWN:
-            map_pan(0, PAN_UNITS);
-            return TRUE;
-
-        case HILDON_HARDKEY_LEFT:
-            map_pan(-PAN_UNITS, 0);
-            return TRUE;
+    route_find_nearest_point();
+    map_render_paths();
+    map_render_poi();
+    MACRO_QUEUE_DRAW_AREA();
 
-        case HILDON_HARDKEY_RIGHT:
-            map_pan(PAN_UNITS, 0);
-            return TRUE;
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-        case HILDON_HARDKEY_SELECT:
-            switch(_center_mode)
-            {
-                case CENTER_LATLON:
-                case CENTER_WAS_LEAD:
-                    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
-                                _menu_ac_lead_item), TRUE);
-                    break;
-                case CENTER_LEAD:
-                case CENTER_WAS_LATLON:
-                    gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
-                                _menu_ac_latlon_item), TRUE);
-                    break;
-            }
-            return TRUE;
+static gboolean
+menu_cb_route_clear(GtkAction *action)
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-        case HILDON_HARDKEY_FULLSCREEN:
-            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
-                        _menu_fullscreen_item), !_fullscreen);
-            return TRUE;
+    _next_way_dist_rough = -1; /* to avoid announcement attempts. */
+    cancel_autoroute();
+    MACRO_CLEAR_TRACK(_route);
+    map_force_redraw();
 
-        case HILDON_HARDKEY_INCREASE:
-        case HILDON_HARDKEY_DECREASE:
-            if(!_key_zoom_timeout_sid)
-            {
-                _key_zoom_new = _zoom
-                    + (event->keyval == HILDON_HARDKEY_INCREASE ? -1 : 1);
-                /* Remember, _key_zoom_new is unsigned. */
-                if(_key_zoom_new < MAX_ZOOM)
-                {
-                    gchar buffer[80];
-                    sprintf(buffer, "%s %d", _("Zoom to Level"), _key_zoom_new);
-                    hildon_banner_show_information(_window, NULL, buffer);
-                    _key_zoom_timeout_sid = g_timeout_add(
-                        500, key_zoom_timeout, NULL);
-                }
-            }
-            return TRUE;
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-        case HILDON_HARDKEY_ESC:
-            {
-                switch(_show_tracks)
-                {
-                    case 0:
-                        /* Nothing shown, nothing saved; just set both. */
-                        _show_tracks = TRACKS_MASK | ROUTES_MASK;
-                        break;
-                    case TRACKS_MASK << 16:
-                    case ROUTES_MASK << 16:
-                    case (ROUTES_MASK | TRACKS_MASK) << 16:
-                        /* Something was saved and nothing changed since.
-                         * Restore saved. */
-                        _show_tracks = _show_tracks >> 16;
-                        break;
-                    default:
-                        /* There is no history, or they changed something since
-                         * the last historical change. Save and clear. */
-                        _show_tracks = _show_tracks << 16;
-                }
+static gboolean
+menu_cb_track_open(GtkAction *action)
+{
+    gchar *buffer;
+    gint size;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
-                            _menu_show_routes_item),
-                        _show_tracks & ROUTES_MASK);
+    if(open_file(&buffer, NULL, &size, NULL, &_track_file_uri,
+                    GTK_FILE_CHOOSER_ACTION_OPEN))
+    {
+        if(parse_track_gpx(buffer, size, -1))
+        {
+            map_force_redraw();
+            hildon_banner_show_information(_window, NULL, _("Track Opened"));
+        }
+        else
+            popup_error(_window, _("Error parsing GPX file."));
+        g_free(buffer);
+    }
 
-                gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
-                            _menu_show_tracks_item),
-                        _show_tracks & TRACKS_MASK);
-            }
-            return TRUE;
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-        default:
-            return FALSE;
-    }
+#define WRITE_STRING(string) { \
+    GnomeVFSResult vfs_result; \
+    GnomeVFSFileSize size; \
+    if(GNOME_VFS_OK != (vfs_result = gnome_vfs_write( \
+                    handle, (string), strlen((string)), &size))) \
+    { \
+        gchar buffer[1024]; \
+        sprintf(buffer, "%s:\n%s\n%s", _("Error while writing to file"), \
+                        _("File is incomplete."), \
+                gnome_vfs_result_to_string(vfs_result)); \
+        popup_error(_window, buffer); \
+        return FALSE; \
+    } \
 }
 
 static gboolean
-window_cb_key_release(GtkWidget* widget, GdkEventKey *event)
+write_track_gpx(GnomeVFSHandle *handle)
 {
+    TrackPoint *curr;
+    gboolean trkseg_break = FALSE;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    switch (event->keyval)
+    /* Find first non-zero point. */
+    for(curr = _track.head-1; curr++ != _track.tail; )
+        if(curr->point.unity)
+            break;
+
+    /* Write the header. */
+    WRITE_STRING(XML_TRKSEG_HEADER);
+
+    /* Curr points to first non-zero point. */
+    for(curr--; curr++ != _track.tail; )
     {
-        case HILDON_HARDKEY_INCREASE:
-        case HILDON_HARDKEY_DECREASE:
-            if(_key_zoom_timeout_sid)
+        gfloat lat, lon;
+        if(curr->point.unity)
+        {
+            gchar buffer[80];
+            gchar strlat[80], strlon[80];
+            if(trkseg_break)
             {
-                g_source_remove(_key_zoom_timeout_sid);
-                _key_zoom_timeout_sid = 0;
-                map_set_zoom(_key_zoom_new);
+                /* First trkpt of the segment - write trkseg header. */
+                WRITE_STRING("    </trkseg>\n"
+                /* Write trkseg header. */
+                             "    <trkseg>\n");
+                trkseg_break = FALSE;
             }
-            return TRUE;
-
-        default:
-            return FALSE;
+            unit2latlon(curr->point.unitx, curr->point.unity, lat, lon);
+            g_ascii_formatd(strlat, 80, "%.06f", lat);
+            g_ascii_formatd(strlon, 80, "%.06f", lon);
+            sprintf(buffer, "      <trkpt lat=\"%s\" lon=\"%s\"",
+                    strlat, strlon);
+            WRITE_STRING(buffer);
+            
+            /* write the time */
+            if(curr->time)
+            {
+                WRITE_STRING(">\n        <time>");
+                {
+                    struct tm time;
+                    localtime_r(&curr->time, &time);
+                    strftime(buffer, 80, XML_DATE_FORMAT, &time);
+                    WRITE_STRING(buffer);
+                    WRITE_STRING(XML_TZONE);
+                }
+                WRITE_STRING("</time>\n"
+                         "      </trkpt>\n");
+            }
+            else
+                WRITE_STRING("/>\n");
+        }
+        else
+            trkseg_break = TRUE;
     }
+
+    /* Write the footer. */
+    WRITE_STRING(XML_TRKSEG_FOOTER);
+
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
 }
 
 static gboolean
-map_cb_configure(GtkWidget *widget, GdkEventConfigure *event)
+write_route_gpx(GnomeVFSHandle *handle)
 {
-    printf("%s(%d, %d)\n", __PRETTY_FUNCTION__,
-            _map_widget->allocation.width, _map_widget->allocation.height);
+    Point *curr;
+    WayPoint *wcurr;
+    gboolean trkseg_break = FALSE;
 
-    _screen_width_pixels = _map_widget->allocation.width;
-    _screen_height_pixels = _map_widget->allocation.height;
-    _screen_grids_halfwidth = pixel2grid(_screen_width_pixels) / 2;
-    _screen_grids_halfheight = pixel2grid(_screen_height_pixels) / 2;
+    /* Find first non-zero point. */
+    for(curr = _route.head-1, wcurr = _route.whead; curr++ != _route.tail; )
+        if(curr->unity)
+            break;
+        else if(curr == wcurr->point)
+            wcurr++;
 
-    MACRO_RECALC_FOCUS_BASE();
-    MACRO_RECALC_FOCUS_SIZE();
+    /* Write the header. */
+    WRITE_STRING(XML_TRKSEG_HEADER);
 
-    _min_center.unitx = pixel2unit(grid2pixel(_screen_grids_halfwidth));
-    _min_center.unity = pixel2unit(grid2pixel(_screen_grids_halfheight));
-    _max_center.unitx = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfwidth) - 1;
-    _max_center.unity = WORLD_SIZE_UNITS-grid2unit(_screen_grids_halfheight)- 1;
+    /* Curr points to first non-zero point. */
+    for(curr--; curr++ != _route.tail; )
+    {
+        gfloat lat, lon;
+        if(curr->unity)
+        {
+            gchar buffer[80];
+            gchar strlat[80], strlon[80];
+            if(trkseg_break)
+            {
+                /* First trkpt of the segment - write trkseg header. */
+                WRITE_STRING("    </trkseg>\n"
+                             "    <trkseg>\n");
+                trkseg_break = FALSE;
+            }
+            unit2latlon(curr->unitx, curr->unity, lat, lon);
+            g_ascii_formatd(strlat, 80, "%.06f", lat);
+            g_ascii_formatd(strlon, 80, "%.06f", lon);
+            sprintf(buffer, "      <trkpt lat=\"%s\" lon=\"%s\"",
+                    strlat, strlon);
+            if(curr == wcurr->point)
+                sprintf(buffer + strlen(buffer),
+                        "><desc>%s</desc></trkpt>\n", wcurr++->desc);
+            else
+                strcat(buffer, "/>\n");
+            WRITE_STRING(buffer);
+        }
+        else
+            trkseg_break = TRUE;
+    }
 
-    map_center_unit(_center.unitx, _center.unity);
+    /* Write the footer. */
+    WRITE_STRING(XML_TRKSEG_FOOTER);
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-map_cb_expose(GtkWidget *widget, GdkEventExpose *event)
+menu_cb_track_save(GtkAction *action)
 {
-    printf("%s(%d, %d, %d, %d)\n", __PRETTY_FUNCTION__,
-            event->area.x, event->area.y,
-            event->area.width, event->area.height);
+    GnomeVFSHandle *handle;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    gdk_draw_drawable(
-            _map_widget->window,
-            _gc_mark,
-            _map_pixmap,
-            event->area.x + _offsetx, event->area.y + _offsety,
-            event->area.x, event->area.y,
-            event->area.width, event->area.height);
-    map_draw_mark();
+    if(open_file(NULL, &handle, NULL, NULL, &_track_file_uri,
+                    GTK_FILE_CHOOSER_ACTION_SAVE))
+    {
+        if(write_track_gpx(handle))
+            hildon_banner_show_information(_window, NULL, _("Track Saved"));
+        else
+            popup_error(_window, _("Error writing GPX file."));
+        gnome_vfs_close(handle);
+    }
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-map_cb_button_press(GtkWidget *widget, GdkEventButton *event)
+menu_cb_track_mark_way(GtkAction *action)
 {
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    _cmenu_position_x = event->x + 0.5;
-    _cmenu_position_y = event->y + 0.5;
+    if(_track.tail->point.unity)
+    {
+        guint x1, y1;
 
-    /* Return FALSE to allow context menu to work. */
-    vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
-    return FALSE;
+        /* To mark a "waypoint" in a track, we'll add a (0, 0) point and then
+         * another instance of the most recent track point. */
+        MACRO_TRACK_INCREMENT_TAIL(_track);
+        *_track.tail = _track_null;
+        MACRO_TRACK_INCREMENT_TAIL(_track);
+        *_track.tail = _track.tail[2];
+        
+        /** Instead of calling map_render_paths(), we'll just add the waypoint
+         * ourselves. */
+        x1 = unit2bufx(_track.tail->point.unitx);
+        y1 = unit2bufy(_track.tail->point.unity);
+        /* Make sure this circle will be visible. */
+        if((x1 < BUF_WIDTH_PIXELS)
+                && ((unsigned)y1 < BUF_HEIGHT_PIXELS))
+            gdk_draw_arc(_map_pixmap, _gc_track_break,
+                    FALSE, /* FALSE: not filled. */
+                    x1 - _draw_line_width,
+                    y1 - _draw_line_width,
+                    2 * _draw_line_width,
+                    2 * _draw_line_width,
+                    0, /* start at 0 degrees. */
+                    360 * 64);
+    }
+
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
 }
 
 static gboolean
-map_cb_button_release(GtkWidget *widget, GdkEventButton *event)
+menu_cb_route_save(GtkAction *action)
 {
+    GnomeVFSHandle *handle;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-#ifdef DEBUG
-    if(event->button != 1)
-    {
-        _pos.unitx = x2unit((gint)(event->x + 0.5));
-        _pos.unity = y2unit((gint)(event->y + 0.5));
-        unit2latlon(_pos.unitx, _pos.unity, _pos_lat, _pos_lon);
-        _speed = 20.f;
-        integerize_data();
-        track_add(time(NULL), FALSE);
-        refresh_mark();
-    }
-    else
-#endif
+    if(!_route.head)
     {
-        if(_center_mode > 0)
-            gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(
-                        _menu_ac_none_item), TRUE);
-        map_center_unit(
-                x2unit((gint)(event->x + 0.5)),
-                y2unit((gint)(event->y + 0.5)));
+        popup_error(_window, _("No route is loaded."));
+        return TRUE;
     }
 
-    /* Return FALSE to avoid context menu (if it hasn't popped up already). */
-    vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
-    return FALSE;
-}
-
-static gboolean
-channel_cb_error(GIOChannel *src, GIOCondition condition, gpointer data)
-{
-    printf("%s(%d)\n", __PRETTY_FUNCTION__, condition);
-
-    /* An error has occurred - re-connect(). */
-    rcvr_disconnect();
-    track_add(0, FALSE);
-
-    if(_conn_state > RCVR_OFF)
+    if(open_file(NULL, &handle, NULL, &_route_dir_uri, NULL,
+                    GTK_FILE_CHOOSER_ACTION_SAVE))
     {
-        set_conn_state(RCVR_DOWN);
-        rcvr_connect_now();
+        if(write_route_gpx(handle))
+            hildon_banner_show_information(_window, NULL, _("Route Saved"));
+        else
+            popup_error(_window, _("Error writing GPX file."));
+        gnome_vfs_close(handle);
     }
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-    return FALSE;
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
 }
 
 static gboolean
-channel_cb_connect(GIOChannel *src, GIOCondition condition, gpointer data)
+menu_cb_track_clear(GtkAction *action)
 {
-    int error, size = sizeof(error);
-    printf("%s(%d)\n", __PRETTY_FUNCTION__, condition);
-
-    if(*_rcvr_mac != '/'
-            && (getsockopt(_fd, SOL_SOCKET, SO_ERROR, &error, &size) || error))
-    {
-        printf("%s(): Error connecting to receiver; retrying...\n",
-                __PRETTY_FUNCTION__);
-        /* Try again. */
-        rcvr_disconnect();
-        rcvr_connect_later();
-    }
-    else
-    {
-        printf("%s(): Connected to receiver!\n",
-                __PRETTY_FUNCTION__);
-        set_conn_state(RCVR_UP);
-        _input_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE,
-                G_IO_IN | G_IO_PRI, channel_cb_input, NULL, NULL);
-    }
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    _connect_sid = 0;
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-    return FALSE;
-}
+    _track.tail = _track.head;
+    map_force_redraw();
 
-#define MACRO_PARSE_INT(tofill, str) { \
-    gchar *error_check; \
-    (tofill) = strtol((str), &error_check, 10); \
-    if(error_check == (str)) \
-    { \
-        fprintf(stderr, "Failed to parse string as int: %s\n", str); \
-        hildon_banner_show_information(_window, NULL, \
-                _("Invalid NMEA input from receiver!")); \
-        return; \
-    } \
-}
-#define MACRO_PARSE_FLOAT(tofill, str) { \
-    gchar *error_check; \
-    (tofill) = g_ascii_strtod((str), &error_check); \
-    if(error_check == (str)) \
-    { \
-        fprintf(stderr, "Failed to parse string as float: %s\n", str); \
-        hildon_banner_show_information(_window, NULL, \
-                _("Invalid NMEA input from receiver!")); \
-        return; \
-    } \
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
 }
-static void
-channel_parse_rmc(gchar *sentence)
-{
-    /* Recommended Minimum Navigation Information C
-     *  1) UTC Time
-     *  2) Status, V=Navigation receiver warning A=Valid
-     *  3) Latitude
-     *  4) N or S
-     *  5) Longitude
-     *  6) E or W
-     *  7) Speed over ground, knots
-     *  8) Track made good, degrees true
-     *  9) Date, ddmmyy
-     * 10) Magnetic Variation, degrees
-     * 11) E or W
-     * 12) FAA mode indicator (NMEA 2.3 and later)
-     * 13) Checksum
-     */
-    gchar *token, *dpoint;
-    gdouble tmpd;
-    guint tmpi;
-    gboolean newly_fixed = FALSE;
-    vprintf("%s(): %s", __PRETTY_FUNCTION__, sentence);
-
-#define DELIM ","
 
-    /* Skip time. */
-    token = strsep(&sentence, DELIM);
+static gboolean
+menu_cb_show_tracks(GtkAction *action)
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    token = strsep(&sentence, DELIM);
-    /* Token is now Status. */
-    if(*token != 'A')
+    _show_tracks ^= TRACKS_MASK;
+    if(gtk_check_menu_item_get_active(
+                GTK_CHECK_MENU_ITEM(_menu_show_tracks_item)))
     {
-        /* Data is invalid - not enough satellites?. */
-        if(_conn_state != RCVR_UP)
-        {
-            set_conn_state(RCVR_UP);
-            track_add(0, FALSE);
-        }
+        _show_tracks |= TRACKS_MASK;
+        map_render_paths();
+        MACRO_QUEUE_DRAW_AREA();
+        hildon_banner_show_information(
+                _window, NULL, _("Tracks are now shown"));
     }
     else
     {
-        /* Data is valid. */
-        if(_conn_state != RCVR_FIXED)
-        {
-            newly_fixed = TRUE;
-            set_conn_state(RCVR_FIXED);
-        }
+        _show_tracks &= ~TRACKS_MASK;
+        map_force_redraw();
+        hildon_banner_show_information(
+                _window, NULL, _("Tracks are now hidden"));
     }
 
-    /* Parse the latitude. */
-    token = strsep(&sentence, DELIM);
-    if(*token)
-    {
-        dpoint = strchr(token, '.');
-        MACRO_PARSE_FLOAT(tmpd, dpoint - 2);
-        dpoint[-2] = '\0';
-        MACRO_PARSE_INT(tmpi, token);
-        _pos_lat = tmpi + (tmpd * (1.0 / 60.0));
-    }
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-    /* Parse N or S. */
-    token = strsep(&sentence, DELIM);
-    if(*token && token[0] == 'S')
-        _pos_lat = -_pos_lat;
+static gboolean
+menu_cb_show_routes(GtkAction *action)
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* Parse the longitude. */
-    token = strsep(&sentence, DELIM);
-    if(*token)
+    if(gtk_check_menu_item_get_active(
+                GTK_CHECK_MENU_ITEM(_menu_show_routes_item)))
     {
-        dpoint = strchr(token, '.');
-        MACRO_PARSE_FLOAT(tmpd, dpoint - 2);
-        dpoint[-2] = '\0';
-        MACRO_PARSE_INT(tmpi, token);
-        _pos_lon = tmpi + (tmpd * (1.0 / 60.0));
+        _show_tracks |= ROUTES_MASK;
+        map_render_paths();
+        MACRO_QUEUE_DRAW_AREA();
+        hildon_banner_show_information(
+                _window, NULL, _("Routes are now shown"));
+    }
+    else
+    {
+        _show_tracks &= ~ROUTES_MASK;
+        map_force_redraw();
+        hildon_banner_show_information(
+                _window, NULL, _("Routes are now hidden"));
     }
 
-    /* Parse E or W. */
-    token = strsep(&sentence, DELIM);
-    if(*token && token[0] == 'W')
-        _pos_lon = -_pos_lon;
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-    /* Parse speed over ground, knots. */
-    token = strsep(&sentence, DELIM);
-    if(*token)
-        MACRO_PARSE_FLOAT(_speed, token);
+static gboolean
+menu_cb_show_velvec(GtkAction *action)
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* Parse heading, degrees from true north. */
-    token = strsep(&sentence, DELIM);
-    if(*token)
-        MACRO_PARSE_FLOAT(_heading, token);
+    _show_velvec = gtk_check_menu_item_get_active(
+            GTK_CHECK_MENU_ITEM(_menu_show_velvec_item));
+    map_move_mark();
+    gtk_widget_set_sensitive(GTK_WIDGET(_menu_gps_details_item), _enable_gps);
+    gps_show_info();
 
-    /* Translate data into integers. */
-    integerize_data();
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-    /* Add new data to track. */
-    if(_conn_state == RCVR_FIXED)
-        track_add(time(NULL), newly_fixed);
+static gboolean
+menu_cb_gps_show_info(GtkAction *action)
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* Move mark to new location. */
-    refresh_mark();
+    _gps_info = gtk_check_menu_item_get_active(
+                GTK_CHECK_MENU_ITEM(_menu_gps_show_info_item));
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    gps_show_info();
+
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
 }
 
-static void
-channel_parse_gsv(gchar *sentence)
+static gboolean
+menu_cb_ac_lead(GtkAction *action)
 {
-    /* Must be GSV - Satellites in view
-     *  1) total number of messages
-     *  2) message number
-     *  3) satellites in view
-     *  4) satellite number
-     *  5) elevation in degrees (0-90)
-     *  6) azimuth in degrees to true north (0-359)
-     *  7) SNR in dB (0-99)
-     *  more satellite infos like 4)-7)
-     *  n) checksum
-     */
-    gchar *token;
-    guint msgcnt, nummsgs;
-    static guint running_total = 0;
-    static guint num_sats_used = 0;
-    vprintf("%s(): %s", __PRETTY_FUNCTION__, sentence);
+    guint new_center_unitx, new_center_unity;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* Parse number of messages. */
-    token = strsep(&sentence, DELIM);
-    if(!sentence)
-        return; /* because this is an invalid sentence. */
-    MACRO_PARSE_INT(nummsgs, token);
+    _center_mode = CENTER_LEAD;
+    hildon_banner_show_information(_window, NULL, _("Auto-Center Mode: Lead"));
+    MACRO_RECALC_CENTER(new_center_unitx, new_center_unity);
+    map_center_unit(new_center_unitx, new_center_unity);
 
-    /* Parse message number. */
-    token = strsep(&sentence, DELIM);
-    if(!sentence)
-        return; /* because this is an invalid sentence. */
-    MACRO_PARSE_INT(msgcnt, token);
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-    /* Skip number of satellites in view. */
-    token = strsep(&sentence, DELIM);
+static gboolean
+menu_cb_ac_latlon(GtkAction *action)
+{
+    guint new_center_unitx, new_center_unity;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* Loop until there are no more satellites to parse. */
-    while(sentence)
-    {
-        guint snr;
-        /* Skip satellite number. */
-        token = strsep(&sentence, DELIM);
-        if(!sentence)
-            break; /* because this is an invalid sentence. */
-        /* Skip elevation in degrees (0-90). */
-        token = strsep(&sentence, DELIM);
-        if(!sentence)
-            break; /* because this is an invalid sentence. */
-        /* Skip azimuth in degrees to true north (0-359). */
-        token = strsep(&sentence, DELIM);
-        if(!sentence)
-            break; /* because this is an invalid sentence. */
+    _center_mode = CENTER_LATLON;
+    hildon_banner_show_information(_window, NULL,
+            _("Auto-Center Mode: Lat/Lon"));
+    MACRO_RECALC_CENTER(new_center_unitx, new_center_unity);
+    map_center_unit(new_center_unitx, new_center_unity);
 
-        /* Parse SNR. */
-        token = strsep(&sentence, DELIM);
-        if((snr = atoi(token)))
-        {
-            /* Snr is non-zero - add to total and count as used. */
-            running_total += snr;
-            num_sats_used++;
-        }
-    }
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-    if(msgcnt == nummsgs)
-    {
-        /*  This is the last message. Calculate signal strength. */
-        if(num_sats_used)
-        {
-            gdouble fraction = running_total * sqrt(num_sats_used)
-                / num_sats_used / 100.0;
-            BOUND(fraction, 0.0, 1.0);
-            running_total = 0;
-            num_sats_used = 0;
-            hildon_banner_set_fraction(HILDON_BANNER(_fix_banner), fraction);
-        }
+static gboolean
+menu_cb_ac_none(GtkAction *action)
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-        /* Keep awake while they watch the progress bar. */
-        KEEP_DISPLAY_ON();
+    _center_mode = -_center_mode;
+    hildon_banner_show_information(_window, NULL, _("Auto-Center Off"));
+
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
+
+
+typedef struct _RepoManInfo RepoManInfo;
+struct _RepoManInfo {
+    GtkWidget *dialog;
+    GtkWidget *notebook;
+    GtkWidget *cmb_repos;
+    GList *repo_edits;
+};
+
+typedef struct _RepoEditInfo RepoEditInfo;
+struct _RepoEditInfo {
+    gchar *name;
+    GtkWidget *page_table;
+    GtkWidget *txt_url;
+    GtkWidget *txt_cache_dir;
+    GtkWidget *num_dl_zoom_steps;
+    GtkWidget *num_view_zoom_steps;
+    GtkWidget *btn_browse;
+    BrowseInfo browse_info;
+};
+
+static gboolean
+repoman_dialog_select(GtkWidget *widget, RepoManInfo *rmi)
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
+    gint curr_index = gtk_combo_box_get_active(GTK_COMBO_BOX(rmi->cmb_repos));
+    gtk_notebook_set_current_page(GTK_NOTEBOOK(rmi->notebook), curr_index);
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
+
+static gboolean
+repoman_dialog_browse(GtkWidget *widget, BrowseInfo *browse_info)
+{
+    GtkWidget *dialog;
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    dialog = GTK_WIDGET(
+            hildon_file_chooser_dialog_new(GTK_WINDOW(browse_info->dialog),
+            GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER));
+
+    gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(dialog), TRUE);
+    gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
+            gtk_entry_get_text(GTK_ENTRY(browse_info->txt)));
+
+    if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(dialog)))
+    {
+        gchar *filename = gtk_file_chooser_get_filename(
+                GTK_FILE_CHOOSER(dialog));
+        gtk_entry_set_text(GTK_ENTRY(browse_info->txt), filename);
+        g_free(filename);
     }
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    gtk_widget_destroy(dialog);
+
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
 }
 
 static gboolean
-channel_cb_input(GIOChannel *src, GIOCondition condition, gpointer data)
+repoman_dialog_rename(GtkWidget *widget, RepoManInfo *rmi)
 {
-    gchar *sentence;
-    vprintf("%s(%d)\n", __PRETTY_FUNCTION__, condition);
-    
-    while(G_IO_STATUS_NORMAL == g_io_channel_read_line(
-                _channel,
-                &sentence,
-                NULL,
-                NULL,
-                NULL) && sentence)
+    GtkWidget *hbox;
+    GtkWidget *label;
+    GtkWidget *txt_name;
+    GtkWidget *dialog;
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    dialog = gtk_dialog_new_with_buttons(_("New Name"),
+            GTK_WINDOW(rmi->dialog), GTK_DIALOG_MODAL,
+            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+            NULL);
+
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+            hbox = gtk_hbox_new(FALSE, 4), FALSE, FALSE, 4);
+
+    gtk_box_pack_start(GTK_BOX(hbox),
+            label = gtk_label_new(_("Name")),
+            FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            txt_name = gtk_entry_new(),
+            TRUE, TRUE, 0);
+
+    gtk_widget_show_all(dialog);
+
+    while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
     {
-        gchar *sptr = sentence + 1;
-        guint csum = 0;
-        while(*sptr && *sptr != '*')
-            csum ^= *sptr++;
-        if (!*sptr || csum == strtol(sptr+1, NULL, 16))
-        {
-            if(*sptr)
-                *sptr = '\0'; /* take checksum out of the sentence. */
-            if(!strncmp(sentence + 3, "RMC", 3))
-                channel_parse_rmc(sentence + 7);
-            else if(_conn_state == RCVR_UP
-                    && !strncmp(sentence + 3, "GSV", 3))
-                channel_parse_gsv(sentence + 7);
-        }
-        else
-        {
-            printf("%s: Bad checksum in NMEA sentence:\n%s\n",
-                    __PRETTY_FUNCTION__, sentence);
-        }
-        g_free(sentence);
+        gint active = gtk_combo_box_get_active(GTK_COMBO_BOX(rmi->cmb_repos));
+        RepoEditInfo *rei = g_list_nth_data(rmi->repo_edits, active);
+        g_free(rei->name);
+        rei->name = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_name)));
+        gtk_combo_box_insert_text(GTK_COMBO_BOX(rmi->cmb_repos),
+                active, g_strdup(rei->name));
+        gtk_combo_box_set_active(GTK_COMBO_BOX(rmi->cmb_repos), active);
+        gtk_combo_box_remove_text(GTK_COMBO_BOX(rmi->cmb_repos), active + 1);
+        break;
     }
 
+    gtk_widget_destroy(dialog);
+
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-gps_toggled_from(GtkToggleButton *chk_gps,
-        GtkWidget *txt_from)
+repoman_dialog_delete(GtkWidget *widget, RepoManInfo *rmi)
 {
-    gchar buffer[80];
-    gchar strlat[32];
-    gchar strlon[32];
+    gchar buffer[100];
+    GtkWidget *confirm;
+    gint active = gtk_combo_box_get_active(GTK_COMBO_BOX(rmi->cmb_repos));
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    g_ascii_formatd(strlat, 80, "%.06f", _pos_lat);
-    g_ascii_formatd(strlon, 80, "%.06f", _pos_lon);
-    sprintf(buffer, "%s, %s", strlat, strlon);
-    gtk_widget_set_sensitive(txt_from, !gtk_toggle_button_get_active(chk_gps));
-    gtk_entry_set_text(GTK_ENTRY(txt_from), buffer);
+    if(gtk_tree_model_iter_n_children(GTK_TREE_MODEL(
+                    gtk_combo_box_get_model(GTK_COMBO_BOX(rmi->cmb_repos))),
+                                NULL) <= 1)
+    {
+        popup_error(rmi->dialog,
+                _("Cannot delete the last repository - there must be at"
+                " lease one repository."));
+        vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+        return TRUE;
+    }
+
+    sprintf(buffer, "%s:\n%s\n",
+            _("Confirm delete of repository"),
+            gtk_combo_box_get_active_text(GTK_COMBO_BOX(rmi->cmb_repos)));
+    confirm = hildon_note_new_confirmation(GTK_WINDOW(_window), buffer);
+
+    if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
+    {
+        gtk_combo_box_remove_text(GTK_COMBO_BOX(rmi->cmb_repos), active);
+        gtk_notebook_remove_page(GTK_NOTEBOOK(rmi->notebook), active);
+        rmi->repo_edits = g_list_remove_link(
+                rmi->repo_edits,
+                g_list_nth(rmi->repo_edits, active));
+        gtk_combo_box_set_active(GTK_COMBO_BOX(rmi->cmb_repos),
+                MAX(0, active - 1));
+    }
+
+    gtk_widget_destroy(confirm);
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
-static gboolean
-gps_toggled_auto(GtkToggleButton *chk_gps,
-        GtkWidget *chk_auto)
+static RepoEditInfo*
+repoman_dialog_add_repo(RepoManInfo *rmi, gchar *name)
 {
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    GtkWidget *label;
+    GtkWidget *hbox;
+    RepoEditInfo *rei = g_new(RepoEditInfo, 1);
+    printf("%s(%s)\n", __PRETTY_FUNCTION__, name);
 
-    gtk_widget_set_sensitive(chk_auto, gtk_toggle_button_get_active(chk_gps));
+    rei->name = name;
+
+    /* Maps page. */
+    gtk_notebook_append_page(GTK_NOTEBOOK(rmi->notebook),
+            rei->page_table = gtk_table_new(4, 4, FALSE),
+            gtk_label_new(name));
+
+    /* Map download URI. */
+    gtk_table_attach(GTK_TABLE(rei->page_table),
+            label = gtk_label_new(_("URI Format")),
+            0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(rei->page_table),
+            rei->txt_url = gtk_entry_new(),
+            1, 3, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+
+    /* Map Directory. */
+    gtk_table_attach(GTK_TABLE(rei->page_table),
+            label = gtk_label_new(_("Cache Dir.")),
+            0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(rei->page_table),
+            hbox = gtk_hbox_new(FALSE, 4),
+            1, 3, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            rei->txt_cache_dir = gtk_entry_new(),
+            TRUE, TRUE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            rei->btn_browse = gtk_button_new_with_label(_("Browse...")),
+            FALSE, FALSE, 0);
+
+    /* Download Zoom Steps. */
+    gtk_table_attach(GTK_TABLE(rei->page_table),
+            label = gtk_label_new(_("Download Zoom Steps")),
+            0, 2, 2, 3, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(rei->page_table),
+            label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+            2, 3, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_container_add(GTK_CONTAINER(label),
+            rei->num_dl_zoom_steps = hildon_controlbar_new());
+    hildon_controlbar_set_range(
+            HILDON_CONTROLBAR(rei->num_dl_zoom_steps), 1, 4);
+    hildon_controlbar_set_value(
+            HILDON_CONTROLBAR(rei->num_dl_zoom_steps), 2);
+    force_min_visible_bars(HILDON_CONTROLBAR(rei->num_dl_zoom_steps), 1);
+
+    /* Download Zoom Steps. */
+    gtk_table_attach(GTK_TABLE(rei->page_table),
+            label = gtk_label_new(_("View Zoom Steps")),
+            0, 2, 3, 4, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(rei->page_table),
+            label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+            2, 3, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_container_add(GTK_CONTAINER(label),
+            rei->num_view_zoom_steps = hildon_controlbar_new());
+    hildon_controlbar_set_range(
+            HILDON_CONTROLBAR(rei->num_view_zoom_steps), 1, 4);
+    hildon_controlbar_set_value(
+            HILDON_CONTROLBAR(rei->num_view_zoom_steps), 1);
+    force_min_visible_bars(HILDON_CONTROLBAR(rei->num_view_zoom_steps), 1);
+
+    rmi->repo_edits = g_list_append(rmi->repo_edits, rei);
+
+    /* Connect signals. */
+    rei->browse_info.dialog = rmi->dialog;
+    rei->browse_info.txt = rei->txt_cache_dir;
+    g_signal_connect(G_OBJECT(rei->btn_browse), "clicked",
+                      G_CALLBACK(repoman_dialog_browse),
+                      &rei->browse_info);
+
+    gtk_widget_show_all(rei->page_table);
+
+    gtk_combo_box_append_text(GTK_COMBO_BOX(rmi->cmb_repos), name);
+    gtk_combo_box_set_active(GTK_COMBO_BOX(rmi->cmb_repos),
+            gtk_tree_model_iter_n_children(GTK_TREE_MODEL(
+                    gtk_combo_box_get_model(GTK_COMBO_BOX(rmi->cmb_repos))),
+                NULL) - 1);
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
+    return rei;
 }
 
-/**
- * Display a dialog box to the user asking them to download a route.  The
- * "From" and "To" textfields may be initialized using the first two
- * parameters.  The third parameter, if set to TRUE, will cause the "Use GPS
- * Location" checkbox to be enabled, which automatically sets the "From" to the
- * current GPS position (this overrides any value that may have been passed as
- * the "To" initializer).
- * None of the passed strings are freed - that is left to the caller, and it is
- * safe to free either string as soon as this function returns.
- */
 static gboolean
-route_download(gchar *from, gchar *to, gboolean from_here)
+repoman_dialog_new(GtkWidget *widget, RepoManInfo *rmi)
 {
-    GtkWidget *dialog;
-    GtkWidget *table;
-    GtkWidget *label;
-    GtkWidget *chk_gps;
-    GtkWidget *chk_auto;
-    GtkWidget *txt_from;
-    GtkWidget *txt_to;
     GtkWidget *hbox;
-    GtkEntryCompletion *from_comp;
-    GtkEntryCompletion *to_comp;
-    gchar *bytes = NULL;
-    gint size;
+    GtkWidget *label;
+    GtkWidget *txt_name;
+    GtkWidget *dialog;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    dialog = gtk_dialog_new_with_buttons(_("Download Route"),
-            GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+    dialog = gtk_dialog_new_with_buttons(_("New Repository"),
+            GTK_WINDOW(rmi->dialog), GTK_DIALOG_MODAL,
             GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
             GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
             NULL);
 
     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
-            table = gtk_table_new(2, 4, FALSE), TRUE, TRUE, 0);
-
-    from_comp = gtk_entry_completion_new();
-    gtk_entry_completion_set_model(from_comp, GTK_TREE_MODEL(_loc_model));
-    gtk_entry_completion_set_text_column(from_comp, 0);
-    to_comp = gtk_entry_completion_new();
-    gtk_entry_completion_set_model(to_comp, GTK_TREE_MODEL(_loc_model));
-    gtk_entry_completion_set_text_column(to_comp, 0);
+            hbox = gtk_hbox_new(FALSE, 4), FALSE, FALSE, 4);
 
-    /* Auto. */
-    gtk_table_attach(GTK_TABLE(table),
-            hbox = gtk_hbox_new(FALSE, 6),
-            0, 2, 0, 1, 0, 0, 2, 4);
     gtk_box_pack_start(GTK_BOX(hbox),
-            chk_gps = gtk_check_button_new_with_label(
-                _("Use GPS Location")),
-            TRUE, TRUE, 0);
+            label = gtk_label_new(_("Name")),
+            FALSE, FALSE, 0);
     gtk_box_pack_start(GTK_BOX(hbox),
-            chk_auto = gtk_check_button_new_with_label(
-                _("Auto-Update")),
+            txt_name = gtk_entry_new(),
             TRUE, TRUE, 0);
-    gtk_widget_set_sensitive(chk_auto, FALSE);
 
-    /* Origin. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Origin")),
-            0, 1, 1, 2, GTK_FILL, 0, 2, 4);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            txt_from = gtk_entry_new(),
-            1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
-    gtk_entry_set_completion(GTK_ENTRY(txt_from), from_comp);
-    gtk_entry_set_width_chars(GTK_ENTRY(txt_from), 25);
+    gtk_widget_show_all(dialog);
 
-    /* Destination. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Destination")),
-            0, 1, 2, 3, GTK_FILL, 0, 2, 4);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            txt_to = gtk_entry_new(),
-            1, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
-    gtk_entry_set_completion(GTK_ENTRY(txt_to), to_comp);
-    gtk_entry_set_width_chars(GTK_ENTRY(txt_to), 25);
+    while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
+    {
+        repoman_dialog_add_repo(rmi,
+                g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_name))));
+        break;
+    }
 
-    g_signal_connect(G_OBJECT(chk_gps), _("toggled"),
-                      G_CALLBACK(gps_toggled_from), txt_from);
-    g_signal_connect(G_OBJECT(chk_gps), _("toggled"),
-                      G_CALLBACK(gps_toggled_auto), chk_auto);
+    gtk_widget_destroy(dialog);
 
-    /* Initialize fields. */
-    gtk_entry_set_text(GTK_ENTRY(txt_from), (from ? from : ""));
-    gtk_entry_set_text(GTK_ENTRY(txt_to), (to ? to : ""));
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-    if(from_here)
-        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_gps), TRUE);
+static gboolean
+menu_cb_maps_repoman(GtkAction *action)
+{
+    RepoManInfo rmi;
+    GtkWidget *hbox;
+    GtkWidget *btn_rename;
+    GtkWidget *btn_delete;
+    GtkWidget *btn_new;
+    GList *curr;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    gtk_widget_show_all(dialog);
+    rmi.dialog = gtk_dialog_new_with_buttons(_("Repositories"),
+            GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+            NULL);
 
-    while(!bytes
-            && GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
-    {
-        GnomeVFSResult vfs_result;
-        gchar buffer[1024];
-        const gchar *from, *to;
-        gchar *from_escaped, *to_escaped;
+    hbox = gtk_hbox_new(FALSE, 4);
 
-        from = gtk_entry_get_text(GTK_ENTRY(txt_from));
-        if(!strlen(from))
-        {
-            popup_error(dialog, _("Please specify a start location."));
-            continue;
-        }
+    gtk_box_pack_start(GTK_BOX(hbox),
+            rmi.cmb_repos = gtk_combo_box_new_text(), FALSE, FALSE, 4);
 
-        to = gtk_entry_get_text(GTK_ENTRY(txt_to));
-        if(!strlen(to))
-        {
-            popup_error(dialog, _("Please specify an end location."));
-            continue;
-        }
+    gtk_box_pack_start(GTK_BOX(hbox),
+            gtk_vseparator_new(), TRUE, TRUE, 4);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            btn_rename = gtk_button_new_with_label("Rename..."),
+            FALSE, FALSE, 4);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            btn_delete = gtk_button_new_with_label("Delete..."),
+            FALSE, FALSE, 4);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            btn_new = gtk_button_new_with_label("New..."),
+            FALSE, FALSE, 4);
 
-        from_escaped = gnome_vfs_escape_string(from);
-        to_escaped = gnome_vfs_escape_string(to);
-        sprintf(buffer, "http://www.gnuite.com/cgi-bin/gpx.cgi?"
-                "saddr=%s&daddr=%s",
-                from_escaped, to_escaped);
-        g_free(from_escaped);
-        g_free(to_escaped);
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(rmi.dialog)->vbox),
+            hbox, FALSE, FALSE, 4);
 
-        if(GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
-                        buffer, &size, &bytes)))
-        {
-            gchar buffer[1024];
-            sprintf(buffer, "%s:\n%s",
-                    _("Failed to connect to GPX Directions server"),
-                    gnome_vfs_result_to_string(vfs_result));
-            popup_error(dialog, buffer);
-        }
-        else if(strncmp(bytes, "<?xml", strlen("<?xml")))
-        {
-            /* Not an XML document - must be bad locations. */
-            popup_error(dialog,
-                    _("Could not generate directions. Make sure your "
-                    "source and destination are valid."));
-            g_free(bytes);
-            bytes = NULL;
-        }
-        else
-        {
-            /* If GPS is enabled, append the route, otherwise replace it. */
-            if(parse_route_gpx(bytes, size,
-                    (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chk_gps))
-                        ? 0 : 1)))
-            {
-                GtkTreeIter iter;
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(rmi.dialog)->vbox),
+            gtk_hseparator_new(), TRUE, TRUE, 4);
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(rmi.dialog)->vbox),
+            rmi.notebook = gtk_notebook_new(), TRUE, TRUE, 4);
 
-                /* Find the nearest route point, if we're connected. */
-                route_find_nearest_point();
+    gtk_notebook_set_show_tabs(GTK_NOTEBOOK(rmi.notebook), FALSE);
+    gtk_notebook_set_show_border(GTK_NOTEBOOK(rmi.notebook), FALSE);
 
-                /* Cancel any autoroute that might be occurring. */
-                cancel_autoroute();
+    rmi.repo_edits = NULL;
 
-                map_force_redraw();
+    /* Populate combo box and pages in notebook. */
+    for(curr = _repo_list; curr; curr = curr->next)
+    {
+        RepoData *rd = (RepoData*)curr->data;
+        RepoEditInfo *rei = repoman_dialog_add_repo(&rmi, g_strdup(rd->name));
 
-                if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chk_auto)))
-                {
-                    /* Kick off a timeout to start the first update. */
-                    _autoroute_data.dest = gnome_vfs_escape_string(to);
-                    _autoroute_data.enabled = TRUE;
-                    _autoroute_data.bytes_maxsize = 2 * size;
-                    _autoroute_data.bytes = g_new(gchar, 2 * size);
-                }
+        /* Initialize fields with data from the RepoData object. */
+        gtk_entry_set_text(GTK_ENTRY(rei->txt_url), rd->url);
+        gtk_entry_set_text(GTK_ENTRY(rei->txt_cache_dir),
+                rd->cache_dir);
+        hildon_controlbar_set_value(
+                HILDON_CONTROLBAR(rei->num_dl_zoom_steps),
+                rd->dl_zoom_steps);
+        hildon_controlbar_set_value(
+                HILDON_CONTROLBAR(rei->num_view_zoom_steps),
+                rd->view_zoom_steps);
+    }
 
-                /* Save Origin in Route Locations list if not from GPS. */
-                if(!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chk_gps))
-                    && !g_slist_find_custom(_loc_list, from,
-                                (GCompareFunc)strcmp))
-                {
-                    _loc_list = g_slist_prepend(_loc_list, g_strdup(from));
-                    gtk_list_store_insert_with_values(_loc_model, &iter,
-                            INT_MAX, 0, from, -1);
-                }
+    /* Connect signals. */
+    g_signal_connect(G_OBJECT(btn_rename), "clicked",
+            G_CALLBACK(repoman_dialog_rename), &rmi);
+    g_signal_connect(G_OBJECT(btn_delete), "clicked",
+            G_CALLBACK(repoman_dialog_delete), &rmi);
+    g_signal_connect(G_OBJECT(btn_new), "clicked",
+            G_CALLBACK(repoman_dialog_new), &rmi);
+    g_signal_connect(G_OBJECT(rmi.cmb_repos), "changed",
+            G_CALLBACK(repoman_dialog_select), &rmi);
+    gtk_combo_box_set_active(GTK_COMBO_BOX(rmi.cmb_repos), 0);
+    gtk_widget_show_all(rmi.dialog);
+
+    while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(rmi.dialog)))
+    {
+        /* Iterate through repos and verify each. */
+        gboolean verified = TRUE;
+        gint i;
+        GList *curr;
+        gchar *old_curr_repo_name = NULL;
+        for(i = 0, curr = rmi.repo_edits;
+                verified && curr; curr = curr->next, i++)
+        {
+            RepoEditInfo *rei = curr->data;
+            /* Verify that cache directory exists or can be created. */
+            GnomeVFSURI *map_dir_uri = gnome_vfs_uri_new(gtk_entry_get_text(
+                        GTK_ENTRY(rei->txt_cache_dir)));
+            if(!gnome_vfs_uri_exists(map_dir_uri))
+            {
+                GnomeVFSURI *parent, *curr_uri;
+                GList *list = NULL;
 
-                /* Save Destination in Route Locations list. */
-                if(!g_slist_find_custom(_loc_list, to,
-                            (GCompareFunc)strcmp))
+                list = g_list_prepend(list, curr_uri = map_dir_uri);
+                while(GNOME_VFS_ERROR_NOT_FOUND
+                        == gnome_vfs_make_directory_for_uri(
+                            parent = gnome_vfs_uri_get_parent(curr_uri), 0755))
+                    list = g_list_prepend(list, curr_uri = parent);
+
+                while(list != NULL)
                 {
-                    _loc_list = g_slist_prepend(_loc_list, g_strdup(to));
-                    gtk_list_store_insert_with_values(_loc_model, &iter,
-                            INT_MAX, 0, to, -1);
+                    if(verified)
+                    {
+                        verified = (GNOME_VFS_OK
+                                == gnome_vfs_make_directory_for_uri(
+                                    (GnomeVFSURI*)list->data, 0755));
+                    }
+                    gnome_vfs_uri_unref((GnomeVFSURI*)list->data);
+                    list = g_list_remove(list, list->data);
                 }
-
-                hildon_banner_show_information(_window, NULL,
-                        _("Route Downloaded"));
-                g_free(bytes);
+                /* verified now equals result of last make-dir attempt. */
             }
-            else
+
+            if(!verified)
             {
-                popup_error(dialog, _("Error parsing GPX file."));
-                g_free(bytes);
-                bytes = NULL; /* Let them try again. */
+                /* Failed to create Map Cache directory. */
+                gchar buffer[1024];
+                sprintf(buffer, "%s: %s",
+                        _("Unable to create cache directory for repository"),
+                        rei->name);
+                gtk_combo_box_set_active(GTK_COMBO_BOX(rmi.cmb_repos), i);
+                popup_error(rmi.dialog, buffer);
             }
         }
+        if(!verified)
+            continue;
+
+        /* We're good to replace.  Delete old _repo_list */
+        menu_maps_remove_repos();
+        while(_repo_list)
+        {
+            if(_repo_list->data == _curr_repo)
+                old_curr_repo_name = g_strdup(
+                        ((RepoData*)_repo_list->data)->name);
+            g_free(((RepoData*)_repo_list->data)->name);
+            g_free(((RepoData*)_repo_list->data)->url);
+            g_free(((RepoData*)_repo_list->data)->cache_dir);
+            g_free(_repo_list->data);
+            _repo_list = g_list_delete_link(_repo_list, _repo_list);
+        }
+
+        /* Write new _repo_list. */
+        _curr_repo = NULL;
+        for(i = 0, curr = rmi.repo_edits; curr; curr = curr->next, i++)
+        {
+            RepoEditInfo *rei = curr->data;
+            RepoData *rd = g_new(RepoData, 1);
+            rd->name = g_strdup(rei->name);
+            rd->url = g_strdup(gtk_entry_get_text(GTK_ENTRY(rei->txt_url)));
+            rd->cache_dir = g_strdup(gtk_entry_get_text(
+                    GTK_ENTRY(rei->txt_cache_dir)));
+            rd->dl_zoom_steps = hildon_controlbar_get_value(
+                    HILDON_CONTROLBAR(rei->num_dl_zoom_steps));
+            rd->view_zoom_steps = hildon_controlbar_get_value(
+                    HILDON_CONTROLBAR(rei->num_view_zoom_steps));
+            _repo_list = g_list_append(_repo_list, rd);
+
+            if(old_curr_repo_name && !strcmp(old_curr_repo_name, rd->name))
+                _curr_repo = rd;
+        }
+        if(!_curr_repo)
+            _curr_repo = (RepoData*)g_list_first(_repo_list)->data;
+        menu_maps_add_repos();
+        break;
     }
 
-    gtk_widget_destroy(dialog);
+    gtk_widget_hide(rmi.dialog); /* Destroying causes a crash (!?!?!??!) */
+
+    map_set_zoom(_zoom); /* make sure we're at an appropriate zoom level. */
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
-static gboolean
-menu_cb_route_download(GtkAction *action)
-{
-    route_download(NULL, NULL, FALSE);
-    return TRUE;
-}
+typedef struct _MapmanInfo MapmanInfo;
+struct _MapmanInfo {
+    GtkWidget *notebook;
+    GtkWidget *tbl_area;
 
-static gboolean
-menu_cb_route_open(GtkAction *action)
-{
-    gchar *buffer;
-    gint size;
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    /* The "Setup" tab. */
+    GtkWidget *rad_download;
+    GtkWidget *rad_delete;
+    GtkWidget *chk_overwrite;
+    GtkWidget *rad_by_area;
+    GtkWidget *rad_along_route;
+    GtkWidget *txt_route_radius;
 
-    if(open_file(&buffer, NULL, &size, &_route_dir_uri, NULL,
-                    GTK_FILE_CHOOSER_ACTION_OPEN))
-    {
-        /* If auto is enabled, append the route, otherwise replace it. */
-        if(parse_route_gpx(buffer, size, _autoroute_data.enabled ? 0 : 1))
-        {
-            cancel_autoroute();
+    /* The "Area" tab. */
+    GtkWidget *txt_topleft_lat;
+    GtkWidget *txt_topleft_lon;
+    GtkWidget *txt_botright_lat;
+    GtkWidget *txt_botright_lon;
 
-            /* Find the nearest route point, if we're connected. */
-            route_find_nearest_point();
+    /* The "Zoom" tab. */
+    GtkWidget *chk_zoom_levels[MAX_ZOOM];
+};
 
-            map_force_redraw();
-            hildon_banner_show_information(_window, NULL,
-                    _("Route Opened"));
-        }
-        else
-            popup_error(_window, _("Error parsing GPX file."));
-        g_free(buffer);
+static void mapman_clear(GtkWidget *widget, MapmanInfo *mapman_info)
+{
+    guint i;
+    printf("%s()\n", __PRETTY_FUNCTION__);
+    if(gtk_notebook_get_current_page(GTK_NOTEBOOK(mapman_info->notebook)))
+        /* This is the second page (the "Zoom" page) - clear the checks. */
+        for(i = 0; i < MAX_ZOOM; i++)
+            gtk_toggle_button_set_active(
+                    GTK_TOGGLE_BUTTON(mapman_info->chk_zoom_levels[i]), FALSE);
+    else
+    {
+        /* This is the first page (the "Area" page) - clear the text fields. */
+        gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_topleft_lat), "");
+        gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_topleft_lon), "");
+        gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_botright_lat), "");
+        gtk_entry_set_text(GTK_ENTRY(mapman_info->txt_botright_lon), "");
     }
-
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
 }
 
-static gboolean
-menu_cb_route_reset(GtkAction *action)
+static void mapman_update_state(GtkWidget *widget, MapmanInfo *mapman_info)
 {
     printf("%s()\n", __PRETTY_FUNCTION__);
+    gtk_widget_set_sensitive( mapman_info->chk_overwrite,
+            gtk_toggle_button_get_active(
+                GTK_TOGGLE_BUTTON(mapman_info->rad_download)));
 
-    route_find_nearest_point();
-    map_render_paths();
-    MACRO_QUEUE_DRAW_AREA();
+    if(gtk_toggle_button_get_active(
+                GTK_TOGGLE_BUTTON(mapman_info->rad_by_area)))
+        gtk_widget_show(mapman_info->tbl_area);
+    else if(gtk_notebook_get_n_pages(GTK_NOTEBOOK(mapman_info->notebook)) == 3)
+        gtk_widget_hide(mapman_info->tbl_area);
 
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
+    gtk_widget_set_sensitive(mapman_info->txt_route_radius,
+            gtk_toggle_button_get_active(
+                GTK_TOGGLE_BUTTON(mapman_info->rad_along_route)));
 }
 
 static gboolean
-menu_cb_route_clear(GtkAction *action)
+menu_cb_maps_select(GtkAction *action, gpointer new_repo)
 {
     printf("%s()\n", __PRETTY_FUNCTION__);
-
-    _next_way_dist_rough = -1; /* to avoid announcement attempts. */
-    cancel_autoroute();
-    MACRO_CLEAR_TRACK(_route);
+    _curr_repo = new_repo;
     map_force_redraw();
-
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-menu_cb_track_open(GtkAction *action)
+menu_cb_mapman(GtkAction *action)
 {
-    gchar *buffer;
-    gint size;
+    GtkWidget *dialog;
+    GtkWidget *vbox;
+    GtkWidget *hbox;
+    GtkWidget *table;
+    GtkWidget *label;
+    GtkWidget *button;
+    GtkWidget *lbl_gps_lat;
+    GtkWidget *lbl_gps_lon;
+    GtkWidget *lbl_center_lat;
+    GtkWidget *lbl_center_lon;
+    MapmanInfo mapman_info;
+    gchar buffer[80];
+    gfloat lat, lon;
+    guint i;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    if(open_file(&buffer, NULL, &size, NULL, &_track_file_uri,
-                    GTK_FILE_CHOOSER_ACTION_OPEN))
+    dialog = gtk_dialog_new_with_buttons(_("Manage Maps"),
+            GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+            NULL);
+
+    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
+            button = gtk_button_new_with_label(_("Clear")));
+    g_signal_connect(G_OBJECT(button), "clicked",
+                      G_CALLBACK(mapman_clear), &mapman_info);
+
+    /* Clear button. */
+    gtk_dialog_add_button(GTK_DIALOG(dialog),
+            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+            mapman_info.notebook = gtk_notebook_new(), TRUE, TRUE, 0);
+
+    /* Setup page. */
+    gtk_notebook_append_page(GTK_NOTEBOOK(mapman_info.notebook),
+            vbox = gtk_vbox_new(FALSE, 2),
+            label = gtk_label_new(_("Setup")));
+    gtk_notebook_set_tab_label_packing(
+            GTK_NOTEBOOK(mapman_info.notebook), vbox,
+            FALSE, FALSE, GTK_PACK_START);
+
+    gtk_box_pack_start(GTK_BOX(vbox),
+            hbox = gtk_hbox_new(FALSE, 4),
+            FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            mapman_info.rad_download
+                    = gtk_radio_button_new_with_label(NULL, _("Download Maps")),
+            FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            label = gtk_alignment_new(0.f, 0.5f, 0.f, 0.f),
+            FALSE, FALSE, 0);
+    gtk_container_add(GTK_CONTAINER(label),
+            mapman_info.chk_overwrite
+                    = gtk_check_button_new_with_label(_("Overwrite"))),
+
+    gtk_box_pack_start(GTK_BOX(vbox),
+            mapman_info.rad_delete
+                    = gtk_radio_button_new_with_label_from_widget(
+                        GTK_RADIO_BUTTON(mapman_info.rad_download),
+                        _("Delete Maps")),
+            FALSE, FALSE, 0);
+
+    gtk_box_pack_start(GTK_BOX(vbox),
+            gtk_hseparator_new(),
+            FALSE, FALSE, 0);
+
+    gtk_box_pack_start(GTK_BOX(vbox),
+            mapman_info.rad_by_area
+                    = gtk_radio_button_new_with_label(NULL,
+                        _("By Area (see tab)")),
+            FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox),
+            hbox = gtk_hbox_new(FALSE, 4),
+            FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            mapman_info.rad_along_route
+                    = gtk_radio_button_new_with_label_from_widget(
+                        GTK_RADIO_BUTTON(mapman_info.rad_by_area),
+                        _("Along Route - Radius:")),
+            FALSE, FALSE, 0);
+    gtk_widget_set_sensitive(mapman_info.rad_along_route, _route.head != NULL);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            mapman_info.txt_route_radius
+                    = gtk_entry_new(),
+            FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            gtk_label_new(UNITS_TEXT[_units]), FALSE, FALSE, 0);
+    gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_route_radius), 1.f);
+
+
+    /* Zoom page. */
+    gtk_notebook_append_page(GTK_NOTEBOOK(mapman_info.notebook),
+            table = gtk_table_new(5, 5, FALSE),
+            label = gtk_label_new(_("Zoom")));
+    gtk_notebook_set_tab_label_packing(
+            GTK_NOTEBOOK(mapman_info.notebook), table,
+            FALSE, FALSE, GTK_PACK_START);
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(
+                _("Zoom Levels to Download: (0 -> most detail)")),
+            0, 5, 0, 1, GTK_FILL, 0, 4, 0);
+    gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
+    for(i = 0; i < MAX_ZOOM; i++)
     {
-        if(parse_track_gpx(buffer, size, -1))
-        {
-            map_force_redraw();
-            hildon_banner_show_information(_window, NULL, _("Track Opened"));
-        }
-        else
-            popup_error(_window, _("Error parsing GPX file."));
-        g_free(buffer);
+        sprintf(buffer, "%d", i);
+        gtk_table_attach(GTK_TABLE(table),
+                mapman_info.chk_zoom_levels[i]
+                        = gtk_check_button_new_with_label(buffer),
+                i % 5, i % 5 + 1, i / 5 + 1, i / 5 + 2,
+                GTK_EXPAND | GTK_FILL, 0, 4, 0);
+    }
+
+    /* Area page. */
+    gtk_notebook_append_page(GTK_NOTEBOOK(mapman_info.notebook),
+        mapman_info.tbl_area = gtk_table_new(3, 4, FALSE),
+        label = gtk_label_new(_("Area")));
+
+    /* Label Columns. */
+    gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+            label = gtk_label_new(_("Latitude")),
+            1, 2, 0, 1, GTK_FILL, 0, 4, 0);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+            label = gtk_label_new(_("Longitude")),
+            2, 3, 0, 1, GTK_FILL, 0, 4, 0);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+
+    /* GPS. */
+    gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+            label = gtk_label_new(_("GPS Location")),
+            0, 1, 1, 2, GTK_FILL, 0, 4, 0);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+            lbl_gps_lat = gtk_label_new(""),
+            1, 2, 1, 2, GTK_FILL, 0, 4, 0);
+    gtk_label_set_selectable(GTK_LABEL(lbl_gps_lat), TRUE);
+    gtk_misc_set_alignment(GTK_MISC(lbl_gps_lat), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+            lbl_gps_lon = gtk_label_new(""),
+            2, 3, 1, 2, GTK_FILL, 0, 4, 0);
+    gtk_label_set_selectable(GTK_LABEL(lbl_gps_lon), TRUE);
+    gtk_misc_set_alignment(GTK_MISC(lbl_gps_lon), 1.f, 0.5f);
+
+    /* Center. */
+    gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+            label = gtk_label_new(_("View Center")),
+            0, 1, 2, 3, GTK_FILL, 0, 4, 0);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+            lbl_center_lat = gtk_label_new(""),
+            1, 2, 2, 3, GTK_FILL, 0, 4, 0);
+    gtk_label_set_selectable(GTK_LABEL(lbl_center_lat), TRUE);
+    gtk_misc_set_alignment(GTK_MISC(lbl_center_lat), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+            lbl_center_lon = gtk_label_new(""),
+            2, 3, 2, 3, GTK_FILL, 0, 4, 0);
+    gtk_label_set_selectable(GTK_LABEL(lbl_center_lon), TRUE);
+    gtk_misc_set_alignment(GTK_MISC(lbl_center_lon), 1.f, 0.5f);
+
+    /* default values for Top Left and Bottom Right are defined by the
+     * rectangle of the current and the previous Center */
+
+    /* Top Left. */
+    gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+            label = gtk_label_new(_("Top-Left")),
+            0, 1, 3, 4, GTK_FILL, 0, 4, 0);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+            mapman_info.txt_topleft_lat = gtk_entry_new(),
+            1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 4, 0);
+    gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_topleft_lat), 1.f);
+    gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+            mapman_info.txt_topleft_lon = gtk_entry_new(),
+            2, 3, 3, 4, GTK_EXPAND | GTK_FILL, 0, 4, 0);
+    gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_topleft_lon), 1.f);
+
+    /* Bottom Right. */
+    gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+            label = gtk_label_new(_("Bottom-Right")),
+            0, 1, 4, 5, GTK_FILL, 0, 4, 0);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+            mapman_info.txt_botright_lat = gtk_entry_new(),
+            1, 2, 4, 5, GTK_EXPAND | GTK_FILL, 0, 4, 0);
+    gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_botright_lat), 1.f);
+    gtk_table_attach(GTK_TABLE(mapman_info.tbl_area),
+            mapman_info.txt_botright_lon = gtk_entry_new(),
+            2, 3, 4, 5, GTK_EXPAND | GTK_FILL, 0, 4, 0);
+    gtk_entry_set_alignment(GTK_ENTRY(mapman_info.txt_botright_lon), 1.f);
+
+    /* Default action is to download by area. */
+    gtk_toggle_button_set_active(
+            GTK_TOGGLE_BUTTON(mapman_info.rad_by_area), TRUE);
+
+    /* Initialize fields.  Do no use g_ascii_formatd; these strings will be
+     * output (and parsed) as locale-dependent. */
+
+    sprintf(buffer, "%.06f", _pos_lat);
+    gtk_label_set_text(GTK_LABEL(lbl_gps_lat), buffer);
+    sprintf(buffer, "%.06f", _pos_lon);
+    gtk_label_set_text(GTK_LABEL(lbl_gps_lon), buffer);
+
+    unit2latlon(_center.unitx, _center.unity, lat, lon);
+    sprintf(buffer, "%.06f", lat);
+    gtk_label_set_text(GTK_LABEL(lbl_center_lat), buffer);
+    sprintf(buffer, "%.06f", lon);
+    gtk_label_set_text(GTK_LABEL(lbl_center_lon), buffer);
+
+    /* Initialize to the bounds of the screen. */
+    unit2latlon(x2unit(0), y2unit(0), lat, lon);
+    sprintf(buffer, "%.06f", lat);
+    gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_topleft_lat), buffer);
+    sprintf(buffer, "%.06f", lon);
+    gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_topleft_lon), buffer);
+
+    unit2latlon(x2unit(_screen_width_pixels), y2unit(_screen_height_pixels),
+            lat, lon);
+    sprintf(buffer, "%.06f", lat);
+    gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_botright_lat), buffer);
+    sprintf(buffer, "%.06f", lon);
+    gtk_entry_set_text(GTK_ENTRY(mapman_info.txt_botright_lon), buffer);
+
+    gtk_toggle_button_set_active(
+            GTK_TOGGLE_BUTTON(mapman_info.chk_zoom_levels[_zoom]), TRUE);
+
+    gtk_widget_show_all(dialog);
+
+    mapman_update_state(NULL, &mapman_info);
+
+    /* Connect signals. */
+    if(*_curr_repo->url)
+    {
+        g_signal_connect(G_OBJECT(mapman_info.rad_download), "clicked",
+                          G_CALLBACK(mapman_update_state), &mapman_info);
+        gtk_widget_set_sensitive(mapman_info.rad_download, TRUE);
     }
+    else
+    {
+        gtk_widget_set_sensitive(mapman_info.rad_download, FALSE);
+        popup_error(dialog,
+                _("NOTE: You must set a Map URI in the Repository Manager in "
+                    "order to download maps."));
+    }
+    g_signal_connect(G_OBJECT(mapman_info.rad_delete), "clicked",
+                      G_CALLBACK(mapman_update_state), &mapman_info);
+    g_signal_connect(G_OBJECT(mapman_info.rad_by_area), "clicked",
+                      G_CALLBACK(mapman_update_state), &mapman_info);
+    g_signal_connect(G_OBJECT(mapman_info.rad_along_route), "clicked",
+                      G_CALLBACK(mapman_update_state), &mapman_info);
+
+    while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
+    {
+        const gchar *text;
+        gchar *error_check;
+        gfloat start_lat, start_lon, end_lat, end_lon;
+        guint start_unitx, start_unity, end_unitx, end_unity;
+        guint num_maps = 0;
+        GtkWidget *confirm;
+        gboolean is_deleting, is_overwriting;
+
+        text = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_topleft_lat));
+        start_lat = strtof(text, &error_check);
+        if(text == error_check) {
+            popup_error(dialog, _("Invalid Top-Left Latitude"));
+            continue;
+        }
 
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
-}
+        text = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_topleft_lon));
+        start_lon = strtof(text, &error_check);
+        if(text == error_check) {
+            popup_error(dialog, _("Invalid Top-Left Longitude"));
+            continue;
+        }
 
-#define WRITE_STRING(string) { \
-    GnomeVFSResult vfs_result; \
-    GnomeVFSFileSize size; \
-    if(GNOME_VFS_OK != (vfs_result = gnome_vfs_write( \
-                    handle, (string), strlen((string)), &size))) \
-    { \
-        gchar buffer[1024]; \
-        sprintf(buffer, "%s:\n%s\n%s", _("Error while writing to file"), \
-                        _("File is incomplete."), \
-                gnome_vfs_result_to_string(vfs_result)); \
-        popup_error(_window, buffer); \
-        return FALSE; \
-    } \
-}
+        text = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_botright_lat));
+        end_lat = strtof(text, &error_check);
+        if(text == error_check) {
+            popup_error(dialog, _("Invalid Bottom-Right Latitude"));
+            continue;
+        }
 
-static gboolean
-write_track_gpx(GnomeVFSHandle *handle)
-{
-    TrackPoint *curr;
-    gboolean trkseg_break = FALSE;
-    printf("%s()\n", __PRETTY_FUNCTION__);
+        text = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_botright_lon));
+        end_lon = strtof(text, &error_check);
+        if(text == error_check) {
+            popup_error(dialog,_("Invalid Bottom-Right Longitude"));
+            continue;
+        }
 
-    /* Find first non-zero point. */
-    for(curr = _track.head-1; curr++ != _track.tail; )
-        if(curr->point.unity)
-            break;
+        latlon2unit(start_lat, start_lon, start_unitx, start_unity);
+        latlon2unit(end_lat, end_lon, end_unitx, end_unity);
 
-    /* Write the header. */
-    WRITE_STRING(XML_TRKSEG_HEADER);
+        /* Swap if they specified flipped lats or lons. */
+        if(start_unitx > end_unitx)
+        {
+            guint swap = start_unitx;
+            start_unitx = end_unitx;
+            end_unitx = swap;
+        }
+        if(start_unity > end_unity)
+        {
+            guint swap = start_unity;
+            start_unity = end_unity;
+            end_unity = swap;
+        }
 
-    /* Curr points to first non-zero point. */
-    for(curr--; curr++ != _track.tail; )
-    {
-        gfloat lat, lon;
-        if(curr->point.unity)
+        /* First, get the number of maps to download. */
+        for(i = 0; i < MAX_ZOOM; i++)
         {
-            gchar buffer[80];
-            gchar strlat[80], strlon[80];
-            if(trkseg_break)
+            if(gtk_toggle_button_get_active(
+                        GTK_TOGGLE_BUTTON(mapman_info.chk_zoom_levels[i])))
             {
-                /* First trkpt of the segment - write trkseg header. */
-                WRITE_STRING("    </trkseg>\n"
-                /* Write trkseg header. */
-                             "    <trkseg>\n");
-                trkseg_break = FALSE;
+                guint start_tilex, start_tiley, end_tilex, end_tiley;
+                start_tilex = unit2ztile(start_unitx, i);
+                start_tiley = unit2ztile(start_unity, i);
+                end_tilex = unit2ztile(end_unitx, i);
+                end_tiley = unit2ztile(end_unity, i);
+                num_maps += (end_tilex - start_tilex + 1)
+                    * (end_tiley - start_tiley + 1);
             }
-            unit2latlon(curr->point.unitx, curr->point.unity, lat, lon);
-            g_ascii_formatd(strlat, 80, "%.06f", lat);
-            g_ascii_formatd(strlon, 80, "%.06f", lon);
-            sprintf(buffer, "      <trkpt lat=\"%s\" lon=\"%s\"",
-                    strlat, strlon);
-            WRITE_STRING(buffer);
-            
-            /* write the time */
-            if(curr->time)
+        }
+        text = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_topleft_lat));
+
+        is_deleting = gtk_toggle_button_get_active(
+                GTK_TOGGLE_BUTTON(mapman_info.rad_delete));
+        is_overwriting = gtk_toggle_button_get_active(
+                GTK_TOGGLE_BUTTON(mapman_info.chk_overwrite));
+
+        if(is_deleting)
+        {
+            sprintf(buffer, "%s %d %s", _("Confirm DELETION of"),
+                    num_maps, _("maps"));
+        }
+        else
+        {
+            sprintf(buffer,
+                    "%s %d %s\n(%s %.2f MB)\n", _("Confirm download of"),
+                    num_maps, _("maps"), _("up to about"),
+                    num_maps * (strstr(_curr_repo->url, "%s") ? 18e-3 : 6e-3));
+        }
+        text = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_topleft_lat));
+        confirm = hildon_note_new_confirmation(GTK_WINDOW(dialog), buffer);
+        text = gtk_entry_get_text(GTK_ENTRY(mapman_info.txt_topleft_lat));
+
+        if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
+        {
+            for(i = 0; i < MAX_ZOOM; i++)
             {
-                WRITE_STRING(">\n        <time>");
+                if(gtk_toggle_button_get_active(
+                            GTK_TOGGLE_BUTTON(mapman_info.chk_zoom_levels[i])))
                 {
-                    struct tm time;
-                    localtime_r(&curr->time, &time);
-                    strftime(buffer, 80, XML_DATE_FORMAT, &time);
-                    WRITE_STRING(buffer);
-                    WRITE_STRING(XML_TZONE);
+                    guint start_tilex, start_tiley, end_tilex, end_tiley;
+                    guint tilex, tiley;
+                    start_tilex = unit2ztile(start_unitx, i);
+                    start_tiley = unit2ztile(start_unity, i);
+                    end_tilex = unit2ztile(end_unitx, i);
+                    end_tiley = unit2ztile(end_unity, i);
+                    for(tiley = start_tiley; tiley <= end_tiley; tiley++)
+                        for(tilex = start_tilex; tilex <= end_tilex; tilex++)
+                            map_initiate_download(tilex, tiley, i,
+                                    is_deleting ? 0 :
+                                              (is_overwriting
+                                                ? -INITIAL_DOWNLOAD_RETRIES
+                                                : INITIAL_DOWNLOAD_RETRIES));
                 }
-                WRITE_STRING("</time>\n"
-                         "      </trkpt>\n");
             }
-            else
-                WRITE_STRING("/>\n");
+            gtk_widget_destroy(confirm);
+            break;
         }
-        else
-            trkseg_break = TRUE;
+        gtk_widget_destroy(confirm);
     }
 
-    /* Write the footer. */
-    WRITE_STRING(XML_TRKSEG_FOOTER);
+    gtk_widget_hide(dialog); /* Destroying causes a crash (!?!?!??!) */
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-write_route_gpx(GnomeVFSHandle *handle)
+menu_cb_fullscreen(GtkAction *action)
 {
-    Point *curr;
-    WayPoint *wcurr;
-    gboolean trkseg_break = FALSE;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* Find first non-zero point. */
-    for(curr = _route.head-1, wcurr = _route.whead; curr++ != _route.tail; )
-        if(curr->unity)
-            break;
-        else if(curr == wcurr->point)
-            wcurr++;
+    if((_fullscreen = gtk_check_menu_item_get_active(
+                GTK_CHECK_MENU_ITEM(_menu_fullscreen_item))))
+        gtk_window_fullscreen(GTK_WINDOW(_window));
+    else
+        gtk_window_unfullscreen(GTK_WINDOW(_window));
 
-    /* Write the header. */
-    WRITE_STRING(XML_TRKSEG_HEADER);
+    gtk_idle_add((GSourceFunc)window_present, NULL);
 
-    /* Curr points to first non-zero point. */
-    for(curr--; curr++ != _route.tail; )
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
+
+static gboolean
+menu_cb_enable_gps(GtkAction *action)
+{
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    if((_enable_gps = gtk_check_menu_item_get_active(
+                GTK_CHECK_MENU_ITEM(_menu_enable_gps_item))))
     {
-        gfloat lat, lon;
-        if(curr->unity)
+        if(_rcvr_mac)
         {
-            gchar buffer[80];
-            gchar strlat[80], strlon[80];
-            if(trkseg_break)
-            {
-                /* First trkpt of the segment - write trkseg header. */
-                WRITE_STRING("    </trkseg>\n"
-                             "    <trkseg>\n");
-                trkseg_break = FALSE;
-            }
-            unit2latlon(curr->unitx, curr->unity, lat, lon);
-            g_ascii_formatd(strlat, 80, "%.06f", lat);
-            g_ascii_formatd(strlon, 80, "%.06f", lon);
-            sprintf(buffer, "      <trkpt lat=\"%s\" lon=\"%s\"",
-                    strlat, strlon);
-            if(curr == wcurr->point)
-                sprintf(buffer + strlen(buffer),
-                        "><desc>%s</desc></trkpt>\n", wcurr++->desc);
-            else
-                strcat(buffer, "/>\n");
-            WRITE_STRING(buffer);
+            set_conn_state(RCVR_DOWN);
+            rcvr_connect_now();
         }
         else
-            trkseg_break = TRUE;
+        {
+            popup_error(_window,
+                    _("Cannot enable GPS until a GPS Receiver MAC "
+                    "is set in the Settings dialog box."));
+            gtk_check_menu_item_set_active(
+                    GTK_CHECK_MENU_ITEM(_menu_enable_gps_item), FALSE);
+        }
     }
-
-    /* Write the footer. */
-    WRITE_STRING(XML_TRKSEG_FOOTER);
+    else
+    {
+        if(_conn_state > RCVR_OFF)
+            set_conn_state(RCVR_OFF);
+        rcvr_disconnect();
+        track_add(0, FALSE);
+    }
+    map_move_mark();
+    gtk_widget_set_sensitive(GTK_WIDGET(_menu_gps_reset_item), _enable_gps);
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-menu_cb_track_save(GtkAction *action)
+menu_cb_auto_download(GtkAction *action)
 {
-    GnomeVFSHandle *handle;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    if(open_file(NULL, &handle, NULL, NULL, &_track_file_uri,
-                    GTK_FILE_CHOOSER_ACTION_SAVE))
+    if((_auto_download = gtk_check_menu_item_get_active(
+            GTK_CHECK_MENU_ITEM(_menu_auto_download_item))))
     {
-        if(write_track_gpx(handle))
-            hildon_banner_show_information(_window, NULL, _("Track Saved"));
-        else
-            popup_error(_window, _("Error writing GPX file."));
-        gnome_vfs_close(handle);
+        if(!*_curr_repo->url)
+            popup_error(_window,
+                _("NOTE: You must set a Map URI in the Repository Manager in "
+                    "order to download maps."));
+        map_force_redraw();
     }
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
@@ -5874,74 +8969,44 @@ menu_cb_track_save(GtkAction *action)
 }
 
 static gboolean
-menu_cb_track_mark_way(GtkAction *action)
+menu_cb_gps_reset(GtkAction *action)
 {
-    printf("%s()\n", __PRETTY_FUNCTION__);
-
-    if(_track.tail->point.unity)
-    {
-        guint x1, y1;
-
-        /* To mark a "waypoint" in a track, we'll add a (0, 0) point and then
-         * another instance of the most recent track point. */
-        MACRO_TRACK_INCREMENT_TAIL(_track);
-        *_track.tail = _track_null;
-        MACRO_TRACK_INCREMENT_TAIL(_track);
-        *_track.tail = _track.tail[2];
-        
-        /** Instead of calling map_render_paths(), we'll just add the waypoint
-         * ourselves. */
-        x1 = unit2bufx(_track.tail->point.unitx);
-        y1 = unit2bufy(_track.tail->point.unity);
-        /* Make sure this circle will be visible. */
-        if((x1 < BUF_WIDTH_PIXELS)
-                && ((unsigned)y1 < BUF_HEIGHT_PIXELS))
-            gdk_draw_arc(_map_pixmap, _gc_track_break,
-                    FALSE, /* FALSE: not filled. */
-                    x1 - _draw_line_width,
-                    y1 - _draw_line_width,
-                    2 * _draw_line_width,
-                    2 * _draw_line_width,
-                    0, /* start at 0 degrees. */
-                    360 * 64);
-    }
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    reset_bluetooth();
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-menu_cb_route_save(GtkAction *action)
+menu_cb_gps_details(GtkAction *action)
 {
-    GnomeVFSHandle *handle;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    if(!_route.head)
-    {
-        popup_error(_window, "No route is loaded.");
-        return TRUE;
-    }
-
-    if(open_file(NULL, &handle, NULL, &_route_dir_uri, NULL,
-                    GTK_FILE_CHOOSER_ACTION_SAVE))
-    {
-        if(write_route_gpx(handle))
-            hildon_banner_show_information(_window, NULL, _("Route Saved"));
-        else
-            popup_error(_window, _("Error writing GPX file."));
-        gnome_vfs_close(handle);
-    }
+    gps_details();
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-menu_cb_track_clear(GtkAction *action)
+menu_cb_settings(GtkAction *action)
 {
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    _track.tail = _track.head;
+    if(settings_dialog())
+    {
+        /* Settings have changed - reconnect to receiver. */
+        if(_enable_gps)
+        {
+            set_conn_state(RCVR_DOWN);
+            rcvr_disconnect();
+            rcvr_connect_now();
+        }
+    }
+    MACRO_RECALC_FOCUS_BASE();
+    MACRO_RECALC_FOCUS_SIZE();
     map_force_redraw();
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
@@ -5949,987 +9014,1416 @@ menu_cb_track_clear(GtkAction *action)
 }
 
 static gboolean
-menu_cb_show_tracks(GtkAction *action)
+menu_cb_help(GtkAction *action)
 {
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    _show_tracks ^= TRACKS_MASK;
-    if(gtk_check_menu_item_get_active(
-                GTK_CHECK_MENU_ITEM(_menu_show_tracks_item)))
-    {
-        _show_tracks |= TRACKS_MASK;
-        map_render_paths();
-        MACRO_QUEUE_DRAW_AREA();
-        hildon_banner_show_information(
-                _window, NULL, _("Tracks are now shown"));
-    }
-    else
-    {
-        _show_tracks &= ~TRACKS_MASK;
-        map_force_redraw();
-        hildon_banner_show_information(
-                _window, NULL, _("Tracks are now hidden"));
-    }
+    ossohelp_show(_osso, HELP_ID_INTRO, OSSO_HELP_SHOW_DIALOG);
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-menu_cb_show_routes(GtkAction *action)
+map_download_idle_refresh(ProgressUpdateInfo *pui)
 {
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    vprintf("%s(%p)\n", __PRETTY_FUNCTION__, pui);
 
-    if(gtk_check_menu_item_get_active(
-                GTK_CHECK_MENU_ITEM(_menu_show_routes_item)))
+    /* Remove pui from hash now in case we need to retry. */
+    g_hash_table_remove(_downloads_hash, pui);
+
+    /* Test if download succeeded (only if retries_left != 0). */
+    if(!pui->retries_left
+            || gnome_vfs_uri_exists((GnomeVFSURI*)pui->dest_list->data))
     {
-        _show_tracks |= ROUTES_MASK;
-        map_render_paths();
-        MACRO_QUEUE_DRAW_AREA();
-        hildon_banner_show_information(
-                _window, NULL, _("Routes are now shown"));
+        gint zoom_diff = pui->zoom - _zoom;
+        /* Only refresh at same or "lower" (more detailed) zoom level. */
+        if(zoom_diff >= 0)
+        {
+            /* If zoom has changed since we first put in the request for this
+             * tile, then we may have to update more than one tile. */
+            guint tilex, tiley, tilex_end, tiley_end;
+            for(tilex = pui->tilex << zoom_diff,
+                    tilex_end = tilex + (1 << zoom_diff);
+                    tilex < tilex_end; tilex++)
+            {
+                for(tiley = pui->tiley<<zoom_diff,
+                        tiley_end = tiley + (1 << zoom_diff);
+                        tiley < tiley_end; tiley++)
+                {
+                    if((tilex - _base_tilex) < 4 && (tiley - _base_tiley) < 3)
+                    {
+                        map_render_tile(
+                                tilex, tiley,
+                                ((tilex - _base_tilex) << TILE_SIZE_P2),
+                                ((tiley - _base_tiley) << TILE_SIZE_P2),
+                                TRUE);
+                        map_render_paths();
+                        map_render_poi();
+                        gtk_widget_queue_draw_area(
+                                _map_widget,
+                                ((tilex-_base_tilex)<<TILE_SIZE_P2) - _offsetx,
+                                ((tiley-_base_tiley)<<TILE_SIZE_P2) - _offsety,
+                                TILE_SIZE_PIXELS, TILE_SIZE_PIXELS);
+                    }
+                }
+            }
+        }
     }
+    /* Else the download failed. Update retries_left and maybe try again. */
     else
     {
-        _show_tracks &= ~ROUTES_MASK;
-        map_force_redraw();
-        hildon_banner_show_information(
-                _window, NULL, "Routes are now hidden");
+        if(pui->retries_left > 0)
+            --pui->retries_left;
+        else if(pui->retries_left < 0)
+            ++pui->retries_left;
+        if(pui->retries_left)
+            map_initiate_download(pui->tilex, pui->tiley,
+                    pui->zoom, pui->retries_left);
     }
 
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
+    progress_update_info_free(pui);
+
+    if(++_curr_download == _num_downloads)
+    {
+        gtk_widget_destroy(_download_banner);
+        _download_banner = NULL;
+        _num_downloads = _curr_download = 0;
+    }
+    else
+        hildon_banner_set_fraction(HILDON_BANNER(_download_banner),
+                _curr_download / (double)_num_downloads);
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return FALSE;
 }
 
-static gboolean
-menu_cb_show_velvec(GtkAction *action)
+static gint
+map_download_cb_async(GnomeVFSAsyncHandle *handle,
+        GnomeVFSXferProgressInfo *info, ProgressUpdateInfo*pui)
 {
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    vprintf("%s(%p, %d, %d, %d, %s)\n", __PRETTY_FUNCTION__, pui->handle,
+            info->status, info->vfs_status, info->phase,
+            info->target_name ? info->target_name + 7 : info->target_name);
 
-    _show_velvec = gtk_check_menu_item_get_active(
-            GTK_CHECK_MENU_ITEM(_menu_show_velvec_item));
-    map_move_mark();
+    if(info->phase == GNOME_VFS_XFER_PHASE_COMPLETED)
+        g_idle_add_full(G_PRIORITY_HIGH_IDLE,
+                (GSourceFunc)map_download_idle_refresh, pui, NULL);
+    else if(info->status != GNOME_VFS_XFER_PROGRESS_STATUS_OK)
+    {
+        if(info->vfs_status == GNOME_VFS_ERROR_NOT_FOUND)
+        {
+            /* Directory doesn't exist yet - create it, then we'll retry */
+            gchar buffer[1024];
+            sprintf(buffer, "%s/%u", _curr_repo->cache_dir, pui->zoom);
+            gnome_vfs_make_directory(buffer, 0775);
+            sprintf(buffer, "%s/%u/%u",
+                    _curr_repo->cache_dir, pui->zoom, pui->tilex);
+            gnome_vfs_make_directory(buffer, 0775);
+        }
+        vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+        return FALSE;
+    }
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
+
 static gboolean
-menu_cb_ac_lead(GtkAction *action)
+cmenu_cb_loc_show_latlon(GtkAction *action)
 {
-    guint new_center_unitx, new_center_unity;
+    gchar buffer[80];
+    guint unitx, unity;
+    gfloat lat, lon;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    _center_mode = CENTER_LEAD;
-    hildon_banner_show_information(_window, NULL, _("Auto-Center Mode: Lead"));
-    MACRO_RECALC_CENTER(new_center_unitx, new_center_unity);
-    map_center_unit(new_center_unitx, new_center_unity);
+    unitx = x2unit(_cmenu_position_x);
+    unity = y2unit(_cmenu_position_y);
+    unit2latlon(unitx, unity, lat, lon);
+
+    sprintf(buffer,
+            "%s: %.06f\n"
+            "%s: %.06f",
+            _("Latitude"), lat,
+            _("Longitude"), lon);
+
+    hildon_banner_show_information(_window, NULL, buffer);
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-menu_cb_ac_latlon(GtkAction *action)
+cmenu_cb_loc_clip_latlon(GtkAction *action)
 {
-    guint new_center_unitx, new_center_unity;
+    gchar buffer[80];
+    guint unitx, unity;
+    gfloat lat, lon;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    _center_mode = CENTER_LATLON;
-    hildon_banner_show_information(_window, NULL,
-            _("Auto-Center Mode: Lat/Lon"));
-    MACRO_RECALC_CENTER(new_center_unitx, new_center_unity);
-    map_center_unit(new_center_unitx, new_center_unity);
+    unitx = x2unit(_cmenu_position_x);
+    unity = y2unit(_cmenu_position_y);
+    unit2latlon(unitx, unity, lat, lon);
+
+    sprintf(buffer, "%.06f, %.06f", lat, lon);
 
+    gtk_clipboard_set_text(
+            gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), buffer, -1);
+    
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-menu_cb_ac_none(GtkAction *action)
+cmenu_cb_loc_route_to(GtkAction *action)
 {
+    gchar buffer[80];
+    gchar strlat[32];
+    gchar strlon[32];
+    guint unitx, unity;
+    gfloat lat, lon;
     printf("%s()\n", __PRETTY_FUNCTION__);
+    
+    unitx = x2unit(_cmenu_position_x);
+    unity = y2unit(_cmenu_position_y);
+    unit2latlon(unitx, unity, lat, lon);
 
-    _center_mode = -_center_mode;
-    hildon_banner_show_information(_window, NULL, _("Auto-Center Off"));
+    g_ascii_formatd(strlat, 32, "%.06f", lat);
+    g_ascii_formatd(strlon, 32, "%.06f", lon);
+    sprintf(buffer, "%s, %s", strlat, strlon);
+    
+    route_download(NULL, buffer, TRUE);
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-menu_cb_maps_dlroute(GtkAction *action)
+cmenu_cb_loc_distance_to(GtkAction *action)
 {
-    guint last_tilex, last_tiley;
-    Point *curr;
+    gchar buffer[80];
+    guint unitx, unity;
+    gfloat lat, lon;
     printf("%s()\n", __PRETTY_FUNCTION__);
+    
+    unitx = x2unit(_cmenu_position_x);
+    unity = y2unit(_cmenu_position_y);
+    unit2latlon(unitx, unity, lat, lon);
 
-    if(!_route.head)
-    {
-        popup_error(_window, "No route is loaded.");
-        return TRUE;
-    }
-
-    last_tilex = 0;
-    last_tiley = 0;
-    for(curr = _route.head - 1; ++curr != _route.tail; )
-    {
-        if(curr->unity)
-        {
-            guint tilex = unit2tile(curr->unitx);
-            guint tiley = unit2tile(curr->unity);
-            if(tilex != last_tilex || tiley != last_tiley)
-            {
-                guint minx, miny, maxx, maxy, x, y;
-                if(last_tiley != 0)
-                {
-                    minx = MIN(tilex, last_tilex) - 2;
-                    miny = MIN(tiley, last_tiley) - 2;
-                    maxx = MAX(tilex, last_tilex) + 2;
-                    maxy = MAX(tiley, last_tiley) + 2;
-                }
-                else
-                {
-                    minx = tilex - 2;
-                    miny = tiley - 2;
-                    maxx = tilex + 2;
-                    maxy = tiley + 2;
-                }
-                for(x = minx; x <= maxx; x++)
-                    for(y = miny; y <= maxy; y++)
-                        map_initiate_download(x, y, _zoom,
-                                INITIAL_DOWNLOAD_RETRIES);
-                last_tilex = tilex;
-                last_tiley = tiley;
-            }
-        }
-    }
+    sprintf(buffer, "%s: %.02f %s", _("Distance to Location"),
+            calculate_distance(_pos_lat, _pos_lon, lat, lon),
+            UNITS_TEXT[_units]);
+    hildon_banner_show_information(_window, NULL, buffer);
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
-typedef struct _DlAreaInfo DlAreaInfo;
-struct _DlAreaInfo {
-    GtkWidget *notebook;
-    GtkWidget *txt_topleft_lat;
-    GtkWidget *txt_topleft_lon;
-    GtkWidget *txt_botright_lat;
-    GtkWidget *txt_botright_lon;
-    GtkWidget *chk_zoom_levels[MAX_ZOOM];
-};
-
-static void dlarea_clear(GtkWidget *widget, DlAreaInfo *dlarea_info)
+static WayPoint *
+find_nearest_visible_waypoint(guint unitx, guint unity)
 {
-    guint i;
-    printf("%s()\n", __PRETTY_FUNCTION__);
-    if(gtk_notebook_get_current_page(GTK_NOTEBOOK(dlarea_info->notebook)))
-        /* This is the second page (the "Zoom" page) - clear the checks. */
-        for(i = 0; i < MAX_ZOOM; i++)
-            gtk_toggle_button_set_active(
-                    GTK_TOGGLE_BUTTON(dlarea_info->chk_zoom_levels[i]), FALSE);
-    else
+    WayPoint *wcurr;
+    WayPoint *wnear;
+    guint nearest_squared;
+    Point pos = { unitx, unity };
+
+    wcurr = wnear = _visible_way_first;
+    if(wcurr && wcurr != _visible_way_last)
     {
-        /* This is the first page (the "Area" page) - clear the text fields. */
-        gtk_entry_set_text(GTK_ENTRY(dlarea_info->txt_topleft_lat), "");
-        gtk_entry_set_text(GTK_ENTRY(dlarea_info->txt_topleft_lon), "");
-        gtk_entry_set_text(GTK_ENTRY(dlarea_info->txt_botright_lat), "");
-        gtk_entry_set_text(GTK_ENTRY(dlarea_info->txt_botright_lon), "");
+        nearest_squared = DISTANCE_SQUARED(pos, *(wcurr->point));
+
+        while(wcurr++ != _visible_way_last)
+        {
+            guint test_squared = DISTANCE_SQUARED(pos, *(wcurr->point));
+            if(test_squared < nearest_squared)
+            {
+                wnear = wcurr;
+                nearest_squared = test_squared;
+            }
+        }
     }
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return wnear;
 }
 
 static gboolean
-menu_cb_maps_dlarea(GtkAction *action)
+cmenu_cb_way_show_latlon(GtkAction *action)
 {
-    GtkWidget *dialog;
-    GtkWidget *table;
-    GtkWidget *label;
-    GtkWidget *button;
-    GtkWidget *lbl_gps_lat;
-    GtkWidget *lbl_gps_lon;
-    GtkWidget *lbl_center_lat;
-    GtkWidget *lbl_center_lon;
-    DlAreaInfo dlarea_info;
     gchar buffer[80];
     gfloat lat, lon;
-    guint i;
+    WayPoint *way;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    dialog = gtk_dialog_new_with_buttons(_("Download Maps by Area"),
-            GTK_WINDOW(_window), GTK_DIALOG_MODAL,
-            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
-            NULL);
+    way = find_nearest_visible_waypoint(
+            x2unit(_cmenu_position_x),
+            y2unit(_cmenu_position_y));
 
-    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
-            button = gtk_button_new_with_label(_("Clear")));
-    g_signal_connect(G_OBJECT(button), "clicked",
-                      G_CALLBACK(dlarea_clear), &dlarea_info);
+    if(way)
+    {
+        unit2latlon(way->point->unitx, way->point->unity, lat, lon);
 
-    gtk_dialog_add_button(GTK_DIALOG(dialog),
-            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+        sprintf(buffer,
+                "%s: %.06f\n"
+                "%s: %.06f",
+                _("Latitude"), lat,
+                _("Longitude"), lon);
 
-    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
-            dlarea_info.notebook = gtk_notebook_new(), TRUE, TRUE, 0);
-    
-    gtk_notebook_append_page(GTK_NOTEBOOK(dlarea_info.notebook),
-            table = gtk_table_new(2, 3, FALSE),
-            label = gtk_label_new(_("Area")));
+        hildon_banner_show_information(_window, NULL, buffer);
+    }
+    else
+        hildon_banner_show_information(_window, NULL,
+                _("No waypoints are visible."));
 
-    /* Clear button and Label Columns. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Latitude")),
-            1, 2, 0, 1, GTK_FILL, 0, 4, 0);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Longitude")),
-            2, 3, 0, 1, GTK_FILL, 0, 4, 0);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-    /* GPS. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("GPS Location")),
-            0, 1, 1, 2, GTK_FILL, 0, 4, 0);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            lbl_gps_lat = gtk_label_new(""),
-            1, 2, 1, 2, GTK_FILL, 0, 4, 0);
-    gtk_label_set_selectable(GTK_LABEL(lbl_gps_lat), TRUE);
-    gtk_misc_set_alignment(GTK_MISC(lbl_gps_lat), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            lbl_gps_lon = gtk_label_new(""),
-            2, 3, 1, 2, GTK_FILL, 0, 4, 0);
-    gtk_label_set_selectable(GTK_LABEL(lbl_gps_lon), TRUE);
-    gtk_misc_set_alignment(GTK_MISC(lbl_gps_lon), 1.f, 0.5f);
+static gboolean
+cmenu_cb_way_show_desc(GtkAction *action)
+{
+    WayPoint *way;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    /* Center. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("View Center")),
-            0, 1, 2, 3, GTK_FILL, 0, 4, 0);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            lbl_center_lat = gtk_label_new(""),
-            1, 2, 2, 3, GTK_FILL, 0, 4, 0);
-    gtk_label_set_selectable(GTK_LABEL(lbl_center_lat), TRUE);
-    gtk_misc_set_alignment(GTK_MISC(lbl_center_lat), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            lbl_center_lon = gtk_label_new(""),
-            2, 3, 2, 3, GTK_FILL, 0, 4, 0);
-    gtk_label_set_selectable(GTK_LABEL(lbl_center_lon), TRUE);
-    gtk_misc_set_alignment(GTK_MISC(lbl_center_lon), 1.f, 0.5f);
+    way = find_nearest_visible_waypoint(
+            x2unit(_cmenu_position_x),
+            y2unit(_cmenu_position_y));
 
-    /* default values for Top Left and Bottom Right are defined by the
-     * rectangle of the current and the previous Center */
+    if(way)
+        hildon_banner_show_information(_window, NULL, way->desc);
+    else
+        hildon_banner_show_information(_window, NULL,
+                _("No waypoints are visible."));
 
-    /* Top Left. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Top-Left")),
-            0, 1, 3, 4, GTK_FILL, 0, 4, 0);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            dlarea_info.txt_topleft_lat = gtk_entry_new(),
-            1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 4, 0);
-    gtk_entry_set_alignment(GTK_ENTRY(dlarea_info.txt_topleft_lat), 1.f);
-    gtk_table_attach(GTK_TABLE(table),
-            dlarea_info.txt_topleft_lon = gtk_entry_new(),
-            2, 3, 3, 4, GTK_EXPAND | GTK_FILL, 0, 4, 0);
-    gtk_entry_set_alignment(GTK_ENTRY(dlarea_info.txt_topleft_lon), 1.f);
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-    /* Bottom Right. */
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(_("Bottom-Right")),
-            0, 1, 4, 5, GTK_FILL, 0, 4, 0);
-    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
-    gtk_table_attach(GTK_TABLE(table),
-            dlarea_info.txt_botright_lat = gtk_entry_new(),
-            1, 2, 4, 5, GTK_EXPAND | GTK_FILL, 0, 4, 0);
-    gtk_entry_set_alignment(GTK_ENTRY(dlarea_info.txt_botright_lat), 1.f);
-    gtk_table_attach(GTK_TABLE(table),
-            dlarea_info.txt_botright_lon = gtk_entry_new(),
-            2, 3, 4, 5, GTK_EXPAND | GTK_FILL, 0, 4, 0);
-    gtk_entry_set_alignment(GTK_ENTRY(dlarea_info.txt_botright_lon), 1.f);
+static gboolean
+cmenu_cb_way_clip_latlon(GtkAction *action)
+{
+    gchar buffer[80];
+    gfloat lat, lon;
+    WayPoint *way;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
+    way = find_nearest_visible_waypoint(
+            x2unit(_cmenu_position_x),
+            y2unit(_cmenu_position_y));
 
-    gtk_notebook_append_page(GTK_NOTEBOOK(dlarea_info.notebook),
-            table = gtk_table_new(5, 5, FALSE),
-            label = gtk_label_new(_("Zoom")));
-    gtk_table_attach(GTK_TABLE(table),
-            label = gtk_label_new(
-                _("Zoom Levels to Download: (0 -> most detail)")),
-            0, 5, 0, 1, GTK_FILL, 0, 4, 0);
-    gtk_misc_set_alignment(GTK_MISC(label), 0.f, 0.5f);
-    for(i = 0; i < MAX_ZOOM; i++)
+    if(way)
     {
-        sprintf(buffer, "%d", i);
-        gtk_table_attach(GTK_TABLE(table),
-                dlarea_info.chk_zoom_levels[i]
-                        = gtk_check_button_new_with_label(buffer),
-                i % 5, i % 5 + 1, i / 5 + 1, i / 5 + 2,
-                GTK_EXPAND | GTK_FILL, 0, 4, 0);
-    }
-
-    /* Initialize fields.  Do no use g_ascii_formatd; these strings will be
-     * output (and parsed) as locale-dependent. */
-    sprintf(buffer, "%.06f", _pos_lat);
-    gtk_label_set_text(GTK_LABEL(lbl_gps_lat), buffer);
-    sprintf(buffer, "%.06f", _pos_lon);
-    gtk_label_set_text(GTK_LABEL(lbl_gps_lon), buffer);
-
-    unit2latlon(_center.unitx, _center.unity, lat, lon);
-    sprintf(buffer, "%.06f", lat);
-    gtk_label_set_text(GTK_LABEL(lbl_center_lat), buffer);
-    sprintf(buffer, "%.06f", lon);
-    gtk_label_set_text(GTK_LABEL(lbl_center_lon), buffer);
-
-    /* Initialize to the bounds of the screen. */
-    unit2latlon(x2unit(0), y2unit(0), lat, lon);
-    sprintf(buffer, "%.06f", lat);
-    gtk_entry_set_text(GTK_ENTRY(dlarea_info.txt_topleft_lat), buffer);
-    sprintf(buffer, "%.06f", lon);
-    gtk_entry_set_text(GTK_ENTRY(dlarea_info.txt_topleft_lon), buffer);
-
-    unit2latlon(x2unit(_screen_width_pixels), y2unit(_screen_height_pixels),
-            lat, lon);
-    sprintf(buffer, "%.06f", lat);
-    gtk_entry_set_text(GTK_ENTRY(dlarea_info.txt_botright_lat), buffer);
-    sprintf(buffer, "%.06f", lon);
-    gtk_entry_set_text(GTK_ENTRY(dlarea_info.txt_botright_lon), buffer);
-
-    for(i = 0; i < MAX_ZOOM; i++)
-        gtk_toggle_button_set_active(
-            GTK_TOGGLE_BUTTON(dlarea_info.chk_zoom_levels[i]), FALSE);
-    gtk_toggle_button_set_active(
-            GTK_TOGGLE_BUTTON(dlarea_info.chk_zoom_levels[_zoom]), TRUE);
-
+        unit2latlon(way->point->unitx, way->point->unity, lat, lon);
 
-    gtk_widget_show_all(dialog);
+        sprintf(buffer, "%.06f, %.06f", lat, lon);
 
-    while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
-    {
-        const gchar *text;
-        gchar *error_check;
-        gfloat start_lat, start_lon, end_lat, end_lon;
-        guint start_unitx, start_unity, end_unitx, end_unity;
-        guint num_maps = 0;
-        GtkWidget *confirm;
+        gtk_clipboard_set_text(
+                gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), buffer, -1);
+    }
+    else
+        hildon_banner_show_information(_window, NULL,
+                _("No waypoints are visible."));
 
-        text = gtk_entry_get_text(GTK_ENTRY(dlarea_info.txt_topleft_lat));
-        start_lat = strtof(text, &error_check);
-        if(text == error_check) {
-            popup_error(dialog, _("Invalid Top-Left Latitude"));
-            continue;
-        }
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-        text = gtk_entry_get_text(GTK_ENTRY(dlarea_info.txt_topleft_lon));
-        start_lon = strtof(text, &error_check);
-        if(text == error_check) {
-            popup_error(dialog, _("Invalid Top-Left Longitude"));
-            continue;
-        }
+static gboolean
+cmenu_cb_way_clip_desc(GtkAction *action)
+{
+    WayPoint *way;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-        text = gtk_entry_get_text(GTK_ENTRY(dlarea_info.txt_botright_lat));
-        end_lat = strtof(text, &error_check);
-        if(text == error_check) {
-            popup_error(dialog, _("Invalid Bottom-Right Latitude"));
-            continue;
-        }
+    way = find_nearest_visible_waypoint(
+            x2unit(_cmenu_position_x),
+            y2unit(_cmenu_position_y));
 
-        text = gtk_entry_get_text(GTK_ENTRY(dlarea_info.txt_botright_lon));
-        end_lon = strtof(text, &error_check);
-        if(text == error_check) {
-            popup_error(dialog,_("Invalid Bottom-Right Longitude"));
-            continue;
-        }
+    if(way)
+        gtk_clipboard_set_text(
+                gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), way->desc, -1);
+    else
+        hildon_banner_show_information(_window, NULL,
+                _("No waypoints are visible."));
 
-        latlon2unit(start_lat, start_lon, start_unitx, start_unity);
-        latlon2unit(end_lat, end_lon, end_unitx, end_unity);
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return TRUE;
+}
 
-        /* Swap if they specified flipped lats or lons. */
-        if(start_unitx > end_unitx)
-        {
-            guint swap = start_unitx;
-            start_unitx = end_unitx;
-            end_unitx = swap;
-        }
-        if(start_unity > end_unity)
-        {
-            guint swap = start_unity;
-            start_unity = end_unity;
-            end_unity = swap;
-        }
+static gboolean
+cmenu_cb_way_route_to(GtkAction *action)
+{
+    WayPoint *way;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-        /* First, get the number of maps to download. */
-        for(i = 0; i < MAX_ZOOM; i++)
-        {
-            if(gtk_toggle_button_get_active(
-                        GTK_TOGGLE_BUTTON(dlarea_info.chk_zoom_levels[i])))
-            {
-                guint start_tilex, start_tiley, end_tilex, end_tiley;
-                start_tilex = unit2ztile(start_unitx, i);
-                start_tiley = unit2ztile(start_unity, i);
-                end_tilex = unit2ztile(end_unitx, i);
-                end_tiley = unit2ztile(end_unity, i);
-                num_maps += (end_tilex - start_tilex + 1)
-                    * (end_tiley - start_tiley + 1);
-            }
-        }
-        text = gtk_entry_get_text(GTK_ENTRY(dlarea_info.txt_topleft_lat));
+    way = find_nearest_visible_waypoint(
+            x2unit(_cmenu_position_x),
+            y2unit(_cmenu_position_y));
 
-        sprintf(buffer,
-                "%s %d %s\n(%s %.2f MB)\n", _("Confirm download of"),
-                num_maps, _("maps"), _("up to about"),
-                num_maps * (strstr(_map_uri_format, "%s") ? 18e-3 : 6e-3));
-        text = gtk_entry_get_text(GTK_ENTRY(dlarea_info.txt_topleft_lat));
-        confirm = hildon_note_new_confirmation(GTK_WINDOW(dialog), buffer);
-        text = gtk_entry_get_text(GTK_ENTRY(dlarea_info.txt_topleft_lat));
+    if(way)
+    {
+        gchar buffer[80];
+        gchar strlat[32];
+        gchar strlon[32];
+        gfloat lat, lon;
+        printf("%s()\n", __PRETTY_FUNCTION__);
 
-        if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
-        {
-            for(i = 0; i < MAX_ZOOM; i++)
-            {
-                if(gtk_toggle_button_get_active(
-                            GTK_TOGGLE_BUTTON(dlarea_info.chk_zoom_levels[i])))
-                {
-                    guint start_tilex, start_tiley, end_tilex, end_tiley;
-                    guint tilex, tiley;
-                    start_tilex = unit2ztile(start_unitx, i);
-                    start_tiley = unit2ztile(start_unity, i);
-                    end_tilex = unit2ztile(end_unitx, i);
-                    end_tiley = unit2ztile(end_unity, i);
-                    for(tiley = start_tiley; tiley <= end_tiley; tiley++)
-                        for(tilex = start_tilex; tilex <= end_tilex; tilex++)
-                            map_initiate_download(tilex, tiley, i,
-                                    INITIAL_DOWNLOAD_RETRIES);
-                }
-            }
-            gtk_widget_destroy(confirm);
-            break;
-        }
-        gtk_widget_destroy(confirm);
+        unit2latlon(way->point->unitx, way->point->unity, lat, lon);
+        g_ascii_formatd(strlat, 32, "%.06f", lat);
+        g_ascii_formatd(strlon, 32, "%.06f", lon);
+        sprintf(buffer, "%s, %s", strlat, strlon);
+        
+        route_download(NULL, buffer, TRUE);
     }
-
-    gtk_widget_hide(dialog); /* Destroying causes a crash (!?!?!??!) */
+    else
+        hildon_banner_show_information(_window, NULL,
+                _("No waypoints are visible."));
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-menu_cb_fullscreen(GtkAction *action)
+cmenu_cb_way_distance_to(GtkAction *action)
 {
+    WayPoint *way;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    if((_fullscreen = gtk_check_menu_item_get_active(
-                GTK_CHECK_MENU_ITEM(_menu_fullscreen_item))))
-        gtk_window_fullscreen(GTK_WINDOW(_window));
-    else
-        gtk_window_unfullscreen(GTK_WINDOW(_window));
+    way = find_nearest_visible_waypoint(
+            x2unit(_cmenu_position_x),
+            y2unit(_cmenu_position_y));
 
-    gtk_idle_add((GSourceFunc)window_present, NULL);
+    if(way)
+    {
+        gchar buffer[80];
+        gfloat lat, lon;
+        printf("%s()\n", __PRETTY_FUNCTION__);
+
+        unit2latlon(way->point->unitx, way->point->unity, lat, lon);
+
+        sprintf(buffer, "%s: %.02f %s", _("Distance to Waypoint"),
+                calculate_distance(_pos_lat, _pos_lon, lat, lon),
+                UNITS_TEXT[_units]);
+        hildon_banner_show_information(_window, NULL, buffer);
+    }
+    else
+        hildon_banner_show_information(_window, NULL,
+                _("No waypoints are visible."));
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-menu_cb_enable_gps(GtkAction *action)
+cmenu_cb_way_delete(GtkAction *action)
 {
+    WayPoint *way;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    if((_enable_gps = gtk_check_menu_item_get_active(
-                GTK_CHECK_MENU_ITEM(_menu_enable_gps_item))))
+    way = find_nearest_visible_waypoint(
+            x2unit(_cmenu_position_x),
+            y2unit(_cmenu_position_y));
+
+    if(way)
     {
-        if(_rcvr_mac)
-        {
-            set_conn_state(RCVR_DOWN);
-            rcvr_connect_now();
-        }
-        else
+        gchar buffer[1024];
+        GtkWidget *confirm;
+
+        sprintf(buffer, "%s:\n%s\n",
+                _("Confirm delete of waypoint"), way->desc);
+        confirm = hildon_note_new_confirmation(GTK_WINDOW(_window), buffer);
+
+        if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
         {
-            popup_error(_window,
-                    _("Cannot enable GPS until a GPS Receiver MAC "
-                    "is set in the Settings dialog box."));
-            gtk_check_menu_item_set_active(
-                    GTK_CHECK_MENU_ITEM(_menu_enable_gps_item), FALSE);
+            while(way++ != _route.wtail)
+                way[-1] = *way;
+            _route.wtail--;
+            map_force_redraw();
         }
+        gtk_widget_destroy(confirm);
     }
     else
-    {
-        if(_conn_state > RCVR_OFF)
-            set_conn_state(RCVR_OFF);
-        rcvr_disconnect();
-        track_add(0, FALSE);
-    }
-    map_move_mark();
+        hildon_banner_show_information(_window, NULL,
+                _("No waypoints are visible."));
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-menu_cb_auto_download(GtkAction *action)
+category_delete(GtkWidget *widget, DeletePOI *dpoi)
 {
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    GtkWidget *dialog;
+    guint i;
+    gchar *buffer;
 
-    if((_auto_download = gtk_check_menu_item_get_active(
-            GTK_CHECK_MENU_ITEM(_menu_auto_download_item))))
+    buffer = g_strdup_printf(_("Delete category?\n%s"), dpoi->txt_label);
+    dialog = hildon_note_new_confirmation (GTK_WINDOW(_window), buffer);
+    g_free(buffer);
+    i = gtk_dialog_run (GTK_DIALOG (dialog));
+    gtk_widget_destroy (GTK_WIDGET (dialog));
+
+    if(i == GTK_RESPONSE_OK)
+    {
+        /* delete dpoi->poi_id */
+        buffer = g_strdup_printf("delete from poi where cat_id = %d",
+            dpoi->id);
+
+        if(sqlite_exec(_db, buffer, NULL, NULL, NULL)
+            != SQLITE_OK)
+        {
+            hildon_banner_show_information(_window, NULL,
+                _("Problem deleting POI"));
+            g_free(buffer);
+            return FALSE;
+        }
+
+        g_free(buffer);
+        buffer = g_strdup_printf("delete from category where cat_id = %d",
+            dpoi->id);
+
+        if(sqlite_exec(_db, buffer, NULL, NULL, NULL)
+            != SQLITE_OK)
+        {
+            hildon_banner_show_information(_window, NULL,
+                _("Problem deleting category"));
+            g_free(buffer);
+            return FALSE;
+        }
+
+        gtk_widget_hide_all(dpoi->dialog);
         map_force_redraw();
+        g_free(buffer);
+    }
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-menu_cb_settings(GtkAction *action)
+category_dialog(guint cat_id)
 {
+    gchar **pszResult;
+    gint nRow, nColumn;
+    gchar *sql;
+    gchar *cat_label = NULL, *cat_desc = NULL;
+    guint cat_enabled;
+    GtkWidget *dialog;
+    GtkWidget *table;
+    GtkWidget *label;
+    GtkWidget *txt_label;
+    GtkWidget *txt_desc;
+    GtkWidget *btn_delete = NULL;
+    GtkWidget *txt_scroll;
+    GtkWidget *chk_enabled;
+    GtkTextBuffer *desc_txt;
+    GtkTextIter begin, end;
+    gboolean results = TRUE;
+    DeletePOI dpoi = {NULL, NULL, 0};
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    if(settings_dialog())
+    if(cat_id > 0)
     {
-        /* Settings have changed - reconnect to receiver. */
-        if(_enable_gps)
+        sql = g_strdup_printf(
+            "select c.label, c. desc, c.enabled"
+            " from category c"
+            " where c.cat_id = %d",
+             cat_id);
+
+        if(sqlite_get_table(_db, sql, &pszResult, &nRow, &nColumn, NULL)
+            != SQLITE_OK)
         {
-            set_conn_state(RCVR_DOWN);
-            rcvr_disconnect();
-            rcvr_connect_now();
+            g_free(sql);
+            printf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+            return FALSE;
         }
+        g_free(sql);
+
+        if(nRow == 0)
+            return FALSE;
+
+        cat_label = g_strdup(pszResult[1 * nColumn + 0]);
+        cat_desc  = g_strdup(pszResult[1 * nColumn + 1]);
+        cat_enabled = atoi(pszResult[1 * nColumn + 2]);
+        sqlite_free_table(pszResult);
+
+        dialog = gtk_dialog_new_with_buttons(_("Edit Category"),
+            GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+            NULL);
+
+        gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
+                btn_delete = gtk_button_new_with_label(_("Delete")));
+
+        dpoi.dialog = dialog;
+        dpoi.txt_label = g_strdup_printf("%s (%s)", cat_label, cat_desc);
+        dpoi.id = cat_id;
+
+        g_signal_connect(G_OBJECT(btn_delete), "clicked",
+                          G_CALLBACK(category_delete), &dpoi);
+
+        gtk_dialog_add_button(GTK_DIALOG(dialog),
+                GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
     }
-    MACRO_RECALC_FOCUS_BASE();
-    MACRO_RECALC_FOCUS_SIZE();
-    map_force_redraw();
+    else
+    {
+        cat_enabled = 1;
+        cat_label = g_strdup("");
+        cat_id = 0;
+        cat_desc = g_strdup("");
 
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
+        dialog = gtk_dialog_new_with_buttons(_("Add Category"),
+            GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+            NULL);
+    }
+
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+            table = gtk_table_new(6, 4, FALSE), TRUE, TRUE, 0);
+
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Label: ")),
+            0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            txt_label = gtk_entry_new(),
+            1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Desc.: ")),
+            0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+
+    txt_scroll = gtk_scrolled_window_new(NULL, NULL);
+    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll),
+                                   GTK_SHADOW_IN);
+    gtk_table_attach(GTK_TABLE(table),
+            txt_scroll,
+            1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll),
+                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+    txt_desc = gtk_text_view_new ();
+    gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD);
+
+    gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc);
+    gtk_widget_show(txt_scroll);
+    gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 400, 60);
+
+    desc_txt = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txt_desc));
+
+    gtk_table_attach(GTK_TABLE(table),
+            chk_enabled = gtk_check_button_new_with_label(
+                _("Enabled")),
+            0, 2, 2, 3, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+
+    /* label */
+    gtk_entry_set_text(GTK_ENTRY(txt_label), cat_label);
+
+    /* desc */
+    gtk_text_buffer_set_text(desc_txt, cat_desc, -1);
+
+    /* enabled */
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chk_enabled),
+            (cat_enabled == 1 ? TRUE : FALSE));
+
+    g_free(cat_label);
+    cat_label = NULL;
+    g_free(cat_desc);
+    cat_desc = NULL;
+
+    gtk_widget_show_all(dialog);
+
+    while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
+    {
+        if(strlen(gtk_entry_get_text(GTK_ENTRY(txt_label))))
+            cat_label = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_label)));
+        else
+        {
+            popup_error(dialog, _("Please specify a name for the category."));
+            continue;
+        }
+
+        gtk_text_buffer_get_iter_at_offset(desc_txt, &begin,0 );
+        gtk_text_buffer_get_end_iter (desc_txt, &end);
+        cat_desc = gtk_text_buffer_get_text(desc_txt, &begin, &end, TRUE);
+
+        cat_enabled = (gtk_toggle_button_get_active(
+                GTK_TOGGLE_BUTTON(chk_enabled)) ? 1 : 0);
+
+        if(cat_id > 0)
+        {
+            /* edit category */
+            sql = g_strdup_printf(
+                "update category set label = '%s', desc = '%s', "
+                "enabled = %d where poi_id = %d",
+                cat_label, cat_desc, cat_enabled, cat_id);
+            if(sqlite_exec(_db, sql, NULL, NULL, NULL) != SQLITE_OK)
+            {
+                hildon_banner_show_information(_window, NULL,
+                    _("Problem updating category"));
+                results = FALSE;
+            }
+        }
+        else
+        {
+            /* add category */
+            sql = g_strdup_printf(
+                "insert into category (label, desc, enabled) "
+                "values ('%s', '%s', %d)",
+                cat_label, cat_desc, cat_enabled);
+            if(sqlite_exec(_db, sql, NULL, NULL, NULL) != SQLITE_OK)
+            {
+                hildon_banner_show_information(_window, NULL,
+                    _("Problem adding category"));
+                results = FALSE;
+            }
+        }
+        g_free(sql);
+        break;
+    }
+
+    if(cat_label)
+        g_free(cat_label);
+    if(cat_desc)
+        g_free(cat_desc);
+    g_object_unref (desc_txt);
+
+    gtk_widget_hide_all(dialog);
+
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return results;
 }
 
-static gboolean
-menu_cb_help(GtkAction *action)
+static void
+category_toggled (GtkCellRendererToggle *cell,
+           gchar                 *path,
+           gpointer               data)
 {
+    GtkTreeIter iter;
+    gboolean cat_enabled;
+    guint cat_id;
+    gchar buffer[100];
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    ossohelp_show(_osso, HELP_ID_INTRO, OSSO_HELP_SHOW_DIALOG);
+    GtkTreeModel *model = GTK_TREE_MODEL(data);
+    if( !gtk_tree_model_get_iter_from_string(model, &iter, path) )
+        return;
+
+    gtk_tree_model_get(model, &iter, CAT_ENABLED, &cat_enabled, -1);
+    gtk_tree_model_get(model, &iter, CAT_ID, &cat_id, -1);
+
+    cat_enabled ^= 1;
+
+    sprintf(buffer, "update category set enabled = %d where cat_id = %d",
+        (cat_enabled ? 1 : 0), cat_id);
+
+    if(sqlite_exec(_db, buffer, NULL, NULL, NULL) != SQLITE_OK)
+        hildon_banner_show_information(_window, NULL,
+            _("Problem updating Category"));
+    else
+        gtk_list_store_set(GTK_LIST_STORE(model), &iter,
+                   CAT_ENABLED, cat_enabled, -1);
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
 }
 
-static gboolean
-map_download_idle_refresh(ProgressUpdateInfo *pui)
+static GtkListStore*
+generate_store()
 {
-    vprintf("%s(%p)\n", __PRETTY_FUNCTION__, pui);
-
-    /* Remove pui from hash now in case we need to retry. */
-    g_hash_table_remove(_downloads_hash, pui);
-
-    /* Test if download succeeded. */
-    if(gnome_vfs_uri_exists((GnomeVFSURI*)pui->dest_list->data))
+    guint i;
+    GtkTreeIter iter;
+    GtkListStore *store;
+    gchar *sql;
+    gchar **pszResult;
+    gint nRow, nColumn;
+    sql = g_strdup(
+        "select c.cat_id, c.enabled, c.label, c.desc"
+        " from category c "
+        " order by c.label");
+
+    if(sqlite_get_table(_db, sql, &pszResult, &nRow, &nColumn, NULL)
+        != SQLITE_OK)
     {
-        gint zoom_diff = pui->zoom - _zoom;
-        /* Only refresh at same or "lower" (more detailed) zoom level. */
-        if(zoom_diff >= 0)
-        {
-            /* If zoom has changed since we first put in the request for this
-             * tile, then we may have to update more than one tile. */
-            guint tilex, tiley, tilex_end, tiley_end;
-            for(tilex = pui->tilex << zoom_diff,
-                    tilex_end = tilex + (1 << zoom_diff);
-                    tilex < tilex_end; tilex++)
-            {
-                for(tiley = pui->tiley<<zoom_diff,
-                        tiley_end = tiley + (1 << zoom_diff);
-                        tiley < tiley_end; tiley++)
-                {
-                    if((tilex - _base_tilex) < 4 && (tiley - _base_tiley) < 3)
-                    {
-                        map_render_tile(
-                                tilex, tiley,
-                                ((tilex - _base_tilex) << TILE_SIZE_P2),
-                                ((tiley - _base_tiley) << TILE_SIZE_P2),
-                                TRUE);
-                        map_render_paths();
-                        gtk_widget_queue_draw_area(
-                                _map_widget,
-                                ((tilex-_base_tilex)<<TILE_SIZE_P2) - _offsetx,
-                                ((tiley-_base_tiley)<<TILE_SIZE_P2) - _offsety,
-                                TILE_SIZE_PIXELS, TILE_SIZE_PIXELS);
-                    }
-                }
-            }
-        }
+        g_free(sql);
+        printf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+        return NULL;
     }
-    /* Else the download failed. Update retries_left and maybe try again. */
-    else if(pui->retries_left--)
-        map_initiate_download(pui->tilex, pui->tiley,
-                pui->zoom, pui->retries_left);
+    g_free(sql);
 
-    progress_update_info_free(pui);
+    store = gtk_list_store_new(CAT_NUM_COLUMNS,
+                               G_TYPE_UINT,
+                               G_TYPE_BOOLEAN,
+                               G_TYPE_STRING,
+                               G_TYPE_STRING);
 
-    if(++_curr_download == _num_downloads)
+    for(i = 1; i < nRow + 1; i++)
     {
-        gtk_widget_destroy(_download_banner);
-        _download_banner = NULL;
-        _num_downloads = _curr_download = 0;
+        gtk_list_store_append(store, &iter);
+        gtk_list_store_set(store, &iter,
+                CAT_ID, atoi(pszResult[i * nColumn + 0]),
+                CAT_ENABLED,
+                (atoi(pszResult[i * nColumn + 1]) == 1 ? TRUE : FALSE),
+                CAT_LABEL, pszResult[i * nColumn + 2],
+                CAT_DESCRIPTION, pszResult[i * nColumn + 3],
+                -1);
     }
-    else
-        hildon_banner_set_fraction(HILDON_BANNER(_download_banner),
-                _curr_download / (double)_num_downloads);
 
-    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
-    return FALSE;
+    sqlite_free_table(pszResult);
+    vprintf("%s(): return %p\n", __PRETTY_FUNCTION__, store);
+    return store;
 }
 
-static gint
-map_download_cb_async(GnomeVFSAsyncHandle *handle,
-        GnomeVFSXferProgressInfo *info, ProgressUpdateInfo*pui)
+static gboolean
+category_add(GtkWidget *widget, GtkWidget *tree_view)
 {
-    vprintf("%s(%p, %d, %d, %d, %s)\n", __PRETTY_FUNCTION__, pui->handle,
-            info->status, info->vfs_status, info->phase,
-            info->target_name ? info->target_name + 7 : info->target_name);
+    GtkListStore *store;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-    if(info->phase == GNOME_VFS_XFER_PHASE_COMPLETED)
-        g_idle_add_full(G_PRIORITY_HIGH_IDLE,
-                (GSourceFunc)map_download_idle_refresh, pui, NULL);
-    else if(info->status != GNOME_VFS_XFER_PROGRESS_STATUS_OK)
+    if(category_dialog(0))
     {
-        if(info->vfs_status == GNOME_VFS_ERROR_NOT_FOUND)
-        {
-            /* Directory doesn't exist yet - create it, then we'll retry */
-            gchar buffer[1024];
-            sprintf(buffer, "%s/%u", _map_dir_name, pui->zoom);
-            gnome_vfs_make_directory(buffer, 0775);
-            sprintf(buffer, "%s/%u/%u", _map_dir_name, pui->zoom, pui->tilex);
-            gnome_vfs_make_directory(buffer, 0775);
-        }
-        vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
-        return FALSE;
+        store = generate_store();
+        gtk_tree_view_set_model(
+                GTK_TREE_VIEW(tree_view),
+                GTK_TREE_MODEL(store));
+        g_object_unref(G_OBJECT(store));
     }
-
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
-
 static gboolean
-cmenu_cb_loc_show_latlon(GtkAction *action)
+category_edit(GtkWidget *widget, GtkWidget *tree_view)
 {
-    gchar buffer[80];
-    guint unitx, unity;
-    gfloat lat, lon;
+    GtkTreeIter iter;
+    GtkTreeModel *store;
+    GtkTreeSelection *selection;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    unitx = x2unit(_cmenu_position_x);
-    unity = y2unit(_cmenu_position_y);
-    unit2latlon(unitx, unity, lat, lon);
-
-    sprintf(buffer,
-            "%s: %.06f\n"
-            "%s: %.06f",
-            _("Latitude"), lat,
-            _("Longitude"), lon);
-
-    hildon_banner_show_information(_window, NULL, buffer);
-
+    store = gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view));
+    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
+    if(gtk_tree_selection_get_selected(selection, &store, &iter))
+    {
+        GValue val;
+        memset(&val, 0, sizeof(val));
+        gtk_tree_model_get_value(store, &iter, 0, &val);
+        if(category_dialog(g_value_get_uint(&val)))
+        {
+            GtkListStore *new_store = generate_store();
+            gtk_tree_view_set_model(
+                    GTK_TREE_VIEW(tree_view),
+                    GTK_TREE_MODEL(new_store));
+            g_object_unref(G_OBJECT(new_store));
+        }
+    }
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-cmenu_cb_loc_clip_latlon(GtkAction *action)
+category_list()
 {
-    gchar buffer[80];
-    guint unitx, unity;
-    gfloat lat, lon;
+    GtkWidget *dialog;
+    GtkWidget *tree_view;
+    GtkWidget *sw;
+    GtkWidget *btn_edit;
+    GtkWidget *btn_add;
+    GtkTreeViewColumn *column;
+    GtkCellRenderer *renderer;
+    GtkListStore *store;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    unitx = x2unit(_cmenu_position_x);
-    unity = y2unit(_cmenu_position_y);
-    unit2latlon(unitx, unity, lat, lon);
+    dialog = gtk_dialog_new_with_buttons(_("Category List"),
+            GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+            NULL);
 
-    sprintf(buffer, "%.06f, %.06f", lat, lon);
+    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
+            btn_edit = gtk_button_new_with_label(_("Edit")));
+
+    gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
+            btn_add = gtk_button_new_with_label(_("Add")));
+
+    store = generate_store();
+
+    if(!store)
+        return TRUE;
+
+    sw = gtk_scrolled_window_new(NULL, NULL);
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (sw),
+                  GTK_POLICY_NEVER,
+                  GTK_POLICY_AUTOMATIC);
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+            sw, TRUE, TRUE, 0);
+
+    tree_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+    /* Maemo-related? */
+    g_object_set(tree_view, "allow-checkbox-mode", FALSE, NULL);
+    gtk_container_add (GTK_CONTAINER (sw), tree_view);
+
+    gtk_tree_selection_set_mode(
+            gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view)),
+            GTK_SELECTION_SINGLE);
+    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view), TRUE);
+
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes(
+            _("ID"), renderer, "text", CAT_ID);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
+    gtk_tree_view_column_set_max_width (column, 1);
+
+    renderer = gtk_cell_renderer_toggle_new();
+    g_signal_connect (renderer, "toggled",
+            G_CALLBACK (category_toggled), store);
+    column = gtk_tree_view_column_new_with_attributes(
+            _("Enabled"), renderer, "active", CAT_ENABLED);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
+
+    g_object_unref(G_OBJECT(store));
+
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes(
+            _("Label"), renderer, "text", CAT_LABEL);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
+
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes(
+            _("Desc."), renderer, "text", CAT_DESCRIPTION);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view), column);
+
+    gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 300);
+    gtk_widget_show_all(dialog);
+
+    g_signal_connect(G_OBJECT(btn_edit), "clicked",
+            G_CALLBACK(category_edit), tree_view);
+
+    g_signal_connect(G_OBJECT(btn_add), "clicked",
+            G_CALLBACK(category_add), tree_view);
+
+    while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
+    {
+        break;
+    }
+    gtk_widget_destroy(dialog);
 
-    gtk_clipboard_set_text(
-            gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), buffer, -1);
-    
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-cmenu_cb_loc_route_to(GtkAction *action)
+menu_cb_category(GtkAction *action)
 {
-    gchar buffer[80];
-    gchar strlat[32];
-    gchar strlon[32];
-    guint unitx, unity;
-    gfloat lat, lon;
     printf("%s()\n", __PRETTY_FUNCTION__);
-    
-    unitx = x2unit(_cmenu_position_x);
-    unity = y2unit(_cmenu_position_y);
-    unit2latlon(unitx, unity, lat, lon);
 
-    g_ascii_formatd(strlat, 32, "%.06f", lat);
-    g_ascii_formatd(strlon, 32, "%.06f", lon);
-    sprintf(buffer, "%s, %s", strlat, strlon);
-    
-    route_download(NULL, buffer, TRUE);
+    if(category_list())
+        map_force_redraw();
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-cmenu_cb_loc_distance_to(GtkAction *action)
+poi_delete(GtkWidget *widget, DeletePOI *dpoi)
 {
-    gchar buffer[80];
-    guint unitx, unity;
-    gfloat lat, lon;
+    GtkWidget *dialog;
+    guint i;
+    gchar *buffer;
     printf("%s()\n", __PRETTY_FUNCTION__);
-    
-    unitx = x2unit(_cmenu_position_x);
-    unity = y2unit(_cmenu_position_y);
-    unit2latlon(unitx, unity, lat, lon);
 
-    sprintf(buffer, "%s: %.02f %s", _("Distance to Location"),
-            calculate_distance(_pos_lat, _pos_lon, lat, lon), _units);
-    hildon_banner_show_information(_window, NULL, buffer);
-    
+    buffer = g_strdup_printf(_("Delete POI?\n%s"), dpoi->txt_label);
+    dialog = hildon_note_new_confirmation (GTK_WINDOW(_window), buffer);
+    g_free(buffer);
+    i = gtk_dialog_run (GTK_DIALOG (dialog));
+    gtk_widget_destroy (GTK_WIDGET (dialog));
+
+    if(i == GTK_RESPONSE_OK)
+    {
+        /* delete dpoi->poi_id */
+        buffer = g_strdup_printf("delete from poi where poi_id = %d",
+            dpoi->id);
+
+        if(sqlite_exec(_db, buffer, NULL, NULL, NULL)
+            != SQLITE_OK)
+        {
+            hildon_banner_show_information(_window, NULL,
+                _("Problem deleting POI"));
+        }
+        else
+        {
+            gtk_widget_hide_all(dpoi->dialog);
+            map_force_redraw();
+        }
+        g_free(buffer);
+    }
+
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
-static WayPoint *
-find_nearest_visible_waypoint(guint unitx, guint unity)
+static guint
+poi_list(gchar **pszResult, gint nRow, gint nColumn)
 {
-    WayPoint *wcurr;
-    WayPoint *wnear;
-    guint nearest_squared;
-    Point pos = { unitx, unity };
+    GtkWidget *dialog;
+    GtkWidget *list;
+    GtkWidget *sw;
+    GtkTreeViewColumn *column;
+    GtkCellRenderer *renderer;
+    GtkListStore *store;
+    GtkTreeIter iter;
+    guint i, row = -1;
+    printf("%s()\n", __PRETTY_FUNCTION__);
+
+    dialog = gtk_dialog_new_with_buttons(_("Select POI"),
+            GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+            NULL);
+
+    store = gtk_list_store_new(POI_NUM_COLUMNS,
+                               G_TYPE_INT,
+                               G_TYPE_FLOAT,
+                               G_TYPE_FLOAT,
+                               G_TYPE_STRING,
+                               G_TYPE_STRING);
+
+    for(i = 1; i < nRow + 1; i++)
+    {
+        gtk_list_store_append(store, &iter);
+        gtk_list_store_set(store, &iter,
+                POI_INDEX, i,
+                POI_LATITUDE, atof(pszResult[i * nColumn + 0]),
+                POI_LONGITUDE, atof(pszResult[i * nColumn + 1]),
+                POI_LABEL, pszResult[i * nColumn + 2],
+                POI_CATEGORY, pszResult[i * nColumn + 6],
+                -1);
+    }
+
+    gtk_window_set_default_size(GTK_WINDOW(dialog), 500, 300);
+
+    sw = gtk_scrolled_window_new (NULL, NULL);
+    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
+                   GTK_SHADOW_ETCHED_IN);
+    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+                  GTK_POLICY_NEVER,
+                  GTK_POLICY_AUTOMATIC);
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+            sw, TRUE, TRUE, 0);
+
+    list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+    g_object_unref(G_OBJECT(store));
+    gtk_container_add (GTK_CONTAINER (sw), list);
+
+    gtk_tree_selection_set_mode(
+            gtk_tree_view_get_selection(GTK_TREE_VIEW(list)),
+            GTK_SELECTION_SINGLE);
+    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), TRUE);
+
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes(
+            _("POI_INDEX"), renderer, "text", POI_INDEX);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
+    gtk_tree_view_column_set_max_width (column, 1);
+
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes(
+            _("Latitude"), renderer, "text", POI_LATITUDE);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
+
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes(
+            _("Longitude"), renderer, "text", POI_LONGITUDE);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
+
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes(
+            _("Label"), renderer, "text", POI_LABEL);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
+
+    renderer = gtk_cell_renderer_text_new();
+    column = gtk_tree_view_column_new_with_attributes(
+            _("Category"), renderer, "text", POI_CATEGORY);
+    gtk_tree_view_append_column(GTK_TREE_VIEW(list), column);
+
+    gtk_widget_show_all(dialog);
+
+    while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
+    {
+        GtkTreeIter iter;
+        if(gtk_tree_selection_get_selected(
+                    gtk_tree_view_get_selection(GTK_TREE_VIEW(list)),
+                    NULL, &iter))
+        {
+            gtk_tree_model_get(GTK_TREE_MODEL(store),
+                &iter, 0, &row, -1);
+            break;
+        }
+        else
+            popup_error(dialog, _("Select one POI from the list."));
+    }
+
+    gtk_widget_destroy(dialog);
+
+    vprintf("%s(): return %d\n", __PRETTY_FUNCTION__, row);
+    return row;
+}
 
-    wcurr = wnear = _visible_way_first;
-    if(wcurr && wcurr != _visible_way_last)
+static void
+poi_populate_cat_combo(GtkWidget *cmb_category, guint cat_id)
+{
+    gchar **pszResult;
+    gint nRow, nColumn, row;
+    guint i, catindex = 0;
+    gint n_children = gtk_tree_model_iter_n_children(
+            gtk_combo_box_get_model(GTK_COMBO_BOX(cmb_category)), NULL);
+
+    for(i = 0; i < n_children; i++)
+        gtk_combo_box_remove_text(GTK_COMBO_BOX(cmb_category), 0);
+
+    if(sqlite_get_table(_db,
+                "select c.label, c.cat_id from category c order by c.label",
+                &pszResult, &nRow, &nColumn, NULL) == SQLITE_OK)
     {
-        nearest_squared = DISTANCE_SQUARED(pos, *(wcurr->point));
-
-        while(wcurr++ != _visible_way_last)
+        for(row=1; row<nRow+1; row++)
         {
-            guint test_squared = DISTANCE_SQUARED(pos, *(wcurr->point));
-            if(test_squared < nearest_squared)
-            {
-                wnear = wcurr;
-                nearest_squared = test_squared;
-            }
+            gtk_combo_box_append_text(GTK_COMBO_BOX(cmb_category),
+                pszResult[row*nColumn]);
+            if(atoi(pszResult[row*nColumn+1]) == cat_id)
+                catindex = row - 1;
         }
+        sqlite_free_table(pszResult);
     }
-    return wnear;
+    gtk_combo_box_set_active(GTK_COMBO_BOX(cmb_category), catindex);
+}
+
+typedef struct _PoiCategoryEditInfo PoiCategoryEditInfo;
+struct _PoiCategoryEditInfo
+{
+    GtkWidget *cmb_category;
+    guint cat_id;
+};
+
+static gboolean
+poi_edit_cat(GtkWidget *widget, PoiCategoryEditInfo *data)
+{
+    if(category_list())
+        poi_populate_cat_combo(data->cmb_category, data->cat_id);
+    return TRUE;
 }
 
 static gboolean
-cmenu_cb_way_show_latlon(GtkAction *action)
+poi_dialog(guint action)
 {
-    gchar buffer[80];
-    gfloat lat, lon;
-    WayPoint *way;
+    gchar **pszResult;
+    gint nRow, nColumn, rowindex;
+    gchar *sql;
+    gchar *poi_label = NULL;
+    gchar *poi_category = NULL;
+    gchar *poi_desc = NULL;
+    guint unitx, unity, cat_id = 0, poi_id = 0;
+    gfloat lat, lon, lat1, lon1, lat2, lon2, tmp;
+    gchar slat1[10], slon1[10];
+    gchar slat2[10], slon2[10];
+    gchar *p_latlon, *p_label = NULL, *p_desc = NULL;
+    GtkWidget *dialog;
+    GtkWidget *table;
+    GtkWidget *label;
+    GtkWidget *txt_label;
+    GtkWidget *cmb_category;
+    GtkWidget *txt_desc;
+    GtkWidget *btn_delete = NULL;
+    GtkWidget *btn_catedit;
+    GtkWidget *hbox;
+    GtkWidget *txt_scroll;
+    GtkTextBuffer *desc_txt;
+    GtkTextIter begin, end;
+    DeletePOI dpoi = {NULL, NULL, 0};
+    PoiCategoryEditInfo pcedit;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    way = find_nearest_visible_waypoint(
-            x2unit(_cmenu_position_x),
-            y2unit(_cmenu_position_y));
+    unitx = x2unit(_cmenu_position_x);
+    unity = y2unit(_cmenu_position_y);
+    unit2latlon(unitx, unity, lat, lon);
 
-    if(way)
+    if(action == ACTION_EDIT_POI)
     {
-        unit2latlon(way->point->unitx, way->point->unity, lat, lon);
-
-        sprintf(buffer,
-                "%s: %.06f\n"
-                "%s: %.06f",
-                _("Latitude"), lat,
-                _("Longitude"), lon);
+        unitx = x2unit(_cmenu_position_x - (3 * _draw_line_width));
+        unity = y2unit(_cmenu_position_y - (3 * _draw_line_width));
+        unit2latlon(unitx, unity, lat1, lon1);
 
-        hildon_banner_show_information(_window, NULL, buffer);
-    }
-    else
-        hildon_banner_show_information(_window, NULL,
-                _("No waypoints are visible."));
+        unitx = x2unit(_cmenu_position_x + (3 * _draw_line_width));
+        unity = y2unit(_cmenu_position_y + (3 * _draw_line_width));
+        unit2latlon(unitx, unity, lat2, lon2);
 
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
-}
+        if(lat1 > lat2)
+        {
+            tmp = lat2;
+            lat2 = lat1;
+            lat1 = tmp;
+        }
+        if(lon1 > lon2)
+        {
+            tmp = lon2;
+            lon2 = lon1;
+            lon1 = tmp;
+        }
 
-static gboolean
-cmenu_cb_way_show_desc(GtkAction *action)
-{
-    WayPoint *way;
-    printf("%s()\n", __PRETTY_FUNCTION__);
+        g_ascii_dtostr(slat1, sizeof(slat1), lat1);
+        g_ascii_dtostr(slon1, sizeof(slon1), lon1);
+        g_ascii_dtostr(slat2, sizeof(slat2), lat2);
+        g_ascii_dtostr(slon2, sizeof(slon2), lon2);
+
+        sql = g_strdup_printf(
+            "select p.lat, p.lon, p.label, p.desc, p.cat_id, p.poi_id, c.label"
+            " from poi p, category c "
+            " where p.lat between %s and %s "
+            " and p.lon between %s and %s "
+            " and c.enabled = 1 and p.cat_id = c.cat_id",
+             slat1, slat2, slon1, slon2);
+
+        if(sqlite_get_table(_db, sql, &pszResult, &nRow, &nColumn, NULL)
+            != SQLITE_OK)
+        {
+            g_free(sql);
+            printf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
+            return FALSE;
+        }
+        g_free(sql);
 
-    way = find_nearest_visible_waypoint(
-            x2unit(_cmenu_position_x),
-            y2unit(_cmenu_position_y));
+        if(nRow == 0)
+            return FALSE;
 
-    if(way)
-        hildon_banner_show_information(_window, NULL, way->desc);
-    else
-        hildon_banner_show_information(_window, NULL,
-                _("No waypoints are visible."));
+        if(nRow > 1)
+        {
+            rowindex = poi_list(pszResult, nRow, nColumn);
+            if(rowindex == -1)
+                return FALSE;
+        }
+        else
+            rowindex = 1;
+
+        p_latlon = g_strdup_printf("%s, %s",
+            pszResult[rowindex * nColumn + 0],
+            pszResult[rowindex * nColumn + 1]);
+        p_label = g_strdup(pszResult[rowindex * nColumn + 2]);
+        p_desc = g_strdup(pszResult[rowindex * nColumn + 3]);
+        cat_id = atoi(pszResult[rowindex * nColumn + 4]);
+        poi_id = atoi(pszResult[rowindex * nColumn + 5]);
+        sqlite_free_table(pszResult);
+
+        dialog = gtk_dialog_new_with_buttons(_("Edit POI"),
+            GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+            NULL);
 
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
-}
+        gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
+                btn_delete = gtk_button_new_with_label(_("Delete")));
 
-static gboolean
-cmenu_cb_way_clip_latlon(GtkAction *action)
-{
-    gchar buffer[80];
-    gfloat lat, lon;
-    WayPoint *way;
-    printf("%s()\n", __PRETTY_FUNCTION__);
+        dpoi.dialog = dialog;
+        dpoi.txt_label = g_strdup(p_label);
+        dpoi.id = poi_id;
 
-    way = find_nearest_visible_waypoint(
-            x2unit(_cmenu_position_x),
-            y2unit(_cmenu_position_y));
+        g_signal_connect(G_OBJECT(btn_delete), "clicked",
+                          G_CALLBACK(poi_delete), &dpoi);
 
-    if(way)
+        gtk_dialog_add_button(GTK_DIALOG(dialog),
+                GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT);
+    }
+    else
     {
-        unit2latlon(way->point->unitx, way->point->unity, lat, lon);
+        p_latlon = g_strdup_printf("%.06f, %.06f", lat, lon);
 
-        sprintf(buffer,
-                "%s: %.06f\n"
-                "%s: %.06f",
-                _("Latitude"), lat,
-                _("Longitude"), lon);
+        if(sqlite_get_table(_db, "select ifnull(max(poi_id) + 1,1) from poi",
+            &pszResult, &nRow, &nColumn, NULL) == SQLITE_OK)
+        {
+            p_label = g_strdup_printf("Point%06d", atoi(pszResult[nColumn]));
+            sqlite_free_table(pszResult);
+        }
 
-        gtk_clipboard_set_text(
-                gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), buffer, -1);
+        p_desc = g_strdup("");
+        cat_id = 0;
+        poi_id = 0;
+
+        dialog = gtk_dialog_new_with_buttons(_("Add POI"),
+            GTK_WINDOW(_window), GTK_DIALOG_MODAL,
+            GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
+            GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+            NULL);
     }
-    else
-        hildon_banner_show_information(_window, NULL,
-                _("No waypoints are visible."));
 
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
-}
+    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
+            table = gtk_table_new(6, 4, FALSE), TRUE, TRUE, 0);
 
-static gboolean
-cmenu_cb_way_clip_desc(GtkAction *action)
-{
-    WayPoint *way;
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Lat, Lon: ")),
+            0, 1, 0, 1, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
 
-    way = find_nearest_visible_waypoint(
-            x2unit(_cmenu_position_x),
-            y2unit(_cmenu_position_y));
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(p_latlon),
+            1, 3, 0, 1, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
 
-    if(way)
-        gtk_clipboard_set_text(
-                gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), way->desc, -1);
-    else
-        hildon_banner_show_information(_window, NULL,
-                _("No waypoints are visible."));
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Label: ")),
+            0, 1, 1, 2, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
+    gtk_table_attach(GTK_TABLE(table),
+            txt_label = gtk_entry_new(),
+            1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
 
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
-}
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Category: ")),
+            0, 1, 3, 4, GTK_FILL, 0, 2, 4);
+    gtk_table_attach(GTK_TABLE(table),
+            hbox = gtk_hbox_new(FALSE, 4),
+            1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            cmb_category = gtk_combo_box_new_text(),
+            FALSE, FALSE, 4);
+    gtk_box_pack_start(GTK_BOX(hbox),
+            btn_catedit = gtk_button_new_with_label(_("Edit Categories...")),
+            FALSE, FALSE, 4);
 
-static gboolean
-cmenu_cb_way_route_to(GtkAction *action)
-{
-    WayPoint *way;
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    gtk_table_attach(GTK_TABLE(table),
+            label = gtk_label_new(_("Desc.: ")),
+            0, 1, 5, 6, GTK_FILL, 0, 2, 4);
+    gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
 
-    way = find_nearest_visible_waypoint(
-            x2unit(_cmenu_position_x),
-            y2unit(_cmenu_position_y));
+    txt_scroll = gtk_scrolled_window_new(NULL, NULL);
+    gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll),
+                                   GTK_SHADOW_IN);
+    gtk_table_attach(GTK_TABLE(table),
+            txt_scroll,
+            1, 2, 5, 6, GTK_EXPAND | GTK_FILL, 0, 2, 4);
 
-    if(way)
-    {
-        gchar buffer[80];
-        gchar strlat[32];
-        gchar strlon[32];
-        gfloat lat, lon;
-        printf("%s()\n", __PRETTY_FUNCTION__);
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll),
+                                 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
 
-        unit2latlon(way->point->unitx, way->point->unity, lat, lon);
-        g_ascii_formatd(strlat, 32, "%.06f", lat);
-        g_ascii_formatd(strlon, 32, "%.06f", lon);
-        sprintf(buffer, "%s, %s", strlat, strlon);
-        
-        route_download(NULL, buffer, TRUE);
-    }
-    else
-        hildon_banner_show_information(_window, NULL,
-                _("No waypoints are visible."));
+    txt_desc = gtk_text_view_new ();
+    gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD);
 
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
-}
+    gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc);
+    gtk_widget_show(txt_scroll);
+    gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 400, 60);
 
-static gboolean
-cmenu_cb_way_distance_to(GtkAction *action)
-{
-    WayPoint *way;
-    printf("%s()\n", __PRETTY_FUNCTION__);
+    desc_txt = gtk_text_view_get_buffer (GTK_TEXT_VIEW (txt_desc));
 
-    way = find_nearest_visible_waypoint(
-            x2unit(_cmenu_position_x),
-            y2unit(_cmenu_position_y));
+    /* label */
+    gtk_entry_set_text(GTK_ENTRY(txt_label), p_label);
 
-    if(way)
+    /* category */
+    poi_populate_cat_combo(cmb_category, cat_id);
+
+    /* poi_desc */
+    gtk_text_buffer_set_text(desc_txt, p_desc, -1);
+
+    /* Connect Signals */
+    pcedit.cmb_category = cmb_category;
+    pcedit.cat_id = cat_id;
+    g_signal_connect(G_OBJECT(btn_catedit), "clicked",
+            G_CALLBACK(poi_edit_cat), &pcedit);
+    gtk_widget_show_all(dialog);
+
+    while(GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog)))
     {
-        gchar buffer[80];
-        gfloat lat, lon;
-        printf("%s()\n", __PRETTY_FUNCTION__);
+        if(strlen(gtk_entry_get_text(GTK_ENTRY(txt_label))))
+            poi_label = g_strdup(gtk_entry_get_text(
+                        GTK_ENTRY(txt_label)));
+        else
+        {
+            popup_error(dialog, _("Please specify a name for the POI."));
+            continue;
+        }
 
-        unit2latlon(way->point->unitx, way->point->unity, lat, lon);
+        gtk_text_buffer_get_iter_at_offset(desc_txt, &begin,0 );
+        gtk_text_buffer_get_end_iter (desc_txt, &end);
+        poi_desc = gtk_text_buffer_get_text(desc_txt, &begin, &end, TRUE);
 
-        sprintf(buffer, "%s: %.02f %s", _("Distance to Waypoint"),
-                calculate_distance(_pos_lat, _pos_lon, lat, lon), _units);
-        hildon_banner_show_information(_window, NULL, buffer);
+        poi_category = gtk_combo_box_get_active_text(
+                GTK_COMBO_BOX(cmb_category));
+
+        sql = g_strdup_printf("select cat_id from category where label = '%s'",
+            poi_category);
+        if(sqlite_get_table(_db, sql, &pszResult, &nRow, &nColumn, NULL)
+            == SQLITE_OK)
+        {
+            g_free(sql);
+
+            if(action == ACTION_EDIT_POI)
+            {
+                /* edit poi */
+                sql = g_strdup_printf(
+                    "update poi set label = '%s', desc = '%s', "
+                    "cat_id = %d where poi_id = %d",
+                    poi_label, poi_desc, atoi(pszResult[nColumn]), poi_id);
+                if(sqlite_exec(_db, sql, NULL, NULL, NULL) != SQLITE_OK)
+                    hildon_banner_show_information(_window, NULL,
+                        _("Problem updating POI"));
+                else
+                    map_render_poi();
+            }
+            else
+            {
+                /* add poi */
+                g_ascii_dtostr(slat1, sizeof(slat1), lat);
+                g_ascii_dtostr(slon1, sizeof(slon1), lon);
+                sql = g_strdup_printf(
+                        "insert into poi (lat, lon, label, desc, cat_id)"
+                        " values (%s, %s, '%s', '%s', %d)",
+                        slat1, slon1, poi_label, poi_desc,
+                        atoi(pszResult[nColumn]));
+                if(sqlite_exec(_db, sql, NULL, NULL, NULL) != SQLITE_OK)
+                    hildon_banner_show_information(_window, NULL,
+                        _("Problem adding POI"));
+                else
+                    map_render_poi();
+            }
+
+            sqlite_free_table(pszResult);
+        }
+        g_free(sql);
+        break;
     }
-    else
-        hildon_banner_show_information(_window, NULL,
-                _("No waypoints are visible."));
+
+    g_object_unref (desc_txt);
+    g_free(poi_label);
+    g_free(poi_category);
+    g_free(poi_desc);
+
+    g_free(p_latlon);
+    g_free(p_label);
+    g_free(p_desc);
+
+    gtk_widget_hide_all(dialog);
 
     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
     return TRUE;
 }
 
 static gboolean
-cmenu_cb_way_delete(GtkAction *action)
+cmenu_cb_add_poi(GtkAction *action)
 {
-    WayPoint *way;
+    gboolean results;
     printf("%s()\n", __PRETTY_FUNCTION__);
 
-    way = find_nearest_visible_waypoint(
-            x2unit(_cmenu_position_x),
-            y2unit(_cmenu_position_y));
+    results = poi_dialog(ACTION_ADD_POI);
 
-    if(way)
-    {
-        gchar buffer[1024];
-        GtkWidget *confirm;
+    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
+    return results;
+}
 
-        sprintf(buffer, "%s:\n%s\n",
-                _("Confirm delete of waypoint"), way->desc);
-        confirm = hildon_note_new_confirmation(GTK_WINDOW(_window), buffer);
+static gboolean
+cmenu_cb_edit_poi(GtkAction *action)
+{
+    gboolean results;
+    printf("%s()\n", __PRETTY_FUNCTION__);
 
-        if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
-        {
-            while(way++ != _route.wtail)
-                way[-1] = *way;
-            _route.wtail--;
-            map_force_redraw();
-        }
-        gtk_widget_destroy(confirm);
-    }
-    else
-        hildon_banner_show_information(_window, NULL,
-                _("No waypoints are visible."));
+    results = poi_dialog(ACTION_EDIT_POI);
 
-    vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
-    return TRUE;
+    vprintf("%s(): return\n", __PRETTY_FUNCTION__);
+    return results;
 }
 
-
 /****************************************************************************
  * ABOVE: CALLBACKS *********************************************************
  ****************************************************************************/
diff --git a/src/maemo-mapper.sh b/src/maemo-mapper.sh
new file mode 100644 (file)
index 0000000..dacb649
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+source /usr/bin/connectivity_preload.sh
+exec /usr/bin/maemo-mapper