~jelmer/viking/brz

« back to all changes in this revision

Viewing changes to src/vikwebtool_datasource.c

  • Committer: Rob Norris
  • Date: 2018-05-13 15:31:57 UTC
  • Revision ID: git-v1:05e677f014a67de166e8e020f7625d9b0cec41f9
Need to redraw after track segment merge.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2
 
/*
3
 
 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4
 
 *
5
 
 * Copyright (C) 2013-2015, Rob Norris <rw_norris@hotmail.com>
6
 
 *
7
 
 * This program is free software; you can redistribute it and/or modify
8
 
 * it under the terms of the GNU General Public License as published by
9
 
 * the Free Software Foundation; either version 2 of the License, or
10
 
 * (at your option) any later version.
11
 
 *
12
 
 * This program is distributed in the hope that it will be useful,
13
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 * GNU General Public License for more details.
16
 
 *
17
 
 * You should have received a copy of the GNU General Public License
18
 
 * along with this program; if not, write to the Free Software
19
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 
 *
21
 
 */
22
 
 
23
 
#ifdef HAVE_CONFIG_H
24
 
#include "config.h"
25
 
#endif
26
 
 
27
 
#include "vikwebtool_datasource.h"
28
 
#include <ctype.h>
29
 
#include <string.h>
30
 
 
31
 
#include <glib.h>
32
 
#include <glib/gi18n.h>
33
 
 
34
 
#include "globals.h"
35
 
#include "acquire.h"
36
 
#include "maputils.h"
37
 
#include "dialog.h"
38
 
 
39
 
static GObjectClass *parent_class;
40
 
static GHashTable *last_user_strings = NULL;
41
 
 
42
 
static void webtool_datasource_finalize ( GObject *gob );
43
 
 
44
 
static gchar *webtool_datasource_get_url ( VikWebtool *self, VikWindow *vw );
45
 
 
46
 
static gboolean webtool_needs_user_string ( VikWebtool *self );
47
 
 
48
 
typedef struct _VikWebtoolDatasourcePrivate VikWebtoolDatasourcePrivate;
49
 
 
50
 
struct _VikWebtoolDatasourcePrivate
51
 
{
52
 
        gchar *url;
53
 
        gchar *url_format_code;
54
 
        gchar *file_type;
55
 
        gchar *babel_filter_args;
56
 
    gchar *input_label;
57
 
        gchar *user_string;
58
 
};
59
 
 
60
 
#define WEBTOOL_DATASOURCE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
61
 
                                           VIK_WEBTOOL_DATASOURCE_TYPE,      \
62
 
                                           VikWebtoolDatasourcePrivate))
63
 
 
64
 
G_DEFINE_TYPE (VikWebtoolDatasource, vik_webtool_datasource, VIK_WEBTOOL_TYPE)
65
 
 
66
 
enum
67
 
{
68
 
        PROP_0,
69
 
        PROP_URL,
70
 
        PROP_URL_FORMAT_CODE,
71
 
        PROP_FILE_TYPE,
72
 
        PROP_BABEL_FILTER_ARGS,
73
 
    PROP_INPUT_LABEL
74
 
};
75
 
 
76
 
static void webtool_datasource_set_property (GObject      *object,
77
 
                                             guint         property_id,
78
 
                                             const GValue *value,
79
 
                                             GParamSpec   *pspec)
80
 
{
81
 
        VikWebtoolDatasource *self = VIK_WEBTOOL_DATASOURCE ( object );
82
 
        VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( self );
83
 
 
84
 
        switch ( property_id ) {
85
 
        
86
 
    case PROP_URL:
87
 
                g_free ( priv->url );
88
 
                priv->url = g_value_dup_string ( value );
89
 
                g_debug ( "VikWebtoolDatasource.url: %s", priv->url );
90
 
                break;
91
 
 
92
 
        case PROP_URL_FORMAT_CODE:
93
 
                g_free ( priv->url_format_code );
94
 
                priv->url_format_code = g_value_dup_string ( value );
95
 
                g_debug ( "VikWebtoolDatasource.url_format_code: %s", priv->url_format_code );
96
 
                break;
97
 
 
98
 
        case PROP_FILE_TYPE:
99
 
                g_free ( priv->file_type );
100
 
                priv->file_type = g_value_dup_string ( value );
101
 
                g_debug ( "VikWebtoolDatasource.file_type: %s", priv->url_format_code );
102
 
                break;
103
 
 
104
 
        case PROP_BABEL_FILTER_ARGS:
105
 
                g_free ( priv->babel_filter_args );
106
 
                priv->babel_filter_args = g_value_dup_string ( value );
107
 
                g_debug ( "VikWebtoolDatasource.babel_filter_args: %s", priv->babel_filter_args );
108
 
                break;
109
 
 
110
 
    case PROP_INPUT_LABEL:
111
 
                g_free ( priv->input_label );
112
 
                priv->input_label = g_value_dup_string ( value );
113
 
                g_debug ( "VikWebtoolDatasource.input_label: %s", priv->input_label );
114
 
                break;
115
 
 
116
 
        default:
117
 
                /* We don't have any other property... */
118
 
                G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, property_id, pspec );
119
 
                break;
120
 
        }
121
 
}
122
 
 
123
 
static void webtool_datasource_get_property (GObject    *object,
124
 
                                             guint       property_id,
125
 
                                             GValue     *value,
126
 
                                             GParamSpec *pspec)
127
 
{
128
 
        VikWebtoolDatasource *self = VIK_WEBTOOL_DATASOURCE ( object );
129
 
        VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( self );
130
 
 
131
 
        switch ( property_id ) {
132
 
 
133
 
        case PROP_URL:               g_value_set_string ( value, priv->url ); break;
134
 
        case PROP_URL_FORMAT_CODE:       g_value_set_string ( value, priv->url_format_code ); break;
135
 
        case PROP_FILE_TYPE:         g_value_set_string ( value, priv->url ); break;
136
 
        case PROP_BABEL_FILTER_ARGS: g_value_set_string ( value, priv->babel_filter_args ); break;
137
 
        case PROP_INPUT_LABEL:       g_value_set_string ( value, priv->input_label ); break;
138
 
 
139
 
        default:
140
 
                /* We don't have any other property... */
141
 
                G_OBJECT_WARN_INVALID_PROPERTY_ID ( object, property_id, pspec );
142
 
                break;
143
 
        }
144
 
}
145
 
 
146
 
typedef struct {
147
 
        VikExtTool *self;
148
 
        VikWindow *vw;
149
 
        VikViewport *vvp;
150
 
        GtkWidget *user_string;
151
 
} datasource_t;
152
 
 
153
 
 
154
 
static void ensure_last_user_strings_hash() {
155
 
    if ( last_user_strings == NULL ) {
156
 
        last_user_strings = g_hash_table_new_full ( g_str_hash, 
157
 
                                                    g_str_equal,
158
 
                                                    g_free,
159
 
                                                    g_free ); 
160
 
    }
161
 
}
162
 
 
163
 
 
164
 
static gchar *get_last_user_string ( const datasource_t *source ) {
165
 
    ensure_last_user_strings_hash();
166
 
    gchar *label = vik_ext_tool_get_label ( source->self );
167
 
    gchar *last_str = g_hash_table_lookup ( last_user_strings, label );
168
 
    g_free( label );
169
 
    return last_str;
170
 
}
171
 
 
172
 
 
173
 
static void set_last_user_string ( const datasource_t *source, const gchar *s ) {
174
 
    ensure_last_user_strings_hash();
175
 
    g_hash_table_insert ( last_user_strings, 
176
 
                          vik_ext_tool_get_label ( source->self ), 
177
 
                          g_strdup ( s ) );
178
 
}
179
 
 
180
 
static gpointer datasource_init ( acq_vik_t *avt )
181
 
{
182
 
        datasource_t *data = g_malloc(sizeof(*data));
183
 
        data->self = avt->userdata;
184
 
        data->vw = avt->vw;
185
 
        data->vvp = avt->vvp;
186
 
        data->user_string = NULL;
187
 
        return data;
188
 
}
189
 
 
190
 
static void datasource_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
191
 
{
192
 
        datasource_t *widgets = (datasource_t *)user_data;
193
 
        VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( widgets->self );
194
 
        GtkWidget *user_string_label;
195
 
    gchar *label = g_strdup_printf( "%s:", priv->input_label );
196
 
        user_string_label = gtk_label_new ( label );
197
 
        widgets->user_string = gtk_entry_new ( );
198
 
 
199
 
    gchar *last_str = get_last_user_string ( widgets );
200
 
    if ( last_str )
201
 
        gtk_entry_set_text( GTK_ENTRY( widgets->user_string ), last_str );
202
 
 
203
 
        // 'ok' when press return in the entry
204
 
        g_signal_connect_swapped (widgets->user_string, "activate", G_CALLBACK(a_dialog_response_accept), dialog);
205
 
 
206
 
        /* Packing all widgets */
207
 
        GtkBox *box = GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog)));
208
 
        gtk_box_pack_start ( box, user_string_label, FALSE, FALSE, 5 );
209
 
        gtk_box_pack_start ( box, widgets->user_string, FALSE, FALSE, 5 );
210
 
        gtk_widget_show_all ( dialog );
211
 
        gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );
212
 
        // NB presently the focus is overridden later on by the acquire.c code.
213
 
        gtk_widget_grab_focus ( widgets->user_string );
214
 
 
215
 
    g_free ( label );
216
 
}
217
 
 
218
 
 
219
 
 
220
 
static void datasource_get_process_options ( gpointer user_data, ProcessOptions *po, DownloadFileOptions *options, const gchar *notused1, const gchar *notused2 )
221
 
{
222
 
        datasource_t *data = (datasource_t*) user_data;
223
 
 
224
 
        VikWebtool *vwd = VIK_WEBTOOL ( data->self );
225
 
        VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( data->self );
226
 
 
227
 
        if ( webtool_needs_user_string ( vwd ) ) {
228
 
                priv->user_string = g_strdup ( gtk_entry_get_text ( GTK_ENTRY ( data->user_string ) ) );
229
 
 
230
 
        if ( priv->user_string[0] != '\0' ) {
231
 
            set_last_user_string ( data, priv->user_string );
232
 
        }
233
 
    }
234
 
 
235
 
        gchar *url = vik_webtool_get_url ( vwd, data->vw );
236
 
        g_debug ("%s: %s", __FUNCTION__, url );
237
 
 
238
 
        po->url = g_strdup ( url );
239
 
 
240
 
        // Only use first section of the file_type string
241
 
        // One can't use values like 'kml -x transform,rte=wpt' in order to do fancy things
242
 
        //  since it won't be in the right order for the overall GPSBabel command
243
 
        // So prevent any potentially dangerous behaviour
244
 
        gchar **parts = NULL;
245
 
        if ( priv->file_type )
246
 
                parts = g_strsplit ( priv->file_type, " ", 0);
247
 
        if ( parts )
248
 
                po->input_file_type = g_strdup ( parts[0] );
249
 
        else
250
 
                po->input_file_type = NULL;
251
 
        g_strfreev ( parts );
252
 
 
253
 
        options = NULL;
254
 
        po->babel_filters = priv->babel_filter_args;
255
 
}
256
 
 
257
 
static void cleanup ( gpointer data )
258
 
{
259
 
        g_free ( data );
260
 
}
261
 
 
262
 
static void webtool_datasource_open ( VikExtTool *self, VikWindow *vw )
263
 
{
264
 
        gboolean search = webtool_needs_user_string ( VIK_WEBTOOL ( self ) );
265
 
 
266
 
        // Use VikDataSourceInterface to give thready goodness controls of downloading stuff (i.e. can cancel the request)
267
 
 
268
 
        // Can now create a 'VikDataSourceInterface' on the fly...
269
 
        VikDataSourceInterface *vik_datasource_interface = g_malloc(sizeof(VikDataSourceInterface));
270
 
 
271
 
        // An 'easy' way of assigning values
272
 
        VikDataSourceInterface data = {
273
 
                vik_ext_tool_get_label (self),
274
 
                vik_ext_tool_get_label (self),
275
 
                VIK_DATASOURCE_ADDTOLAYER,
276
 
                VIK_DATASOURCE_INPUTTYPE_NONE,
277
 
                FALSE, // Maintain current view - rather than setting it to the acquired points
278
 
                TRUE,
279
 
                TRUE,
280
 
                (VikDataSourceInitFunc)               datasource_init,
281
 
                (VikDataSourceCheckExistenceFunc)     NULL,
282
 
                (VikDataSourceAddSetupWidgetsFunc)    (search ? datasource_add_setup_widgets : NULL),
283
 
                (VikDataSourceGetProcessOptionsFunc)  datasource_get_process_options,
284
 
                (VikDataSourceProcessFunc)            a_babel_convert_from,
285
 
                (VikDataSourceProgressFunc)           NULL,
286
 
                (VikDataSourceAddProgressWidgetsFunc) NULL,
287
 
                (VikDataSourceCleanupFunc)            cleanup,
288
 
                (VikDataSourceOffFunc)                NULL,
289
 
                NULL,
290
 
                0,
291
 
                NULL,
292
 
                NULL,
293
 
                0
294
 
        };
295
 
        memcpy ( vik_datasource_interface, &data, sizeof(VikDataSourceInterface) );
296
 
 
297
 
        a_acquire ( vw, vik_window_layers_panel(vw), vik_window_viewport (vw), data.mode, vik_datasource_interface, self, cleanup );
298
 
}
299
 
 
300
 
static void vik_webtool_datasource_class_init ( VikWebtoolDatasourceClass *klass )
301
 
{
302
 
        GObjectClass *gobject_class;
303
 
        VikWebtoolClass *base_class;
304
 
        GParamSpec *pspec;
305
 
 
306
 
        gobject_class = G_OBJECT_CLASS (klass);
307
 
 
308
 
        gobject_class->finalize = webtool_datasource_finalize;
309
 
        gobject_class->set_property = webtool_datasource_set_property;
310
 
        gobject_class->get_property = webtool_datasource_get_property;
311
 
 
312
 
        pspec = g_param_spec_string ("url",
313
 
                                     "Template URL",
314
 
                                     "Set the template URL",
315
 
                                     VIKING_URL /* default value */,
316
 
                                     G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
317
 
        g_object_class_install_property (gobject_class,
318
 
                                         PROP_URL,
319
 
                                         pspec);
320
 
 
321
 
        pspec = g_param_spec_string ("url_format_code",
322
 
                                     "Template URL Format Code",
323
 
                                     "Set the template URL format code",
324
 
                                     "LRBT", // default value
325
 
                                     G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
326
 
        g_object_class_install_property (gobject_class,
327
 
                                         PROP_URL_FORMAT_CODE,
328
 
                                         pspec);
329
 
 
330
 
        pspec = g_param_spec_string ("file_type",
331
 
                                     "The file type expected",
332
 
                                     "Set the file type",
333
 
                                     NULL, // default value ~ equates to internal GPX reading
334
 
                                     G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
335
 
        g_object_class_install_property (gobject_class,
336
 
                                         PROP_FILE_TYPE,
337
 
                                         pspec);
338
 
 
339
 
        pspec = g_param_spec_string ("babel_filter_args",
340
 
                                     "The command line filter options to pass to gpsbabel",
341
 
                                     "Set the command line filter options for gpsbabel",
342
 
                                     NULL, // default value 
343
 
                                     G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
344
 
        g_object_class_install_property (gobject_class,
345
 
                                         PROP_BABEL_FILTER_ARGS,
346
 
                                         pspec);
347
 
 
348
 
        pspec = g_param_spec_string ("input_label",
349
 
                                     "The label for the user input box if input is required.",
350
 
                                     "Set the label to be shown next to the user input box if an input term is required",
351
 
                                     _("Search Term"),
352
 
                                     G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
353
 
        g_object_class_install_property (gobject_class,
354
 
                                         PROP_INPUT_LABEL,
355
 
                                         pspec);
356
 
 
357
 
        parent_class = g_type_class_peek_parent (klass);
358
 
 
359
 
        base_class = VIK_WEBTOOL_CLASS ( klass );
360
 
        base_class->get_url = webtool_datasource_get_url;
361
 
 
362
 
        // Override default open function here:
363
 
        VikExtToolClass *ext_tool_class = VIK_EXT_TOOL_CLASS ( klass );
364
 
        ext_tool_class->open = webtool_datasource_open;
365
 
 
366
 
        g_type_class_add_private (klass, sizeof (VikWebtoolDatasourcePrivate));
367
 
}
368
 
 
369
 
VikWebtoolDatasource *vik_webtool_datasource_new ()
370
 
{
371
 
        return VIK_WEBTOOL_DATASOURCE ( g_object_new ( VIK_WEBTOOL_DATASOURCE_TYPE, NULL ) );
372
 
}
373
 
 
374
 
VikWebtoolDatasource *vik_webtool_datasource_new_with_members ( const gchar *label,
375
 
                                                                const gchar *url,
376
 
                                                                const gchar *url_format_code,
377
 
                                                                const gchar *file_type,
378
 
                                                                const gchar *babel_filter_args,
379
 
                                                                const gchar *input_label )
380
 
{
381
 
        VikWebtoolDatasource *result = VIK_WEBTOOL_DATASOURCE ( g_object_new ( VIK_WEBTOOL_DATASOURCE_TYPE,
382
 
                                                                "label", label,
383
 
                                                                "url", url,
384
 
                                                                "url_format_code", url_format_code,
385
 
                                                                "file_type", file_type,
386
 
                                                                "babel_filter_args", babel_filter_args,
387
 
                                                            "input_label", input_label,
388
 
                                                                NULL ) );
389
 
 
390
 
        return result;
391
 
}
392
 
 
393
 
static void vik_webtool_datasource_init ( VikWebtoolDatasource *self )
394
 
{
395
 
        VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE (self);
396
 
        priv->url = NULL;
397
 
        priv->url_format_code = NULL;
398
 
        priv->file_type = NULL;
399
 
        priv->babel_filter_args = NULL;
400
 
    priv->input_label = NULL;
401
 
        priv->user_string = NULL;
402
 
}
403
 
 
404
 
static void webtool_datasource_finalize ( GObject *gob )
405
 
{
406
 
        VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( gob );
407
 
        g_free ( priv->url ); priv->url = NULL;
408
 
        g_free ( priv->url_format_code ); priv->url_format_code = NULL;
409
 
        g_free ( priv->file_type ); priv->file_type = NULL;
410
 
        g_free ( priv->babel_filter_args ); priv->babel_filter_args = NULL;
411
 
        g_free ( priv->input_label ); priv->input_label = NULL;
412
 
        g_free ( priv->user_string); priv->user_string = NULL;
413
 
        G_OBJECT_CLASS(parent_class)->finalize(gob);
414
 
}
415
 
 
416
 
#define MAX_NUMBER_CODES 7
417
 
 
418
 
/**
419
 
 * Calculate individual elements (similarly to the VikWebtool Bounds & Center) for *all* potential values
420
 
 * Then only values specified by the URL format are used in parameterizing the URL
421
 
 */
422
 
static gchar *webtool_datasource_get_url ( VikWebtool *self, VikWindow *vw )
423
 
{
424
 
        VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( self );
425
 
        VikViewport *viewport = vik_window_viewport ( vw );
426
 
 
427
 
        // Get top left and bottom right lat/lon pairs from the viewport
428
 
        gdouble min_lat, max_lat, min_lon, max_lon;
429
 
        gchar sminlon[G_ASCII_DTOSTR_BUF_SIZE];
430
 
        gchar smaxlon[G_ASCII_DTOSTR_BUF_SIZE];
431
 
        gchar sminlat[G_ASCII_DTOSTR_BUF_SIZE];
432
 
        gchar smaxlat[G_ASCII_DTOSTR_BUF_SIZE];
433
 
        vik_viewport_get_min_max_lat_lon ( viewport, &min_lat, &max_lat, &min_lon, &max_lon );
434
 
 
435
 
        // Cannot simply use g_strdup_printf and gdouble due to locale.
436
 
        // As we compute an URL, we have to think in C locale.
437
 
        g_ascii_dtostr (sminlon, G_ASCII_DTOSTR_BUF_SIZE, min_lon);
438
 
        g_ascii_dtostr (smaxlon, G_ASCII_DTOSTR_BUF_SIZE, max_lon);
439
 
        g_ascii_dtostr (sminlat, G_ASCII_DTOSTR_BUF_SIZE, min_lat);
440
 
        g_ascii_dtostr (smaxlat, G_ASCII_DTOSTR_BUF_SIZE, max_lat);
441
 
 
442
 
        // Center values
443
 
        const VikCoord *coord = vik_viewport_get_center ( viewport );
444
 
        struct LatLon ll;
445
 
        vik_coord_to_latlon ( coord, &ll );
446
 
 
447
 
        gchar scenterlat[G_ASCII_DTOSTR_BUF_SIZE];
448
 
        gchar scenterlon[G_ASCII_DTOSTR_BUF_SIZE];
449
 
        g_ascii_dtostr (scenterlat, G_ASCII_DTOSTR_BUF_SIZE, ll.lat);
450
 
        g_ascii_dtostr (scenterlon, G_ASCII_DTOSTR_BUF_SIZE, ll.lon);
451
 
 
452
 
        guint8 zoom = 17; // A zoomed in default
453
 
        // zoom - ideally x & y factors need to be the same otherwise use the default
454
 
        if ( vik_viewport_get_xmpp ( viewport ) == vik_viewport_get_ympp ( viewport ) )
455
 
                zoom = map_utils_mpp_to_zoom_level ( vik_viewport_get_zoom ( viewport ) );
456
 
 
457
 
        gchar szoom[G_ASCII_DTOSTR_BUF_SIZE];
458
 
        g_snprintf ( szoom, G_ASCII_DTOSTR_BUF_SIZE, "%d", zoom );
459
 
 
460
 
        gint len = 0;
461
 
        if ( priv->url_format_code )
462
 
                len = strlen ( priv->url_format_code );
463
 
        if ( len > MAX_NUMBER_CODES )
464
 
                len = MAX_NUMBER_CODES;
465
 
 
466
 
        gchar* values[MAX_NUMBER_CODES];
467
 
        int i;
468
 
        for ( i = 0; i < MAX_NUMBER_CODES; i++ ) {
469
 
                values[i] = '\0';
470
 
        }
471
 
 
472
 
        for ( i = 0; i < len; i++ ) {
473
 
                switch ( g_ascii_toupper ( priv->url_format_code[i] ) ) {
474
 
                case 'L': values[i] = g_strdup ( sminlon ); break;
475
 
                case 'R': values[i] = g_strdup ( smaxlon ); break;
476
 
                case 'B': values[i] = g_strdup ( sminlat ); break;
477
 
                case 'T': values[i] = g_strdup ( smaxlat ); break;
478
 
                case 'A': values[i] = g_strdup ( scenterlat ); break;
479
 
                case 'O': values[i] = g_strdup ( scenterlon ); break;
480
 
                case 'Z': values[i] = g_strdup ( szoom ); break;
481
 
                case 'S': values[i] = g_strdup ( priv->user_string ); break;
482
 
                default: break;
483
 
                }
484
 
        }
485
 
 
486
 
        gchar *url = g_strdup_printf ( priv->url, values[0], values[1], values[2], values[3], values[4], values[5], values[6] );
487
 
 
488
 
        for ( i = 0; i < MAX_NUMBER_CODES; i++ ) {
489
 
                g_free ( values[i] );
490
 
        }
491
 
        
492
 
        return url;
493
 
}
494
 
 
495
 
// NB Only works for ascii strings
496
 
char* strcasestr2(const char *dst, const char *src)
497
 
{
498
 
        if ( !dst || !src )
499
 
                return NULL;
500
 
 
501
 
        if(src[0] == '\0')
502
 
                return (char*)dst;
503
 
 
504
 
        int len = strlen(src) - 1;
505
 
        char sc = tolower(src[0]);
506
 
        for(char dc = *dst; (dc = *dst); dst++) {
507
 
                dc = tolower(dc);
508
 
                if(sc == dc && (len == 0 || !strncasecmp(dst+1, src+1, len)))
509
 
                        return (char*)dst;
510
 
        }
511
 
 
512
 
        return NULL;
513
 
}
514
 
 
515
 
/**
516
 
 * Returns true if the URL format contains 'S' -- that is, a search term entry
517
 
 * box needs to be displayed
518
 
 */
519
 
static gboolean webtool_needs_user_string ( VikWebtool *self )
520
 
{
521
 
        VikWebtoolDatasourcePrivate *priv = WEBTOOL_DATASOURCE_GET_PRIVATE ( self );
522
 
        // For some reason (my) Windows build gets built with -D_GNU_SOURCE
523
 
#if (_GNU_SOURCE && !WINDOWS)
524
 
        return (strcasestr(priv->url_format_code, "S") != NULL);
525
 
#else
526
 
        return (strcasestr2(priv->url_format_code, "S") != NULL);
527
 
#endif
528
 
}