]> git.itanic.dy.fi Git - maemo-mapper/blob - src/cmenu.c
Added basic APRS support - Can be disabled by removing definition of INCLUDE_APRS
[maemo-mapper] / src / cmenu.c
1 /*
2  * Copyright (C) 2006, 2007 John Costigan.
3  *
4  * POI and GPS-Info code originally written by Cezary Jackiewicz.
5  *
6  * Default map data provided by http://www.openstreetmap.org/
7  *
8  * This file is part of Maemo Mapper.
9  *
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.
14  *
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.
19  *
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/>.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #    include "config.h"
26 #endif
27
28 #define _GNU_SOURCE
29
30 #include <string.h>
31 #include <math.h>
32 #include <gtk/gtk.h>
33 #include <gconf/gconf-client.h>
34
35 #ifndef LEGACY
36 #    include <hildon/hildon-note.h>
37 #    include <hildon/hildon-banner.h>
38 #else
39 #    include <hildon-widgets/hildon-note.h>
40 #    include <hildon-widgets/hildon-banner.h>
41 #endif
42
43 #include "types.h"
44 #include "data.h"
45 #include "defines.h"
46
47 #include "cmenu.h"
48 #include "display.h"
49 #include "gdk-pixbuf-rotate.h"
50 #include "menu.h"
51 #include "path.h"
52 #include "poi.h"
53 #include "util.h"
54
55 #define GCONF_SUPL_KEY_PREFIX "/system/osso/supl"
56 #define GCONF_KEY_SUPL_LAT GCONF_SUPL_KEY_PREFIX"/pos_latitude"
57 #define GCONF_KEY_SUPL_LON GCONF_SUPL_KEY_PREFIX"/pos_longitude"
58 #define GCONF_KEY_SUPL_TIME GCONF_SUPL_KEY_PREFIX"/pos_timestamp"
59
60 static void
61 cmenu_show_latlon(gint unitx, gint unity)
62 {
63   gdouble lat, lon;
64   gint tmp_degformat = _degformat;
65   gint fallback_deg_format = _degformat;
66   gchar buffer[80], tmp1[LL_FMT_LEN], tmp2[LL_FMT_LEN];
67   
68   printf("%s()\n", __PRETTY_FUNCTION__);
69
70   unit2latlon(unitx, unity, lat, lon);
71   
72   // Check that the current coord system supports the select position
73   if(!coord_system_check_lat_lon (lat, lon, &fallback_deg_format))
74   {
75         _degformat = fallback_deg_format;
76   }
77       
78   format_lat_lon(lat, lon, tmp1, tmp2);
79   
80
81   if(DEG_FORMAT_ENUM_TEXT[_degformat].field_2_in_use)
82   {
83           snprintf(buffer, sizeof(buffer),
84                     "%s: %s\n"
85                   "%s: %s",
86                   DEG_FORMAT_ENUM_TEXT[_degformat].long_field_1, tmp1,
87                   DEG_FORMAT_ENUM_TEXT[_degformat].long_field_2, tmp2);
88   }
89   else
90   {
91           snprintf(buffer, sizeof(buffer),
92                     "%s: %s",
93                   DEG_FORMAT_ENUM_TEXT[_degformat].long_field_1, tmp1);
94   }
95   
96   MACRO_BANNER_SHOW_INFO(_window, buffer);
97
98   _degformat = tmp_degformat;
99   
100   vprintf("%s(): return\n", __PRETTY_FUNCTION__);
101 }
102
103 static void
104 cmenu_clip_latlon(gint unitx, gint unity)
105 {
106     gchar buffer[80];
107     gdouble lat, lon;
108     printf("%s()\n", __PRETTY_FUNCTION__);
109
110     unit2latlon(unitx, unity, lat, lon);
111
112     snprintf(buffer, sizeof(buffer), "%.06f,%.06f", lat, lon);
113
114     gtk_clipboard_set_text(
115             gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), buffer, -1);
116
117     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
118 }
119
120 static void
121 cmenu_route_to(gint unitx, gint unity)
122 {
123     gchar buffer[80];
124     gchar strlat[32];
125     gchar strlon[32];
126     gdouble lat, lon;
127     printf("%s()\n", __PRETTY_FUNCTION__);
128
129     unit2latlon(unitx, unity, lat, lon);
130
131     g_ascii_formatd(strlat, 32, "%.06f", lat);
132     g_ascii_formatd(strlon, 32, "%.06f", lon);
133     snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon);
134
135     route_download(buffer);
136
137     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
138 }
139
140 static void
141 cmenu_distance_to(gint unitx, gint unity)
142 {
143     gchar buffer[80];
144     gdouble lat, lon;
145     printf("%s()\n", __PRETTY_FUNCTION__);
146
147     unit2latlon(unitx, unity, lat, lon);
148
149     snprintf(buffer, sizeof(buffer), "%s: %.02f %s", _("Distance"),
150             calculate_distance(_gps.lat, _gps.lon, lat, lon)
151               * UNITS_CONVERT[_units],
152             UNITS_ENUM_TEXT[_units]);
153     MACRO_BANNER_SHOW_INFO(_window, buffer);
154
155     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
156 }
157
158 static void
159 cmenu_add_route(gint unitx, gint unity)
160 {
161     printf("%s()\n", __PRETTY_FUNCTION__);
162     MACRO_PATH_INCREMENT_TAIL(_route);
163     screen2unit(_cmenu_position_x, _cmenu_position_y,
164             _route.tail->unitx, _route.tail->unity);
165     route_find_nearest_point();
166     map_force_redraw();
167     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
168 }
169
170 static gboolean
171 cmenu_cb_loc_show_latlon(GtkMenuItem *item)
172 {
173     gint unitx, unity;
174     gdouble lat, lon;
175     printf("%s()\n", __PRETTY_FUNCTION__);
176
177     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
178     unit2latlon(unitx, unity, lat, lon);
179
180     latlon_dialog(lat, lon);
181
182     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
183     return TRUE;
184 }
185
186 static gboolean
187 cmenu_cb_loc_route_to(GtkMenuItem *item)
188 {
189     gint unitx, unity;
190     printf("%s()\n", __PRETTY_FUNCTION__);
191
192     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
193     cmenu_route_to(unitx, unity);
194
195     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
196     return TRUE;
197 }
198
199 static gboolean
200 cmenu_cb_loc_download_poi(GtkMenuItem *item)
201 {
202     gint unitx, unity;
203     printf("%s()\n", __PRETTY_FUNCTION__);
204
205     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
206     poi_download_dialog(unitx, unity);
207
208     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
209     return TRUE;
210 }
211
212 static gboolean
213 cmenu_cb_loc_browse_poi(GtkMenuItem *item)
214 {
215     gint unitx, unity;
216     printf("%s()\n", __PRETTY_FUNCTION__);
217
218     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
219     poi_browse_dialog(unitx, unity);
220
221     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
222     return TRUE;
223 }
224
225 static gboolean
226 cmenu_cb_loc_distance_to(GtkMenuItem *item)
227 {
228     gint unitx, unity;
229     printf("%s()\n", __PRETTY_FUNCTION__);
230
231     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
232     cmenu_distance_to(unitx, unity);
233
234     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
235     return TRUE;
236 }
237
238 static gboolean
239 cmenu_cb_loc_add_route(GtkMenuItem *item)
240 {
241     gint unitx, unity;
242     printf("%s()\n", __PRETTY_FUNCTION__);
243
244     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
245     cmenu_add_route(unitx, unity);
246
247     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
248     return TRUE;
249 }
250
251 static gboolean
252 cmenu_cb_loc_add_way(GtkMenuItem *item)
253 {
254     gint unitx, unity;
255     printf("%s()\n", __PRETTY_FUNCTION__);
256
257     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
258     route_add_way_dialog(unitx, unity);
259
260     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
261     return TRUE;
262 }
263
264 static gboolean
265 cmenu_cb_loc_add_poi(GtkMenuItem *item)
266 {
267     gint unitx, unity;
268     printf("%s()\n", __PRETTY_FUNCTION__);
269
270     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
271     poi_add_dialog(_window, unitx, unity);
272
273     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
274     return TRUE;
275 }
276
277 static gboolean
278 cmenu_cb_loc_set_gps(GtkMenuItem *item)
279 {
280     printf("%s()\n", __PRETTY_FUNCTION__);
281
282     screen2unit(_cmenu_position_x, _cmenu_position_y, _pos.unitx, _pos.unity);
283     unit2latlon(_pos.unitx, _pos.unity, _gps.lat, _gps.lon);
284
285     /* Move mark to new location. */
286     map_refresh_mark(_center_mode > 0);
287
288     GConfClient *gconf_client = gconf_client_get_default();
289     GTimeVal curtime;
290
291     gconf_client_set_float(gconf_client, GCONF_KEY_SUPL_LON, _gps.lon, NULL);
292     gconf_client_set_float(gconf_client, GCONF_KEY_SUPL_LAT, _gps.lat, NULL);
293     g_get_current_time(&curtime);
294     gconf_client_set_float(gconf_client, GCONF_KEY_SUPL_TIME, curtime.tv_sec, NULL);
295
296     g_object_unref(gconf_client);
297
298     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
299     return TRUE;
300 }
301
302 static gboolean
303 cmenu_cb_loc_apply_correction(GtkMenuItem *item)
304 {
305     printf("%s()\n", __PRETTY_FUNCTION__);
306
307     if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item)))
308     {
309         /* Get difference between tap point and GPS location. */
310         gint unitx, unity;
311         screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
312         _map_correction_unitx = unitx - _pos.unitx;
313         _map_correction_unity = unity - _pos.unity;
314         map_refresh_mark(TRUE);
315         MACRO_BANNER_SHOW_INFO(_window, _("Map correction applied."));
316     }
317     else
318     {
319         _map_correction_unitx = 0;
320         _map_correction_unity = 0;
321         map_refresh_mark(TRUE);
322         MACRO_BANNER_SHOW_INFO(_window, _("Map correction removed."));
323     }
324
325     printf("Map correction now set to: %d, %d\n");
326
327     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
328     return TRUE;
329 }
330
331 static gboolean
332 cmenu_cb_way_show_latlon(GtkMenuItem *item)
333 {
334     gint unitx, unity;
335     WayPoint *way;
336     printf("%s()\n", __PRETTY_FUNCTION__);
337
338     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
339     if((way = find_nearest_waypoint(unitx, unity)))
340         cmenu_show_latlon(way->point->unitx, way->point->unity);
341     else
342     {
343         MACRO_BANNER_SHOW_INFO(_window, _("There are no waypoints."));
344     }
345
346
347     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
348     return TRUE;
349 }
350
351 static gboolean
352 cmenu_cb_way_show_desc(GtkMenuItem *item)
353 {
354     gint unitx, unity;
355     WayPoint *way;
356     printf("%s()\n", __PRETTY_FUNCTION__);
357
358     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
359     if((way = find_nearest_waypoint(unitx, unity)))
360     {
361         MACRO_BANNER_SHOW_INFO(_window, way->desc);
362     }
363     else
364     {
365         MACRO_BANNER_SHOW_INFO(_window, _("There are no waypoints."));
366     }
367
368     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
369     return TRUE;
370 }
371
372 static gboolean
373 cmenu_cb_way_clip_latlon(GtkMenuItem *item)
374 {
375     gint unitx, unity;
376     WayPoint *way;
377     printf("%s()\n", __PRETTY_FUNCTION__);
378
379     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
380     if((way = find_nearest_waypoint(unitx, unity)))
381         cmenu_clip_latlon(way->point->unitx, way->point->unity);
382     else
383     {
384         MACRO_BANNER_SHOW_INFO(_window, _("There are no waypoints."));
385     }
386
387     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
388     return TRUE;
389 }
390
391 static gboolean
392 cmenu_cb_way_clip_desc(GtkMenuItem *item)
393 {
394     gint unitx, unity;
395     WayPoint *way;
396     printf("%s()\n", __PRETTY_FUNCTION__);
397
398     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
399     if((way = find_nearest_waypoint(unitx, unity)))
400         gtk_clipboard_set_text(
401                 gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), way->desc, -1);
402     else
403     {
404         MACRO_BANNER_SHOW_INFO(_window, _("There are no waypoints."));
405     }
406
407     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
408     return TRUE;
409 }
410
411 static gboolean
412 cmenu_cb_way_route_to(GtkMenuItem *item)
413 {
414     gint unitx, unity;
415     WayPoint *way;
416     printf("%s()\n", __PRETTY_FUNCTION__);
417
418     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
419     if((way = find_nearest_waypoint(unitx, unity)))
420         cmenu_route_to(way->point->unitx, way->point->unity);
421     else
422     {
423         MACRO_BANNER_SHOW_INFO(_window, _("There are no waypoints."));
424     }
425
426     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
427     return TRUE;
428 }
429
430 static gboolean
431 cmenu_cb_way_distance_to(GtkMenuItem *item)
432 {
433     gint unitx, unity;
434     WayPoint *way;
435     printf("%s()\n", __PRETTY_FUNCTION__);
436
437     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
438     if((way = find_nearest_waypoint(unitx, unity)))
439         route_show_distance_to(way->point);
440     else
441     {
442         MACRO_BANNER_SHOW_INFO(_window, _("There are no waypoints."));
443     }
444
445     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
446     return TRUE;
447 }
448
449 static gboolean
450 cmenu_cb_way_delete(GtkMenuItem *item)
451 {
452     gint unitx, unity;
453     WayPoint *way;
454     printf("%s()\n", __PRETTY_FUNCTION__);
455
456     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
457     if((way = find_nearest_waypoint(unitx, unity)))
458     {
459         gchar buffer[BUFFER_SIZE];
460         GtkWidget *confirm;
461
462         snprintf(buffer, sizeof(buffer), "%s:\n%s\n",
463                 _("Confirm delete of waypoint"), way->desc);
464         confirm = hildon_note_new_confirmation(GTK_WINDOW(_window), buffer);
465
466         if(GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm)))
467         {
468             Point *pdel_min, *pdel_max, *pdel_start, *pdel_end;
469             gint num_del;
470
471             /* Delete surrounding route data, too. */
472             if(way == _route.whead)
473                 pdel_min = _route.head;
474             else
475                 pdel_min = way[-1].point;
476
477             if(way == _route.wtail)
478                 pdel_max = _route.tail;
479             else
480                 pdel_max = way[1].point;
481
482             /* Find largest continuous segment around the waypoint, EXCLUDING
483              * pdel_min and pdel_max. */
484             for(pdel_start = way->point - 1; pdel_start->unity
485                     && pdel_start > pdel_min; pdel_start--) { }
486             for(pdel_end = way->point + 1; pdel_end->unity
487                     && pdel_end < pdel_max; pdel_end++) { }
488
489             /* If pdel_end is set to _route.tail, and if _route.tail is a
490              * non-zero point, then delete _route.tail. */
491             if(pdel_end == _route.tail && pdel_end->unity)
492                 pdel_end++; /* delete _route.tail too */
493             /* else, if *both* endpoints are zero points, delete one. */
494             else if(!pdel_start->unity && !pdel_end->unity)
495                 pdel_start--;
496
497             /* Delete BETWEEN pdel_start and pdel_end, exclusive. */
498             num_del = pdel_end - pdel_start - 1;
499
500             memmove(pdel_start + 1, pdel_end,
501                     (_route.tail - pdel_end + 1) * sizeof(Point));
502             _route.tail -= num_del;
503
504             /* Remove waypoint and move/adjust subsequent waypoints. */
505             g_free(way->desc);
506             while(way++ != _route.wtail)
507             {
508                 way[-1] = *way;
509                 way[-1].point -= num_del;
510             }
511             _route.wtail--;
512
513             route_find_nearest_point();
514             map_force_redraw();
515         }
516         gtk_widget_destroy(confirm);
517     }
518     else
519     {
520         MACRO_BANNER_SHOW_INFO(_window, _("There are no waypoints."));
521     }
522
523     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
524     return TRUE;
525 }
526
527 static gboolean
528 cmenu_cb_way_add_poi(GtkMenuItem *item)
529 {
530     gint unitx, unity;
531     WayPoint *way;
532     printf("%s()\n", __PRETTY_FUNCTION__);
533
534     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
535     if((way = find_nearest_waypoint(unitx, unity)))
536         poi_add_dialog(_window, way->point->unitx, way->point->unity);
537     else
538     {
539         MACRO_BANNER_SHOW_INFO(_window, _("There are no waypoints."));
540     }
541
542     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
543     return TRUE;
544 }
545
546 static gboolean
547 cmenu_cb_poi_route_to(GtkMenuItem *item)
548 {
549     gint unitx, unity;
550     PoiInfo poi;
551     printf("%s()\n", __PRETTY_FUNCTION__);
552
553     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
554     if(select_poi(unitx, unity, &poi, FALSE)) /* FALSE = not quick */
555     {
556         gint unitx, unity;
557         latlon2unit(poi.lat, poi.lon, unitx, unity);
558         cmenu_route_to(unitx, unity);
559     }
560
561     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
562     return TRUE;
563 }
564
565 static gboolean
566 cmenu_cb_poi_distance_to(GtkMenuItem *item)
567 {
568     gint unitx, unity;
569     PoiInfo poi;
570     printf("%s()\n", __PRETTY_FUNCTION__);
571
572     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
573     if(select_poi(unitx, unity, &poi, FALSE)) /* FALSE = not quick */
574     {
575         gint unitx, unity;
576         latlon2unit(poi.lat, poi.lon, unitx, unity);
577         cmenu_distance_to(unitx, unity);
578     }
579
580     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
581     return TRUE;
582 }
583
584 static gboolean
585 cmenu_cb_poi_add_route(GtkMenuItem *item)
586 {
587     gint unitx, unity;
588     PoiInfo poi;
589     printf("%s()\n", __PRETTY_FUNCTION__);
590
591     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
592     if(select_poi(unitx, unity, &poi, FALSE)) /* FALSE = not quick */
593     {
594         gint unitx, unity;
595         latlon2unit(poi.lat, poi.lon, unitx, unity);
596         cmenu_add_route(unitx, unity);
597     }
598
599     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
600     return TRUE;
601 }
602
603 static gboolean
604 cmenu_cb_poi_add_way(GtkMenuItem *item)
605 {
606     gint unitx, unity;
607     PoiInfo poi;
608     printf("%s()\n", __PRETTY_FUNCTION__);
609
610     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
611     if(select_poi(unitx, unity, &poi, FALSE)) /* FALSE = not quick */
612     {
613         gint unitx, unity;
614         latlon2unit(poi.lat, poi.lon, unitx, unity);
615         route_add_way_dialog(unitx, unity);
616     }
617
618     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
619     return TRUE;
620 }
621
622 static gboolean
623 cmenu_cb_poi_edit_poi(GtkMenuItem *item)
624 {
625     PoiInfo poi;
626     gint unitx, unity;
627     printf("%s()\n", __PRETTY_FUNCTION__);
628
629     memset(&poi, 0, sizeof(poi));
630     screen2unit(_cmenu_position_x, _cmenu_position_y, unitx, unity);
631     select_poi(unitx, unity, &poi, FALSE); /* FALSE = not quick */
632     poi_view_dialog(_window, &poi);
633     if(poi.label)
634         g_free(poi.label);
635     if(poi.desc)
636         g_free(poi.desc);
637     if(poi.clabel)
638         g_free(poi.clabel);
639
640     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
641     return TRUE;
642 }
643
644 static gboolean
645 cmenu_cb_hide(GtkMenuItem *item)
646 {
647     printf("%s()\n", __PRETTY_FUNCTION__);
648
649     if(_mouse_is_down)
650         g_mutex_unlock(_mouse_mutex);
651     _mouse_is_down = _mouse_is_dragging = FALSE;
652
653     vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
654     return TRUE;
655 }
656
657 void cmenu_init()
658 {
659     /* Create needed handles. */
660     GtkWidget *submenu;
661     GtkWidget *menu_item;
662     printf("%s()\n", __PRETTY_FUNCTION__);
663
664     /* Setup the context menu. */
665     _map_cmenu = GTK_MENU(gtk_menu_new());
666
667     /* Setup the map context menu. */
668     gtk_menu_append(_map_cmenu, menu_item
669             = gtk_menu_item_new_with_label(_("Tap Point")));
670     gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
671             submenu = gtk_menu_new());
672
673     /* Setup the map context menu. */
674     gtk_menu_append(submenu, _cmenu_loc_show_latlon_item
675             = gtk_menu_item_new_with_label(_("Show Position")));
676     gtk_menu_append(submenu, gtk_separator_menu_item_new());
677     gtk_menu_append(submenu, _cmenu_loc_distance_to_item
678             = gtk_menu_item_new_with_label(_("Show Distance to")));
679     gtk_menu_append(submenu, _cmenu_loc_route_to_item
680             = gtk_menu_item_new_with_label(_("Download Route to...")));
681     gtk_menu_append(submenu, _cmenu_loc_download_poi_item
682                 = gtk_menu_item_new_with_label(_("Download POI...")));
683     gtk_menu_append(submenu, _cmenu_loc_browse_poi_item
684                 = gtk_menu_item_new_with_label(_("Browse POI...")));
685     gtk_menu_append(submenu, gtk_separator_menu_item_new());
686     gtk_menu_append(submenu, _cmenu_loc_add_route_item
687                 = gtk_menu_item_new_with_label(_("Add Route Point")));
688     gtk_menu_append(submenu, _cmenu_loc_add_way_item
689                 = gtk_menu_item_new_with_label(_("Add Waypoint...")));
690     gtk_menu_append(submenu, _cmenu_loc_add_poi_item
691                 = gtk_menu_item_new_with_label(_("Add POI...")));
692     gtk_menu_append(submenu, gtk_separator_menu_item_new());
693     gtk_menu_append(submenu, _cmenu_loc_set_gps_item
694                 = gtk_menu_item_new_with_label(_("Set as GPS Location")));
695     gtk_menu_append(submenu, _cmenu_loc_apply_correction_item
696                 = gtk_check_menu_item_new_with_label(
697                     _("Apply Map Correction")));
698     gtk_check_menu_item_set_active(
699             GTK_CHECK_MENU_ITEM(_cmenu_loc_apply_correction_item),
700             _map_correction_unitx != 0 || _map_correction_unity != 0);
701
702     /* Setup the waypoint context menu. */
703     gtk_menu_append(_map_cmenu, menu_item
704             = gtk_menu_item_new_with_label(_("Waypoint")));
705     gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item),
706             submenu = gtk_menu_new());
707
708     gtk_menu_append(submenu, _cmenu_way_show_latlon_item
709             = gtk_menu_item_new_with_label(_("Show Position")));
710     gtk_menu_append(submenu, _cmenu_way_show_desc_item
711             = gtk_menu_item_new_with_label(_("Show Description")));
712     gtk_menu_append(submenu, _cmenu_way_clip_latlon_item
713             = gtk_menu_item_new_with_label(_("Copy Position")));
714     gtk_menu_append(submenu, _cmenu_way_clip_desc_item
715             = gtk_menu_item_new_with_label(_("Copy Description")));
716     gtk_menu_append(submenu, gtk_separator_menu_item_new());
717     gtk_menu_append(submenu, _cmenu_way_distance_to_item
718             = gtk_menu_item_new_with_label(_("Show Distance to")));
719     gtk_menu_append(submenu, _cmenu_way_route_to_item
720             = gtk_menu_item_new_with_label(_("Download Route to...")));
721     gtk_menu_append(submenu, _cmenu_way_delete_item
722             = gtk_menu_item_new_with_label(_("Delete...")));
723     gtk_menu_append(submenu, gtk_separator_menu_item_new());
724     gtk_menu_append(submenu, _cmenu_way_add_poi_item
725                 = gtk_menu_item_new_with_label(_("Add POI...")));
726     gtk_menu_append(submenu, gtk_separator_menu_item_new());
727     gtk_menu_append(submenu, _cmenu_way_goto_nextway_item
728                 = gtk_menu_item_new_with_label(_("Go to Next")));
729
730     /* Setup the POI context menu. */
731     gtk_menu_append(_map_cmenu, _cmenu_poi_submenu
732             = gtk_menu_item_new_with_label(_("POI")));
733     gtk_menu_item_set_submenu(GTK_MENU_ITEM(_cmenu_poi_submenu),
734             submenu = gtk_menu_new());
735
736     gtk_menu_append(submenu, _cmenu_poi_edit_poi_item
737                 = gtk_menu_item_new_with_label(_("View/Edit...")));
738     gtk_menu_append(submenu, gtk_separator_menu_item_new());
739     gtk_menu_append(submenu, _cmenu_poi_distance_to_item
740             = gtk_menu_item_new_with_label(_("Show Distance to")));
741     gtk_menu_append(submenu, _cmenu_poi_route_to_item
742             = gtk_menu_item_new_with_label(_("Download Route to...")));
743     gtk_menu_append(submenu, gtk_separator_menu_item_new());
744     gtk_menu_append(submenu, _cmenu_poi_add_route_item
745                 = gtk_menu_item_new_with_label(_("Add Route Point")));
746     gtk_menu_append(submenu, _cmenu_poi_add_way_item
747                 = gtk_menu_item_new_with_label(_("Add Waypoint...")));
748     gtk_menu_append(submenu, gtk_separator_menu_item_new());
749     gtk_menu_append(submenu, _cmenu_poi_goto_nearpoi_item
750                 = gtk_menu_item_new_with_label(_("Go to Nearest")));
751
752     /* Connect signals for context menu. */
753     g_signal_connect(G_OBJECT(_cmenu_loc_show_latlon_item), "activate",
754                       G_CALLBACK(cmenu_cb_loc_show_latlon), NULL);
755     g_signal_connect(G_OBJECT(_cmenu_loc_route_to_item), "activate",
756                       G_CALLBACK(cmenu_cb_loc_route_to), NULL);
757     g_signal_connect(G_OBJECT(_cmenu_loc_download_poi_item), "activate",
758                       G_CALLBACK(cmenu_cb_loc_download_poi), NULL);
759     g_signal_connect(G_OBJECT(_cmenu_loc_browse_poi_item), "activate",
760                       G_CALLBACK(cmenu_cb_loc_browse_poi), NULL);
761     g_signal_connect(G_OBJECT(_cmenu_loc_distance_to_item), "activate",
762                       G_CALLBACK(cmenu_cb_loc_distance_to), NULL);
763     g_signal_connect(G_OBJECT(_cmenu_loc_add_route_item), "activate",
764                         G_CALLBACK(cmenu_cb_loc_add_route), NULL);
765     g_signal_connect(G_OBJECT(_cmenu_loc_add_way_item), "activate",
766                         G_CALLBACK(cmenu_cb_loc_add_way), NULL);
767     g_signal_connect(G_OBJECT(_cmenu_loc_add_poi_item), "activate",
768                         G_CALLBACK(cmenu_cb_loc_add_poi), NULL);
769     g_signal_connect(G_OBJECT(_cmenu_loc_set_gps_item), "activate",
770                         G_CALLBACK(cmenu_cb_loc_set_gps), NULL);
771     g_signal_connect(G_OBJECT(_cmenu_loc_apply_correction_item), "toggled",
772                         G_CALLBACK(cmenu_cb_loc_apply_correction), NULL);
773
774     g_signal_connect(G_OBJECT(_cmenu_way_show_latlon_item), "activate",
775                       G_CALLBACK(cmenu_cb_way_show_latlon), NULL);
776     g_signal_connect(G_OBJECT(_cmenu_way_show_desc_item), "activate",
777                       G_CALLBACK(cmenu_cb_way_show_desc), NULL);
778     g_signal_connect(G_OBJECT(_cmenu_way_clip_latlon_item), "activate",
779                       G_CALLBACK(cmenu_cb_way_clip_latlon), NULL);
780     g_signal_connect(G_OBJECT(_cmenu_way_clip_desc_item), "activate",
781                       G_CALLBACK(cmenu_cb_way_clip_desc), NULL);
782     g_signal_connect(G_OBJECT(_cmenu_way_route_to_item), "activate",
783                       G_CALLBACK(cmenu_cb_way_route_to), NULL);
784     g_signal_connect(G_OBJECT(_cmenu_way_distance_to_item), "activate",
785                       G_CALLBACK(cmenu_cb_way_distance_to), NULL);
786     g_signal_connect(G_OBJECT(_cmenu_way_delete_item), "activate",
787                       G_CALLBACK(cmenu_cb_way_delete), NULL);
788     g_signal_connect(G_OBJECT(_cmenu_way_add_poi_item), "activate",
789                         G_CALLBACK(cmenu_cb_way_add_poi), NULL);
790     g_signal_connect(G_OBJECT(_cmenu_way_goto_nextway_item), "activate",
791                         G_CALLBACK(menu_cb_view_goto_nextway), NULL);
792
793     g_signal_connect(G_OBJECT(_cmenu_poi_edit_poi_item), "activate",
794                         G_CALLBACK(cmenu_cb_poi_edit_poi), NULL);
795     g_signal_connect(G_OBJECT(_cmenu_poi_route_to_item), "activate",
796                       G_CALLBACK(cmenu_cb_poi_route_to), NULL);
797     g_signal_connect(G_OBJECT(_cmenu_poi_distance_to_item), "activate",
798                       G_CALLBACK(cmenu_cb_poi_distance_to), NULL);
799     g_signal_connect(G_OBJECT(_cmenu_poi_add_route_item), "activate",
800                         G_CALLBACK(cmenu_cb_poi_add_route), NULL);
801     g_signal_connect(G_OBJECT(_cmenu_poi_add_way_item), "activate",
802                         G_CALLBACK(cmenu_cb_poi_add_way), NULL);
803     g_signal_connect(G_OBJECT(_cmenu_poi_goto_nearpoi_item), "activate",
804                         G_CALLBACK(menu_cb_view_goto_nearpoi), NULL);
805
806     gtk_widget_show_all(GTK_WIDGET(_map_cmenu));
807
808 #ifdef MAEMO_CHANGES
809     gtk_widget_tap_and_hold_setup(_map_widget, GTK_WIDGET(_map_cmenu), NULL, 0);
810 #endif
811
812     /* Add a "hide" signal event handler to handle dismissing the context
813      * menu. */
814     g_signal_connect(GTK_WIDGET(_map_cmenu), "hide",
815             G_CALLBACK(cmenu_cb_hide), NULL);
816
817     vprintf("%s(): return\n", __PRETTY_FUNCTION__);
818 }