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