summaryrefslogtreecommitdiffstats
path: root/info.c
diff options
context:
space:
mode:
authorGravatar Dirk Hohndel <dirk@hohndel.org>2013-02-08 19:27:54 -0800
committerGravatar Dirk Hohndel <dirk@hohndel.org>2013-02-08 19:30:30 -0800
commit51f97a97cebbedaed102e9a3e7e694401c880526 (patch)
tree1059af2081920fec7934b98e89afbf0e03d4c011 /info.c
parentb12b2f1c85a3c18a66b7bddffbae574212a33bc2 (diff)
downloadsubsurface-51f97a97cebbedaed102e9a3e7e694401c880526.tar.gz
Avoid using float when dealing with GPS location
Float values have insufficient precision compared to the udeg we usually store - so we create a special callback function to use from osm-gps-map and everywhere else use integers. This patch also increases the decimal places displayed in the GPS text entry box - this way we can cut and paste the text without loss of precision. Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Diffstat (limited to 'info.c')
-rw-r--r--info.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/info.c b/info.c
index 18ff11146..d64b4775c 100644
--- a/info.c
+++ b/info.c
@@ -639,31 +639,32 @@ struct location_update {
void (*callback)(float, float);
} location_update;
-static void print_gps_coordinates(char *buffer, int len, float lat, float lon)
+/* take latitude and longitude in udeg and print them in a human readable
+ * form, without losing precision */
+static void print_gps_coordinates(char *buffer, int len, int lat, int lon)
{
unsigned int latdeg, londeg;
- float latmin, lonmin;
+ double latmin, lonmin;
char *lath, *lonh;
if (!lat && !lon) {
*buffer = 0;
return;
}
-
- lath = lat >= 0.0 ? _("N") : _("S");
- lonh = lon >= 0.0 ? _("E") : _("W");
- lat = fabs(lat);
- lon = fabs(lon);
- latdeg = lat;
- londeg = lon;
- latmin = (lat - latdeg) * 60.0;
- lonmin = (lon - londeg) * 60.0;
+ lath = lat >= 0 ? _("N") : _("S");
+ lonh = lon >= 0 ? _("E") : _("W");
+ lat = abs(lat);
+ lon = abs(lon);
+ latdeg = lat / 1000000;
+ londeg = lon / 1000000;
+ latmin = (lat % 1000000) * 60.0 / 1000000.0;
+ lonmin = (lon % 1000000) * 60.0 / 1000000.0;
snprintf(buffer, len, "%s%u%s %8.5f\' , %s%u%s %8.5f\'",
lath, latdeg, UTF8_DEGREE, latmin,
lonh, londeg, UTF8_DEGREE, lonmin);
}
-static void update_gps_entry(float lat, float lon)
+static void update_gps_entry(int lat, int lon)
{
if (location_update.entry) {
print_gps_coordinates(location_update.text, 45, lat, lon);
@@ -671,6 +672,11 @@ static void update_gps_entry(float lat, float lon)
}
}
+static void update_gps_entry_callback(float lat, float lon)
+{
+ update_gps_entry(lat * 1000000, lon * 1000000);
+}
+
#if HAVE_OSM_GPS_MAP
static gboolean gps_map_callback(GtkWidget *w, gpointer data)
{
@@ -680,7 +686,7 @@ static gboolean gps_map_callback(GtkWidget *w, gpointer data)
gps_text = gtk_entry_get_text(location_update.entry);
(void)gps_changed(dive, NULL, gps_text);
}
- show_gps_location(dive, update_gps_entry);
+ show_gps_location(dive, update_gps_entry_callback);
location_update.set_by_hand = 1;
return TRUE;
}
@@ -740,7 +746,7 @@ static void location_entry_change_cb(GtkComboBox *location, gpointer *userdata)
continue;
if (!dive->location || strcasecmp(dive->location, name))
continue;
- update_gps_entry(dive->latitude.udeg / 1000000.0, dive->longitude.udeg / 1000000.0);
+ update_gps_entry(dive->latitude.udeg, dive->longitude.udeg);
return;
}
update_gps_entry(0, 0);
@@ -770,7 +776,7 @@ static void dive_info_widget(GtkWidget *box, struct dive *dive, struct dive_info
location_update.entry = info->gps;
location_update.dive = dive;
- update_gps_entry(dive->latitude.udeg / 1000000.0, dive->longitude.udeg / 1000000.0);
+ update_gps_entry(dive->latitude.udeg, dive->longitude.udeg);
location_update.set_by_hand = !!location_update.text[0];
gtk_widget_add_events(GTK_WIDGET(info->gps), GDK_FOCUS_CHANGE_MASK);