[PATCH 1/2] Initial communication between Subsurface and the GoogleMaps API

Lubomir I. Ivanov neolit123 at gmail.com
Wed Jan 16 05:55:39 PST 2013


From: "Lubomir I. Ivanov" <neolit123 at gmail.com>

A menu entry is added in the Log menu:
'Dive Locations (GoogleMaps)'

A couple of new methods are added to gps.c:
- open_google_maps_for_dives(), which is called from
the menu entry
- add_maker_info_for_dive(), which appends maker information
for dives into a URI buffer

In open_google_maps_for_dives(), we consider doing a malloc
for the URI buffer before calling subsurface_launch_for_uri().
Given that the location string is truncated to 60 gunichars
(in add_maker_info_for_dive())
and that we know the relative size of all other characters
needed for coordinates and separators, we can estimate a buffer
of length in gchars for a single dive:

dive_info_buf = ((60 * 2) * enc_inflate) + (16 * 2) + sep
where:
	enc_inflate is set to 3, e.g. " " => "%20"
	sep is set to 6, e.g. for "@", "'", etc.

dive_info_buf = 360 + 32 + 6 = 398

then the the total length of the buffer would be:
total = dive_info_buf * amount_selected

Signed-off-by: Lubomir I. Ivanov <neolit123 at gmail.com>
---
 display-gtk.h |  2 ++
 gps.c         | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 gtk-gui.c     |  2 ++
 3 files changed, 74 insertions(+), 1 deletion(-)

diff --git a/display-gtk.h b/display-gtk.h
index b889ff1..2dc419e 100644
--- a/display-gtk.h
+++ b/display-gtk.h
@@ -45,6 +45,8 @@ extern int process_ui_events(void);
 extern void update_progressbar(progressbar_t *progress, double value);
 extern void update_progressbar_text(progressbar_t *progress, const char *text);
 
+extern void open_google_maps_for_dives(void);
+
 extern const char *default_dive_computer_vendor;
 extern const char *default_dive_computer_product;
 extern const char *default_dive_computer_device;
diff --git a/gps.c b/gps.c
index 87c8a99..40c052c 100644
--- a/gps.c
+++ b/gps.c
@@ -30,7 +30,6 @@ static void add_gps_point(OsmGpsMap *map, float latitude, float longitude)
 	osm_gps_map_track_add (map, track);
 }
 
-
 OsmGpsMap *init_map()
 {
 	OsmGpsMap *map;
@@ -134,3 +133,73 @@ void show_gps_locations()
 
 	show_map(map);
 }
+
+void add_maker_info_for_dive(char *buf, struct dive *dp)
+{
+	const double inv_10e6 = 1.0 / 1000000.0;
+	const int buf_sz_fp = 16;
+	gchar locbuf[360] = {0}; /* possible URI inflation post the escape */
+	gchar fbuf[16], *utf8_uri;
+
+	strcat(buf, "q=");
+	if (dp->location) {
+		/* append truncated location */
+		g_utf8_strncpy(locbuf, dp->location, 60);
+		utf8_uri = g_uri_escape_string(locbuf, NULL, TRUE);
+	} else {
+		utf8_uri = g_uri_escape_string(_("No location specified"), NULL, TRUE);
+	}
+	strcat(buf, utf8_uri);
+	free(utf8_uri);
+	strcat(buf, "@");
+	/* append coordinates using locale agnostic "ftoa" conversation */
+	g_ascii_formatd(fbuf, buf_sz_fp, "%.6f", (double)dp->latitude.udeg * inv_10e6);
+	strcat(buf, fbuf);
+	g_ascii_formatd(fbuf, buf_sz_fp, "%.6f", (double)dp->longitude.udeg * inv_10e6);
+	strcat(buf, ",");
+	strcat(buf, fbuf);
+	strcat(buf, "&");
+}
+
+/* example of how to make a call to a online google maps based interface
+ * by passing coordinates and location to create a marker. used format is:
+ *
+ *   http://econym.org.uk/gmap/example_plotpoints.htm?q=Some%20Location@53,-2&..
+ *
+ * the above website (view source) provides an example of an easy URL based
+ * implementation. */
+void open_google_maps_for_dives(void)
+{
+	const char *url = "http://econym.org.uk/gmap/example_plotpoints.htm?";
+	const int buf_chunk = 398;
+	char *buf;
+	struct dive *dp;
+	int i, with_coord = 0;
+
+	if (!amount_selected) {
+		g_message("open_google_maps_for_dives(): no dives selected");
+		return;
+	}
+	/* an estimate for the URI buffer */
+	buf = (char *)malloc(buf_chunk * amount_selected);
+	memset(buf, 0, buf_chunk);
+	if (!buf)
+		g_error("open_google_maps_for_dives(): failed to allocate buffer");
+
+	/* append url */
+	strcat(buf, url);
+	for (i = 0; i < dive_table.nr; i++) {
+		dp = dive_table.dives[i];
+		if (dp->selected) {
+			if (dp->latitude.udeg == 0 || dp->longitude.udeg == 0)
+				continue;
+			add_maker_info_for_dive(buf, dp);
+			with_coord++;
+		}
+	}
+	if (with_coord)
+		subsurface_launch_for_uri(buf);
+	else
+		g_message("open_google_maps_for_dives(): no coordinates for selected dives");
+	free(buf);
+}
diff --git a/gtk-gui.c b/gtk-gui.c
index d21fac5..ab2599a 100644
--- a/gtk-gui.c
+++ b/gtk-gui.c
@@ -1063,6 +1063,7 @@ static GtkActionEntry menu_items[] = {
 	{ "Renumber",       NULL, N_("Renumber..."), NULL, NULL, G_CALLBACK(renumber_dialog) },
 	{ "YearlyStats",    NULL, N_("Yearly Statistics"), NULL, NULL, G_CALLBACK(show_yearly_stats) },
 	{ "DivesLocations", NULL, N_("Dives Locations"), CTRLCHAR "M", NULL, G_CALLBACK(show_gps_locations) },
+	{ "DivesLocationsGoogle", NULL, N_("Dive Locations (GoogleMaps)"), NULL, NULL, G_CALLBACK(open_google_maps_for_dives) },
 	{ "SelectEvents",   NULL, N_("Select Events..."), NULL, NULL, G_CALLBACK(selectevents_dialog) },
 	{ "Quit",           GTK_STOCK_QUIT, N_("Quit"),   CTRLCHAR "Q", NULL, G_CALLBACK(quit) },
 	{ "About",          GTK_STOCK_ABOUT, N_("About Subsurface"),  NULL, NULL, G_CALLBACK(about_dialog) },
@@ -1110,6 +1111,7 @@ static const gchar* ui_string = " \
 				<menuitem name=\"Toggle Zoom\" action=\"ToggleZoom\" /> \
 				<menuitem name=\"YearlyStats\" action=\"YearlyStats\" /> \
 				<menuitem name=\"DivesLocations\" action=\"DivesLocations\" /> \
+				<menuitem name=\"DivesLocationsGoogle\" action=\"DivesLocationsGoogle\" /> \
 				<menu name=\"View\" action=\"ViewMenuAction\"> \
 					<menuitem name=\"List\" action=\"ViewList\" /> \
 					<menuitem name=\"Profile\" action=\"ViewProfile\" /> \
-- 
1.7.11.msysgit.0



More information about the subsurface mailing list