]> err.no Git - mapper/blob - src/cb.c
Import fork of maemo-mapper.
[mapper] / src / cb.c
1 #include <config.h>
2
3 #define _GNU_SOURCE
4
5 #include <unistd.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <strings.h>
9 #include <stddef.h>
10 #include <locale.h>
11 #include <math.h>
12 #include <errno.h>
13 #include <sys/wait.h>
14 #include <glib/gstdio.h>
15 #include <gtk/gtk.h>
16 #include <fcntl.h>
17 #include <libgnomevfs/gnome-vfs.h>
18 #include <curl/multi.h>
19 #include <gconf/gconf-client.h>
20 #include <libxml/parser.h>
21 #include <libintl.h>
22 #include <locale.h>
23 #include <sqlite3.h>
24
25 #include "utils.h"
26 #include "poi.h"
27 #include "route.h"
28 #include "settings.h"
29 #include "gps.h"
30 #include "map.h"
31 #include "mapper-types.h"
32 #include "bt.h"
33 #include "ui-common.h"
34
35 #include "cb.h"
36
37 gboolean map_cb_configure(GtkWidget * widget, GdkEventConfigure * event)
38 {
39         printf("%s(%d, %d)\n", __PRETTY_FUNCTION__,
40                _map_widget->allocation.width, _map_widget->allocation.height);
41
42         _screen_width_pixels = _map_widget->allocation.width;
43         _screen_height_pixels = _map_widget->allocation.height;
44         _screen_grids_halfwidth = pixel2grid(_screen_width_pixels) / 2;
45         _screen_grids_halfheight = pixel2grid(_screen_height_pixels) / 2;
46
47         /* Set _scale_rect. */
48         _scale_rect.x = (_screen_width_pixels - SCALE_WIDTH) / 2;
49         _scale_rect.width = SCALE_WIDTH;
50         pango_layout_set_text(_scale_layout, "0", -1);
51         pango_layout_get_pixel_size(_scale_layout, NULL, &_scale_rect.height);
52         _scale_rect.y = _screen_height_pixels - _scale_rect.height - 1;
53
54         MACRO_RECALC_FOCUS_BASE();
55         MACRO_RECALC_FOCUS_SIZE();
56
57         _min_center.unitx = pixel2unit(grid2pixel(_screen_grids_halfwidth));
58         _min_center.unity = pixel2unit(grid2pixel(_screen_grids_halfheight));
59         _max_center.unitx =
60             WORLD_SIZE_UNITS - grid2unit(_screen_grids_halfwidth) - 1;
61         _max_center.unity =
62             WORLD_SIZE_UNITS - grid2unit(_screen_grids_halfheight) - 1;
63
64         map_center_unit(_center.unitx, _center.unity);
65
66         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
67         return TRUE;
68 }
69
70 gboolean menu_cb_route_download(GtkAction * action)
71 {
72         printf("%s()\n", __PRETTY_FUNCTION__);
73         route_download(NULL);
74         vprintf("%s(): return\n", __PRETTY_FUNCTION__);
75         return TRUE;
76 }
77
78 gboolean menu_cb_route_open(GtkAction * action)
79 {
80         printf("%s()\n", __PRETTY_FUNCTION__);
81
82         route_open_file();
83
84         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
85         return TRUE;
86 }
87
88 gboolean menu_cb_route_distnext(GtkAction * action)
89 {
90         printf("%s()\n", __PRETTY_FUNCTION__);
91
92         route_show_distance_to_next();
93
94         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
95         return TRUE;
96 }
97
98 gboolean menu_cb_route_distlast(GtkAction * action)
99 {
100         printf("%s()\n", __PRETTY_FUNCTION__);
101
102         route_show_distance_to_last();
103
104         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
105         return TRUE;
106 }
107
108 gboolean menu_cb_route_reset(GtkAction * action)
109 {
110         printf("%s()\n", __PRETTY_FUNCTION__);
111
112         route_find_nearest_point();
113         MACRO_MAP_RENDER_DATA();
114         MACRO_QUEUE_DRAW_AREA();
115
116         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
117         return TRUE;
118 }
119
120 gboolean menu_cb_route_clear(GtkAction * action)
121 {
122         printf("%s()\n", __PRETTY_FUNCTION__);
123
124         cancel_autoroute(FALSE);
125         MACRO_PATH_FREE(_route);
126         MACRO_PATH_INIT(_route);
127         route_find_nearest_point();
128         map_force_redraw();
129
130         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
131         return TRUE;
132 }
133
134 gboolean menu_cb_track_open(GtkAction * action)
135 {
136         printf("%s()\n", __PRETTY_FUNCTION__);
137
138         track_open();
139
140         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
141         return TRUE;
142 }
143
144 gboolean menu_cb_track_save(GtkAction * action)
145 {
146         printf("%s()\n", __PRETTY_FUNCTION__);
147
148         track_save();
149
150         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
151         return TRUE;
152 }
153
154 gboolean menu_cb_track_insert_break(GtkAction * action)
155 {
156         printf("%s()\n", __PRETTY_FUNCTION__);
157
158         track_insert_break();
159
160         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
161         return TRUE;
162 }
163
164 gboolean menu_cb_track_insert_mark(GtkAction * action)
165 {
166         printf("%s()\n", __PRETTY_FUNCTION__);
167
168         track_insert_mark();
169
170         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
171         return TRUE;
172 }
173
174 gboolean menu_cb_track_distlast(GtkAction * action)
175 {
176         printf("%s()\n", __PRETTY_FUNCTION__);
177
178         track_show_distance_from_last();
179
180         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
181         return TRUE;
182 }
183
184 gboolean menu_cb_track_distfirst(GtkAction * action)
185 {
186         printf("%s()\n", __PRETTY_FUNCTION__);
187
188         track_show_distance_from_first();
189
190         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
191         return TRUE;
192 }
193
194 gboolean menu_cb_route_save(GtkAction * action)
195 {
196         GnomeVFSHandle *handle;
197         printf("%s()\n", __PRETTY_FUNCTION__);
198
199         if (open_file(NULL, &handle, NULL, &_route_dir_uri, NULL,
200                       GTK_FILE_CHOOSER_ACTION_SAVE)) {
201                 if (write_gpx(&_route, handle)) {
202                         MACRO_BANNER_SHOW_INFO(_window, _("Route Saved"));
203                 } else
204                         popup_error(_window, _("Error writing GPX file."));
205                 gnome_vfs_close(handle);
206         }
207
208         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
209         return TRUE;
210 }
211
212 gboolean menu_cb_track_clear(GtkAction * action)
213 {
214         printf("%s()\n", __PRETTY_FUNCTION__);
215
216         track_clear();
217
218         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
219         return TRUE;
220 }
221
222 gboolean menu_cb_show_tracks(GtkAction * action)
223 {
224         printf("%s()\n", __PRETTY_FUNCTION__);
225
226         _show_tracks ^= TRACKS_MASK;
227         if (gtk_check_menu_item_get_active
228             (GTK_CHECK_MENU_ITEM(_menu_show_tracks_item))) {
229                 _show_tracks |= TRACKS_MASK;
230                 map_render_paths();
231                 MACRO_QUEUE_DRAW_AREA();
232                 MACRO_BANNER_SHOW_INFO(_window, _("Tracks are now shown"));
233         } else {
234                 _show_tracks &= ~TRACKS_MASK;
235                 map_force_redraw();
236                 MACRO_BANNER_SHOW_INFO(_window, _("Tracks are now hidden"));
237         }
238
239         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
240         return TRUE;
241 }
242
243 gboolean menu_cb_show_scale(GtkAction * action)
244 {
245         printf("%s()\n", __PRETTY_FUNCTION__);
246
247         _show_scale =
248             gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM
249                                            (_menu_show_scale_item));
250         MACRO_QUEUE_DRAW_AREA();
251
252         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
253         return TRUE;
254 }
255
256 gboolean menu_cb_show_routes(GtkAction * action)
257 {
258         printf("%s()\n", __PRETTY_FUNCTION__);
259
260         if (gtk_check_menu_item_get_active
261             (GTK_CHECK_MENU_ITEM(_menu_show_routes_item))) {
262                 _show_tracks |= ROUTES_MASK;
263                 map_render_paths();
264                 MACRO_QUEUE_DRAW_AREA();
265                 MACRO_BANNER_SHOW_INFO(_window, _("Routes are now shown"));
266         } else {
267                 _show_tracks &= ~ROUTES_MASK;
268                 map_force_redraw();
269                 MACRO_BANNER_SHOW_INFO(_window, _("Routes are now hidden"));
270         }
271
272         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
273         return TRUE;
274 }
275
276 gboolean menu_cb_show_velvec(GtkAction * action)
277 {
278         printf("%s()\n", __PRETTY_FUNCTION__);
279
280         _show_velvec =
281             gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM
282                                            (_menu_show_velvec_item));
283         map_move_mark();
284
285         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
286         return TRUE;
287 }
288
289 gboolean menu_cb_show_poi(GtkAction * action)
290 {
291         printf("%s()\n", __PRETTY_FUNCTION__);
292
293         _show_poi =
294             gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM
295                                            (_menu_show_poi_item));
296         map_force_redraw();
297
298         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
299         return TRUE;
300 }
301
302 gboolean menu_cb_gps_show_info(GtkAction * action)
303 {
304         printf("%s()\n", __PRETTY_FUNCTION__);
305
306         _gps_info =
307             gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM
308                                            (_menu_gps_show_info_item));
309
310         gps_show_info();
311
312         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
313         return TRUE;
314 }
315
316 gboolean menu_cb_ac_lead(GtkAction * action)
317 {
318         guint new_center_unitx, new_center_unity;
319         printf("%s()\n", __PRETTY_FUNCTION__);
320
321         _center_mode = CENTER_LEAD;
322         MACRO_BANNER_SHOW_INFO(_window, _("Auto-Center Mode: Lead"));
323         MACRO_RECALC_CENTER(new_center_unitx, new_center_unity);
324         map_center_unit(new_center_unitx, new_center_unity);
325
326         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
327         return TRUE;
328 }
329
330 gboolean menu_cb_ac_latlon(GtkAction * action)
331 {
332         guint new_center_unitx, new_center_unity;
333         printf("%s()\n", __PRETTY_FUNCTION__);
334
335         _center_mode = CENTER_LATLON;
336         MACRO_BANNER_SHOW_INFO(_window, _("Auto-Center Mode: Lat/Lon"));
337         MACRO_RECALC_CENTER(new_center_unitx, new_center_unity);
338         map_center_unit(new_center_unitx, new_center_unity);
339
340         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
341         return TRUE;
342 }
343
344 gboolean menu_cb_ac_none(GtkAction * action)
345 {
346         printf("%s()\n", __PRETTY_FUNCTION__);
347
348         _center_mode = -_center_mode;
349         MACRO_BANNER_SHOW_INFO(_window, _("Auto-Center Off"));
350
351         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
352         return TRUE;
353 }
354
355 gboolean menu_cb_goto_latlon(GtkAction * action)
356 {
357         GtkWidget *dialog;
358         GtkWidget *table;
359         GtkWidget *label;
360         GtkWidget *txt_lat;
361         GtkWidget *txt_lon;
362         printf("%s()\n", __PRETTY_FUNCTION__);
363
364         dialog = gtk_dialog_new_with_buttons(_("Go to Lat/Lon"),
365                                              GTK_WINDOW(_window),
366                                              GTK_DIALOG_MODAL, GTK_STOCK_OK,
367                                              GTK_RESPONSE_ACCEPT,
368                                              GTK_STOCK_CANCEL,
369                                              GTK_RESPONSE_REJECT, NULL);
370
371         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
372                            table = gtk_table_new(2, 3, FALSE), TRUE, TRUE, 0);
373
374         gtk_table_attach(GTK_TABLE(table),
375                          label = gtk_label_new(_("Latitude")),
376                          0, 1, 0, 1, GTK_FILL, 0, 2, 4);
377         gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
378
379         gtk_table_attach(GTK_TABLE(table),
380                          txt_lat = gtk_entry_new(),
381                          1, 2, 0, 1, GTK_FILL, 0, 2, 4);
382         gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
383
384         gtk_table_attach(GTK_TABLE(table),
385                          label = gtk_label_new(_("Longitude")),
386                          0, 1, 1, 2, GTK_FILL, 0, 2, 4);
387         gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
388
389         gtk_table_attach(GTK_TABLE(table),
390                          txt_lon = gtk_entry_new(),
391                          1, 2, 1, 2, GTK_FILL, 0, 2, 4);
392         gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
393
394 #ifdef WITH_HILDON
395         g_object_set(G_OBJECT(txt_lat), HILDON_INPUT_MODE_HINT,
396                      HILDON_INPUT_MODE_HINT_NUMERICSPECIAL, NULL);
397         g_object_set(G_OBJECT(txt_lon), HILDON_INPUT_MODE_HINT,
398                      HILDON_INPUT_MODE_HINT_NUMERICSPECIAL, NULL);
399 #endif
400
401         /* Initialize with the current center position. */
402         {
403                 gchar buffer[32];
404                 gfloat lat, lon;
405                 unit2latlon(_center.unitx, _center.unity, lat, lon);
406                 snprintf(buffer, sizeof(buffer), "%.06f", lat);
407                 gtk_label_set_text(GTK_LABEL(txt_lat), buffer);
408                 snprintf(buffer, sizeof(buffer), "%.06f", lon);
409                 gtk_label_set_text(GTK_LABEL(txt_lon), buffer);
410         }
411
412         gtk_widget_show_all(dialog);
413
414         while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
415                 const gchar *text;
416                 gchar *error_check;
417                 gfloat lat, lon;
418                 guint unitx, unity;
419
420                 text = gtk_entry_get_text(GTK_ENTRY(txt_lat));
421                 lat = strtof(text, &error_check);
422                 if (text == error_check || lat < -90.f || lat > 90.f) {
423                         popup_error(dialog, _("Invalid Latitude"));
424                         continue;
425                 }
426
427                 text = gtk_entry_get_text(GTK_ENTRY(txt_lon));
428                 lon = strtof(text, &error_check);
429                 if (text == error_check || lon < -180.f || lon > 180.f) {
430                         popup_error(dialog, _("Invalid Longitude"));
431                         continue;
432                 }
433
434                 latlon2unit(lat, lon, unitx, unity);
435                 if (_center_mode > 0)
436                         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
437                                                        (_menu_ac_none_item),
438                                                        TRUE);
439                 map_center_unit(unitx, unity);
440                 break;
441         }
442         gtk_widget_destroy(dialog);
443         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
444         return TRUE;
445 }
446
447 gboolean menu_cb_goto_gps(GtkAction * action)
448 {
449         printf("%s()\n", __PRETTY_FUNCTION__);
450
451         if (_center_mode > 0)
452                 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
453                                                (_menu_ac_none_item), TRUE);
454
455         map_center_unit(_pos.unitx, _pos.unity);
456
457         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
458         return TRUE;
459 }
460
461 gboolean menu_cb_goto_nextway(GtkAction * action)
462 {
463         printf("%s()\n", __PRETTY_FUNCTION__);
464
465         if (_next_way && _next_way->point->unity) {
466                 if (_center_mode > 0)
467                         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
468                                                        (_menu_ac_none_item),
469                                                        TRUE);
470
471                 map_center_unit(_next_way->point->unitx,
472                                 _next_way->point->unity);
473         } else {
474                 MACRO_BANNER_SHOW_INFO(_window,
475                                        _("There is no next waypoint."));
476         }
477
478         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
479         return TRUE;
480 }
481
482 gboolean menu_cb_goto_nearpoi(GtkAction * action)
483 {
484         printf("%s()\n", __PRETTY_FUNCTION__);
485
486         if (_db) {
487                 gfloat lat, lon;
488
489                 if (_center_mode > 0) {
490                         /* Auto-Center is enabled - use the GPS position. */
491                         unit2latlon(_pos.unitx, _pos.unity, lat, lon);
492                 } else {
493                         /* Auto-Center is disabled - use the view center. */
494                         unit2latlon(_center.unitx, _center.unity, lat, lon);
495                 }
496
497                 if (SQLITE_OK ==
498                     sqlite3_bind_double(_stmt_select_nearest_poi, 1, lat)
499                     && SQLITE_OK ==
500                     sqlite3_bind_double(_stmt_select_nearest_poi, 2, lon)
501                     && SQLITE_ROW == sqlite3_step(_stmt_select_nearest_poi)) {
502                         guint unitx, unity;
503                         gchar *banner;
504                         const gchar *poi_label, *cat_label;
505
506                         lat =
507                             sqlite3_column_double(_stmt_select_nearest_poi, 0);
508                         lon =
509                             sqlite3_column_double(_stmt_select_nearest_poi, 1);
510                         poi_label =
511                             sqlite3_column_text(_stmt_select_nearest_poi, 2);
512                         cat_label =
513                             sqlite3_column_text(_stmt_select_nearest_poi, 3);
514
515                         latlon2unit(lat, lon, unitx, unity);
516                         banner =
517                             g_strdup_printf("%s (%s)", poi_label, cat_label);
518                         MACRO_BANNER_SHOW_INFO(_window, banner);
519                         g_free(banner);
520
521                         if (_center_mode > 0)
522                                 gtk_check_menu_item_set_active
523                                     (GTK_CHECK_MENU_ITEM(_menu_ac_none_item),
524                                      TRUE);
525
526                         map_center_unit(unitx, unity);
527                 } else {
528                         MACRO_BANNER_SHOW_INFO(_window, _("No POIs found."));
529                 }
530                 sqlite3_reset(_stmt_select_nearest_poi);
531         }
532
533         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
534         return TRUE;
535 }
536
537 gboolean menu_cb_maps_repoman(GtkAction * action)
538 {
539         printf("%s()\n", __PRETTY_FUNCTION__);
540         repoman_dialog();
541         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
542         return TRUE;
543 }
544
545 gboolean menu_cb_maps_select(GtkAction * action, gpointer new_repo)
546 {
547         printf("%s()\n", __PRETTY_FUNCTION__);
548         repo_set_curr(new_repo);
549         map_force_redraw();
550         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
551         return TRUE;
552 }
553
554 gboolean menu_cb_zoomin(GtkAction * action)
555 {
556         printf("%s()\n", __PRETTY_FUNCTION__);
557
558         map_zoom(-1);
559
560         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
561         return TRUE;
562 }
563
564 gboolean menu_cb_zoomout(GtkAction * action)
565 {
566         printf("%s()\n", __PRETTY_FUNCTION__);
567
568         map_zoom(1);
569
570         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
571         return TRUE;
572 }
573
574 gboolean menu_cb_fullscreen(GtkAction * action)
575 {
576         printf("%s()\n", __PRETTY_FUNCTION__);
577
578         if ((_fullscreen =
579              gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM
580                                             (_menu_fullscreen_item))))
581                 gtk_window_fullscreen(GTK_WINDOW(_window));
582         else
583                 gtk_window_unfullscreen(GTK_WINDOW(_window));
584
585         gtk_idle_add((GSourceFunc) window_present, NULL);
586
587         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
588         return TRUE;
589 }
590
591 gboolean menu_cb_enable_gps(GtkAction * action)
592 {
593         printf("%s()\n", __PRETTY_FUNCTION__);
594
595         if ((_enable_gps =
596              gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM
597                                             (_menu_enable_gps_item)))) {
598                 if (_rcvr_mac) {
599                         set_conn_state(RCVR_DOWN);
600                         rcvr_connect_now();
601                 } else {
602                         popup_error(_window,
603                                     _
604                                     ("Cannot enable GPS until a GPS Receiver MAC "
605                                      "is set in the Settings dialog box."));
606                         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
607                                                        (_menu_enable_gps_item),
608                                                        FALSE);
609                 }
610         } else {
611                 if (_conn_state > RCVR_OFF)
612                         set_conn_state(RCVR_OFF);
613                 rcvr_disconnect();
614                 track_add(0, FALSE);
615                 _speed_excess = FALSE;
616         }
617         map_move_mark();
618         gps_show_info();
619         gtk_widget_set_sensitive(GTK_WIDGET(_menu_gps_details_item),
620                                  _enable_gps);
621         gtk_widget_set_sensitive(GTK_WIDGET(_menu_gps_reset_item), _enable_gps);
622
623         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
624         return TRUE;
625 }
626
627 gboolean menu_cb_auto_download(GtkAction * action)
628 {
629         printf("%s()\n", __PRETTY_FUNCTION__);
630
631         if ((_auto_download =
632              gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM
633                                             (_menu_auto_download_item)))) {
634                 if (_curr_repo->url == REPOTYPE_NONE)
635                         popup_error(_window,
636                                     _
637                                     ("NOTE: You must set a Map URI in the current repository in "
638                                      "order to download maps."));
639                 map_force_redraw();
640         }
641
642         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
643         return TRUE;
644 }
645
646 gboolean menu_cb_gps_reset(GtkAction * action)
647 {
648         printf("%s()\n", __PRETTY_FUNCTION__);
649
650         reset_bluetooth();
651
652         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
653         return TRUE;
654 }
655
656 gboolean menu_cb_gps_details(GtkAction * action)
657 {
658         printf("%s()\n", __PRETTY_FUNCTION__);
659
660         gps_details();
661
662         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
663         return TRUE;
664 }
665
666 gboolean menu_cb_settings(GtkAction * action)
667 {
668         printf("%s()\n", __PRETTY_FUNCTION__);
669
670         if (settings_dialog()) {
671                 /* Settings have changed - reconnect to receiver. */
672                 if (_enable_gps) {
673                         set_conn_state(RCVR_DOWN);
674                         rcvr_disconnect();
675                         rcvr_connect_now();
676                 }
677         }
678         MACRO_RECALC_FOCUS_BASE();
679         MACRO_RECALC_FOCUS_SIZE();
680         map_force_redraw();
681
682         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
683         return TRUE;
684 }
685
686 gboolean menu_cb_help(GtkAction * action)
687 {
688         printf("%s()\n", __PRETTY_FUNCTION__);
689
690 #ifdef WITH_HILDON
691         ossohelp_show(_osso, HELP_ID_INTRO, 0);
692 #endif
693
694         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
695         return TRUE;
696 }
697
698 gboolean menu_cb_about(GtkAction * action)
699 {
700         printf("%s()\n", __PRETTY_FUNCTION__);
701
702 #ifdef WITH_HILDON
703         ossohelp_show(_osso, HELP_ID_ABOUT, OSSO_HELP_SHOW_DIALOG);
704 #else
705         gtk_show_about_dialog(GTK_WINDOW(_window), "name", "OSM-Mapper",
706                               "version", "0.1", NULL);
707 #endif
708
709         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
710         return TRUE;
711 }
712
713 gboolean window_cb_key_press(GtkWidget * widget, GdkEventKey * event)
714 {
715         CustomKey custom_key;
716         printf("%s()\n", __PRETTY_FUNCTION__);
717
718         switch (event->keyval) {
719         case HILDON_HARDKEY_UP:
720                 custom_key = CUSTOM_KEY_UP;
721                 break;
722         case HILDON_HARDKEY_DOWN:
723                 custom_key = CUSTOM_KEY_DOWN;
724                 break;
725         case HILDON_HARDKEY_LEFT:
726                 custom_key = CUSTOM_KEY_LEFT;
727                 break;
728         case HILDON_HARDKEY_RIGHT:
729                 custom_key = CUSTOM_KEY_RIGHT;
730                 break;
731         case HILDON_HARDKEY_SELECT:
732                 custom_key = CUSTOM_KEY_SELECT;
733                 break;
734         case HILDON_HARDKEY_INCREASE:
735                 custom_key = CUSTOM_KEY_INCREASE;
736                 break;
737         case HILDON_HARDKEY_DECREASE:
738                 custom_key = CUSTOM_KEY_DECREASE;
739                 break;
740         case HILDON_HARDKEY_FULLSCREEN:
741                 custom_key = CUSTOM_KEY_FULLSCREEN;
742                 break;
743         case HILDON_HARDKEY_ESC:
744                 custom_key = CUSTOM_KEY_ESC;
745                 break;
746         default:
747                 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
748                 return FALSE;
749         }
750
751         switch (_action[custom_key]) {
752         case CUSTOM_ACTION_PAN_NORTH:
753                 map_pan(0, -PAN_UNITS);
754                 break;
755
756         case CUSTOM_ACTION_PAN_WEST:
757                 map_pan(-PAN_UNITS, 0);
758                 break;
759
760         case CUSTOM_ACTION_PAN_SOUTH:
761                 map_pan(0, PAN_UNITS);
762                 break;
763
764         case CUSTOM_ACTION_PAN_EAST:
765                 map_pan(PAN_UNITS, 0);
766                 break;
767
768         case CUSTOM_ACTION_TOGGLE_AUTOCENTER:
769                 switch (_center_mode) {
770                 case CENTER_LATLON:
771                 case CENTER_WAS_LEAD:
772                         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
773                                                        (_menu_ac_lead_item),
774                                                        TRUE);
775                         break;
776                 case CENTER_LEAD:
777                 case CENTER_WAS_LATLON:
778                         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
779                                                        (_menu_ac_latlon_item),
780                                                        TRUE);
781                         break;
782                 }
783                 break;
784
785         case CUSTOM_ACTION_ZOOM_IN:
786         case CUSTOM_ACTION_ZOOM_OUT:
787                 if (!_key_zoom_timeout_sid) {
788                         g_printf("Z: %d %d\n", _key_zoom_new, _zoom);
789                         _key_zoom_new = _zoom
790                             + (_action[custom_key] == CUSTOM_ACTION_ZOOM_IN
791                                ? -_curr_repo->view_zoom_steps
792                                : _curr_repo->view_zoom_steps);
793                         /* Remember, _key_zoom_new is unsigned. */
794                         if (_key_zoom_new < MAX_ZOOM) {
795                                 gchar buffer[80];
796                                 snprintf(buffer, sizeof(buffer), "%s %d",
797                                          _("Zoom to Level"), _key_zoom_new);
798                                 MACRO_BANNER_SHOW_INFO(_window, buffer);
799                                 _key_zoom_timeout_sid =
800                                     g_timeout_add(500, map_key_zoom_timeout,
801                                                   NULL);
802                         }
803                 }
804                 break;
805
806         case CUSTOM_ACTION_TOGGLE_FULLSCREEN:
807                 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
808                                                (_menu_fullscreen_item),
809                                                !_fullscreen);
810                 break;
811
812         case CUSTOM_ACTION_TOGGLE_TRACKS:
813                 switch (_show_tracks) {
814                 case 0:
815                         /* Nothing shown, nothing saved; just set both. */
816                         _show_tracks = TRACKS_MASK | ROUTES_MASK;
817                         break;
818                 case TRACKS_MASK << 16:
819                 case ROUTES_MASK << 16:
820                 case (ROUTES_MASK | TRACKS_MASK) << 16:
821                         /* Something was saved and nothing changed since.
822                          * Restore saved. */
823                         _show_tracks = _show_tracks >> 16;
824                         break;
825                 default:
826                         /* There is no history, or they changed something
827                          * since the last historical change. Save and
828                          * clear. */
829                         _show_tracks = _show_tracks << 16;
830                 }
831                 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
832                                                (_menu_show_routes_item),
833                                                _show_tracks & ROUTES_MASK);
834
835                 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
836                                                (_menu_show_tracks_item),
837                                                _show_tracks & TRACKS_MASK);
838
839         case CUSTOM_ACTION_TOGGLE_SCALE:
840                 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
841                                                (_menu_show_scale_item),
842                                                !_show_scale);
843                 break;
844
845         case CUSTOM_ACTION_TOGGLE_POI:
846                 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
847                                                (_menu_show_poi_item),
848                                                !_show_poi);
849                 break;
850         case CUSTOM_ACTION_CHANGE_REPO:{
851                         GList *curr = g_list_find(_repo_list, _curr_repo);
852                         if (!curr)
853                                 break;
854
855                         /* Loop until we reach a next-able repo, or until we get
856                          * back to the current repo. */
857                         while ((curr = (curr->next ? curr->next : _repo_list))
858                                && !((RepoData *) curr->data)->nextable
859                                && curr->data != _curr_repo) {
860                         }
861
862                         if (curr->data != _curr_repo) {
863                                 repo_set_curr(curr->data);
864                                 gtk_check_menu_item_set_active
865                                     (GTK_CHECK_MENU_ITEM(_curr_repo->menu_item),
866                                      TRUE);
867                         } else {
868                                 popup_error(_window,
869                                             _
870                                             ("There are no other next-able repositories."));
871                         }
872                         break;
873                 }
874
875         case CUSTOM_ACTION_RESET_BLUETOOTH:
876                 reset_bluetooth();
877                 break;
878
879         case CUSTOM_ACTION_ROUTE_DISTNEXT:
880                 route_show_distance_to_next();
881                 break;
882
883         case CUSTOM_ACTION_ROUTE_DISTLAST:
884                 route_show_distance_to_last();
885                 break;
886
887         case CUSTOM_ACTION_TRACK_BREAK:
888                 track_insert_break();
889                 break;
890
891         case CUSTOM_ACTION_TRACK_DISTLAST:
892                 track_show_distance_from_last();
893                 break;
894
895         case CUSTOM_ACTION_TRACK_DISTFIRST:
896                 track_show_distance_from_first();
897                 break;
898
899         case CUSTOM_ACTION_TOGGLE_GPS:
900                 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
901                                                (_menu_enable_gps_item),
902                                                !_enable_gps);
903                 break;
904
905         case CUSTOM_ACTION_TOGGLE_GPSINFO:
906                 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM
907                                                (_menu_gps_show_info_item),
908                                                !_gps_info);
909                 break;
910
911         case CUSTOM_ACTION_TOGGLE_SPEEDLIMIT:
912                 _speed_limit_on ^= 1;
913                 break;
914
915         default:
916                 vprintf("%s(): return FALSE\n", __PRETTY_FUNCTION__);
917                 return FALSE;
918         }
919
920         return TRUE;
921         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
922 }
923
924 gboolean window_cb_key_release(GtkWidget * widget, GdkEventKey * event)
925 {
926         printf("%s()\n", __PRETTY_FUNCTION__);
927
928         switch (event->keyval) {
929         case HILDON_HARDKEY_INCREASE:
930         case HILDON_HARDKEY_DECREASE:
931                 if (_key_zoom_timeout_sid) {
932                         g_source_remove(_key_zoom_timeout_sid);
933                         _key_zoom_timeout_sid = 0;
934                         map_set_zoom(_key_zoom_new);
935                 }
936                 return TRUE;
937
938         default:
939                 return FALSE;
940         }
941         vprintf("%s(): return\n", __PRETTY_FUNCTION__);
942 }
943
944 void cmenu_show_latlon(guint unitx, guint unity)
945 {
946         gfloat lat, lon;
947         gchar buffer[80], tmp1[16], tmp2[16];
948         printf("%s()\n", __PRETTY_FUNCTION__);
949
950         unit2latlon(unitx, unity, lat, lon);
951         lat_format(lat, tmp1);
952         lon_format(lon, tmp2);
953
954         snprintf(buffer, sizeof(buffer),
955                  "%s: %s\n"
956                  "%s: %s", _("Latitude"), tmp1, _("Longitude"), tmp2);
957
958         MACRO_BANNER_SHOW_INFO(_window, buffer);
959
960         vprintf("%s(): return\n", __PRETTY_FUNCTION__);
961 }
962
963 void cmenu_clip_latlon(guint unitx, guint unity)
964 {
965         gchar buffer[80];
966         gfloat lat, lon;
967         printf("%s()\n", __PRETTY_FUNCTION__);
968
969         unit2latlon(unitx, unity, lat, lon);
970
971         snprintf(buffer, sizeof(buffer), "%.06f,%.06f", lat, lon);
972
973         gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
974                                buffer, -1);
975
976         vprintf("%s(): return\n", __PRETTY_FUNCTION__);
977 }
978
979 void cmenu_route_to(guint unitx, guint unity)
980 {
981         gchar buffer[80];
982         gchar strlat[32];
983         gchar strlon[32];
984         gfloat lat, lon;
985         printf("%s()\n", __PRETTY_FUNCTION__);
986
987         unit2latlon(unitx, unity, lat, lon);
988
989         g_ascii_formatd(strlat, 32, "%.06f", lat);
990         g_ascii_formatd(strlon, 32, "%.06f", lon);
991         snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon);
992
993         route_download(buffer);
994
995         vprintf("%s(): return\n", __PRETTY_FUNCTION__);
996 }
997
998 void cmenu_distance_to(guint unitx, guint unity)
999 {
1000         gchar buffer[80];
1001         gfloat lat, lon;
1002         printf("%s()\n", __PRETTY_FUNCTION__);
1003
1004         unit2latlon(unitx, unity, lat, lon);
1005
1006         snprintf(buffer, sizeof(buffer), "%s: %.02f %s", _("Distance"),
1007                  calculate_distance(_gps.lat, _gps.lon, lat, lon)
1008                  * UNITS_CONVERT[_units], UNITS_TEXT[_units]);
1009         MACRO_BANNER_SHOW_INFO(_window, buffer);
1010
1011         vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1012 }
1013
1014 void cmenu_add_route(guint unitx, guint unity)
1015 {
1016         printf("%s()\n", __PRETTY_FUNCTION__);
1017         MACRO_PATH_INCREMENT_TAIL(_route);
1018         _route.tail->unitx = x2unit(_cmenu_position_x);
1019         _route.tail->unity = y2unit(_cmenu_position_y);
1020         route_find_nearest_point();
1021         map_force_redraw();
1022         vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1023 }
1024
1025 void cmenu_route_add_way(guint unitx, guint unity)
1026 {
1027         gfloat lat, lon;
1028         gchar tmp1[16], tmp2[16], *p_latlon;
1029         GtkWidget *dialog;
1030         GtkWidget *table;
1031         GtkWidget *label;
1032         GtkWidget *txt_scroll;
1033         GtkWidget *txt_desc;
1034         printf("%s()\n", __PRETTY_FUNCTION__);
1035
1036         dialog = gtk_dialog_new_with_buttons(_("Add Waypoint"),
1037                                              GTK_WINDOW(_window),
1038                                              GTK_DIALOG_MODAL, GTK_STOCK_OK,
1039                                              GTK_RESPONSE_ACCEPT,
1040                                              GTK_STOCK_CANCEL,
1041                                              GTK_RESPONSE_REJECT, NULL);
1042
1043         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
1044                            table = gtk_table_new(2, 2, FALSE), TRUE, TRUE, 0);
1045
1046         gtk_table_attach(GTK_TABLE(table),
1047                          label = gtk_label_new(_("Lat, Lon")),
1048                          0, 1, 0, 1, GTK_FILL, 0, 2, 4);
1049         gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1050
1051         unit2latlon(unitx, unity, lat, lon);
1052         lat_format(lat, tmp1);
1053         lon_format(lon, tmp2);
1054         p_latlon = g_strdup_printf("%s, %s", tmp1, tmp2);
1055         gtk_table_attach(GTK_TABLE(table),
1056                          label = gtk_label_new(p_latlon),
1057                          1, 2, 0, 1, GTK_FILL, 0, 2, 4);
1058         gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
1059         g_free(p_latlon);
1060
1061         gtk_table_attach(GTK_TABLE(table),
1062                          label = gtk_label_new(_("Description")),
1063                          0, 1, 1, 2, GTK_FILL, 0, 2, 4);
1064         gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
1065
1066         txt_scroll = gtk_scrolled_window_new(NULL, NULL);
1067         gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll),
1068                                             GTK_SHADOW_IN);
1069         gtk_table_attach(GTK_TABLE(table),
1070                          txt_scroll,
1071                          1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
1072
1073         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll),
1074                                        GTK_POLICY_AUTOMATIC,
1075                                        GTK_POLICY_AUTOMATIC);
1076
1077         txt_desc = gtk_text_view_new();
1078         gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD);
1079
1080         gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc);
1081         gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 400, 60);
1082
1083         gtk_widget_show_all(dialog);
1084
1085         while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
1086                 GtkTextBuffer *tbuf;
1087                 GtkTextIter ti1, ti2;
1088                 gchar *desc;
1089
1090                 tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txt_desc));
1091                 gtk_text_buffer_get_iter_at_offset(tbuf, &ti1, 0);
1092                 gtk_text_buffer_get_end_iter(tbuf, &ti2);
1093                 desc = gtk_text_buffer_get_text(tbuf, &ti1, &ti2, TRUE);
1094
1095                 if (*desc) {
1096                         /* There's a description.  Add a waypoint. */
1097                         MACRO_PATH_INCREMENT_TAIL(_route);
1098                         _route.tail->unitx = unitx;
1099                         _route.tail->unity = unity;
1100                         _route.tail->time = 0;
1101                         _route.tail->altitude = NAN;
1102
1103                         MACRO_PATH_INCREMENT_WTAIL(_route);
1104                         _route.wtail->point = _route.tail;
1105                         _route.wtail->desc
1106                             = gtk_text_buffer_get_text(tbuf, &ti1, &ti2, TRUE);
1107                 } else {
1108                         GtkWidget *confirm;
1109
1110                         g_free(desc);
1111
1112                         confirm =
1113                             hildon_note_new_confirmation(GTK_WINDOW(dialog),
1114                                                          _
1115                                                          ("Creating a \"waypoint\" with no description actually "
1116                                                           "adds a break point.  Is that what you want?"));
1117
1118                         if (GTK_RESPONSE_OK ==
1119                             gtk_dialog_run(GTK_DIALOG(confirm))) {
1120                                 /* There's no description.  Add a break by adding a (0, 0)
1121                                  * point (if necessary), and then the ordinary route point. */
1122                                 if (_route.tail->unity) {
1123                                         MACRO_PATH_INCREMENT_TAIL(_route);
1124                                         *_route.tail = _point_null;
1125                                 }
1126
1127                                 MACRO_PATH_INCREMENT_TAIL(_route);
1128                                 _route.tail->unitx = unitx;
1129                                 _route.tail->unity = unity;
1130                                 _route.tail->time = 0;
1131                                 _route.tail->altitude = NAN;
1132
1133                                 gtk_widget_destroy(confirm);
1134                         } else {
1135                                 gtk_widget_destroy(confirm);
1136                                 continue;
1137                         }
1138                 }
1139
1140                 route_find_nearest_point();
1141                 map_render_paths();
1142                 MACRO_QUEUE_DRAW_AREA();
1143                 break;
1144         }
1145         gtk_widget_destroy(dialog);
1146         vprintf("%s(): return\n", __PRETTY_FUNCTION__);
1147 }
1148
1149 gboolean cmenu_cb_loc_show_latlon(GtkAction * action)
1150 {
1151         printf("%s()\n", __PRETTY_FUNCTION__);
1152
1153         cmenu_show_latlon(x2unit(_cmenu_position_x), y2unit(_cmenu_position_y));
1154
1155         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1156         return TRUE;
1157 }
1158
1159 gboolean cmenu_cb_loc_clip_latlon(GtkAction * action)
1160 {
1161         printf("%s()\n", __PRETTY_FUNCTION__);
1162
1163         cmenu_clip_latlon(x2unit(_cmenu_position_x), y2unit(_cmenu_position_y));
1164
1165         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1166         return TRUE;
1167 }
1168
1169 gboolean cmenu_cb_loc_route_to(GtkAction * action)
1170 {
1171         printf("%s()\n", __PRETTY_FUNCTION__);
1172
1173         cmenu_route_to(x2unit(_cmenu_position_x), y2unit(_cmenu_position_y));
1174
1175         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1176         return TRUE;
1177 }
1178
1179 gboolean cmenu_cb_loc_distance_to(GtkAction * action)
1180 {
1181         printf("%s()\n", __PRETTY_FUNCTION__);
1182
1183         cmenu_distance_to(x2unit(_cmenu_position_x), y2unit(_cmenu_position_y));
1184
1185         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1186         return TRUE;
1187 }
1188
1189 gboolean cmenu_cb_loc_add_route(GtkAction * action)
1190 {
1191         printf("%s()\n", __PRETTY_FUNCTION__);
1192
1193         cmenu_add_route(x2unit(_cmenu_position_x), y2unit(_cmenu_position_y));
1194
1195         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1196         return TRUE;
1197 }
1198
1199 gboolean cmenu_cb_loc_add_way(GtkAction * action)
1200 {
1201         printf("%s()\n", __PRETTY_FUNCTION__);
1202
1203         cmenu_route_add_way(x2unit(_cmenu_position_x),
1204                             y2unit(_cmenu_position_y));
1205
1206         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1207         return TRUE;
1208 }
1209
1210 gboolean cmenu_cb_loc_add_poi(GtkAction * action)
1211 {
1212         printf("%s()\n", __PRETTY_FUNCTION__);
1213
1214         poi_dialog(ACTION_ADD_POI,
1215                    x2unit(_cmenu_position_x), y2unit(_cmenu_position_y));
1216
1217         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1218         return TRUE;
1219 }
1220
1221 gboolean cmenu_cb_loc_set_gps(GtkAction * action)
1222 {
1223         printf("%s()\n", __PRETTY_FUNCTION__);
1224
1225         _pos.unitx = x2unit(_cmenu_position_x);
1226         _pos.unity = y2unit(_cmenu_position_y);
1227         unit2latlon(_pos.unitx, _pos.unity, _gps.lat, _gps.lon);
1228
1229         /* Move mark to new location. */
1230         refresh_mark();
1231
1232         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1233         return TRUE;
1234 }
1235
1236 gboolean cmenu_cb_way_show_latlon(GtkAction * action)
1237 {
1238         WayPoint *way;
1239         printf("%s()\n", __PRETTY_FUNCTION__);
1240
1241         if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x),
1242                                          y2unit(_cmenu_position_y))))
1243                 cmenu_show_latlon(way->point->unitx, way->point->unity);
1244
1245         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1246         return TRUE;
1247 }
1248
1249 gboolean cmenu_cb_way_show_desc(GtkAction * action)
1250 {
1251         WayPoint *way;
1252         printf("%s()\n", __PRETTY_FUNCTION__);
1253
1254         if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x),
1255                                          y2unit(_cmenu_position_y)))) {
1256                 MACRO_BANNER_SHOW_INFO(_window, way->desc);
1257         }
1258
1259         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1260         return TRUE;
1261 }
1262
1263 gboolean cmenu_cb_way_clip_latlon(GtkAction * action)
1264 {
1265         WayPoint *way;
1266         printf("%s()\n", __PRETTY_FUNCTION__);
1267
1268         if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x),
1269                                          y2unit(_cmenu_position_y))))
1270                 cmenu_clip_latlon(way->point->unitx, way->point->unity);
1271
1272         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1273         return TRUE;
1274 }
1275
1276 gboolean cmenu_cb_way_clip_desc(GtkAction * action)
1277 {
1278         WayPoint *way;
1279         printf("%s()\n", __PRETTY_FUNCTION__);
1280
1281         if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x),
1282                                          y2unit(_cmenu_position_y))))
1283                 gtk_clipboard_set_text(gtk_clipboard_get
1284                                        (GDK_SELECTION_CLIPBOARD), way->desc,
1285                                        -1);
1286
1287         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1288         return TRUE;
1289 }
1290
1291 gboolean cmenu_cb_way_route_to(GtkAction * action)
1292 {
1293         WayPoint *way;
1294         printf("%s()\n", __PRETTY_FUNCTION__);
1295
1296         if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x),
1297                                          y2unit(_cmenu_position_y))))
1298                 cmenu_route_to(way->point->unitx, way->point->unity);
1299
1300         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1301         return TRUE;
1302 }
1303
1304 gboolean cmenu_cb_way_distance_to(GtkAction * action)
1305 {
1306         WayPoint *way;
1307         printf("%s()\n", __PRETTY_FUNCTION__);
1308
1309         if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x),
1310                                          y2unit(_cmenu_position_y))))
1311                 route_show_distance_to(way->point);
1312
1313         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1314         return TRUE;
1315 }
1316
1317 gboolean cmenu_cb_way_delete(GtkAction * action)
1318 {
1319         WayPoint *way;
1320         printf("%s()\n", __PRETTY_FUNCTION__);
1321
1322         if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x),
1323                                          y2unit(_cmenu_position_y)))) {
1324                 gchar buffer[BUFFER_SIZE];
1325                 GtkWidget *confirm;
1326
1327                 snprintf(buffer, sizeof(buffer), "%s:\n%s\n",
1328                          _("Confirm delete of waypoint"), way->desc);
1329                 confirm =
1330                     hildon_note_new_confirmation(GTK_WINDOW(_window), buffer);
1331
1332                 if (GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm))) {
1333                         Point *pdel_min, *pdel_max, *pdel_start, *pdel_end;
1334                         guint num_del;
1335
1336                         /* Delete surrounding route data, too. */
1337                         if (way == _route.whead)
1338                                 pdel_min = _route.head;
1339                         else
1340                                 pdel_min = way[-1].point;
1341
1342                         if (way == _route.wtail)
1343                                 pdel_max = _route.tail;
1344                         else
1345                                 pdel_max = way[1].point;
1346
1347                         /* Find largest continuous segment around the waypoint, EXCLUDING
1348                          * pdel_min and pdel_max. */
1349                         for (pdel_start = way->point - 1; pdel_start->unity
1350                              && pdel_start > pdel_min; pdel_start--) {
1351                         }
1352                         for (pdel_end = way->point + 1; pdel_end->unity
1353                              && pdel_end < pdel_max; pdel_end++) {
1354                         }
1355
1356                         /* If pdel_end is set to _route.tail, and if _route.tail is a
1357                          * non-zero point, then delete _route.tail. */
1358                         if (pdel_end == _route.tail && pdel_end->unity)
1359                                 pdel_end++;     /* delete _route.tail too */
1360                         /* else, if *both* endpoints are zero points, delete one. */
1361                         else if (!pdel_start->unity && !pdel_end->unity)
1362                                 pdel_start--;
1363
1364                         /* Delete BETWEEN pdel_start and pdel_end, exclusive. */
1365                         num_del = pdel_end - pdel_start - 1;
1366
1367                         memmove(pdel_start + 1, pdel_end,
1368                                 (_route.tail - pdel_end + 1) * sizeof(Point));
1369                         _route.tail -= num_del;
1370
1371                         /* Remove waypoint and move/adjust subsequent waypoints. */
1372                         g_free(way->desc);
1373                         while (way++ != _route.wtail) {
1374                                 way[-1] = *way;
1375                                 way[-1].point -= num_del;
1376                         }
1377                         _route.wtail--;
1378
1379                         route_find_nearest_point();
1380                         map_force_redraw();
1381                 }
1382                 gtk_widget_destroy(confirm);
1383         }
1384
1385         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1386         return TRUE;
1387 }
1388
1389 gboolean cmenu_cb_way_add_poi(GtkAction * action)
1390 {
1391         WayPoint *way;
1392         printf("%s()\n", __PRETTY_FUNCTION__);
1393
1394         if ((way = find_nearest_waypoint(x2unit(_cmenu_position_x),
1395                                          y2unit(_cmenu_position_y))))
1396                 poi_dialog(ACTION_ADD_POI, way->point->unitx,
1397                            way->point->unity);
1398
1399         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1400         return TRUE;
1401 }
1402
1403 gboolean cmenu_cb_poi_route_to(GtkAction * action)
1404 {
1405         PoiInfo poi;
1406         printf("%s()\n", __PRETTY_FUNCTION__);
1407
1408         if (select_poi
1409             (x2unit(_cmenu_position_x), y2unit(_cmenu_position_y), &poi)) {
1410                 guint unitx, unity;
1411                 latlon2unit(poi.lat, poi.lon, unitx, unity);
1412                 cmenu_route_to(unitx, unity);
1413         }
1414
1415         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1416         return TRUE;
1417 }
1418
1419 gboolean cmenu_cb_poi_distance_to(GtkAction * action)
1420 {
1421         PoiInfo poi;
1422         printf("%s()\n", __PRETTY_FUNCTION__);
1423
1424         if (select_poi
1425             (x2unit(_cmenu_position_x), y2unit(_cmenu_position_y), &poi)) {
1426                 guint unitx, unity;
1427                 latlon2unit(poi.lat, poi.lon, unitx, unity);
1428                 cmenu_distance_to(unitx, unity);
1429         }
1430
1431         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1432         return TRUE;
1433 }
1434
1435 gboolean cmenu_cb_poi_add_route(GtkAction * action)
1436 {
1437         PoiInfo poi;
1438         printf("%s()\n", __PRETTY_FUNCTION__);
1439
1440         if (select_poi
1441             (x2unit(_cmenu_position_x), y2unit(_cmenu_position_y), &poi)) {
1442                 guint unitx, unity;
1443                 latlon2unit(poi.lat, poi.lon, unitx, unity);
1444                 cmenu_add_route(unitx, unity);
1445         }
1446
1447         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1448         return TRUE;
1449 }
1450
1451 gboolean cmenu_cb_poi_add_way(GtkAction * action)
1452 {
1453         PoiInfo poi;
1454         printf("%s()\n", __PRETTY_FUNCTION__);
1455
1456         if (select_poi
1457             (x2unit(_cmenu_position_x), y2unit(_cmenu_position_y), &poi)) {
1458                 guint unitx, unity;
1459                 latlon2unit(poi.lat, poi.lon, unitx, unity);
1460                 cmenu_route_add_way(unitx, unity);
1461         }
1462
1463         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1464         return TRUE;
1465 }
1466
1467 gboolean cmenu_cb_poi_edit_poi(GtkAction * action)
1468 {
1469         printf("%s()\n", __PRETTY_FUNCTION__);
1470
1471         poi_dialog(ACTION_EDIT_POI,
1472                    x2unit(_cmenu_position_x), y2unit(_cmenu_position_y));
1473
1474         vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__);
1475         return TRUE;
1476 }