Contents of /trunk/src/misc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 213 - (hide annotations)
Wed Nov 25 20:19:32 2009 UTC (14 years, 5 months ago) by harbaum
File MIME type: text/plain
File size: 19968 byte(s)
Position tool icon work
1 harbaum 1 /*
2     * Copyright (C) 2008 Till Harbaum <till@harbaum.org>.
3     *
4     * This file is part of GPXView.
5     *
6     * GPXView is free software: you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation, either version 3 of the License, or
9     * (at your option) any later version.
10     *
11     * GPXView is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with GPXView. If not, see <http://www.gnu.org/licenses/>.
18     */
19    
20     #include <math.h>
21     #include <string.h>
22     #include <ctype.h>
23    
24 harbaum 77 #include <glib.h>
25     #include <glib/gstdio.h>
26    
27 harbaum 1 #include "gpxview.h"
28    
29 harbaum 190 #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR >= 5)
30     #include <hildon/hildon-entry.h>
31     #endif
32    
33 harbaum 1 char strlastchr(char *str) {
34     return str[strlen(str)]-1;
35     }
36    
37     /* make sure the entire path "dir" exists and create it if not */
38     int checkdir(char *dir) {
39     struct stat filestat;
40     char *p = dir, tmp;
41    
42     /* don't try to create root dir */
43     if(p[0] == '/') p++;
44    
45     do {
46     while(*p && *p != '/') p++;
47     tmp = *p;
48     *p = 0;
49    
50     int err = stat(dir, &filestat);
51     if(err) {
52     if(mkdir(dir, S_IRWXU) != 0) {
53     perror("mkdir()");
54     *p++ = tmp;
55     return -1;
56     }
57     } else {
58     if(!filestat.st_mode & S_IFDIR) {
59     printf("File %s exists and is _no_ directory\n", dir);
60     *p++ = tmp;
61     return -1;
62     }
63     }
64    
65     *p++ = tmp;
66     } while(tmp && strchr(p, '/'));
67    
68     return 0;
69     }
70    
71     void pos_lat_str(char *str, int len, float latitude) {
72     char *c = _("N");
73     float integral, fractional;
74    
75 harbaum 13 if(isnan(latitude))
76     str[0] = 0;
77     else {
78     if(latitude < 0) { latitude = fabs(latitude); c = _("S"); }
79     fractional = modff(latitude, &integral);
80 harbaum 1
81 harbaum 13 snprintf(str, len, "%s %02d° %06.3f'", c, (int)integral, fractional*60.0);
82     }
83 harbaum 1 }
84    
85     GtkWidget *pos_lat(float latitude, int size, int strikethrough) {
86     char str[32];
87    
88     pos_lat_str(str, sizeof(str), latitude);
89     return gtk_label_attrib(str, size, strikethrough);
90     }
91    
92     void pos_lon_str(char *str, int len, float longitude) {
93     char *c = _("E");
94     float integral, fractional;
95    
96 harbaum 13 if(isnan(longitude))
97     str[0] = 0;
98     else {
99     if(longitude < 0) { longitude = fabs(longitude); c = _("W"); }
100     fractional = modff(longitude, &integral);
101 harbaum 1
102 harbaum 13 snprintf(str, len, "%s %03d° %06.3f'", c, (int)integral, fractional*60.0);
103     }
104 harbaum 1 }
105    
106     GtkWidget *pos_lon(float longitude, int size, int strikethrough) {
107     char str[32];
108    
109     pos_lon_str(str, sizeof(str), longitude);
110     return gtk_label_attrib(str, size, strikethrough);
111     }
112    
113     float pos_parse_lat(char *str) {
114     int integral_int;
115     float fractional;
116     char c;
117    
118     if(sscanf(str, "%c %d° %f'", &c, &integral_int, &fractional) == 3) {
119     c = toupper(c);
120    
121     if(c != 'S' && c != 'N')
122     return NAN;
123    
124     /* prevent -0.0 */
125     if(!integral_int && (fractional == 0.0))
126     return 0.0;
127    
128     return ((c == 'S')?-1:+1) * (integral_int + fractional/60.0);
129     }
130    
131     return NAN;
132     }
133    
134     float pos_parse_lon(char *str) {
135     int integral_int;
136     float fractional;
137     char c;
138    
139     if(sscanf(str, "%c %d° %f'", &c, &integral_int, &fractional) == 3) {
140     c = toupper(c);
141    
142     /* O is german "Ost" for "East" */
143     if(c != 'E' && c != 'W' && c != 'O')
144     return NAN;
145    
146     /* prevent -0.0 */
147     if(!integral_int && (fractional == 0.0))
148     return 0.0;
149    
150     return ((c == 'W')?-1:+1) * (integral_int + fractional/60.0);
151     }
152    
153     return NAN;
154     }
155    
156     const char *pos_get_bearing_str(pos_t from, pos_t to) {
157     static const char *bear_str[]={
158 harbaum 185 "N", "NE", "E", "SE", "S", "SW", "W", "NW", "" };
159    
160     float bearing = gpx_pos_get_bearing(from, to);
161     if(!isnan(bearing)) {
162     int idx = (bearing+22.5)/45.0;
163     /* make sure we stay in icon bounds */
164     while(idx < 0) idx += 8;
165     while(idx > 7) idx -= 8;
166     return _(bear_str[idx]);
167     }
168    
169     return bear_str[8]; // empty string
170 harbaum 1 }
171    
172     /* the maemo font size is quite huge, so we adjust some fonts */
173     /* differently on maemo and non-maemo. Basically "BIG" does nothing */
174     /* on maemo and "SMALL" only does something on maemo */
175     #ifdef USE_MAEMO
176     #define MARKUP_SMALL "<span size='small'>%s</span>"
177     GtkWidget *gtk_label_small(char *str) {
178     GtkWidget *label = gtk_label_new("");
179     char *markup = g_markup_printf_escaped(MARKUP_SMALL, str);
180     gtk_label_set_markup(GTK_LABEL(label), markup);
181     g_free(markup);
182     return label;
183     }
184     #else
185     #define MARKUP_BIG "<span size='x-large'>%s</span>"
186     GtkWidget *gtk_label_big(char *str) {
187     GtkWidget *label = gtk_label_new("");
188     char *markup = g_markup_printf_escaped(MARKUP_BIG, str);
189     gtk_label_set_markup(GTK_LABEL(label), markup);
190     g_free(markup);
191     return label;
192     }
193     #endif
194    
195     void gtk_label_attrib_set(GtkWidget *label,
196     char *str, int size, int strikethrough) {
197     char format[80];
198    
199     snprintf(format, sizeof(format), "<span%s%s%s>%%s</span>",
200     #ifdef USE_MAEMO
201     (size==SIZE_SMALL)?" size='small'":"",
202     #else
203     (size==SIZE_BIG)?" size='x-large'":"",
204     #endif
205     strikethrough?" strikethrough='yes'":"",
206     (strikethrough==STRIKETHROUGH_RED)?" strikethrough_color='red'":"");
207    
208     char *markup = g_markup_printf_escaped(format, str);
209     // printf("markup = %s\n", markup);
210     gtk_label_set_markup(GTK_LABEL(label), markup);
211     g_free(markup);
212     }
213    
214     GtkWidget *gtk_label_attrib(char *str, int size, int strikethrough) {
215     GtkWidget *label = gtk_label_new("");
216     gtk_label_attrib_set(label, str, size, strikethrough);
217     return label;
218     }
219    
220     GtkWidget *gtk_button_attrib(char *str, int size, int strikethrough) {
221     GtkWidget *button = gtk_button_new_with_label("");
222     gtk_label_attrib_set(gtk_bin_get_child(GTK_BIN(button)),
223     str, size, strikethrough);
224     return button;
225     }
226    
227     void textbox_disable(GtkWidget *widget) {
228     gtk_editable_set_editable(GTK_EDITABLE(widget), FALSE);
229     gtk_widget_set_sensitive(widget, FALSE);
230     }
231    
232     void textbox_enable(GtkWidget *widget) {
233     gtk_widget_set_sensitive(widget, TRUE);
234     gtk_editable_set_editable(GTK_EDITABLE(widget), TRUE);
235     }
236    
237     pos_t *get_pos(appdata_t *appdata) {
238     pos_t *pos = &appdata->home;
239    
240     if(appdata->active_location) {
241     int i = appdata->active_location-1;
242     location_t *loc = appdata->location;
243     while(i--) loc = loc->next;
244     pos = &loc->pos;
245     }
246    
247     if(appdata->use_gps) {
248     pos = gps_get_pos(appdata);
249    
250     if(!pos) pos = &appdata->gps; /* use saved position */
251     else appdata->gps = *pos; /* save position */
252     }
253     return pos;
254     }
255    
256     void distance_str(char *str, int len, float dist, gboolean imperial) {
257 harbaum 34 if(isnan(dist))
258     snprintf(str, len, "---");
259     else if(imperial) {
260 harbaum 1 /* 1 mil = 1760 yd = 5280 ft ... */
261     if(dist<0.018) snprintf(str, len, "%.1f ft", dist*5280.0);
262     else if(dist<0.055) snprintf(str, len, "%.1f yd", dist*1760.0);
263     else if(dist<0.55) snprintf(str, len, "%.0f yd", dist*1760.0);
264     else if(dist<10.0) snprintf(str, len, "%.2f mi", dist);
265     else if(dist<100.0) snprintf(str, len, "%.1f mi", dist);
266     else snprintf(str, len, "%.0f mi", dist);
267     } else {
268     if(dist<0.01) snprintf(str, len, "%.2f m", dist*1000.0);
269     else if(dist<0.1) snprintf(str, len, "%.1f m", dist*1000.0);
270     else if(dist<1.0) snprintf(str, len, "%.0f m", dist*1000.0);
271     else if(dist<100.0) snprintf(str, len, "%.1f km", dist);
272     else snprintf(str, len, "%.0f km", dist);
273     }
274     }
275    
276     /* return distance in miles or kilometers */
277     float distance_parse(char *str, gboolean imperial) {
278     char unit[4];
279     float val = NAN;
280    
281     if(sscanf(str, "%f %3s", &val, unit) == 2) {
282     gboolean fimp = FALSE;
283    
284     if(strcasecmp(unit, "ft") == 0) { fimp = TRUE; val /= 5280.0; }
285     else if(strcasecmp(unit, "yd") == 0) { fimp = TRUE; val /= 1760.0; }
286     else if(strcasecmp(unit, "mi") == 0) { fimp = TRUE; }
287     else if(strcasecmp(unit, "m") == 0) { fimp = FALSE; val /= 1000.0; }
288     else if(strcasecmp(unit, "km") == 0) { fimp = FALSE; }
289     else val = NAN;
290    
291     /* found imperial and metric requested? convert miles into kilometers */
292     if(fimp & !imperial) val *= 1.609344;
293    
294     /* found metric and imperial requested? convert kilometers into miles */
295     if(!fimp & imperial) val /= 1.609344;
296     }
297     return val;
298     }
299    
300     static gboolean mark(GtkWidget *widget, gboolean valid) {
301     gtk_widget_set_state(widget, valid?GTK_STATE_NORMAL:TAG_STATE);
302     return valid;
303     }
304    
305     static void callback_modified_lat(GtkWidget *widget, gpointer data ) {
306     float i = pos_parse_lat((char*)gtk_entry_get_text(GTK_ENTRY(widget)));
307     mark(widget, !isnan(i));
308     }
309    
310     /* a entry that is colored red when being "active" */
311     GtkWidget *lat_entry_new(float lat) {
312     GdkColor color;
313 harbaum 190
314 harbaum 212 GtkWidget *widget = entry_new();
315 harbaum 1 gdk_color_parse("#ff0000", &color);
316     gtk_widget_modify_text(widget, TAG_STATE, &color);
317    
318     char str[32];
319     pos_lat_str(str, sizeof(str), lat);
320     gtk_entry_set_text(GTK_ENTRY(widget), str);
321    
322     g_signal_connect(G_OBJECT(widget), "changed",
323     G_CALLBACK(callback_modified_lat), NULL);
324    
325     return widget;
326     }
327    
328     static void callback_modified_lon(GtkWidget *widget, gpointer data ) {
329     float i = pos_parse_lon((char*)gtk_entry_get_text(GTK_ENTRY(widget)));
330     mark(widget, !isnan(i));
331     }
332    
333     /* a entry that is colored red when filled with invalid coordinate */
334     GtkWidget *lon_entry_new(float lon) {
335     GdkColor color;
336 harbaum 190
337 harbaum 212 GtkWidget *widget = entry_new();
338 harbaum 190 // gtk_entry_set_width_chars(GTK_ENTRY(widget), 14);
339    
340 harbaum 1 gdk_color_parse("#ff0000", &color);
341     gtk_widget_modify_text(widget, TAG_STATE, &color);
342    
343     char str[32];
344     pos_lon_str(str, sizeof(str), lon);
345     gtk_entry_set_text(GTK_ENTRY(widget), str);
346    
347     g_signal_connect(G_OBJECT(widget), "changed",
348     G_CALLBACK(callback_modified_lon), NULL);
349    
350     return widget;
351     }
352    
353    
354     float lat_get(GtkWidget *widget) {
355     char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
356     return pos_parse_lat(p);
357     }
358    
359     float lon_get(GtkWidget *widget) {
360     char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
361     return pos_parse_lon(p);
362     }
363    
364     static void callback_modified_dist(GtkWidget *widget, gpointer data ) {
365     /* don't care for metric/imperial since we only want to know if this */
366     /* is parseable at all */
367     float i = distance_parse((char*)gtk_entry_get_text(GTK_ENTRY(widget)), FALSE);
368     mark(widget, !isnan(i));
369     }
370    
371     /* a entry that is colored red when filled with invalid distance */
372     GtkWidget *dist_entry_new(float dist, gboolean mil) {
373     GdkColor color;
374 harbaum 212 GtkWidget *widget = entry_new();
375 harbaum 1 gdk_color_parse("#ff0000", &color);
376     gtk_widget_modify_text(widget, TAG_STATE, &color);
377    
378     char str[32];
379     distance_str(str, sizeof(str), dist, mil);
380     gtk_entry_set_text(GTK_ENTRY(widget), str);
381    
382     g_signal_connect(G_OBJECT(widget), "changed",
383     G_CALLBACK(callback_modified_dist), NULL);
384    
385     return widget;
386     }
387    
388     float dist_get(GtkWidget *widget, gboolean mil) {
389     char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
390     return distance_parse(p, mil);
391     }
392    
393     #ifndef USE_MAEMO
394     #ifdef ENABLE_BROWSER_INTERFACE
395     #include <libgnome/gnome-url.h>
396    
397     int browser_url(appdata_t *appdata, char *url) {
398     /* taken from gnome-open, part of libgnome */
399     GError *err = NULL;
400     gnome_url_show(url, &err);
401     return 0;
402     }
403     #endif
404     #endif
405 harbaum 77
406     /* recursively remove an entire file system */
407     void rmdir_recursive(char *path) {
408     GDir *dir = g_dir_open(path, 0, NULL);
409     if(dir) {
410     const char *name = g_dir_read_name(dir);
411     while(name) {
412     char *fullname = g_strdup_printf("%s/%s", path, name);
413     // printf("deleting %s\n", fullname);
414    
415     if(g_file_test(fullname, G_FILE_TEST_IS_DIR))
416     rmdir_recursive(fullname);
417     else if(g_file_test(fullname, G_FILE_TEST_IS_REGULAR))
418     g_remove(fullname);
419    
420     g_free(fullname);
421     name = g_dir_read_name(dir);
422     }
423    
424     g_dir_close(dir);
425     }
426     g_rmdir(path);
427     }
428    
429 harbaum 137 #ifdef ENABLE_BROWSER_INTERFACE
430     static void on_link_clicked(GtkButton *button, gpointer data) {
431     appdata_t *appdata = (appdata_t*)data;
432     char *url = g_object_get_data(G_OBJECT(button), "url");
433     if(url) browser_url(appdata, url);
434     }
435     #endif
436    
437     /* a button containing a weblink */
438     GtkWidget *link_button_attrib(appdata_t *appdata, char *str, char *url,
439     int size, int strikethrough) {
440    
441     #ifdef ENABLE_BROWSER_INTERFACE
442     if(url) {
443     GtkWidget *button = gtk_button_attrib(str, size, strikethrough);
444     g_object_set_data(G_OBJECT(button), "url", url);
445     gtk_signal_connect(GTK_OBJECT(button), "clicked",
446     (GtkSignalFunc)on_link_clicked, appdata);
447    
448     return button;
449     }
450     #endif
451     return gtk_label_attrib(str, size, strikethrough);
452     }
453    
454     #ifdef ENABLE_BROWSER_INTERFACE
455     static void on_link_id_clicked(GtkButton *button, gpointer data) {
456     appdata_t *appdata = (appdata_t*)data;
457    
458     unsigned int id = (unsigned int)g_object_get_data(G_OBJECT(button), "id");
459     char *type = g_object_get_data(G_OBJECT(button), "type");
460    
461     char *url = g_strdup_printf("http://www.geocaching.com/%s?id=%u",
462     type, id);
463    
464     if(url) {
465     browser_url(appdata, url);
466     g_free(url);
467     }
468     }
469     #endif
470    
471     GtkWidget *link_button_by_id(appdata_t *appdata, char *str,
472     const char *type, int id) {
473    
474     #ifdef ENABLE_BROWSER_INTERFACE
475     if(id) {
476     GtkWidget *ref = gtk_button_new_with_label(str);
477     #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
478     // hildon_gtk_widget_set_theme_size(ref,
479     // (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
480     #endif
481     g_object_set_data(G_OBJECT(ref), "id", (gpointer)id);
482     g_object_set_data(G_OBJECT(ref), "type", (gpointer)type);
483     gtk_signal_connect(GTK_OBJECT(ref), "clicked",
484     GTK_SIGNAL_FUNC(on_link_id_clicked), appdata);
485    
486     return ref;
487     }
488     #endif
489     return gtk_label_new(str);
490     }
491    
492 harbaum 138
493     GtkWidget *link_icon_button_by_id(appdata_t *appdata, GtkWidget *icon,
494     const char *type, int id) {
495    
496     #ifdef ENABLE_BROWSER_INTERFACE
497     if(id) {
498     GtkWidget *ref = gtk_button_new();
499     gtk_button_set_image(GTK_BUTTON(ref), icon);
500    
501     #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
502     // hildon_gtk_widget_set_theme_size(ref,
503     // (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
504     #endif
505     g_object_set_data(G_OBJECT(ref), "id", (gpointer)id);
506     g_object_set_data(G_OBJECT(ref), "type", (gpointer)type);
507     gtk_signal_connect(GTK_OBJECT(ref), "clicked",
508     GTK_SIGNAL_FUNC(on_link_id_clicked), appdata);
509    
510     return ref;
511     }
512     #endif
513     return icon;
514     }
515    
516 harbaum 165 /* left aligned, word wrapped multiline widget */
517     GtkWidget *simple_text_widget(char *text) {
518     GtkWidget *label = gtk_label_new(text);
519    
520     gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
521     gtk_label_set_line_wrap_mode(GTK_LABEL(label), PANGO_WRAP_WORD);
522     gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
523    
524     return label;
525     }
526 harbaum 198
527    
528     /* a label that is left aligned */
529     GtkWidget *left_label_new(char *str) {
530     GtkWidget *widget = gtk_label_new(str);
531     gtk_misc_set_alignment(GTK_MISC(widget), 0.0f, 0.5f);
532     return widget;
533     }
534 harbaum 212
535     static void pos_set(GtkMenuItem *item, float lat, float lon) {
536     char str[32];
537    
538     pos_lat_str(str, sizeof(str)-1, lat);
539     GtkWidget *lat_entry = g_object_get_data(G_OBJECT(item), "lat_entry");
540     gtk_entry_set_text(GTK_ENTRY(lat_entry), str);
541    
542     pos_lon_str(str, sizeof(str)-1, lon);
543     GtkWidget *lon_entry = g_object_get_data(G_OBJECT(item), "lon_entry");
544     gtk_entry_set_text(GTK_ENTRY(lon_entry), str);
545     }
546    
547     static void cb_gps(GtkMenuItem *item, gpointer data) {
548     appdata_t *appdata = (appdata_t*)data;
549    
550     pos_t *refpos = get_pos(appdata);
551     if(!refpos) pos_set(item, NAN, NAN);
552     else pos_set(item, refpos->lat, refpos->lon);
553     }
554    
555     static void cb_geomath(GtkMenuItem *item, gpointer data) {
556     appdata_t *appdata = (appdata_t*)data;
557    
558     pos_set(item, appdata->geomath.lat, appdata->geomath.lon);
559     }
560    
561     #ifdef ENABLE_OSM_GPS_MAP
562     static void cb_map(GtkMenuItem *item, gpointer data) {
563     appdata_t *appdata = (appdata_t*)data;
564    
565     pos_set(item, appdata->map.pos.lat, appdata->map.pos.lon);
566     }
567     #endif
568    
569     static const gchar *menu_item_get_label(GtkMenuItem *menu_item) {
570     GList *children, *l;
571     GtkWidget *child;
572     children = gtk_container_get_children (GTK_CONTAINER (menu_item));
573     for (l = g_list_first (children); l != NULL;
574     l = g_list_next (l)) {
575     child = (GtkWidget *)l->data;
576     if (GTK_IS_LABEL (child)) {
577     return gtk_label_get_label (GTK_LABEL (child));
578     }
579     }
580     return NULL;
581     }
582    
583     static void cb_cache(GtkMenuItem *item, gpointer data) {
584     const char *label = menu_item_get_label(item);
585     appdata_t *appdata = (appdata_t*)data;
586    
587     cache_t *cache = appdata->cur_cache;
588     g_assert(cache);
589    
590     if(!strcmp(label, cache->id))
591     pos_set(item, cache->pos.lat, cache->pos.lon);
592     else {
593     wpt_t *wpt = cache->wpt;
594     while(wpt) {
595     if(!strcmp(label, wpt->id)) {
596     pos_set(item, wpt->pos.lat, wpt->pos.lon);
597     return;
598     }
599    
600     wpt = wpt->next;
601     }
602     }
603     }
604    
605     static GtkWidget *menu_add(GtkWidget *menu, appdata_t *appdata,
606     GtkWidget *icon, char *menu_str,
607     void(*func)(GtkMenuItem*, gpointer),
608     GtkWidget *lon_entry, GtkWidget *lat_entry) {
609    
610     GtkWidget *item = gtk_image_menu_item_new_with_label(menu_str);
611    
612     if(icon)
613     gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), icon);
614    
615     g_object_set_data(G_OBJECT(item), "lat_entry", (gpointer)lat_entry);
616     g_object_set_data(G_OBJECT(item), "lon_entry", (gpointer)lon_entry);
617    
618     if(func)
619     gtk_signal_connect(GTK_OBJECT(item), "activate",
620     (GtkSignalFunc)func, appdata);
621    
622     gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
623    
624     return item;
625     }
626    
627     static GtkWidget *popup_menu_create(appdata_t *appdata,
628     GtkWidget *lat_entry, GtkWidget *lon_entry) {
629     GtkWidget *menu = gtk_menu_new();
630    
631 harbaum 213 menu_add(menu, appdata, icon_get_widget(ICON_POS, 7),
632     _("Current position (GPS)"), cb_gps, lon_entry, lat_entry);
633 harbaum 212 menu_add(menu, appdata, NULL, _("Geomath projection"),
634     cb_geomath, lon_entry, lat_entry);
635     #ifdef ENABLE_OSM_GPS_MAP
636     menu_add(menu, appdata, NULL, _("Map position"),
637     cb_map, lon_entry, lat_entry);
638     #endif
639    
640     if(appdata->cur_cache) {
641     cache_t *cache = appdata->cur_cache;
642    
643     if(!isnan(cache->pos.lat) && !isnan(cache->pos.lon)) {
644     menu_add(menu, appdata, icon_get_widget(ICON_CACHE_TYPE, cache->type),
645     cache->id, cb_cache, lon_entry, lat_entry);
646     }
647    
648     printf("appending cache waypoints\n");
649     wpt_t *wpt = cache->wpt;
650     while(wpt) {
651     GtkWidget *icon = NULL;
652     if(wpt->sym != WPT_SYM_UNKNOWN)
653 harbaum 213 icon = icon_get_widget(ICON_POS, wpt->sym);
654 harbaum 212
655     menu_add(menu, appdata, icon, wpt->id, cb_cache,
656     lon_entry, lat_entry);
657    
658     wpt = wpt->next;
659     }
660     }
661    
662     gtk_widget_show_all(menu);
663    
664     return menu;
665     }
666    
667     static gint on_popup_button_press(GtkWidget *button, GdkEventButton *event,
668     gpointer data) {
669    
670     if(event->type == GDK_BUTTON_PRESS) {
671     GtkWidget *menu = g_object_get_data(G_OBJECT(button), "menu");
672    
673     /* draw a popup menu */
674     gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL,
675     event->button, event->time);
676     return TRUE;
677     }
678     return FALSE;
679     }
680    
681     static void on_popup_destroy(GtkWidget *widget, gpointer user_data ) {
682     GtkWidget *menu = g_object_get_data(G_OBJECT(widget), "menu");
683     gtk_widget_destroy(menu);
684     }
685    
686     GtkWidget *coo_popup(appdata_t *appdata,
687     GtkWidget *lat_entry, GtkWidget *lon_entry) {
688    
689     GtkWidget *button = gtk_button_new();
690     #ifdef FREMANTLE
691     hildon_gtk_widget_set_theme_size(button,
692     (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
693     #endif
694    
695 harbaum 213 gtk_button_set_image(GTK_BUTTON(button), icon_get_widget(ICON_POS, 6));
696 harbaum 212
697     gtk_widget_set_tooltip_text(button, _("Preset coordinates"));
698    
699     gtk_signal_connect(GTK_OBJECT(button), "button-press-event",
700     (GtkSignalFunc)on_popup_button_press, appdata);
701    
702     gtk_signal_connect(GTK_OBJECT(button), "destroy",
703     (GtkSignalFunc)on_popup_destroy, appdata);
704    
705     g_object_set_data(G_OBJECT(button), "menu",
706     popup_menu_create(appdata, lat_entry, lon_entry));
707    
708     return button;
709     }
710    
711     GtkWidget *entry_new(void) {
712     #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)
713     return gtk_entry_new();
714     #else
715     return hildon_entry_new(HILDON_SIZE_AUTO);
716     #endif
717     }