summaryrefslogtreecommitdiffstats
path: root/info.c
diff options
context:
space:
mode:
Diffstat (limited to 'info.c')
-rw-r--r--info.c90
1 files changed, 82 insertions, 8 deletions
diff --git a/info.c b/info.c
index d8a2fdc00..4104b5af5 100644
--- a/info.c
+++ b/info.c
@@ -394,12 +394,19 @@ static int get_rating(const char *string)
return rating_val;
}
+/* this has to be done with UTF8 as people might want to enter the degree symbol */
static gboolean parse_gps_text(const char *gps_text, double *latitude, double *longitude)
{
const char *text = gps_text;
+ char *endptr;
+ gboolean south = FALSE;
+ gboolean west = FALSE;
+ double parselat, parselong;
+ gunichar degrees = UCS4_DEGREE;
+ gunichar c;
- while (isspace(*text))
- text++;
+ while (g_unichar_isspace(g_utf8_get_char(text)))
+ text = g_utf8_next_char(text);
/* an empty string is interpreted as 0.0,0.0 and therefore "no gps location" */
if (!*text) {
@@ -407,11 +414,78 @@ static gboolean parse_gps_text(const char *gps_text, double *latitude, double *l
*longitude = 0.0;
return TRUE;
}
- /* WGS84 style decimal degrees */
- if (sscanf(text, "%lf,%lf", latitude, longitude) == 2)
- return TRUE;
+ /* ok, let's parse by hand - first degrees of latitude */
+ if (g_unichar_toupper(g_utf8_get_char(text)) == 'N')
+ text++;
+ if (g_unichar_toupper(g_utf8_get_char(text)) == 'S') {
+ text++;
+ south = TRUE;
+ }
+ parselat = strtod(text, &endptr);
+ if (text == endptr)
+ return FALSE;
+ text = endptr;
+ if (parselat < 0.0) {
+ south = TRUE;
+ parselat *= -1;
+ }
- return FALSE;
+ /* next optional minutes as decimal, skipping degree symbol */
+ while (g_unichar_isspace(c = g_utf8_get_char(text)) || c == degrees)
+ text = g_utf8_next_char(text);
+ if (g_unichar_toupper(c) != 'E' && g_unichar_toupper(c) != 'W' && c != ';' && c != ',') {
+ parselat += strtod(text, &endptr) / 60.0;
+ if (text == endptr)
+ return FALSE;
+ text = endptr;
+ /* skip trailing minute symbol */
+ if (g_utf8_get_char(text) == '\'')
+ text = g_utf8_next_char(text);
+ }
+ /* skip seperator between latitude and longitude */
+ while (g_unichar_isspace(c = g_utf8_get_char(text)) || c == ';' || c == ',')
+ text = g_utf8_next_char(text);
+
+ /* next degrees of longitude */
+ if (g_unichar_toupper(g_utf8_get_char(text)) == 'E')
+ text++;
+ if (g_unichar_toupper(g_utf8_get_char(text)) == 'W') {
+ text++;
+ west = TRUE;
+ }
+ parselong = strtod(text, &endptr);
+ if (text == endptr)
+ return FALSE;
+ text = endptr;
+ if (parselong < 0.0) {
+ west = TRUE;
+ parselong *= -1;
+ }
+
+ /* next optional minutes as decimal, skipping degree symbol */
+ while (g_unichar_isspace(c = g_utf8_get_char(text)) || c == degrees)
+ text = g_utf8_next_char(text);
+ if (*text) {
+ parselong += strtod(text, &endptr) / 60.0;
+ if (text == endptr)
+ return FALSE;
+ text = endptr;
+ /* skip trailing minute symbol */
+ if (g_utf8_get_char(text) == '\'')
+ text = g_utf8_next_char(text);
+ /* make sure there's nothing else left on the input */
+ while (g_unichar_isspace(g_utf8_get_char(text)))
+ text = g_utf8_next_char(text);
+ if (*text)
+ return FALSE;
+ }
+ if (west && parselong > 0.0)
+ parselong *= -1;
+ if (south && parselat > 0.0)
+ parselat *= -1;
+ *latitude = parselat;
+ *longitude = parselong;
+ return TRUE;
}
static gboolean gps_changed(struct dive *dive, struct dive *master, const char *gps_text)
@@ -571,9 +645,9 @@ static void dive_info_widget(GtkWidget *box, struct dive *dive, struct dive_info
info->location = text_entry(box, _("Location"), location_list, dive->location);
if (dive_has_location(dive))
- snprintf(gps_text, sizeof(gps_text), "%3.5lf,%3.5lf", dive->latitude.udeg / 1000000.0,
+ snprintf(gps_text, sizeof(gps_text), "%3.5lf;%3.5lf", dive->latitude.udeg / 1000000.0,
dive->longitude.udeg / 1000000.0);
- info->gps = single_text_entry(box, _("GPS"), gps_text);
+ info->gps = single_text_entry(box, _("GPS (WGS84 or GPS format - use ';' as separator)"), gps_text);
hbox = gtk_hbox_new(FALSE, 3);
gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, TRUE, 0);