~darkxst/ubuntu/saucy/gdm/lp1212408

« back to all changes in this revision

Viewing changes to vicious-extensions/ve-config.c

  • Committer: Bazaar Package Importer
  • Author(s): Josselin Mouette
  • Date: 2008-09-02 10:37:20 UTC
  • mfrom: (1.4.27 upstream)
  • mto: This revision was merged to the branch mainline in revision 261.
  • Revision ID: james.westby@ubuntu.com-20080902103720-p810vv530hqj45wg
Tags: 2.20.7-3
* Install the debian-moreblue-orbit theme, thanks Andre Luiz Rodrigues 
  Ferreira. Closes: #497440.
* 35_gdm.conf.patch: make it the default.
* copyright: fix encoding.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Config reader routines
2
 
 *
3
 
 * (c) 2002 George Lebl
4
 
 *
5
 
 * This library is free software; you can redistribute it and/or
6
 
 * modify it under the terms of the GNU Library General Public
7
 
 * License as published by the Free Software Foundation; either
8
 
 * version 2 of the License, or (at your option) any later version.
9
 
 *
10
 
 * This library is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 
 * Library General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU Library General Public
16
 
 * License along with this library; if not, write to the
17
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18
 
 * Boston, MA 02111-1307, USA.
19
 
 */
20
 
#include "config.h"
21
 
 
22
 
#include <string.h>
23
 
#include <unistd.h>
24
 
#include <stdlib.h>
25
 
#include <stdio.h>
26
 
#include <sys/types.h>
27
 
#include <sys/stat.h>
28
 
#include <time.h>
29
 
 
30
 
#include <glib.h>
31
 
 
32
 
#include "ve-i18n.h"
33
 
#include "ve-misc.h"
34
 
#include "ve-config.h"
35
 
 
36
 
typedef struct _VeSection VeSection;
37
 
typedef struct _VeLine VeLine;
38
 
 
39
 
enum {
40
 
        VE_LINE_TEXT /* comment or some other line */,
41
 
        VE_LINE_KEY
42
 
};
43
 
 
44
 
struct _VeLine {
45
 
        int type;
46
 
        VeSection *parent;
47
 
        char *fullkey; /* key with section name */
48
 
        const char *key; /* key without section name, pointer
49
 
                            into fullkey, or NULL if of type TEXT */
50
 
        char *string;
51
 
};
52
 
 
53
 
struct _VeSection {
54
 
        char *name;
55
 
        VeConfig *config;
56
 
        GList *lines;
57
 
};
58
 
 
59
 
struct _VeConfig {
60
 
        char *file;
61
 
        time_t mtime;
62
 
        time_t last_recheck;
63
 
        gboolean dirty;
64
 
 
65
 
        gboolean hashed;
66
 
 
67
 
        VeSection *root;
68
 
 
69
 
        GList *sections;
70
 
 
71
 
        GHashTable *line_ht;
72
 
};
73
 
 
74
 
static GHashTable *config_hash = NULL;
75
 
 
76
 
static VeSection *
77
 
find_section (VeConfig *config, const char *name)
78
 
{
79
 
        GList *li;
80
 
 
81
 
        if (name == NULL) {
82
 
                return config->root;
83
 
        }
84
 
 
85
 
        for (li = config->sections; li != NULL; li = li->next) {
86
 
                VeSection *section = li->data;
87
 
                if (strcmp (section->name, name) == 0)
88
 
                        return section;
89
 
        }
90
 
        return NULL;
91
 
}
92
 
 
93
 
static void
94
 
free_line (VeLine *line)
95
 
{
96
 
        g_free (line->fullkey);
97
 
        line->fullkey = NULL;
98
 
        g_free (line->string);
99
 
        line->string = NULL;
100
 
        g_free (line);
101
 
}
102
 
 
103
 
/* does not remove from parent->lines */
104
 
static void
105
 
destroy_line (VeLine *line)
106
 
{
107
 
        if (line->fullkey != NULL)
108
 
                g_hash_table_remove (line->parent->config->line_ht,
109
 
                                     line->fullkey);
110
 
 
111
 
        free_line (line);
112
 
}
113
 
 
114
 
static void
115
 
destroy_section (VeSection *section)
116
 
{
117
 
        g_free (section->name);
118
 
        section->name = NULL;
119
 
 
120
 
        g_list_foreach (section->lines, (GFunc) destroy_line, NULL);
121
 
        g_list_free (section->lines);
122
 
        section->lines = NULL;
123
 
 
124
 
        g_free (section);
125
 
}
126
 
 
127
 
static VeSection *
128
 
new_section (VeConfig *config, const char *name)
129
 
{
130
 
        VeSection *section = g_new0 (VeSection, 1);
131
 
        section->config = config;
132
 
        section->name = g_strdup (name);
133
 
        return section;
134
 
}
135
 
 
136
 
static void
137
 
add_text_line (VeConfig *config, VeSection *section, const char *text)
138
 
{
139
 
        VeLine *line = g_new0 (VeLine, 1);
140
 
        line->type = VE_LINE_TEXT;
141
 
        line->parent = section;
142
 
        line->string = g_strdup (text);
143
 
 
144
 
        section->lines = g_list_append (section->lines, line);
145
 
}
146
 
 
147
 
/* Find first instance of this key where it is commented out, this
148
 
   is likely where we want to insert this key */
149
 
static GList *
150
 
find_commented_out (VeSection *section, VeLine *line)
151
 
{
152
 
        GList *li;
153
 
        int keylen = strlen (line->key);
154
 
       
155
 
        for (li = section->lines; li != NULL; li = li->next) {
156
 
                char *p;
157
 
                VeLine *ll = li->data;
158
 
                if (ll->type != VE_LINE_TEXT)
159
 
                        continue;
160
 
                p = ll->string;
161
 
                while (*p == ' ' || *p == '\t')
162
 
                        p++;
163
 
                if (*p != '#')
164
 
                        continue;
165
 
                p++;
166
 
                while (*p == ' ' || *p == '\t')
167
 
                        p++;
168
 
                if (strncmp (p, line->key, keylen) == 0 &&
169
 
                    (p[keylen] == '[' ||
170
 
                     p[keylen] == '=' ||
171
 
                     p[keylen] == ' ' ||
172
 
                     p[keylen] == '\t'))
173
 
                        return li;
174
 
        }
175
 
        return NULL;
176
 
}
177
 
 
178
 
/* append, but be nice to whitespace and comments */
179
 
static void
180
 
careful_append (VeSection *section, VeLine *line)
181
 
{
182
 
        GList *li;
183
 
        VeLine *ll;
184
 
        gboolean seen_white = FALSE;
185
 
 
186
 
        g_assert (line->type == VE_LINE_KEY);
187
 
 
188
 
        li = find_commented_out (section, line);
189
 
        if (li != NULL) {
190
 
                if (li->next == NULL)
191
 
                        section->lines = g_list_append
192
 
                                (section->lines, line);
193
 
                else
194
 
                        section->lines = g_list_insert_before
195
 
                                (section->lines,
196
 
                                 li->next, line);
197
 
 
198
 
                return;
199
 
        }
200
 
 
201
 
        li = g_list_last (section->lines);
202
 
        while (li != NULL) {
203
 
                ll = li->data;
204
 
 
205
 
                if (ll->type == VE_LINE_TEXT) {
206
 
                        if (ll->string[0] == '\0') {
207
 
                                seen_white = TRUE;
208
 
                        } else if (seen_white) {
209
 
                                section->lines = g_list_insert_before
210
 
                                        (section->lines,
211
 
                                         li->next, line);
212
 
                                return;
213
 
                        }
214
 
                } else {
215
 
                        if (li->next == NULL)
216
 
                                section->lines = g_list_append
217
 
                                        (section->lines, line);
218
 
                        else
219
 
                                section->lines = g_list_insert_before
220
 
                                        (section->lines,
221
 
                                         li->next, line);
222
 
                        return;
223
 
                }
224
 
                li = li->prev;
225
 
        }
226
 
 
227
 
        section->lines = g_list_prepend (section->lines, line);
228
 
}
229
 
 
230
 
static void
231
 
add_key_line (VeConfig *config, VeSection *section,
232
 
              const char *key, const char *val,
233
 
              gboolean careful_add)
234
 
{
235
 
        VeLine *line = g_new0 (VeLine, 1);
236
 
        line->type = VE_LINE_KEY;
237
 
        line->parent = section;
238
 
        if (section->name == NULL) {
239
 
                line->fullkey = g_strdup (key);
240
 
                line->key = line->fullkey;
241
 
        } else {
242
 
                line->fullkey = g_strdup_printf ("%s/%s",
243
 
                                                 section->name,
244
 
                                                 key);
245
 
                line->key = strchr (line->fullkey, '/');
246
 
                line->key++;
247
 
        }
248
 
        line->string = g_strdup (val);
249
 
 
250
 
        /* rare */
251
 
        if (g_hash_table_lookup (config->line_ht, line->fullkey) != NULL) {
252
 
                free_line (line);
253
 
                return;
254
 
        }
255
 
 
256
 
        if ( ! careful_add ||
257
 
            section->lines == NULL) {
258
 
                section->lines = g_list_append (section->lines, line);
259
 
        } else {
260
 
                careful_append (section, line);
261
 
        }
262
 
 
263
 
        g_hash_table_insert (config->line_ht,
264
 
                             line->fullkey,
265
 
                             line);
266
 
}
267
 
 
268
 
static time_t
269
 
get_mtime (const char *file)
270
 
{
271
 
        struct stat s;
272
 
        if (g_stat (file, &s) == 0)
273
 
                return s.st_mtime;
274
 
        else
275
 
                return 0;
276
 
}
277
 
 
278
 
static void
279
 
read_config (VeConfig *config)
280
 
{
281
 
        FILE *fp;
282
 
        VeSection *section = config->root;
283
 
        char buf[2048];
284
 
        int cnt;
285
 
        char *getsret;
286
 
 
287
 
        config->mtime = get_mtime (config->file);
288
 
 
289
 
        VE_IGNORE_EINTR (fp = fopen (config->file, "r"));
290
 
        if (fp == NULL)
291
 
                return;
292
 
 
293
 
        cnt = 0;
294
 
 
295
 
        for (;;) {
296
 
                char *nows = buf;
297
 
                char *eq;
298
 
                char *p;
299
 
 
300
 
                VE_IGNORE_EINTR (getsret = fgets (buf, sizeof (buf), fp));
301
 
                if (getsret == NULL)
302
 
                        break;
303
 
 
304
 
                p = strchr (buf, '\n');
305
 
                if (p != NULL)
306
 
                        *p = '\0';
307
 
 
308
 
                while (*nows == ' ' || *nows == '\t')
309
 
                        nows++;
310
 
                if (*nows == '[') {
311
 
                        p = strchr (nows, ']');
312
 
 
313
 
                        if (p != NULL)
314
 
                                *p = '\0';
315
 
 
316
 
                        nows++;
317
 
 
318
 
                        section = new_section (config, nows);
319
 
                        config->sections = g_list_append (config->sections,
320
 
                                                          section);
321
 
                } else if (*nows == '\0') {
322
 
                        add_text_line (config, section, "");
323
 
                } else if (*nows == '#') {
324
 
                        add_text_line (config, section, buf);
325
 
                } else if ((eq = strchr (nows, '=')) != NULL) {
326
 
                        char *val;
327
 
                        *eq = '\0';
328
 
                        eq++;
329
 
                        val = g_strcompress (eq);
330
 
                        add_key_line (config, section,
331
 
                                      nows /* key */,
332
 
                                      val /* value */,
333
 
                                      FALSE /* careful_add */);
334
 
                        g_free (val);
335
 
                }
336
 
                /* Note: all invalid lines are whacked from the file */
337
 
 
338
 
                /* Note this is a hard limit to avoid run away files.
339
 
                   Do we really expect files longer then 5000 lines?
340
 
                   This is to be ultra anal for security's sake. */
341
 
                cnt++;
342
 
                if (cnt > 5000)
343
 
                        break;
344
 
        }
345
 
 
346
 
        VE_IGNORE_EINTR (fclose (fp));
347
 
}
348
 
 
349
 
static VeLine *
350
 
find_line (VeConfig *config,
351
 
           const char *key)
352
 
{
353
 
        char *dkey;
354
 
        char *p;
355
 
        VeLine *line;
356
 
 
357
 
        dkey = g_strdup (key);
358
 
        p = strchr (dkey, '=');
359
 
        if (p != NULL)
360
 
                *p = '\0';
361
 
 
362
 
        line = g_hash_table_lookup (config->line_ht, dkey);
363
 
        g_free (dkey);
364
 
        return line;
365
 
}
366
 
 
367
 
static VeSection *
368
 
find_last_section (VeConfig *config)
369
 
{
370
 
        GList *li;
371
 
 
372
 
        if (config->sections == NULL)
373
 
                return config->root;
374
 
 
375
 
        li = g_list_last (config->sections);
376
 
        return li->data;
377
 
}
378
 
 
379
 
static VeSection *
380
 
find_or_make_section (VeConfig *config,
381
 
                      const char *key,
382
 
                      char **key_name,
383
 
                      gboolean make_new)
384
 
{
385
 
        char *dkey;
386
 
        char *p;
387
 
        VeSection *section;
388
 
        VeSection *last_sect;
389
 
 
390
 
        dkey = g_strdup (key);
391
 
        p = strchr (dkey, '=');
392
 
        if (p != NULL)
393
 
                *p = '\0';
394
 
        p = strchr (dkey, '/');
395
 
        if (p == NULL) {
396
 
                *key_name = dkey;
397
 
                /* we're adding to the root which is completely
398
 
                   empty so add a blank line to separate it */
399
 
                if (make_new && config->root->lines == NULL)
400
 
                        add_text_line (config, config->root, "");
401
 
                return config->root;
402
 
        }
403
 
        *p = '\0';
404
 
 
405
 
        *key_name = g_strdup (p+1);;
406
 
 
407
 
        section = find_section (config, dkey);
408
 
        if (section != NULL) {
409
 
                g_free (dkey);
410
 
                return section;
411
 
        }
412
 
 
413
 
        if ( ! make_new) {
414
 
                g_free (dkey);
415
 
                return NULL;
416
 
        }
417
 
 
418
 
        /* Add an empty line on end of last section */
419
 
        last_sect = find_last_section (config);
420
 
        if (last_sect != config->root ||
421
 
            config->root->lines != NULL)
422
 
                add_text_line (config, last_sect, "");
423
 
 
424
 
        section = new_section (config, dkey);
425
 
        config->sections = g_list_append (config->sections, section);
426
 
 
427
 
        g_free (dkey);
428
 
 
429
 
        return section;
430
 
}
431
 
 
432
 
VeConfig *
433
 
ve_config_new (const char *file)
434
 
{
435
 
        VeConfig *config;
436
 
 
437
 
        g_return_val_if_fail (file != NULL, NULL);
438
 
       
439
 
        config = g_new0 (VeConfig, 1);
440
 
 
441
 
        config->file = g_strdup (file);
442
 
        config->root = new_section (config, NULL);
443
 
        config->line_ht = g_hash_table_new (g_str_hash, g_str_equal);
444
 
 
445
 
        read_config (config);
446
 
 
447
 
        return config;
448
 
}
449
 
 
450
 
VeConfig *
451
 
ve_config_get (const char *file)
452
 
{
453
 
        VeConfig *config = NULL;
454
 
 
455
 
        if (config_hash == NULL)
456
 
                config_hash = g_hash_table_new (g_str_hash, g_str_equal);
457
 
        else
458
 
                config = g_hash_table_lookup (config_hash, file);
459
 
 
460
 
        if (config == NULL) {
461
 
                config = ve_config_new (file);
462
 
                config->hashed = TRUE;
463
 
                g_hash_table_insert (config_hash, g_strdup (file), config);
464
 
        } else {
465
 
                ve_config_recheck (config);
466
 
        }
467
 
 
468
 
        return config;
469
 
}
470
 
 
471
 
static void
472
 
config_clear (VeConfig *config)
473
 
{
474
 
        g_free (config->file);
475
 
        config->file = NULL;
476
 
 
477
 
        destroy_section (config->root);
478
 
 
479
 
        g_list_foreach (config->sections, (GFunc) destroy_section, NULL);
480
 
        g_list_free (config->sections);
481
 
        config->sections = NULL;
482
 
 
483
 
        g_hash_table_destroy (config->line_ht);
484
 
        config->line_ht = NULL;
485
 
 
486
 
        memset (config, 0, sizeof (VeConfig));
487
 
}
488
 
 
489
 
void
490
 
ve_config_recheck (VeConfig *config)
491
 
{
492
 
        time_t curtime = time (NULL);
493
 
 
494
 
        g_return_if_fail (config != NULL);
495
 
 
496
 
        /* don't check more then once a second,
497
 
         * it would be pointless anyway */
498
 
        if (config->last_recheck == curtime)
499
 
                return;
500
 
 
501
 
        if (get_mtime (config->file) != config->mtime) {
502
 
                char *file = g_strdup (config->file);
503
 
 
504
 
                /* clear all data and null the structure */
505
 
                config_clear (config);
506
 
 
507
 
                /* reset the config file */
508
 
                config->file = file;
509
 
                config->root = new_section (config, NULL);
510
 
                config->line_ht = g_hash_table_new (g_str_hash, g_str_equal);
511
 
 
512
 
                /* read it again */
513
 
                read_config (config);
514
 
        }
515
 
 
516
 
        config->last_recheck = curtime;
517
 
}
518
 
 
519
 
void
520
 
ve_config_destroy (VeConfig *config)
521
 
{
522
 
        g_return_if_fail (config != NULL);
523
 
        g_return_if_fail ( ! config->hashed);
524
 
 
525
 
        config_clear (config);
526
 
 
527
 
        g_free (config);
528
 
}
529
 
 
530
 
static gchar*
531
 
strescape_but_high (const gchar *source)
532
 
{
533
 
        const guchar *p;
534
 
        gchar *dest;
535
 
        gchar *q;
536
 
 
537
 
        g_return_val_if_fail (source != NULL, NULL);
538
 
 
539
 
        p = (guchar *) source;
540
 
        /* Each source byte needs maximally four destination chars (\000) */
541
 
        q = dest = g_malloc (strlen (source) * 4 + 1);
542
 
 
543
 
        while (*p) {
544
 
                switch (*p) {
545
 
                        case '\b':
546
 
                                *q++ = '\\';
547
 
                                *q++ = 'b';
548
 
                                break;
549
 
                        case '\f':
550
 
                                *q++ = '\\';
551
 
                                *q++ = 'f';
552
 
                                break;
553
 
                        case '\n':
554
 
                                *q++ = '\\';
555
 
                                *q++ = 'n';
556
 
                                break;
557
 
                        case '\r':
558
 
                                *q++ = '\\';
559
 
                                *q++ = 'r';
560
 
                                break;
561
 
                        case '\t':
562
 
                                *q++ = '\\';
563
 
                                *q++ = 't';
564
 
                                break;
565
 
                        case '\\':
566
 
                                *q++ = '\\';
567
 
                                *q++ = '\\';
568
 
                                break;
569
 
                        case '\"':
570
 
                                *q++ = '\\';
571
 
                                *q++ = '"';
572
 
                                break;
573
 
                        default:
574
 
                                if (*p < ' ') {
575
 
                                        *q++ = '\\';
576
 
                                        *q++ = '0' + (((*p) >> 6) & 07);
577
 
                                        *q++ = '0' + (((*p) >> 3) & 07);
578
 
                                        *q++ = '0' + ((*p) & 07);
579
 
                                } else {
580
 
                                        *q++ = *p;
581
 
                                }
582
 
                                break;
583
 
                }
584
 
                p++;
585
 
        }
586
 
        *q = 0;
587
 
        return dest;
588
 
}
589
 
 
590
 
 
591
 
static void
592
 
save_section (VeSection *section, FILE *fp)
593
 
{
594
 
        GList *li;
595
 
        for (li = section->lines; li != NULL; li = li->next) {
596
 
                VeLine *line = li->data;
597
 
                if (line->type == VE_LINE_TEXT) {
598
 
                        VE_IGNORE_EINTR (fprintf (fp, "%s\n", line->string));
599
 
                } else if (line->type == VE_LINE_KEY) {
600
 
                        char *out = strescape_but_high (ve_sure_string (line->string));
601
 
                        VE_IGNORE_EINTR (fprintf (fp, "%s=%s\n",
602
 
                                                  line->key,
603
 
                                                  out));
604
 
                        g_free (out);
605
 
                }
606
 
        }
607
 
}
608
 
 
609
 
gboolean
610
 
ve_config_save (VeConfig *config, gboolean force)
611
 
{
612
 
        FILE *fp;
613
 
        GList *li;
614
 
 
615
 
        g_return_val_if_fail (config != NULL, FALSE);
616
 
 
617
 
        if ( ! force && ! config->dirty)
618
 
                return TRUE;
619
 
 
620
 
        VE_IGNORE_EINTR (fp = fopen (config->file, "w"));
621
 
        if (fp == NULL)
622
 
                return FALSE;
623
 
 
624
 
        save_section (config->root, fp);
625
 
 
626
 
        for (li = config->sections; li != NULL; li = li->next) {
627
 
                VeSection *section = li->data;
628
 
                VE_IGNORE_EINTR (fprintf (fp, "[%s]\n", section->name));
629
 
                save_section (section, fp);
630
 
        }
631
 
 
632
 
        VE_IGNORE_EINTR (fclose (fp));
633
 
 
634
 
        /* update the mtime */
635
 
        config->mtime = get_mtime (config->file);
636
 
        config->dirty = FALSE;
637
 
 
638
 
        return TRUE;
639
 
}
640
 
 
641
 
char *
642
 
ve_config_get_translated_string (VeConfig *config,
643
 
                                 const char *key)
644
 
{
645
 
        const GList *li;
646
 
        char *dkey;
647
 
        char *def;
648
 
        VeLine *line = NULL;
649
 
        char *ret;
650
 
 
651
 
        g_return_val_if_fail (config != NULL, NULL);
652
 
        g_return_val_if_fail (key != NULL, NULL);
653
 
 
654
 
        dkey = g_strdup (key);
655
 
        def = strchr (dkey, '=');
656
 
        if (def != NULL) {
657
 
                *def = '\0';
658
 
                def++;
659
 
        }
660
 
 
661
 
        for (li = ve_i18n_get_language_list ("LC_MESSAGES");
662
 
             li != NULL;
663
 
             li = li->next) {
664
 
                char *full = g_strdup_printf ("%s[%s]", dkey, (char *)li->data);
665
 
                line = g_hash_table_lookup (config->line_ht, full);
666
 
                g_free (full);
667
 
                if (line != NULL)
668
 
                        break;
669
 
        }
670
 
        if (line == NULL)
671
 
                line = g_hash_table_lookup (config->line_ht, dkey);
672
 
 
673
 
        if (line != NULL)
674
 
                ret = g_strdup (line->string);
675
 
        else
676
 
                ret = g_strdup (def);
677
 
        g_free (dkey);
678
 
        return ret;
679
 
}
680
 
 
681
 
char *
682
 
ve_config_get_string (VeConfig *config,
683
 
                      const char *key)
684
 
{
685
 
        char *dkey;
686
 
        char *def;
687
 
        VeLine *line = NULL;
688
 
        char *ret;
689
 
 
690
 
        g_return_val_if_fail (config != NULL, NULL);
691
 
        g_return_val_if_fail (key != NULL, NULL);
692
 
 
693
 
        dkey = g_strdup (key);
694
 
        def = strchr (dkey, '=');
695
 
        if (def != NULL) {
696
 
                *def = '\0';
697
 
                def++;
698
 
        }
699
 
 
700
 
        line = g_hash_table_lookup (config->line_ht, dkey);
701
 
 
702
 
        if (line != NULL)
703
 
                ret = g_strdup (line->string);
704
 
        else
705
 
                ret = g_strdup (def);
706
 
 
707
 
        g_free (dkey);
708
 
        return ret;
709
 
}
710
 
 
711
 
gboolean
712
 
ve_config_get_bool (VeConfig *config,
713
 
                    const char *key)
714
 
{
715
 
        char *val;
716
 
 
717
 
        g_return_val_if_fail (config != NULL, FALSE);
718
 
        g_return_val_if_fail (key != NULL, FALSE);
719
 
 
720
 
        val = ve_config_get_string (config, key);
721
 
        if (val != NULL &&
722
 
            (val[0] == 'T' ||
723
 
             val[0] == 't' ||
724
 
             val[0] == 'Y' ||
725
 
             val[0] == 'y' ||
726
 
             atoi (val) != 0)) {
727
 
                g_free (val);
728
 
                return TRUE;
729
 
        } else {
730
 
                g_free (val);
731
 
                return FALSE;
732
 
        }
733
 
}
734
 
 
735
 
int
736
 
ve_config_get_int (VeConfig *config,
737
 
                   const char *key)
738
 
{
739
 
        char *val;
740
 
        int ret;
741
 
 
742
 
        g_return_val_if_fail (config != NULL, 0);
743
 
        g_return_val_if_fail (key != NULL, 0);
744
 
 
745
 
        val = ve_config_get_string (config, key);
746
 
        if (val == NULL)
747
 
                return 0;
748
 
        ret = atoi (val);
749
 
        g_free (val);
750
 
        return ret;
751
 
}
752
 
 
753
 
void
754
 
ve_config_set_string (VeConfig *config,
755
 
                      const char *key,
756
 
                      const char *string)
757
 
{
758
 
        VeLine *line;
759
 
        VeSection *section;
760
 
        char *key_name = NULL;
761
 
 
762
 
        g_return_if_fail (config != NULL);
763
 
        g_return_if_fail (key != NULL);
764
 
        g_return_if_fail (string != NULL);
765
 
 
766
 
        config->dirty = TRUE;
767
 
 
768
 
        line = find_line (config, key);
769
 
        if (line != NULL) {
770
 
                g_free (line->string);
771
 
                line->string = g_strdup (string);
772
 
                return;
773
 
        }
774
 
 
775
 
        section = find_or_make_section (config, key, &key_name,
776
 
                                        TRUE /* make_new */);
777
 
        add_key_line (config, section, key_name, string,
778
 
                      TRUE /* careful_add */);
779
 
        g_free (key_name);
780
 
}
781
 
 
782
 
void
783
 
ve_config_set_bool (VeConfig *config,
784
 
                    const char *key,
785
 
                    gboolean boolean)
786
 
{
787
 
        VeLine *line;
788
 
        VeSection *section;
789
 
        char *key_name = NULL;
790
 
 
791
 
        g_return_if_fail (config != NULL);
792
 
        g_return_if_fail (key != NULL);
793
 
 
794
 
        config->dirty = TRUE;
795
 
 
796
 
        line = find_line (config, key);
797
 
        if (line != NULL) {
798
 
                g_free (line->string);
799
 
                line->string = g_strdup (boolean ? "true" : "false");
800
 
                return;
801
 
        }
802
 
 
803
 
        section = find_or_make_section (config, key, &key_name,
804
 
                                        TRUE /* make_new */);
805
 
        add_key_line (config, section, key_name, boolean ? "true" : "false",
806
 
                      TRUE /* careful_add */);
807
 
        g_free (key_name);
808
 
}
809
 
 
810
 
void
811
 
ve_config_set_int (VeConfig *config,
812
 
                   const char *key,
813
 
                   int integer)
814
 
{
815
 
        VeLine *line;
816
 
        VeSection *section;
817
 
        char *key_name = NULL;
818
 
        char *num;
819
 
 
820
 
        g_return_if_fail (config != NULL);
821
 
        g_return_if_fail (key != NULL);
822
 
 
823
 
        config->dirty = TRUE;
824
 
 
825
 
        num = g_strdup_printf ("%d", integer);
826
 
 
827
 
        line = find_line (config, key);
828
 
        if (line != NULL) {
829
 
                g_free (line->string);
830
 
                line->string = num;
831
 
                return;
832
 
        }
833
 
 
834
 
        section = find_or_make_section (config, key, &key_name,
835
 
                                        TRUE /* make_new */);
836
 
        add_key_line (config, section, key_name, num,
837
 
                      TRUE /* careful_add */);
838
 
        g_free (key_name);
839
 
        g_free (num);
840
 
}
841
 
 
842
 
void
843
 
ve_config_delete_section (VeConfig *config,
844
 
                          const char *section)
845
 
{
846
 
        VeSection *sec;
847
 
 
848
 
        g_return_if_fail (config != NULL);
849
 
        g_return_if_fail (section != NULL);
850
 
 
851
 
        if (section == NULL) {
852
 
                config->dirty = TRUE;
853
 
 
854
 
                destroy_section (config->root);
855
 
                config->root = new_section (config, NULL);
856
 
                return;
857
 
        }
858
 
 
859
 
        sec = find_section (config, section);
860
 
        if (sec != NULL) {
861
 
                config->dirty = TRUE;
862
 
 
863
 
                config->sections = g_list_remove (config->sections, sec);
864
 
                destroy_section (sec);
865
 
        }
866
 
}
867
 
 
868
 
void
869
 
ve_config_delete_key (VeConfig *config,
870
 
                      const char *key)
871
 
{
872
 
        VeLine *line = NULL;
873
 
 
874
 
        g_return_if_fail (config != NULL);
875
 
        g_return_if_fail (key != NULL);
876
 
 
877
 
        line = find_line (config, key);
878
 
        if (line != NULL) {
879
 
                config->dirty = TRUE;
880
 
 
881
 
                line->parent->lines = g_list_remove (line->parent->lines,
882
 
                                                     line);
883
 
                destroy_line (line);
884
 
        }
885
 
}
886
 
 
887
 
void
888
 
ve_config_delete_translations (VeConfig *config, const char *key)
889
 
{
890
 
        VeSection *section;
891
 
        char *key_name;
892
 
        int len;
893
 
        GList *lines, *li;
894
 
 
895
 
        g_return_if_fail (config != NULL);
896
 
        g_return_if_fail (key != NULL);
897
 
 
898
 
        section = find_or_make_section (config, key, &key_name,
899
 
                                        FALSE /* make_new */);
900
 
        if (section == NULL) {
901
 
                g_free (key_name);
902
 
                return;
903
 
        }
904
 
 
905
 
        len = strlen (key_name);
906
 
        lines = g_list_copy (section->lines);
907
 
        for (li = lines; li != NULL; li = li->next) {
908
 
                VeLine *line = li->data;
909
 
                if (line->type == VE_LINE_KEY &&
910
 
                    strncmp (line->key, key_name, len) == 0 &&
911
 
                    line->key[len] == '[') {
912
 
                        config->dirty = TRUE;
913
 
 
914
 
                        section->lines = g_list_remove (section->lines, line);
915
 
                        destroy_line (line);
916
 
                }
917
 
        }
918
 
        g_list_free (lines);
919
 
}
920
 
 
921
 
GList *
922
 
ve_config_get_sections (VeConfig *config)
923
 
{
924
 
        GList *li;
925
 
        GList *list;
926
 
 
927
 
        g_return_val_if_fail (config != NULL, NULL);
928
 
 
929
 
        list = NULL;
930
 
 
931
 
        for (li = config->sections; li != NULL; li = li->next) {
932
 
                VeSection *section = li->data;
933
 
                list = g_list_prepend (list, g_strdup (section->name));
934
 
        }
935
 
        return g_list_reverse (list);
936
 
}
937
 
 
938
 
GList *
939
 
ve_config_get_keys (VeConfig *config, const char *section)
940
 
{
941
 
        VeSection *sec;
942
 
        GList *li;
943
 
        GList *list;
944
 
 
945
 
        g_return_val_if_fail (config != NULL, NULL);
946
 
        g_return_val_if_fail (section != NULL, NULL);
947
 
 
948
 
        sec = find_section (config, section);
949
 
        if (sec == NULL)
950
 
                return NULL;
951
 
 
952
 
        list = NULL;
953
 
 
954
 
        for (li = sec->lines; li != NULL; li = li->next) {
955
 
                VeLine *ll = li->data;
956
 
                if (ll->type == VE_LINE_KEY &&
957
 
                    ! ve_string_empty (ll->key))
958
 
                        list = g_list_prepend (list, g_strdup (ll->key));
959
 
        }
960
 
        return g_list_reverse (list);
961
 
}
962
 
 
963
 
void
964
 
ve_config_free_list_of_strings (GList *list)
965
 
{
966
 
        GList *li;
967
 
 
968
 
        if (list == NULL)
969
 
                return;
970
 
 
971
 
        for (li = list; li != NULL; li = li->next) {
972
 
                g_free (li->data);
973
 
                li->data = NULL;
974
 
        }
975
 
 
976
 
        g_list_free (list);
977
 
}
978