2 * Copyright (C) 2006, 2007 John Costigan.
4 * POI and GPS-Info code originally written by Cezary Jackiewicz.
6 * Default map data provided by http://www.openstreetmap.org/
8 * This file is part of Maemo Mapper.
10 * Maemo Mapper is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
15 * Maemo Mapper is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with Maemo Mapper. If not, see <http://www.gnu.org/licenses/>.
35 # include <hildon/hildon-note.h>
37 # include <hildon-widgets/hildon-note.h>
49 * Pop up a modal dialog box with simple error information in it.
52 popup_error(GtkWidget *window, const gchar *error)
55 printf("%s(\"%s\")\n", __PRETTY_FUNCTION__, error);
57 dialog = hildon_note_new_information(GTK_WINDOW(window), error);
59 gtk_dialog_run(GTK_DIALOG(dialog));
60 gtk_widget_destroy(dialog);
62 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
66 deg_format(gdouble coor, gchar *scoor, gchar neg_char, gchar pos_char)
69 gdouble acoor = fabs(coor);
70 printf("%s()\n", __PRETTY_FUNCTION__);
75 sprintf(scoor, "%.5f°", coor);
78 sprintf(scoor, "%.5f° %c", acoor,
79 coor < 0.0 ? neg_char : pos_char);
82 sprintf(scoor, "%c %.5f°",
83 coor < 0.0 ? neg_char : pos_char,
88 sprintf(scoor, "%d°%06.3f'",
89 (int)coor, (acoor - (int)acoor)*60.0);
92 sprintf(scoor, "%d°%06.3f' %c",
93 (int)acoor, (acoor - (int)acoor)*60.0,
94 coor < 0.0 ? neg_char : pos_char);
97 sprintf(scoor, "%c %d° %06.3f'",
98 coor < 0.0 ? neg_char : pos_char,
99 (int)acoor, (acoor - (int)acoor)*60.0);
103 min = (acoor - (int)acoor)*60.0;
104 sprintf(scoor, "%d°%02d'%04.1f\"", (int)coor, (int)min,
105 ((min - (int)min)*60.0));
107 case DD_MM_SSPS_NSEW:
108 min = (acoor - (int)acoor)*60.0;
109 sprintf(scoor, "%d°%02d'%04.1f\" %c", (int)acoor, (int)min,
110 ((min - (int)min)*60.0),
111 coor < 0.0 ? neg_char : pos_char);
113 case NSEW_DD_MM_SSPS:
114 min = (acoor - (int)acoor)*60.0;
115 sprintf(scoor, "%c %d° %02d' %04.1f\"",
116 coor < 0.0 ? neg_char : pos_char,
117 (int)acoor, (int)min,
118 ((min - (int)min)*60.0));
121 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
124 /** Return the location (in units) of the given string address. This function
125 * makes a call to the internet, so it may take some time. */
126 Point locate_address(GtkWidget *parent, const gchar *addr)
129 Point retval = _point_null;
130 GnomeVFSResult vfs_result;
135 printf("%s(%s)\n", __PRETTY_FUNCTION__, addr);
137 addr_escaped = gnome_vfs_escape_string(addr);
138 buffer = g_strdup_printf(_route_dl_url, addr_escaped, addr_escaped);
139 g_free(addr_escaped);
141 /* Attempt to download the route from the server. */
142 if(GNOME_VFS_OK != (vfs_result = gnome_vfs_read_entire_file(
143 buffer, &size, &bytes)))
147 popup_error(parent, _("Failed to connect to GPX Directions server"));
153 MACRO_PATH_INIT(temp);
155 if(strncmp(bytes, "<?xml", strlen("<?xml")))
157 /* Not an XML document - must be bad locations. */
158 popup_error(parent, _("Invalid address."));
160 /* Else, if GPS is enabled, replace the route, otherwise append it. */
161 else if(!gpx_path_parse(&temp, bytes, size, 0) || !temp.head[1].unity)
163 popup_error(parent, _("Unknown error while locating address."));
167 /* Save Destination in Route Locations list. */
169 if(!g_slist_find_custom(_loc_list, addr, (GCompareFunc)strcmp))
171 _loc_list = g_slist_prepend(_loc_list, g_strdup(addr));
172 gtk_list_store_insert_with_values(_loc_model, &iter,
173 INT_MAX, 0, addr, -1);
176 retval = temp.head[1];
179 MACRO_PATH_FREE(temp);
182 vprintf("%s(): return (%d, %d)\n", __PRETTY_FUNCTION__,
183 retval.unitx, retval.unity);
188 * Calculate the distance between two lat/lon pairs. The distance is returned
189 * in nautical miles and should be converted using UNITS_CONVERT[_units].
192 calculate_distance(gdouble lat1, gdouble lon1, gdouble lat2, gdouble lon2)
194 gdouble dlat, dlon, slat, slon, a;
196 /* Convert to radians. */
197 lat1 = deg2rad(lat1);
198 lon1 = deg2rad(lon1);
199 lat2 = deg2rad(lat2);
200 lon2 = deg2rad(lon2);
205 slat = sin(dlat / 2.0);
206 slon = sin(dlon / 2.0);
207 a = (slat * slat) + (cos(lat1) * cos(lat2) * slon * slon);
209 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
210 return ((2.0 * atan2(sqrt(a), sqrt(1.0 - a))) * EARTH_RADIUS);
214 * Calculate the bearing between two lat/lon pairs. The bearing is returned
215 * as the angle from lat1/lon1 to lat2/lon2.
218 calculate_bearing(gdouble lat1, gdouble lon1, gdouble lat2, gdouble lon2)
221 gdouble dlon = deg2rad(lon2 - lon1);
222 lat1 = deg2rad(lat1);
223 lat2 = deg2rad(lat2);
225 y = sin(dlon) * cos(lat2);
226 x = (cos(lat1) * sin(lat2)) - (sin(lat1) * cos(lat2) * cos(dlon));
228 dlon = rad2deg(atan2(y, x));
237 force_min_visible_bars(HildonControlbar *control_bar, gint num_bars)
241 printf("%s()\n", __PRETTY_FUNCTION__);
242 memset(&val, 0, sizeof(val));
243 g_value_init(&val, G_TYPE_INT);
244 g_value_set_int(&val, num_bars);
245 g_object_set_property(G_OBJECT(control_bar), "minimum-visible-bars", &val);
246 vprintf("%s(): return\n", __PRETTY_FUNCTION__);
253 printf("%s()\n", __PRETTY_FUNCTION__);
255 /* Re-enable any banners that might have been up. */
259 gtk_widget_hide(_connect_banner);
260 gtk_widget_unrealize(_connect_banner);
261 gtk_widget_realize(_connect_banner);
262 gtk_widget_show(_connect_banner);
267 gtk_widget_hide(_fix_banner);
268 gtk_widget_unrealize(_fix_banner);
269 gtk_widget_realize(_fix_banner);
270 gtk_widget_show(_fix_banner);
275 gtk_widget_hide(_waypoint_banner);
276 gtk_widget_unrealize(_waypoint_banner);
277 gtk_widget_realize(_waypoint_banner);
278 gtk_widget_show(_waypoint_banner);
283 gtk_widget_hide(_download_banner);
284 gtk_widget_unrealize(_download_banner);
285 gtk_widget_realize(_download_banner);
286 gtk_widget_show(_download_banner);
290 ConnState old_state = _gps_state;
291 set_conn_state(RCVR_OFF);
292 set_conn_state(old_state);
296 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
300 * Get one numeric token off the string, fractional part separator
301 * is ',' or '.' and number may follow any token from sep.
302 * Return value found is in d.
304 * If utf8_deg is set then accept also Unicode degree symbol U+00B0
305 * encoded as UTF-8 octets 0xc2 0xb0.
309 * 1 : when nothing or just white space was seen.
310 * 2 : when fractional number was seen.
311 * 3 : when whole number was seen.
312 * In case 0, endptr points to the beginning of the input string nptr,
315 * In case 1 endptr points past the whitespace, d is undefined.
317 * In cases 2 and 3 the found number is stored in d and endptr points
318 * to first char not part of the number.
322 strdmstod_1(gdouble *d, gchar *nptr, gchar **endptr, gchar *sep, gint utf8_deg)
330 while (*p && isspace(*p)) {
339 while (*p && isdigit(*p)) {
346 if (*p && (*p == '.' || *p == ',')) {
352 /* fractional part */
355 while (*p && isdigit(*p)) {
367 /* allow for extra sep char at the end */
368 if (*p && strchr(sep, *p)) {
370 } else if (utf8_deg && *p == 0xc2 && *(p+1) == 0xb0) {
375 if (endptr) *endptr = p;
376 return f_flag ? 2 : 3;
379 if (endptr) *endptr = p;
384 strdmstod_2(gchar *nptr, gchar **endptr)
393 ret = strdmstod_1(&d, p, endptr, "dD@", 1);
397 if (endptr) *endptr = (char *)nptr;
405 ret = strdmstod_1(&m, p, endptr, "mM'", 0);
409 case 2: return d + m/60.0;
414 ret = strdmstod_1(&s, p, endptr, "sS\"", 0);
417 case 1: return d + m/60.0;
419 case 3: return d + m/60.0 + s/3600.0;
427 * format: / \s* [+-NSWE]? \s* ( d | D \s+ m | D \s+ M \s+ s ) [NSWE]? /x
428 * where D := / \d+[@d°]? /ix
429 * M := / \d+['m]? /ix
430 * d := / D | \d+[,.]\d+[@d°]? /ix
431 * m := / M | \d+[,.]\d+['m]? /ix
432 * s := / S | \d+[,.]\d+["s]? /ix
434 * and N or W are treated as positive, S or E are treated as negative,
435 * they may occur only once.
438 strdmstod(const gchar *nptr, gchar **endptr)
447 while(*p && isspace(*p))
452 *endptr = (char *)nptr;
456 if(strchr("nwseNWSE-+", *p)) {
461 d = strdmstod_2(p, &end);
462 if(p == end && d == 0.0) {
463 if(endptr) *endptr = end;
468 while(*p && isspace(*p))
473 if(*p && strchr("nwseNWSE", *p)) {
474 if(tolower(*p) == 's' || tolower(*p) == 'w')
479 if(tolower(*sign) == 's' || tolower(*sign) == 'w' || *sign == '-')
481 printf("s: %d\n", s);
484 if(endptr) *endptr = p;
495 { "-12.345d", -12.345 },
496 { "12.345 E", -12.345 },
497 { "12d34m", 12.5666667 },
498 { "N 12 34", 12.5666667 },
499 { "S 12d34.56m", -12.576 },
500 { "W 12 34.56", 12.576 },
501 { "E 12d34m56s", -12.582222 },
502 { "12 34 56 S", -12.582222 },
503 { "12 34 56", 12.582222 },
504 { "12d34m56.7s E", -12.582417 },
505 { "12 34 56.7 W", 12.582417 },
506 { "12° 34 56.7 W", 12.582417 },
519 for (t = t_cases; t->fmt; t++) {
523 v = strdmstod(t->fmt, &endp);
524 if (endp == t->fmt || *endp != 0) {
525 fprintf(stderr, "FAIL syntax %s\n", t->fmt);
527 } else if (fabs(v - t->value) > 0.000001) {
528 fprintf(stderr, "FAIL value %s -> %.10g (%.10g)\n",
529 t->fmt, v, t->value);
537 fprintf(stderr, "ALL TESTS OK\n");
539 fprintf(stderr, "FAIL %d, OK %d\n", fail, ok);