Contents of /trunk/src/misc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 13 - (show annotations)
Sat Jun 27 11:09:19 2009 UTC (14 years, 10 months ago) by harbaum
File MIME type: text/plain
File size: 10800 byte(s)
Welcome.gpx auto load
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 #include "gpxview.h"
25
26 char strlastchr(char *str) {
27 return str[strlen(str)]-1;
28 }
29
30 /* make sure the entire path "dir" exists and create it if not */
31 int checkdir(char *dir) {
32 struct stat filestat;
33 char *p = dir, tmp;
34
35 /* don't try to create root dir */
36 if(p[0] == '/') p++;
37
38 do {
39 while(*p && *p != '/') p++;
40 tmp = *p;
41 *p = 0;
42
43 int err = stat(dir, &filestat);
44 if(err) {
45 if(mkdir(dir, S_IRWXU) != 0) {
46 perror("mkdir()");
47 *p++ = tmp;
48 return -1;
49 }
50 } else {
51 if(!filestat.st_mode & S_IFDIR) {
52 printf("File %s exists and is _no_ directory\n", dir);
53 *p++ = tmp;
54 return -1;
55 }
56 }
57
58 *p++ = tmp;
59 } while(tmp && strchr(p, '/'));
60
61 return 0;
62 }
63
64 void pos_lat_str(char *str, int len, float latitude) {
65 char *c = _("N");
66 float integral, fractional;
67
68 if(isnan(latitude))
69 str[0] = 0;
70 else {
71 if(latitude < 0) { latitude = fabs(latitude); c = _("S"); }
72 fractional = modff(latitude, &integral);
73
74 snprintf(str, len, "%s %02d° %06.3f'", c, (int)integral, fractional*60.0);
75 }
76 }
77
78 GtkWidget *pos_lat(float latitude, int size, int strikethrough) {
79 char str[32];
80
81 pos_lat_str(str, sizeof(str), latitude);
82 return gtk_label_attrib(str, size, strikethrough);
83 }
84
85 void pos_lon_str(char *str, int len, float longitude) {
86 char *c = _("E");
87 float integral, fractional;
88
89 if(isnan(longitude))
90 str[0] = 0;
91 else {
92 if(longitude < 0) { longitude = fabs(longitude); c = _("W"); }
93 fractional = modff(longitude, &integral);
94
95 snprintf(str, len, "%s %03d° %06.3f'", c, (int)integral, fractional*60.0);
96 }
97 }
98
99 GtkWidget *pos_lon(float longitude, int size, int strikethrough) {
100 char str[32];
101
102 pos_lon_str(str, sizeof(str), longitude);
103 return gtk_label_attrib(str, size, strikethrough);
104 }
105
106 float pos_parse_lat(char *str) {
107 int integral_int;
108 float fractional;
109 char c;
110
111 if(sscanf(str, "%c %d° %f'", &c, &integral_int, &fractional) == 3) {
112 c = toupper(c);
113
114 if(c != 'S' && c != 'N')
115 return NAN;
116
117 /* prevent -0.0 */
118 if(!integral_int && (fractional == 0.0))
119 return 0.0;
120
121 return ((c == 'S')?-1:+1) * (integral_int + fractional/60.0);
122 }
123
124 return NAN;
125 }
126
127 float pos_parse_lon(char *str) {
128 int integral_int;
129 float fractional;
130 char c;
131
132 if(sscanf(str, "%c %d° %f'", &c, &integral_int, &fractional) == 3) {
133 c = toupper(c);
134
135 /* O is german "Ost" for "East" */
136 if(c != 'E' && c != 'W' && c != 'O')
137 return NAN;
138
139 /* prevent -0.0 */
140 if(!integral_int && (fractional == 0.0))
141 return 0.0;
142
143 return ((c == 'W')?-1:+1) * (integral_int + fractional/60.0);
144 }
145
146 return NAN;
147 }
148
149 const char *pos_get_bearing_str(pos_t from, pos_t to) {
150 static const char *bear_str[]={
151 "N", "NE", "E", "SE", "S", "SW", "W", "NW" };
152 int idx = (gpx_pos_get_bearing(from, to)+22.5)/45.0;
153 /* make sure we stay in icon bounds */
154 while(idx < 0) idx += 8;
155 while(idx > 7) idx -= 8;
156 return _(bear_str[idx]);
157 }
158
159 /* the maemo font size is quite huge, so we adjust some fonts */
160 /* differently on maemo and non-maemo. Basically "BIG" does nothing */
161 /* on maemo and "SMALL" only does something on maemo */
162 #ifdef USE_MAEMO
163 #define MARKUP_SMALL "<span size='small'>%s</span>"
164 GtkWidget *gtk_label_small(char *str) {
165 GtkWidget *label = gtk_label_new("");
166 char *markup = g_markup_printf_escaped(MARKUP_SMALL, str);
167 gtk_label_set_markup(GTK_LABEL(label), markup);
168 g_free(markup);
169 return label;
170 }
171 #else
172 #define MARKUP_BIG "<span size='x-large'>%s</span>"
173 GtkWidget *gtk_label_big(char *str) {
174 GtkWidget *label = gtk_label_new("");
175 char *markup = g_markup_printf_escaped(MARKUP_BIG, str);
176 gtk_label_set_markup(GTK_LABEL(label), markup);
177 g_free(markup);
178 return label;
179 }
180 #endif
181
182 void gtk_label_attrib_set(GtkWidget *label,
183 char *str, int size, int strikethrough) {
184 char format[80];
185
186 snprintf(format, sizeof(format), "<span%s%s%s>%%s</span>",
187 #ifdef USE_MAEMO
188 (size==SIZE_SMALL)?" size='small'":"",
189 #else
190 (size==SIZE_BIG)?" size='x-large'":"",
191 #endif
192 strikethrough?" strikethrough='yes'":"",
193 (strikethrough==STRIKETHROUGH_RED)?" strikethrough_color='red'":"");
194
195 char *markup = g_markup_printf_escaped(format, str);
196 // printf("markup = %s\n", markup);
197 gtk_label_set_markup(GTK_LABEL(label), markup);
198 g_free(markup);
199 }
200
201 GtkWidget *gtk_label_attrib(char *str, int size, int strikethrough) {
202 GtkWidget *label = gtk_label_new("");
203 gtk_label_attrib_set(label, str, size, strikethrough);
204 return label;
205 }
206
207 GtkWidget *gtk_button_attrib(char *str, int size, int strikethrough) {
208 GtkWidget *button = gtk_button_new_with_label("");
209 gtk_label_attrib_set(gtk_bin_get_child(GTK_BIN(button)),
210 str, size, strikethrough);
211 return button;
212 }
213
214 void textbox_disable(GtkWidget *widget) {
215 gtk_editable_set_editable(GTK_EDITABLE(widget), FALSE);
216 gtk_widget_set_sensitive(widget, FALSE);
217 }
218
219 void textbox_enable(GtkWidget *widget) {
220 gtk_widget_set_sensitive(widget, TRUE);
221 gtk_editable_set_editable(GTK_EDITABLE(widget), TRUE);
222 }
223
224 pos_t *get_pos(appdata_t *appdata) {
225 pos_t *pos = &appdata->home;
226
227 if(appdata->active_location) {
228 int i = appdata->active_location-1;
229 location_t *loc = appdata->location;
230 while(i--) loc = loc->next;
231 pos = &loc->pos;
232 }
233
234 if(appdata->use_gps) {
235 pos = gps_get_pos(appdata);
236
237 if(!pos) pos = &appdata->gps; /* use saved position */
238 else appdata->gps = *pos; /* save position */
239 }
240 return pos;
241 }
242
243 void distance_str(char *str, int len, float dist, gboolean imperial) {
244 if(imperial) {
245 /* 1 mil = 1760 yd = 5280 ft ... */
246 if(dist<0.018) snprintf(str, len, "%.1f ft", dist*5280.0);
247 else if(dist<0.055) snprintf(str, len, "%.1f yd", dist*1760.0);
248 else if(dist<0.55) snprintf(str, len, "%.0f yd", dist*1760.0);
249 else if(dist<10.0) snprintf(str, len, "%.2f mi", dist);
250 else if(dist<100.0) snprintf(str, len, "%.1f mi", dist);
251 else snprintf(str, len, "%.0f mi", dist);
252 } else {
253 if(dist<0.01) snprintf(str, len, "%.2f m", dist*1000.0);
254 else if(dist<0.1) snprintf(str, len, "%.1f m", dist*1000.0);
255 else if(dist<1.0) snprintf(str, len, "%.0f m", dist*1000.0);
256 else if(dist<100.0) snprintf(str, len, "%.1f km", dist);
257 else snprintf(str, len, "%.0f km", dist);
258 }
259 }
260
261 /* return distance in miles or kilometers */
262 float distance_parse(char *str, gboolean imperial) {
263 char unit[4];
264 float val = NAN;
265
266 if(sscanf(str, "%f %3s", &val, unit) == 2) {
267 gboolean fimp = FALSE;
268
269 if(strcasecmp(unit, "ft") == 0) { fimp = TRUE; val /= 5280.0; }
270 else if(strcasecmp(unit, "yd") == 0) { fimp = TRUE; val /= 1760.0; }
271 else if(strcasecmp(unit, "mi") == 0) { fimp = TRUE; }
272 else if(strcasecmp(unit, "m") == 0) { fimp = FALSE; val /= 1000.0; }
273 else if(strcasecmp(unit, "km") == 0) { fimp = FALSE; }
274 else val = NAN;
275
276 /* found imperial and metric requested? convert miles into kilometers */
277 if(fimp & !imperial) val *= 1.609344;
278
279 /* found metric and imperial requested? convert kilometers into miles */
280 if(!fimp & imperial) val /= 1.609344;
281 }
282 return val;
283 }
284
285 static gboolean mark(GtkWidget *widget, gboolean valid) {
286 gtk_widget_set_state(widget, valid?GTK_STATE_NORMAL:TAG_STATE);
287 return valid;
288 }
289
290 static void callback_modified_lat(GtkWidget *widget, gpointer data ) {
291 float i = pos_parse_lat((char*)gtk_entry_get_text(GTK_ENTRY(widget)));
292 mark(widget, !isnan(i));
293 }
294
295 /* a entry that is colored red when being "active" */
296 GtkWidget *lat_entry_new(float lat) {
297 GdkColor color;
298 GtkWidget *widget = gtk_entry_new();
299 gdk_color_parse("#ff0000", &color);
300 gtk_widget_modify_text(widget, TAG_STATE, &color);
301
302 char str[32];
303 pos_lat_str(str, sizeof(str), lat);
304 gtk_entry_set_text(GTK_ENTRY(widget), str);
305
306 g_signal_connect(G_OBJECT(widget), "changed",
307 G_CALLBACK(callback_modified_lat), NULL);
308
309 return widget;
310 }
311
312 static void callback_modified_lon(GtkWidget *widget, gpointer data ) {
313 float i = pos_parse_lon((char*)gtk_entry_get_text(GTK_ENTRY(widget)));
314 mark(widget, !isnan(i));
315 }
316
317 /* a entry that is colored red when filled with invalid coordinate */
318 GtkWidget *lon_entry_new(float lon) {
319 GdkColor color;
320 GtkWidget *widget = gtk_entry_new();
321 gdk_color_parse("#ff0000", &color);
322 gtk_widget_modify_text(widget, TAG_STATE, &color);
323
324 char str[32];
325 pos_lon_str(str, sizeof(str), lon);
326 gtk_entry_set_text(GTK_ENTRY(widget), str);
327
328 g_signal_connect(G_OBJECT(widget), "changed",
329 G_CALLBACK(callback_modified_lon), NULL);
330
331 return widget;
332 }
333
334
335 float lat_get(GtkWidget *widget) {
336 char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
337 return pos_parse_lat(p);
338 }
339
340 float lon_get(GtkWidget *widget) {
341 char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
342 return pos_parse_lon(p);
343 }
344
345 static void callback_modified_dist(GtkWidget *widget, gpointer data ) {
346 /* don't care for metric/imperial since we only want to know if this */
347 /* is parseable at all */
348 float i = distance_parse((char*)gtk_entry_get_text(GTK_ENTRY(widget)), FALSE);
349 mark(widget, !isnan(i));
350 }
351
352 /* a entry that is colored red when filled with invalid distance */
353 GtkWidget *dist_entry_new(float dist, gboolean mil) {
354 GdkColor color;
355 GtkWidget *widget = gtk_entry_new();
356 gdk_color_parse("#ff0000", &color);
357 gtk_widget_modify_text(widget, TAG_STATE, &color);
358
359 char str[32];
360 distance_str(str, sizeof(str), dist, mil);
361 gtk_entry_set_text(GTK_ENTRY(widget), str);
362
363 g_signal_connect(G_OBJECT(widget), "changed",
364 G_CALLBACK(callback_modified_dist), NULL);
365
366 return widget;
367 }
368
369 float dist_get(GtkWidget *widget, gboolean mil) {
370 char *p = (char*)gtk_entry_get_text(GTK_ENTRY(widget));
371 return distance_parse(p, mil);
372 }
373
374 #ifndef USE_MAEMO
375 #ifdef ENABLE_BROWSER_INTERFACE
376 #include <libgnome/gnome-url.h>
377
378 int browser_url(appdata_t *appdata, char *url) {
379 /* taken from gnome-open, part of libgnome */
380 GError *err = NULL;
381 gnome_url_show(url, &err);
382 return 0;
383 }
384 #endif
385 #endif