1 /*
2 | Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
3 | Copyright (C) 2006 James Liggett <jrliggett at cox.net>
4 | Part of the gtkpod project.
5 |
6 | URL: http://www.gtkpod.org/
7 | URL: http://gtkpod.sourceforge.net/
8 |
9 | This program is free software; you can redistribute it and/or modify
10 | it under the terms of the GNU General Public License as published by
11 | the Free Software Foundation; either version 2 of the License, or
12 | (at your option) any later version.
13 |
14 | This program is distributed in the hope that it will be useful,
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | GNU General Public License for more details.
18 |
19 | You should have received a copy of the GNU General Public License
20 | along with this program; if not, write to the Free Software
21 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 |
23 | iTunes and iPod are trademarks of Apple
24 |
25 | This product is not supported/written/published by Apple!
26 |
27 | $Id$
28 */
29
30 /* -------------------------------------------------------------------
31 *
32 * HOWTO add a new_option to the prefs dialog
33 *
34 * - add the desired option to the prefs window using glade-2
35 *
36 * - set the default value of new_option in set_default_preferences() in prefs.c
37 *
38 * - add a callback on_new_option_*() to prefs_windows.c to set the
39 * new value.
40 * The value is applied to the actual prefs when pressing the "OK"
41 * or "Apply" button in the prefs window.
42 *
43 * - add code to prefs_window_create() in prefs_window.c to set the
44 * correct state of the option in the prefs window.
45 *
46 * - if you want new_option to be a command line option as well, add
47 * code to usage() and read_commandline().
48 *
49 * - for environment variables, add code to read_environment().
50 *
51 * ---------------------------------------------------------------- */
52
53 /* ----------------------------------------------------------------
54 *
55 * The prefs module should be thread safe. The hash table is locked
56 * before each read or write access.
57 *
58 * The temp_prefs module is not thread-safe. If necessary a locking
59 * mechanism can be implemented.
60 *
61 * ---------------------------------------------------------------- */
62
63
64
65
66 /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
67 Ditto for AIX 3.2 and <stdlib.h>. */
68 #ifndef _NO_PROTO
69 # define _NO_PROTO
70 #endif
71
72 #ifdef HAVE_CONFIG_H
73 # include <config.h>
74 #endif
75
76 #include <stdio.h>
77 #include <string.h>
78 #include <glib/gstdio.h>
79 #ifdef HAVE_GETOPT_LONG_ONLY
80 # include <getopt.h>
81 #else
82 # include "getopt.h"
83 #endif
84
85 #include "clientserver.h"
86 #include "misc.h"
87 #include "prefs.h"
88
89 /*
90 * Data global to this module only
91 */
92
93 /* End-of-list marker for variable-length lists */
94 #define LIST_END_MARKER "----++++----"
95
96 struct temp_prefs_save
97 {
98 GIOChannel *gio;
99 GError **error;
100 gboolean success;
101 };
102
103 struct sub_data
104 {
105 TempPrefs *temp_prefs;
106 TempPrefs *temp_prefs_orig;
107 const gchar *subkey;
108 const gchar *subkey2;
109 gboolean exists;
110 };
111
112 /* Pointer to preferences hash table */
113 static GHashTable *prefs_table = NULL;
114 static GMutex *prefs_table_mutex = NULL;
115
116 /*
117 * Functions used by this module only
118 */
119 void discard_prefs (void);
120
121 /* Different paths that can be set in the prefs window */
122 typedef enum
123 {
124 PATH_PLAY_NOW = 0,
125 PATH_PLAY_ENQUEUE,
126 PATH_MP3GAIN,
127 PATH_SYNC_CONTACTS,
128 PATH_SYNC_CALENDAR,
129 PATH_MSERV_MUSIC_ROOT,
130 PATH_MSERV_TRACKINFO_ROOT,
131 PATH_SYNC_NOTES,
132 PATH_AACGAIN,
133 PATH_NUM
134 } PathType;
135
136 /* enum for reading of options */
137 enum {
138 GP_HELP,
139 GP_PLAYCOUNT,
140 GP_MOUNT,
141 GP_PRINT_HASH,
142 };
143
144
145 /* Lock the prefs table. If the table is already locked the calling
146 * thread will remain blocked until the lock is released by the other thread. */
lock_prefs_table()147 static void lock_prefs_table ()
148 {
149 g_return_if_fail (prefs_table_mutex);
150 g_mutex_lock (prefs_table_mutex);
151 }
152
153 /* Unlock the prefs table again. */
unlock_prefs_table()154 static void unlock_prefs_table ()
155 {
156 g_return_if_fail (prefs_table_mutex);
157 g_mutex_unlock (prefs_table_mutex);
158 }
159
160
161 /* Set default preferences */
set_default_preferences()162 static void set_default_preferences()
163 {
164 int i;
165 gchar *str;
166
167 prefs_set_int("update_existing", FALSE);
168 prefs_set_int("id3_write", FALSE);
169 prefs_set_int("id3_write_id3v24", FALSE);
170 prefs_set_int(KEY_SYNC_DELETE_TRACKS, TRUE);
171 prefs_set_int(KEY_SYNC_CONFIRM_DELETE, TRUE);
172 prefs_set_int(KEY_SYNC_SHOW_SUMMARY, TRUE);
173 prefs_set_int("show_duplicates", TRUE);
174 prefs_set_int("show_non_updated", TRUE);
175 prefs_set_int("show_updated", TRUE);
176 prefs_set_int("photo_library_confirm_delete", TRUE);
177 prefs_set_int("mserv_report_probs", TRUE);
178 prefs_set_int("delete_ipod", TRUE);
179 prefs_set_int("delete_file", TRUE);
180 prefs_set_int("delete_local_file", TRUE);
181 prefs_set_int("delete_database", TRUE);
182 prefs_set_string("initial_mountpoint", "/mnt/ipod");
183 prefs_set_string ("path_play_now", "xmms %s");
184 prefs_set_string ("path_play_enqueue", "xmms -e %s");
185 prefs_set_string ("path_mserv_trackinfo_root", "/var/lib/mserv/trackinfo/");
186 prefs_set_string ("coverart_display_bg_color", "#000000");
187 prefs_set_string ("coverart_display_fg_color", "#FFFFFF");
188
189 str = g_build_filename (SCRIPTDIR, "convert-ogg2mp3.sh", NULL);
190 prefs_set_string ("path_conv_ogg", str);
191 g_free (str);
192 prefs_set_int ("convert_ogg", TRUE);
193
194 str = g_build_filename (SCRIPTDIR, "convert-flac2mp3.sh", NULL);
195 prefs_set_string ("path_conv_flac", str);
196 g_free (str);
197 prefs_set_int ("convert_flac", TRUE);
198
199 str = g_build_filename (SCRIPTDIR, "convert-wav2mp3.sh", NULL);
200 prefs_set_string ("path_conv_wav", str);
201 g_free (str);
202 prefs_set_int ("convert_wav", FALSE);
203
204
205 /* Set sorting tab defaults */
206 for (i = 0; i < SORT_TAB_MAX; i++)
207 {
208 prefs_set_int_index("st_autoselect", i, TRUE);
209 prefs_set_int_index("st_category", i, (i < ST_CAT_NUM ? i : 0));
210 prefs_set_int_index("sp_or", i, FALSE);
211 prefs_set_int_index("sp_rating_cond", i, FALSE);
212 prefs_set_int_index("sp_playcount_cond", i, FALSE);
213 prefs_set_int_index("sp_played_cond", i, FALSE);
214 prefs_set_int_index("sp_modified_cond", i, FALSE);
215 prefs_set_int_index("sp_added_cond", i, FALSE);
216 prefs_set_int_index("sp_rating_state", i, 0);
217 prefs_set_string_index("sp_played_state", i, ">4w");
218 prefs_set_string_index("sp_modified_state", i, "<1d");
219 prefs_set_string_index("sp_added_state", i, "<1d");
220 prefs_set_int_index("sp_playcount_low", i, 0);
221 prefs_set_int_index("sp_playcount_high", i, -1);
222 prefs_set_int_index("sp_autodisplay", i, FALSE);
223 }
224
225 prefs_set_int("sort_tab_num", 2);
226
227 /* Set colum preferences */
228 for (i = 0; i < TM_NUM_COLUMNS; i++)
229 {
230 prefs_set_int_index("col_order", i, i);
231 }
232
233 prefs_set_int_index("col_visible", TM_COLUMN_ARTIST, TRUE);
234 prefs_set_int_index("col_visible", TM_COLUMN_ALBUM, TRUE);
235 prefs_set_int_index("col_visible", TM_COLUMN_TITLE, TRUE);
236 prefs_set_int_index("col_visible", TM_COLUMN_TRACKLEN, TRUE);
237 prefs_set_int_index("col_visible", TM_COLUMN_RATING, TRUE);
238
239 for (i = 0; i < TM_NUM_TAGS_PREFS; i++)
240 {
241 prefs_set_int_index("tag_autoset", i, FALSE);
242 }
243
244 prefs_set_int_index("tag_autoset", TM_COLUMN_TITLE, TRUE);
245
246 prefs_set_int("horizontal_scrollbar", TRUE);
247 prefs_set_int("filter_tabs_top", FALSE);
248
249 /* Set pane positions--Let gtk worry about position */
250 for (i = 0; i < PANED_NUM; i++)
251 prefs_set_int_index("paned_pos_", i, -1);
252
253 prefs_set_int("mpl_autoselect", TRUE);
254
255 /* Set window sizes */
256 prefs_set_int("size_gtkpod.x", 780);
257 prefs_set_int("size_gtkpod.y", 580);
258 prefs_set_int("size_cal.x", 500);
259 prefs_set_int("size_cal.y", 300);
260 prefs_set_int("size_conf_sw.x", 300);
261 prefs_set_int("size_conf_sw.y", 300);
262 prefs_set_int("size_conf.x", 300);
263 prefs_set_int("size_conf.y", -1);
264 prefs_set_int("size_dirbr.x", 300);
265 prefs_set_int("size_dirbr.y", 400);
266 prefs_set_int("size_prefs.x", -1);
267 prefs_set_int("size_prefs.y", 480);
268 prefs_set_int("size_info.x", 510);
269 prefs_set_int("size_info.y", 300);
270
271 /* size of file dialog if there is not a details textview */
272 prefs_set_int("size_file_dialog.x", 320);
273 prefs_set_int("size_file_dialog.y", 140);
274
275 /* size of file dialog if there is a details textview */
276 prefs_set_int("size_file_dialog_details.x", 320);
277 prefs_set_int("size_file_dialog_details.y", 140);
278
279 prefs_set_int("readtags", TRUE);
280 prefs_set_int("parsetags", FALSE);
281 prefs_set_int("parsetags_overwrite", FALSE);
282 prefs_set_string("parsetags_template", "%a - %A/%T %t.mp3;%t.wav");
283 prefs_set_int("coverart_apic", TRUE);
284 prefs_set_int("coverart_file", TRUE);
285 prefs_set_string("coverart_template", "%A;folder.jpg");
286 prefs_set_string("video_thumbnailer_prog", "totem-video-thumbnailer %f %o");
287 prefs_set_int("mserv_use", FALSE);
288 prefs_set_string("mserv_username", "");
289 prefs_set_int("startup_messages", TRUE);
290 prefs_set_int("add_recursively", TRUE);
291 prefs_set_int("info_window", FALSE);
292 prefs_set_int("last_prefs_page", 0);
293 prefs_set_int("multi_edit_title", TRUE);
294 prefs_set_int("multi_edit", FALSE);
295 prefs_set_int("not_played_track", TRUE);
296 prefs_set_int("misc_track_nr", 25);
297 prefs_set_int("update_charset", FALSE);
298 prefs_set_int("display_tooltips_main", TRUE);
299 prefs_set_int("display_tooltips_prefs", TRUE);
300 prefs_set_int("display_toolbar", TRUE);
301 prefs_set_int("toolbar_style", GTK_TOOLBAR_BOTH);
302 prefs_set_int("sha1", TRUE);
303 prefs_set_int("file_dialog_details_expanded", FALSE);
304
305 /* Set last browsed directory */
306 str = g_get_current_dir();
307
308 if (str)
309 {
310 prefs_set_string("last_dir_browsed", str);
311 g_free(str);
312 }
313 else
314 prefs_set_string("last_dir_browsed", g_get_home_dir());
315
316 /* Set sorting prefs */
317 prefs_set_int("case_sensitive", FALSE);
318 prefs_set_int("tm_autostore", FALSE);
319 prefs_set_int("st_sort", SORT_NONE);
320 prefs_set_int("pm_sort", SORT_NONE);
321 prefs_set_int("tm_sortcol", TM_COLUMN_TITLE);
322 prefs_set_int("tm_sort", SORT_NONE);
323
324 /* New conversion preferences */
325 prefs_set_int("conversion_target_format", TARGET_FORMAT_MP3);
326
327 /* ReplayGain prefs */
328 prefs_set_int("replaygain_offset", 0);
329 prefs_set_int("replaygain_mode_album_priority", TRUE);
330 }
331
332 /* Initialize default variable-length list entries */
set_default_list_entries()333 static void set_default_list_entries()
334 {
335 if (!prefs_get_string_value_index("sort_ign_string_", 0, NULL))
336 {
337 prefs_set_string_index("sort_ign_string_", 0, "a ");
338 prefs_set_string_index("sort_ign_string_", 1, "an ");
339 prefs_set_string_index("sort_ign_string_", 2, LIST_END_MARKER);
340 }
341 }
342
343 /* A printf-like function that outputs in the system locale */
locale_fprintf(FILE * fp,const gchar * format,...)344 static void locale_fprintf(FILE *fp, const gchar *format, ...)
345 {
346 gchar *utf8_string; /* Raw UTF-8 string */
347 gchar *locale_string; /* String in system locale format */
348 va_list format_list; /* Printf-like formatting arguments */
349
350 /* Create the locale format string based on the given format */
351 va_start(format_list, format);
352 utf8_string = g_strdup_vprintf(format, format_list);
353 va_end(format_list);
354
355 locale_string = g_locale_from_utf8 (utf8_string, -1, NULL, NULL, NULL);
356
357 if (fp)
358 fprintf(fp, "%s", locale_string);
359
360 g_free(utf8_string);
361 g_free(locale_string);
362 }
363
364 /* Print commandline usage information */
usage(FILE * fp)365 static void usage(FILE *fp)
366 {
367 locale_fprintf(fp, _("gtkpod version %s usage:\n"), VERSION);
368 locale_fprintf(fp, _(" -h, --help: display this message\n"));
369 locale_fprintf(fp, _(" -p <file>: increment playcount for file by one\n"));
370 locale_fprintf(fp, _(" --hash <file>:print gtkpod hash for file\n"));
371 locale_fprintf(fp, _(" -m path: define the mountpoint of your iPod\n"));
372 locale_fprintf(fp, _(" --mountpoint: same as '-m'.\n"));
373 }
374
375 /* Parse commandline based options */
read_commandline(int argc,char * argv[])376 static void read_commandline(int argc, char *argv[])
377 {
378 int option; /* Code returned by getopt */
379
380 /* The options data structure. The format is standard getopt. */
381 struct option const options[] =
382 {
383 { "h", no_argument, NULL, GP_HELP },
384 { "help", no_argument, NULL, GP_HELP },
385 { "p", required_argument, NULL, GP_PLAYCOUNT },
386 { "hash", required_argument, NULL, GP_PRINT_HASH },
387 { "m", required_argument, NULL, GP_MOUNT },
388 { "mountpoint", required_argument, NULL, GP_MOUNT },
389 { 0, 0, 0, 0 }
390 };
391
392 /* Handle commandline options */
393 while ((option = getopt_long_only(argc, argv, "", options, NULL)) != -1)
394 {
395 switch (option)
396 {
397 case GP_HELP:
398 usage(stdout);
399 exit(0);
400 break;
401 case GP_PLAYCOUNT:
402 client_playcount(optarg);
403 exit(0);
404 break;
405 case GP_PRINT_HASH:
406 print_sha1_hash (optarg);
407 exit(0);
408 break;
409 case GP_MOUNT:
410 prefs_set_string("initial_mountpoint", optarg);
411 break;
412 default:
413 locale_fprintf(stderr, "Unknown option: %s\n", argv[optind]);
414 usage(stderr);
415 exit(1);
416 break;
417 };
418 }
419 }
420
421 /* Read options from environment variables */
read_environment()422 static void read_environment()
423 {
424 gchar *buf;
425
426 buf = convert_filename(getenv("IPOD_MOUNTPOINT"));
427 if (buf)
428 prefs_set_string("initial_mountpoint", buf);
429 g_free(buf);
430 }
431
432 /* Create a full numbered key from a base key string and a number.
433 * Free returned string. */
create_full_key(const gchar * base_key,gint index)434 static gchar *create_full_key(const gchar *base_key, gint index)
435 {
436 if (base_key)
437 return g_strdup_printf("%s%i", base_key, index);
438 else
439 return NULL;
440 }
441
442 /* Remove key present in the temp prefs tree from the hash table */
flush_key(gpointer key,gpointer value,gpointer user_data)443 static gboolean flush_key (gpointer key, gpointer value, gpointer user_data)
444 {
445 g_return_val_if_fail (prefs_table, FALSE);
446
447 g_hash_table_remove (prefs_table, key);
448
449 return FALSE;
450 }
451
452
453 /* Copy key data from the temp prefs tree to the hash table (or to
454 * sub_data->temp_prefs_orig if non-NULL). The old key is removed. */
subst_key(gpointer key,gpointer value,gpointer user_data)455 static gboolean subst_key (gpointer key, gpointer value, gpointer user_data)
456 {
457 struct sub_data *sub_data = user_data;
458 gint len;
459
460 g_return_val_if_fail (key && value && user_data, FALSE);
461 g_return_val_if_fail (sub_data->subkey && sub_data->subkey2, FALSE);
462 if (!sub_data->temp_prefs_orig)
463 g_return_val_if_fail (prefs_table, FALSE);
464 if (sub_data->temp_prefs_orig)
465 g_return_val_if_fail (sub_data->temp_prefs_orig->tree, FALSE);
466
467 len = strlen (sub_data->subkey);
468
469 if (strncmp (key, sub_data->subkey, len) == 0)
470 {
471 gchar *new_key = g_strdup_printf ("%s%s",
472 sub_data->subkey2,
473 ((gchar *)key)+len);
474 if (sub_data->temp_prefs_orig)
475 {
476 g_tree_remove (sub_data->temp_prefs_orig->tree, key);
477 g_tree_insert (sub_data->temp_prefs_orig->tree,
478 new_key, g_strdup(value));
479 }
480 else
481 {
482 g_hash_table_remove (prefs_table, key);
483 g_hash_table_insert (prefs_table, new_key, g_strdup(value));
484 }
485 }
486 return FALSE;
487 }
488
489 /* return TRUE if @key starts with @subkey */
match_subkey(gpointer key,gpointer value,gpointer subkey)490 static gboolean match_subkey (gpointer key, gpointer value, gpointer subkey)
491 {
492 g_return_val_if_fail (key && subkey, FALSE);
493
494 if (strncmp (key, subkey, strlen (subkey)) == 0) return TRUE;
495 return FALSE;
496 }
497
498
499 /* return TRUE and set sub_data->exists to TRUE if @key starts with
500 * @subkey */
check_subkey(gpointer key,gpointer value,gpointer user_data)501 static gboolean check_subkey (gpointer key, gpointer value, gpointer user_data)
502 {
503 struct sub_data *sub_data = user_data;
504
505 g_return_val_if_fail (key && user_data, TRUE);
506 g_return_val_if_fail (sub_data->subkey, TRUE);
507
508 if (strncmp (key, sub_data->subkey, strlen (sub_data->subkey)) == 0)
509 {
510 sub_data->exists = TRUE;
511 return TRUE;
512 }
513 return FALSE;
514 }
515
516
517
518 /* Add key/value to temp_prefs if it matches subkey -- called by
519 * prefs_create_subset() and temp_prefs_create_subset() */
get_subset(gpointer key,gpointer value,gpointer user_data)520 static gboolean get_subset (gpointer key, gpointer value, gpointer user_data)
521 {
522 struct sub_data *sub_data = user_data;
523
524 g_return_val_if_fail (key && value && user_data, TRUE);
525 g_return_val_if_fail (sub_data->subkey && sub_data->temp_prefs, TRUE);
526
527 if (strncmp (key, sub_data->subkey,
528 strlen (sub_data->subkey)) == 0)
529 { /* match */
530 temp_prefs_set_string (sub_data->temp_prefs, key, value);
531 }
532 return FALSE; /* continue traversal (g_tree), ignored for g_hash */
533 }
534
535
536 /* Copy a variable-length list to the prefs table */
copy_list(gpointer key,gpointer value,gpointer user_data)537 static gboolean copy_list(gpointer key, gpointer value, gpointer user_data)
538 {
539 prefs_apply_list((gchar*)key, (GList*)value);
540 return FALSE;
541 }
542
543 /* Callback that writes pref table data to a file */
write_key(gpointer key,gpointer value,gpointer user_data)544 static void write_key(gpointer key, gpointer value, gpointer user_data)
545 {
546 FILE *fp; /* file pointer passed in through user_data */
547
548 /* Write out each key and value to the given file */
549 fp = (FILE*)user_data;
550
551 if (fp)
552 fprintf(fp, "%s=%s\n", (gchar*)key, (gchar*)value);
553 }
554
555 /* Gets a string that contains ~/.gtkpod/ If the folder doesn't exist,
556 * create it. Free the string when you are done with it.
557 * If the folder wasn't found, and couldn't be created, return NULL */
prefs_get_cfgdir()558 gchar *prefs_get_cfgdir()
559 {
560 gchar *folder; /* Folder path */
561
562 /* Create the folder path. If the folder doesn't exist, create it. */
563 folder = g_build_filename(g_get_home_dir(), ".gtkpod", NULL);
564
565 if (!g_file_test(folder, G_FILE_TEST_IS_DIR))
566 {
567 if ((g_mkdir(folder, 0777)) == -1)
568 {
569 printf(_("Couldn't create '%s'\n"), folder);
570 g_free (folder);
571 return NULL;
572 }
573 }
574 return folder;
575 }
576
577
578 /* get @key and @value from a string like "key=value" */
579 /* you must g_free (*key) and (*value) after use */
read_prefs_get_key_value(const gchar * buf,gchar ** key,gchar ** value)580 static gboolean read_prefs_get_key_value (const gchar *buf,
581 gchar **key, gchar **value)
582 {
583 size_t len; /* string length */
584 const gchar *buf_start; /* Pointer to where actual useful data starts in line */
585
586 g_return_val_if_fail (buf && key && value, FALSE);
587
588 /* Strip out any comments (lines that begin with ; or #) */
589 if ((buf[0] == ';') || (buf[0] == '#'))
590 return FALSE;
591
592 /* Find the key and value, and look for malformed lines */
593 buf_start = strchr (buf, '=');
594
595 if ((!buf_start) || (buf_start == buf))
596 {
597 printf("Parse error reading prefs: %s", buf);
598 return FALSE;
599 }
600
601 /* Find the key name */
602 *key = g_strndup (buf, (buf_start - buf));
603
604 /* Strip whitespace */
605 g_strstrip (*key);
606
607 /* Find the value string */
608 *value = strdup (buf_start+1);
609
610 /* remove newline */
611 len = strlen (*value);
612 if ((len > 0) && ((*value)[len - 1] == 0x0a))
613 (*value)[len - 1] = 0;
614
615 /* Don't strip whitespace! If there is any, there's a reason for it. */
616 /* g_strstrip (*value); */
617
618 return TRUE;
619 }
620
621
622 /* Read preferences from a file */
read_prefs_from_file(FILE * fp)623 static void read_prefs_from_file(FILE *fp)
624 {
625 gchar buf[PATH_MAX]; /* Buffer that contains one line */
626 gchar *key; /* Pref value key */
627 gchar *value; /* Pref value */
628
629
630 g_return_if_fail (prefs_table && fp);
631
632 while (fgets(buf, PATH_MAX, fp))
633 {
634 if (read_prefs_get_key_value (buf, &key, &value))
635 {
636 g_hash_table_insert (prefs_table, key, value);
637 }
638 }
639 }
640
641 /* Write prefs to file */
write_prefs_to_file(FILE * fp)642 static void write_prefs_to_file(FILE *fp)
643 {
644 lock_prefs_table ();
645
646 if (!prefs_table)
647 {
648 unlock_prefs_table ();
649 g_return_if_reached ();
650 }
651
652 g_hash_table_foreach(prefs_table, write_key, (gpointer)fp);
653
654 unlock_prefs_table ();
655 }
656
657 /* Load preferences, first loading the defaults, and then overwrite that with
658 * preferences in the user home folder. */
load_prefs()659 static void load_prefs()
660 {
661 gchar *filename; /* Config path to open */
662 gchar *config_dir; /* Directory where config is (usually ~/.gtkpod) */
663 FILE *fp;
664
665 /* Start by initializing the prefs to their default values */
666 set_default_preferences();
667
668 /* and then override those values with those found in the home folder. */
669 config_dir = prefs_get_cfgdir();
670
671 if (config_dir)
672 {
673 filename = g_build_filename(config_dir, "prefs", NULL);
674
675 if (filename)
676 {
677 fp = fopen(filename, "r");
678
679 if (fp)
680 {
681 read_prefs_from_file(fp);
682 fclose(fp);
683 }
684
685 g_free(filename);
686 }
687
688 g_free(config_dir);
689 }
690
691 /* Finally, initialize variable-length lists. Do this after everything else
692 * so that list defaults don't hang out in the table after prefs have been
693 * read from the file. */
694 set_default_list_entries();
695 }
696
697 /* Save preferences to user home folder (~/.gtkpod/prefs) */
prefs_save()698 void prefs_save ()
699 {
700 gchar *filename; /* Path of file to write to */
701 gchar *config_dir; /* Folder where prefs file is */
702 FILE *fp; /* File pointer */
703
704 /* Open $HOME/.gtkpod/prefs, and write prefs */
705 config_dir = prefs_get_cfgdir();
706
707 if (config_dir)
708 {
709 filename = g_build_filename(config_dir, "prefs", NULL);
710
711 if (filename)
712 {
713 fp = fopen(filename, "w");
714
715 if (fp)
716 {
717 write_prefs_to_file(fp);
718 fclose(fp);
719 }
720
721 g_free(filename);
722 }
723
724 g_free(config_dir);
725 }
726 }
727
728
temp_prefs_save_fe(gchar * key,gchar * value,struct temp_prefs_save * tps)729 static gboolean temp_prefs_save_fe (gchar *key, gchar *value,
730 struct temp_prefs_save *tps)
731 {
732 gchar *buf;
733 GIOStatus status;
734
735 buf=g_strdup_printf ("%s=%s\n", key, value);
736 status = g_io_channel_write_chars (tps->gio, buf, -1, NULL, tps->error);
737 g_free (buf);
738 if (status != G_IO_STATUS_NORMAL)
739 {
740 tps->success = FALSE;
741 return TRUE; /* stop traversal */
742 }
743 return FALSE;
744 }
745
746
747 /* Save @temp_prefs to @filename in the same manner as prefs_save is
748 * saving to ~/.gtkpod/prefs. @error: location where to store
749 * information about errors or NULL.
750 *
751 * Return value: TRUE on success, FALSE if an error occured, in which
752 * case @error will be set accordingly.
753 */
temp_prefs_save(TempPrefs * temp_prefs,const gchar * filename,GError ** error)754 gboolean temp_prefs_save (TempPrefs *temp_prefs,
755 const gchar *filename,
756 GError **error)
757 {
758 GIOChannel *gio;
759 struct temp_prefs_save tps;
760
761 g_return_val_if_fail (temp_prefs && filename, FALSE);
762
763 gio = g_io_channel_new_file (filename, "w", error);
764 tps.gio = gio;
765 tps.error = error;
766 tps.success = TRUE;
767 if (gio)
768 {
769 g_tree_foreach (temp_prefs->tree, (GTraverseFunc)temp_prefs_save_fe, &tps);
770 g_io_channel_unref (gio);
771 }
772
773 return tps.success;
774 }
775
776
temp_prefs_load(const gchar * filename,GError ** error)777 TempPrefs *temp_prefs_load (const gchar *filename, GError **error)
778 {
779 GIOChannel *gio;
780 TempPrefs *temp_prefs = NULL;
781
782 g_return_val_if_fail (filename, NULL);
783
784 gio = g_io_channel_new_file (filename, "r", error);
785 if (gio)
786 {
787 GIOStatus status;
788
789 temp_prefs = temp_prefs_create ();
790
791 do
792 {
793 gchar *line = NULL;
794
795 status = g_io_channel_read_line (gio, &line, NULL, NULL, error);
796 if (status == G_IO_STATUS_NORMAL)
797 {
798 gchar *key, *value;
799 if (read_prefs_get_key_value (line, &key, &value))
800 {
801 temp_prefs_set_string (temp_prefs, key, value);
802 g_free (key);
803 g_free (value);
804 }
805 }
806 g_free (line);
807 } while (status == G_IO_STATUS_NORMAL);
808
809 g_io_channel_unref (gio);
810
811 if (status != G_IO_STATUS_EOF)
812 {
813 temp_prefs_destroy (temp_prefs);
814 temp_prefs = NULL;
815 }
816 }
817
818 return temp_prefs;
819 }
820
821
822 /* Removes already existing list keys from the prefs table */
wipe_list(const gchar * key)823 static void wipe_list(const gchar *key)
824 {
825 gchar *full_key; /* Complete key, with its number suffix */
826 guint i; /* Loop counter */
827
828 /* Go through the prefs table, starting at key<number>, delete it and go
829 * through key<number+1>... until there are no keys left */
830
831 for (i = 0;;i++)
832 {
833 full_key = create_full_key(key, i);
834
835 if (g_hash_table_remove(prefs_table, full_key))
836 {
837 g_free(full_key);
838 continue;
839 }
840 else /* We got all the unneeded keys, leave the loop... */
841 {
842 g_free(full_key);
843 break;
844 }
845 }
846 }
847
848 /* Delete and rename keys */
cleanup_keys()849 static void cleanup_keys()
850 {
851 gchar *buf;
852 gint int_buf;
853 gint i;
854 gint x, y, p; /* Window position */
855 float version=0;
856
857 /* Get version */
858 version = prefs_get_double("version");
859
860 /* rename mountpoint to initial_mountpoint */
861 if (prefs_get_string_value(KEY_MOUNTPOINT, &buf))
862 {
863 prefs_set_string("initial_mountpoint", buf);
864 g_free(buf);
865 prefs_set_string(KEY_MOUNTPOINT, NULL);
866 }
867
868 /* rename coverart to coverart_file */
869 if (prefs_get_string_value("coverart", &buf))
870 {
871 prefs_set_string("coverart_file", buf);
872 g_free(buf);
873 prefs_set_string("coverart", NULL);
874 }
875
876 /* rename tm_sort_ to tm_sort */
877 if (prefs_get_string_value("tm_sort_", &buf))
878 {
879 prefs_set_string("tm_sort", buf);
880 g_free(buf);
881 prefs_set_string("tm_sort_", NULL);
882 }
883
884 /* rename md5 to sha1 */
885 if (prefs_get_string_value("md5", &buf))
886 {
887 prefs_set_string("sha1", buf);
888 g_free(buf);
889 prefs_set_string("md5", NULL);
890 }
891
892 /* Convert old path numbered keys to named ones */
893
894 /* Play Now */
895 if (prefs_get_string_value_index("path", PATH_PLAY_NOW, &buf))
896 {
897 prefs_set_string("path_play_now", buf);
898 prefs_set_string_index("path", PATH_PLAY_NOW, NULL);
899 if (version < 0.87)
900 { /* default changed from "xmms -p %s" to "xmms
901 %s" which avoids xmms from hanging --
902 thanks to Chris Vine */
903 if (strcmp (buf, "xmms -p %s") == 0)
904 {
905 prefs_set_string ("path_play_now", "xmms %s");
906 }
907 }
908 g_free(buf);
909 }
910
911 if (prefs_get_string_value_index("toolpath", PATH_PLAY_NOW, &buf))
912 {
913 prefs_set_string("path_play_now", buf);
914 g_free(buf);
915 prefs_set_string_index("toolpath", PATH_PLAY_NOW, NULL);
916 }
917
918 /* Enqueue */
919 if (prefs_get_string_value_index("path", PATH_PLAY_ENQUEUE, &buf))
920 {
921 prefs_set_string("path_play_enqueue", buf);
922 g_free(buf);
923 prefs_set_string_index("path", PATH_PLAY_ENQUEUE, NULL);
924 }
925
926 if (prefs_get_string_value_index("toolpath", PATH_PLAY_ENQUEUE, &buf))
927 {
928 prefs_set_string("path_play_enqueue", buf);
929 g_free(buf);
930 prefs_set_string_index("toolpath", PATH_PLAY_ENQUEUE, NULL);
931 }
932
933 /* MP3 Gain */
934 if (prefs_get_string_value_index("path", PATH_MP3GAIN, &buf))
935 {
936 prefs_set_string("path_mp3gain", buf);
937 g_free(buf);
938 prefs_set_string_index("path", PATH_MP3GAIN, NULL);
939 }
940
941 if (prefs_get_string_value_index("toolpath", PATH_MP3GAIN, &buf))
942 {
943 prefs_set_string("path_mp3gain", buf);
944 g_free(buf);
945 prefs_set_string_index("toolpath", PATH_MP3GAIN, NULL);
946 }
947
948 /* Sync contacts */
949 if (prefs_get_string_value_index("path", PATH_SYNC_CONTACTS, &buf))
950 {
951 prefs_set_string("itdb_0_path_sync_contacts", buf);
952 g_free(buf);
953 prefs_set_string_index("path", PATH_SYNC_CONTACTS, NULL);
954 }
955
956 if (prefs_get_string_value_index("toolpath", PATH_SYNC_CONTACTS, &buf))
957 {
958 prefs_set_string("itdb_0_path_sync_contacts", buf);
959 g_free(buf);
960 prefs_set_string_index("toolpath", PATH_SYNC_CONTACTS, NULL);
961 }
962
963 /* Sync calendar */
964 if (prefs_get_string_value_index("path", PATH_SYNC_CALENDAR, &buf))
965 {
966 prefs_set_string("itdb_0_path_sync_calendar", buf);
967 g_free(buf);
968 prefs_set_string_index("path", PATH_SYNC_CALENDAR, NULL);
969 }
970
971 if (prefs_get_string_value_index("toolpath", PATH_SYNC_CALENDAR, &buf))
972 {
973 prefs_set_string("itdb_0_path_sync_calendar", buf);
974 g_free(buf);
975 prefs_set_string_index("toolpath", PATH_SYNC_CALENDAR, NULL);
976 }
977
978 /* Sync notes */
979 if (prefs_get_string_value_index("path", PATH_SYNC_NOTES, &buf))
980 {
981 prefs_set_string("itdb_0_path_sync_notes", buf);
982 g_free(buf);
983 prefs_set_string_index("path", PATH_SYNC_NOTES, NULL);
984 }
985
986 if (prefs_get_string_value_index("toolpath", PATH_SYNC_NOTES, &buf))
987 {
988 prefs_set_string("itdb_0_path_sync_notes", buf);
989 g_free(buf);
990 prefs_set_string_index("toolpath", PATH_SYNC_NOTES, NULL);
991 }
992
993 /* MSERV music root */
994 if (prefs_get_string_value_index("path", PATH_MSERV_MUSIC_ROOT, &buf))
995 {
996 prefs_set_string("path_mserv_music_root", buf);
997 g_free(buf);
998 prefs_set_string_index("path", PATH_MSERV_MUSIC_ROOT, NULL);
999 }
1000
1001 if (prefs_get_string_value_index("toolpath", PATH_MSERV_MUSIC_ROOT, &buf))
1002 {
1003 prefs_set_string("path_mserv_music_root", buf);
1004 g_free(buf);
1005 prefs_set_string_index("toolpath", PATH_MSERV_MUSIC_ROOT, NULL);
1006 }
1007
1008 /* MSERV track info root */
1009 if (prefs_get_string_value_index("path", PATH_MSERV_TRACKINFO_ROOT, &buf))
1010 {
1011 prefs_set_string("path_mserv_trackinfo_root", buf);
1012 g_free(buf);
1013 prefs_set_string_index("path", PATH_MSERV_TRACKINFO_ROOT, NULL);
1014 }
1015
1016 if (prefs_get_string_value_index("toolpath", PATH_MSERV_TRACKINFO_ROOT, &buf))
1017 {
1018 prefs_set_string("path_mserv_trackinfo_root", buf);
1019 g_free(buf);
1020 prefs_set_string_index("toolpath", PATH_MSERV_TRACKINFO_ROOT, NULL);
1021 }
1022
1023 /* If there's an extra (PATH_NUM) key, delete it */
1024 prefs_set_string_index("path", PATH_NUM, NULL);
1025 prefs_set_string_index("toolpath", PATH_NUM, NULL);
1026
1027 /* Ignore/remove some keys */
1028 prefs_set_string("play_now_path", NULL);
1029 prefs_set_string("sync_remove", NULL);
1030 prefs_set_string("sync_remove_confirm", NULL);
1031 prefs_set_string("show_sync_dirs", NULL);
1032 prefs_set_string("play_enqueue_path", NULL);
1033 prefs_set_string("mp3gain_path", NULL);
1034 prefs_set_string("statusbar_timeout", NULL);
1035 prefs_set_string("offline", NULL);
1036 prefs_set_string("time_format", NULL);
1037 prefs_set_string("id3_all", NULL);
1038 prefs_set_string("pm_autostore", NULL);
1039 prefs_set_string("backups", NULL);
1040 prefs_set_string("save_sorted_order", NULL);
1041 prefs_set_string("fix_path", NULL);
1042 prefs_set_string("write_gaintag", NULL);
1043 prefs_set_string("automount", NULL);
1044 prefs_set_string("display_artcovers", NULL);
1045 prefs_set_string("block_display", NULL);
1046 prefs_set_string("tmp_disable_sort", NULL);
1047 prefs_set_string("size_file_dialog.x", NULL);
1048 prefs_set_string("size_file_dialog.y", NULL);
1049 prefs_set_string("size_file_dialog_details.x", NULL);
1050 prefs_set_string("size_file_dialog_details.y", NULL);
1051 prefs_set_string("autoimport", NULL);
1052 prefs_set_string("auto_import", NULL);
1053 prefs_set_string("conversion_enable", NULL);
1054 prefs_set_string("export_template", NULL);
1055 prefs_set_string("filename_format", NULL);
1056 prefs_set_string("write_extended_info", NULL);
1057
1058 /* sp_created_cond renamed to sp_added_cond */
1059 for (i = 0; i < SORT_TAB_MAX; i++)
1060 {
1061 if (prefs_get_int_value_index("sp_created_cond", i, &int_buf))
1062 {
1063 prefs_set_int_index("sp_added_cond", i, int_buf);
1064 prefs_set_string("sp_created_cond", NULL);
1065 }
1066 }
1067
1068 /* sp_created_state renamed to sp_added_state */
1069 for (i = 0; i < SORT_TAB_MAX; i++)
1070 {
1071 if (prefs_get_int_value_index("sp_created_state", i, &int_buf))
1072 {
1073 prefs_set_int_index("sp_added_state", i, int_buf);
1074 prefs_set_string("sp_created_state", NULL);
1075 }
1076 }
1077
1078 /* sm_col_width renamed to tm_col_width */
1079 for (i = 0; i < TM_NUM_COLUMNS; i++)
1080 {
1081 if (prefs_get_int_value_index("sm_col_width", i, &int_buf))
1082 {
1083 prefs_set_int_index("tm_col_width", i, int_buf);
1084 prefs_set_string_index("sm_col_width", i, NULL);
1085 }
1086 }
1087
1088 /* handle version changes in prefs */
1089 if (version == 0.0)
1090 {
1091 /* most likely prefs file written by V0.50 */
1092 /* I added two new PANED elements since V0.50 --> shift */
1093 for (i=PANED_NUM_ST-1; i>=0; --i)
1094 {
1095 prefs_set_int_index("paned_pos_", PANED_NUM_GLADE + i,
1096 prefs_get_int_index("paned_pos_", PANED_NUM_GLADE + i - 2));
1097 }
1098 prefs_set_int_index("paned_pos_", PANED_STATUS1, -1);
1099 prefs_set_int_index("paned_pos_", PANED_STATUS2, -1);
1100 }
1101
1102 /* set statusbar paned to a decent value if unset */
1103 if (prefs_get_int_index("paned_pos_", PANED_STATUS1) == -1)
1104 {
1105 x = prefs_get_int("size_gtkpod.x");
1106 /* set to about 2/3 of the window width */
1107 if (x>0)
1108 prefs_set_int_index("paned_pos_", PANED_STATUS1, 20*x/30);
1109 }
1110
1111 if (prefs_get_int_index("paned_pos_", PANED_STATUS2) == -1)
1112 {
1113 x = prefs_get_int("size_gtkpod.x");
1114 y = prefs_get_int("size_gtkpod.y");
1115 p = prefs_get_int_index("paned_pos_", PANED_STATUS1);
1116 /* set to about half of the remaining window */
1117 if (x>0)
1118 prefs_set_int_index("paned_pos_", PANED_STATUS2, (x-p)/2 );
1119 }
1120
1121 /* Changed layout of info window between 0.72 and 0.73 */
1122 if (version < 0.73)
1123 {
1124 prefs_set_string("size_info.x", NULL);
1125 prefs_set_string("size_info.y", NULL);
1126 }
1127
1128 /* not_played_song renamed to not_played_track */
1129 if (prefs_get_int_value("not_played_song", &int_buf))
1130 {
1131 prefs_set_int("not_played_track", int_buf);
1132 prefs_set_string("not_played_song", NULL);
1133 }
1134
1135 /* misc_song_nr renamed to misc_track_nr */
1136 if (prefs_get_int_value("misc_song_nr", &int_buf))
1137 {
1138 prefs_set_int("misc_track_nr", int_buf);
1139 prefs_set_string("misc_song_nr", NULL);
1140 }
1141
1142 /* sm_autostore renamed to tm_autostore */
1143 if (prefs_get_int_value("sm_autostore", &int_buf))
1144 {
1145 prefs_set_int("tm_autostore", int_buf);
1146 prefs_set_string("sm_autostore", NULL);
1147 }
1148
1149 /* sm_sortcol renamed to tm_sortcol */
1150 if (prefs_get_int_value("sm_sortcol", &int_buf))
1151 {
1152 prefs_set_int("tm_sortcol", int_buf);
1153 prefs_set_string("sm_sortcol", NULL);
1154 }
1155
1156 /* sm_sort_ renamed to tm_sort */
1157 if (prefs_get_int_value("sm_sort_", &int_buf))
1158 {
1159 prefs_set_int("tm_sort", int_buf);
1160 prefs_set_string("sm_sort_", NULL);
1161 }
1162
1163 /* For versions < 0.91, remove all itdb keys */
1164 if (version < 0.91)
1165 prefs_flush_subkey("itdb_");
1166
1167 /* rename convert scripts */
1168 if (version <= 0.99001)
1169 {
1170
1171 const gchar **keyp;
1172 const gchar *keys[] =
1173 {"path_conv_m4a", "path_conv_wav", "path_conv_mp3",
1174 "path_conv_ogg", "path_conv_flac", NULL};
1175
1176 for (keyp=keys; *keyp; ++keyp)
1177 {
1178 buf = prefs_get_string (*keyp);
1179 if (buf)
1180 {
1181 const gchar *needles[] =
1182 { "convert-flac2mp3.sh", "convert-m4a2mp3.sh",
1183 "convert-ogg2mp3.sh", "convert-wav2mp3.sh",
1184 "convert-flac2m4a.sh", "convert-m4a2m4a.sh",
1185 "convert-ogg2m4a.sh", "convert-wav2m4a.sh", NULL };
1186 const gchar *replacements[] =
1187 { "convert-2mp3.sh ", "convert-2mp3.sh ",
1188 "convert-2mp3.sh ", "convert-2mp3.sh " ,
1189 "convert-2m4a.sh ", "convert-2m4a.sh ",
1190 "convert-2m4a.sh ", "convert-2m4a.sh " };
1191 const gchar **needlep;
1192 const gchar **replp;
1193 replp = replacements;
1194 for (needlep=needles; *needlep; ++needlep, ++replp)
1195 {
1196 gchar *bufp = strstr (buf, *needlep);
1197 if (bufp)
1198 {
1199 g_memmove (bufp, *replp, strlen (*replp));
1200 prefs_set_string (*keyp, buf);
1201 break;
1202 }
1203 }
1204 g_free (buf);
1205 }
1206 }
1207 }
1208
1209 prefs_set_string ("version", VERSION);
1210 }
1211
1212 /* Initialize the prefs table and read configuration */
prefs_init(int argc,char * argv[])1213 void prefs_init (int argc, char *argv[])
1214 {
1215 if (!prefs_table_mutex)
1216 prefs_table_mutex = g_mutex_new ();
1217
1218 lock_prefs_table ();
1219
1220 /* Create the prefs hash table */
1221 prefs_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
1222 g_free);
1223
1224 unlock_prefs_table ();
1225
1226 /* Load preferences */
1227 load_prefs();
1228
1229 /* Clean up old prefs keys */
1230 cleanup_keys();
1231
1232 /* Read environment variables */
1233 read_environment();
1234
1235 /* Read commandline arguments */
1236 read_commandline(argc, argv);
1237 }
1238
1239 /* Delete the hash table */
prefs_shutdown()1240 void prefs_shutdown ()
1241 {
1242 lock_prefs_table ();
1243
1244 if (!prefs_table)
1245 {
1246 unlock_prefs_table ();
1247 g_return_if_reached ();
1248 }
1249
1250 /* Delete the prefs hash table */
1251 g_hash_table_destroy(prefs_table);
1252 prefs_table = NULL;
1253
1254 unlock_prefs_table ();
1255
1256 /* We can't free the prefs_table_mutex in a thread-safe way */
1257 }
1258
1259 /* Create the temp prefs tree */
1260 /* Free the returned structure with delete_temp_prefs() */
temp_prefs_create()1261 TempPrefs *temp_prefs_create ()
1262 {
1263 TempPrefs *temp_prefs; /* Returned temp prefs structure */
1264
1265 temp_prefs = (TempPrefs*)g_malloc(sizeof(TempPrefs));
1266
1267 temp_prefs->tree = g_tree_new_full((GCompareDataFunc)strcmp, NULL,
1268 g_free, g_free);
1269
1270 return temp_prefs;
1271 }
1272
copy_key_to_temp_prefs(gpointer key,gpointer value,gpointer user_data)1273 static void copy_key_to_temp_prefs (gpointer key, gpointer value, gpointer user_data)
1274 {
1275 temp_prefs_set_string ((TempPrefs *)user_data, key, value);
1276 }
1277
temp_prefs_copy_prefs(TempPrefs * temp_prefs)1278 void temp_prefs_copy_prefs (TempPrefs *temp_prefs)
1279 {
1280 g_return_if_fail (prefs_table);
1281 g_return_if_fail (temp_prefs);
1282 g_return_if_fail (temp_prefs->tree);
1283
1284 lock_prefs_table ();
1285 g_hash_table_foreach (prefs_table, copy_key_to_temp_prefs, temp_prefs);
1286 unlock_prefs_table ();
1287 }
1288
1289 /* Delete temp prefs */
temp_prefs_destroy(TempPrefs * temp_prefs)1290 void temp_prefs_destroy (TempPrefs *temp_prefs)
1291 {
1292 g_return_if_fail (temp_prefs);
1293 g_return_if_fail (temp_prefs->tree);
1294
1295 g_tree_destroy(temp_prefs->tree);
1296 g_free(temp_prefs);
1297 }
1298
1299 /* Copy key data from the temp prefs tree to the hash table */
copy_key(gpointer key,gpointer value,gpointer user_data)1300 static gboolean copy_key (gpointer key, gpointer value, gpointer user_data)
1301 {
1302 prefs_set_string(key, value);
1303
1304 return FALSE;
1305 }
1306
1307 /* Copy the data from the temp prefs tree to the permanent prefs table */
temp_prefs_apply(TempPrefs * temp_prefs)1308 void temp_prefs_apply (TempPrefs *temp_prefs)
1309 {
1310 g_return_if_fail (temp_prefs);
1311 g_return_if_fail (temp_prefs->tree);
1312
1313 g_tree_foreach (temp_prefs->tree, copy_key, NULL);
1314 }
1315
1316
1317 /* Create a temp_prefs tree containing a subset of keys in the
1318 permanent prefs table (those starting with @subkey */
prefs_create_subset_unlocked(const gchar * subkey)1319 static TempPrefs *prefs_create_subset_unlocked (const gchar *subkey)
1320 {
1321 struct sub_data sub_data;
1322
1323 g_return_val_if_fail (prefs_table, NULL);
1324
1325 sub_data.temp_prefs = temp_prefs_create ();
1326 sub_data.subkey = subkey;
1327
1328 g_hash_table_foreach (prefs_table, (GHFunc)get_subset, &sub_data);
1329
1330 return sub_data.temp_prefs;
1331 }
1332
1333 /* Create a temp_prefs tree containing a subset of keys in the
1334 permanent prefs table (those starting with @subkey */
prefs_create_subset(const gchar * subkey)1335 TempPrefs *prefs_create_subset (const gchar *subkey)
1336 {
1337 TempPrefs *temp_prefs;
1338
1339 lock_prefs_table ();
1340
1341 temp_prefs = prefs_create_subset_unlocked (subkey);
1342
1343 unlock_prefs_table ();
1344
1345 return temp_prefs;
1346 }
1347
1348
1349 /* Create a temp_prefs tree containing a subset of keys in the
1350 permanent prefs table (those starting with @subkey */
temp_prefs_create_subset(TempPrefs * temp_prefs,const gchar * subkey)1351 TempPrefs *temp_prefs_create_subset (TempPrefs *temp_prefs,
1352 const gchar *subkey)
1353 {
1354 struct sub_data sub_data;
1355
1356 g_return_val_if_fail (temp_prefs, NULL);
1357 g_return_val_if_fail (temp_prefs->tree, NULL);
1358
1359 sub_data.temp_prefs = temp_prefs_create ();
1360 sub_data.subkey = subkey;
1361
1362 g_tree_foreach (temp_prefs->tree, get_subset, &sub_data);
1363
1364 return sub_data.temp_prefs;
1365 }
1366
1367
1368 /* Remove all keys in the temp prefs tree from the permanent prefs
1369 table */
temp_prefs_flush(TempPrefs * temp_prefs)1370 void temp_prefs_flush (TempPrefs *temp_prefs)
1371 {
1372 g_return_if_fail (temp_prefs);
1373 g_return_if_fail (temp_prefs->tree);
1374
1375 lock_prefs_table ();
1376
1377 g_tree_foreach (temp_prefs->tree, flush_key, NULL);
1378
1379 unlock_prefs_table ();
1380 }
1381
1382 /* Return the number of keys stored in @temp_prefs */
temp_prefs_size(TempPrefs * temp_prefs)1383 gint temp_prefs_size (TempPrefs *temp_prefs)
1384 {
1385 g_return_val_if_fail (temp_prefs, 0);
1386 g_return_val_if_fail (temp_prefs->tree, 0);
1387
1388 return g_tree_nnodes (temp_prefs->tree);
1389 }
1390
1391
1392 /* Returns TRUE if at least one key starting with @subkey exists */
temp_prefs_subkey_exists(TempPrefs * temp_prefs,const gchar * subkey)1393 gboolean temp_prefs_subkey_exists (TempPrefs *temp_prefs,
1394 const gchar *subkey)
1395 {
1396 struct sub_data sub_data;
1397
1398 g_return_val_if_fail (temp_prefs && subkey, FALSE);
1399
1400 sub_data.temp_prefs = NULL;
1401 sub_data.subkey = subkey;
1402 sub_data.exists = FALSE;
1403
1404 g_tree_foreach (temp_prefs->tree, check_subkey, &sub_data);
1405
1406 return sub_data.exists;
1407 }
1408
1409
1410 /* Special functions */
1411
1412 /* Remove all keys that start with @subkey */
prefs_flush_subkey(const gchar * subkey)1413 void prefs_flush_subkey (const gchar *subkey)
1414 {
1415 lock_prefs_table ();
1416
1417 if (!prefs_table)
1418 {
1419 unlock_prefs_table ();
1420 g_return_if_reached ();
1421 }
1422
1423 g_hash_table_foreach_remove (prefs_table, match_subkey, (gchar *)subkey);
1424
1425 unlock_prefs_table ();
1426 }
1427
1428
1429 /* Rename all keys that start with @subkey_old in such a way that they
1430 start with @subkey_new */
prefs_rename_subkey(const gchar * subkey_old,const gchar * subkey_new)1431 void prefs_rename_subkey (const gchar *subkey_old, const gchar *subkey_new){
1432 struct sub_data sub_data;
1433
1434 g_return_if_fail (subkey_old);
1435 g_return_if_fail (subkey_new);
1436
1437 lock_prefs_table ();
1438
1439 if (!prefs_table)
1440 {
1441 unlock_prefs_table ();
1442 g_return_if_reached ();
1443 }
1444
1445 sub_data.temp_prefs = prefs_create_subset_unlocked (subkey_old);
1446 sub_data.temp_prefs_orig = NULL;
1447
1448 if (temp_prefs_size (sub_data.temp_prefs) > 0)
1449 {
1450 sub_data.subkey = subkey_old;
1451 sub_data.subkey2 = subkey_new;
1452 g_tree_foreach (sub_data.temp_prefs->tree, subst_key, &sub_data);
1453 }
1454
1455 temp_prefs_destroy (sub_data.temp_prefs);
1456
1457 unlock_prefs_table ();
1458 }
1459
1460
1461 /* Rename all keys that start with @subkey_old in such a way that they
1462 start with @subkey_new */
temp_prefs_rename_subkey(TempPrefs * temp_prefs,const gchar * subkey_old,const gchar * subkey_new)1463 void temp_prefs_rename_subkey (TempPrefs *temp_prefs,
1464 const gchar *subkey_old,
1465 const gchar *subkey_new)
1466 {
1467 struct sub_data sub_data;
1468
1469 g_return_if_fail (temp_prefs);
1470 g_return_if_fail (subkey_old);
1471 g_return_if_fail (subkey_new);
1472
1473 sub_data.temp_prefs_orig = temp_prefs;
1474 sub_data.temp_prefs = temp_prefs_create_subset (temp_prefs,
1475 subkey_old);
1476
1477 if (temp_prefs_size (sub_data.temp_prefs) > 0)
1478 {
1479 sub_data.subkey = subkey_old;
1480 sub_data.subkey2 = subkey_new;
1481 g_tree_foreach (sub_data.temp_prefs->tree, subst_key, &sub_data);
1482 }
1483
1484 temp_prefs_destroy (sub_data.temp_prefs);
1485 }
1486
1487 /* Functions for non-numbered pref keys */
1488
1489 /* Set a string value with the given key, or remove key if @value is
1490 NULL */
prefs_set_string(const gchar * key,const gchar * value)1491 void prefs_set_string(const gchar *key, const gchar *value)
1492 {
1493 g_return_if_fail (key);
1494
1495 lock_prefs_table ();
1496
1497 if (!prefs_table)
1498 {
1499 unlock_prefs_table ();
1500 g_return_if_reached ();
1501 }
1502
1503 if (value)
1504 g_hash_table_insert (prefs_table,
1505 g_strdup(key), g_strdup(value));
1506 else
1507 g_hash_table_remove (prefs_table, key);
1508
1509 unlock_prefs_table ();
1510 }
1511
1512 /* Set a key value to a given integer */
prefs_set_int(const gchar * key,const gint value)1513 void prefs_set_int(const gchar *key, const gint value)
1514 {
1515 gchar *strvalue; /* String value converted from integer */
1516
1517 lock_prefs_table ();
1518
1519 if (!prefs_table)
1520 {
1521 unlock_prefs_table ();
1522 g_return_if_reached ();
1523 }
1524
1525 strvalue = g_strdup_printf("%i", value);
1526 g_hash_table_insert(prefs_table, g_strdup(key), strvalue);
1527
1528 unlock_prefs_table ();
1529 }
1530
1531 /* Set a key to an int64 value */
prefs_set_int64(const gchar * key,const gint64 value)1532 void prefs_set_int64(const gchar *key, const gint64 value)
1533 {
1534 gchar *strvalue; /* String value converted from int64 */
1535
1536 lock_prefs_table ();
1537
1538 if (!prefs_table)
1539 {
1540 unlock_prefs_table ();
1541 g_return_if_reached ();
1542 }
1543
1544 strvalue = g_strdup_printf("%" G_GINT64_FORMAT, value);
1545 g_hash_table_insert(prefs_table, g_strdup(key), strvalue);
1546
1547 unlock_prefs_table ();
1548 }
1549
prefs_set_double(const gchar * key,gdouble value)1550 void prefs_set_double(const gchar *key, gdouble value)
1551 {
1552 gchar *strvalue; /* String value converted from integer */
1553
1554 lock_prefs_table ();
1555
1556 if (!prefs_table)
1557 {
1558 unlock_prefs_table ();
1559 g_return_if_reached ();
1560 }
1561
1562 strvalue = g_strdup_printf("%f", value);
1563 g_hash_table_insert(prefs_table, g_strdup(key), strvalue);
1564
1565 unlock_prefs_table ();
1566 }
1567
1568 /* Get a string value associated with a key. Free returned string. */
prefs_get_string(const gchar * key)1569 gchar *prefs_get_string(const gchar *key)
1570 {
1571 gchar *string = NULL;
1572
1573 lock_prefs_table ();
1574
1575 g_return_val_if_fail (prefs_table, (unlock_prefs_table(), NULL));
1576
1577 string = g_strdup(g_hash_table_lookup(prefs_table, key));
1578
1579 unlock_prefs_table ();
1580
1581 return string;
1582 }
1583
1584 /* Use this if you need to know if the given key actually exists */
1585 /* The value parameter can be NULL if you don't need the value itself. */
prefs_get_string_value(const gchar * key,gchar ** value)1586 gboolean prefs_get_string_value(const gchar *key, gchar **value)
1587 {
1588 const gchar *string; /* String value from prefs table */
1589 gboolean valid = FALSE;
1590
1591 lock_prefs_table ();
1592
1593 g_return_val_if_fail (prefs_table, (unlock_prefs_table(), FALSE));
1594
1595 string = g_hash_table_lookup(prefs_table, key);
1596
1597 if (value)
1598 *value = g_strdup (string);
1599 if (string)
1600 valid = TRUE;
1601
1602 unlock_prefs_table ();
1603
1604 return valid;
1605 }
1606
1607 /* Get an integer value from a key */
prefs_get_int(const gchar * key)1608 gint prefs_get_int(const gchar *key)
1609 {
1610 gchar *string; /* Hash value string */
1611 gint value; /* Returned value */
1612
1613 value = 0;
1614
1615 lock_prefs_table ();
1616
1617 g_return_val_if_fail (prefs_table, (unlock_prefs_table(), value));
1618
1619 string = g_hash_table_lookup(prefs_table, key);
1620
1621 if (string)
1622 value = atoi(string);
1623
1624 unlock_prefs_table ();
1625
1626 return value;
1627 }
1628
1629 /* Use this if you need to know if the given key actually exists */
1630 /* The value parameter can be NULL if you don't need the value itself. */
prefs_get_int_value(const gchar * key,gint * value)1631 gboolean prefs_get_int_value(const gchar *key, gint *value)
1632 {
1633 gchar *string; /* String value from prefs table */
1634 gboolean valid = FALSE;
1635
1636 lock_prefs_table ();
1637
1638 g_return_val_if_fail (prefs_table, (unlock_prefs_table(), FALSE));
1639
1640 string = g_hash_table_lookup(prefs_table, key);
1641
1642 if (value)
1643 {
1644 if (string)
1645 *value = atoi(string);
1646 else
1647 *value = 0;
1648 }
1649
1650 if (string)
1651 valid = TRUE;
1652
1653 unlock_prefs_table ();
1654
1655 return valid;
1656 }
1657
1658 /* Get a 64 bit integer value from a key */
prefs_get_int64(const gchar * key)1659 gint64 prefs_get_int64(const gchar *key)
1660 {
1661 gchar *string; /* Key value string */
1662 gint64 value; /* Returned value */
1663
1664 value = 0;
1665
1666 lock_prefs_table ();
1667
1668 g_return_val_if_fail (prefs_table, (unlock_prefs_table(), value));
1669
1670 string = g_hash_table_lookup(prefs_table, key);
1671
1672 if (string)
1673 value = g_ascii_strtoull(string, NULL, 10);
1674
1675 unlock_prefs_table ();
1676
1677 return value;
1678 }
1679
1680 /* Get a 64 bit integer value from a key */
1681 /* Use this if you need to know if the given key actually exists */
1682 /* The value parameter can be NULL if you don't need the value itself. */
prefs_get_int64_value(const gchar * key,gint64 * value)1683 gboolean prefs_get_int64_value(const gchar *key, gint64 *value)
1684 {
1685 gchar *string; /* String value from prefs table */
1686 gboolean valid = FALSE;
1687
1688 lock_prefs_table ();
1689
1690 g_return_val_if_fail (prefs_table, (unlock_prefs_table(), FALSE));
1691
1692 string = g_hash_table_lookup(prefs_table, key);
1693
1694 if (value)
1695 {
1696 if (string)
1697 *value = g_ascii_strtoull(string, NULL, 10);
1698 else
1699 *value = 0;
1700 }
1701
1702 if (string)
1703 valid = TRUE;
1704
1705 unlock_prefs_table ();
1706
1707 return valid;
1708 }
1709
prefs_get_double(const gchar * key)1710 gdouble prefs_get_double(const gchar *key)
1711 {
1712 gchar *string; /* Key value string */
1713 gdouble value; /* Returned value */
1714
1715 value = 0;
1716
1717 lock_prefs_table ();
1718
1719 g_return_val_if_fail (prefs_table, (unlock_prefs_table(), value));
1720
1721 string = g_hash_table_lookup(prefs_table, key);
1722
1723 if (string)
1724 value = g_ascii_strtod(string, NULL);
1725
1726 unlock_prefs_table ();
1727
1728 return value;
1729 }
1730
prefs_get_double_value(const gchar * key,gdouble * value)1731 gboolean prefs_get_double_value(const gchar *key, gdouble *value)
1732 {
1733 gchar *string; /* String value from prefs table */
1734 gboolean valid = FALSE;
1735
1736 lock_prefs_table ();
1737
1738 g_return_val_if_fail (prefs_table, (unlock_prefs_table(), FALSE));
1739
1740 string = g_hash_table_lookup(prefs_table, key);
1741
1742 if (value)
1743 {
1744 if (string)
1745 *value = g_ascii_strtod(string, NULL);
1746 else
1747 *value = 0;
1748 }
1749
1750 if (string)
1751 valid = TRUE;
1752
1753 unlock_prefs_table ();
1754
1755 return valid;
1756 }
1757
1758 /* Functions for numbered pref keys */
1759
1760 /* Set a string value with the given key */
prefs_set_string_index(const gchar * key,const guint index,const gchar * value)1761 void prefs_set_string_index(const gchar *key, const guint index,
1762 const gchar *value)
1763 {
1764 gchar *full_key; /* Complete numbered key */
1765
1766 full_key = create_full_key(key, index);
1767 prefs_set_string(full_key, value);
1768
1769 g_free(full_key);
1770 }
1771
1772 /* Set a key value to a given integer */
prefs_set_int_index(const gchar * key,const guint index,const gint value)1773 void prefs_set_int_index(const gchar *key, const guint index,
1774 const gint value)
1775 {
1776 gchar *full_key; /* Complete numbered key */
1777
1778 full_key = create_full_key(key, index);
1779 prefs_set_int(full_key, value);
1780
1781 g_free(full_key);
1782 }
1783
1784 /* Set a key to an int64 value */
prefs_set_int64_index(const gchar * key,const guint index,const gint64 value)1785 void prefs_set_int64_index(const gchar *key, const guint index,
1786 const gint64 value)
1787 {
1788 gchar *full_key; /* Complete numbered key */
1789
1790 full_key = create_full_key(key, index);
1791 prefs_set_int64(full_key, value);
1792
1793 g_free(full_key);
1794 }
1795
1796 /* Set a key to a gdouble value */
prefs_set_double_index(const gchar * key,guint index,gdouble value)1797 void prefs_set_double_index(const gchar *key, guint index,
1798 gdouble value)
1799 {
1800 gchar *full_key; /* Complete numbered key */
1801
1802 full_key = create_full_key(key, index);
1803 prefs_set_double(full_key, value);
1804
1805 g_free(full_key);
1806 }
1807
1808 /* Get a string value associated with a key. Free returned string. */
prefs_get_string_index(const gchar * key,const guint index)1809 gchar *prefs_get_string_index(const gchar *key, const guint index)
1810 {
1811 gchar *full_key; /* Complete numbered key */
1812 gchar *string; /* Return string */
1813
1814 full_key = create_full_key(key, index);
1815 string = prefs_get_string(full_key);
1816
1817 g_free(full_key);
1818 return string;
1819 }
1820
1821 /* Get a string value associated with a key. Free returned string. */
1822 /* Use this if you need to know if the given key actually exists */
prefs_get_string_value_index(const gchar * key,const guint index,gchar ** value)1823 gboolean prefs_get_string_value_index(const gchar *key, const guint index,
1824 gchar **value)
1825 {
1826 gchar *full_key; /* Complete numbered key */
1827 gboolean ret; /* Return value */
1828
1829 full_key = create_full_key(key, index);
1830 ret = prefs_get_string_value(full_key, value);
1831
1832 g_free(full_key);
1833 return ret;
1834 }
1835
1836 /* Get an integer value from a key */
prefs_get_int_index(const gchar * key,const guint index)1837 gint prefs_get_int_index(const gchar *key, const guint index)
1838 {
1839 gchar *full_key; /* Complete numbered key */
1840 gint value; /* Returned integer value */
1841
1842 full_key = create_full_key(key, index);
1843 value = prefs_get_int(full_key);
1844
1845 g_free(full_key);
1846 return value;
1847 }
1848
1849 /* Get an integer value from a key */
1850 /* Use this if you need to know if the given key actually exists */
prefs_get_int_value_index(const gchar * key,const guint index,gint * value)1851 gboolean prefs_get_int_value_index(const gchar *key, const guint index,
1852 gint *value)
1853 {
1854 gchar *full_key; /* Complete numbered key */
1855 gboolean ret; /* Return value */
1856
1857 full_key = create_full_key(key, index);
1858 ret = prefs_get_int_value(full_key, value);
1859
1860 g_free(full_key);
1861 return ret;
1862 }
1863
1864 /* Get a 64 bit integer value from a key */
prefs_get_int64_index(const gchar * key,const guint index)1865 gint64 prefs_get_int64_index(const gchar *key, const guint index)
1866 {
1867 gchar *full_key; /* Complete numbered key */
1868 gint64 value; /* Return value */
1869
1870 full_key = create_full_key(key, index);
1871 value = prefs_get_int64(full_key);
1872
1873 g_free(full_key);
1874 return value;
1875 }
1876
1877 /* Get a 64 bit integer value from a key */
1878 /* Use this if you need to know if the given key actually exists */
prefs_get_int64_value_index(const gchar * key,const guint index,gint64 * value)1879 gboolean prefs_get_int64_value_index(const gchar *key, const guint index,
1880 gint64 *value)
1881 {
1882 gchar *full_key; /* Complete numbered key */
1883 gboolean ret; /* Return value */
1884
1885 full_key = create_full_key(key, index);
1886 ret = prefs_get_int64_value(full_key, value);
1887
1888 g_free(full_key);
1889 return ret;
1890 }
1891
prefs_get_double_index(const gchar * key,guint index)1892 gdouble prefs_get_double_index(const gchar *key, guint index)
1893 {
1894 gchar *full_key; /* Complete numbered key */
1895 gdouble value; /* Return value */
1896
1897 full_key = create_full_key(key, index);
1898 value = prefs_get_double(full_key);
1899
1900 g_free(full_key);
1901 return value;
1902 }
1903
prefs_get_double_value_index(const gchar * key,guint index,gdouble * value)1904 gboolean prefs_get_double_value_index(const gchar *key, guint index,
1905 gdouble *value)
1906 {
1907 gchar *full_key; /* Complete numbered key */
1908 gboolean ret; /* Return value */
1909
1910 full_key = create_full_key(key, index);
1911 ret = prefs_get_double_value(full_key, value);
1912
1913 g_free(full_key);
1914 return ret;
1915 }
1916
1917 /* Add string value with the given key to temp prefs. Note: use
1918 * temp_prefs_remove_key() to remove key from the temp prefs. Setting
1919 * it to NULL will not remove the key. It will instead remove the key
1920 * in the main prefs table when you call temp_prefs_apply(). */
temp_prefs_set_string(TempPrefs * temp_prefs,const gchar * key,const gchar * value)1921 void temp_prefs_set_string (TempPrefs *temp_prefs, const gchar *key,
1922 const gchar *value)
1923 {
1924 g_return_if_fail (temp_prefs && temp_prefs->tree);
1925 g_return_if_fail (key);
1926
1927 g_tree_insert (temp_prefs->tree, g_strdup(key), g_strdup(value));
1928 }
1929
1930 /* Add string value with the given key to temp prefs. Remove the key
1931 * if @value is NULL. */
temp_prefs_remove_key(TempPrefs * temp_prefs,const gchar * key)1932 void temp_prefs_remove_key (TempPrefs *temp_prefs, const gchar *key)
1933 {
1934 g_return_if_fail (temp_prefs && temp_prefs->tree);
1935 g_return_if_fail (key);
1936
1937 g_tree_remove (temp_prefs->tree, key);
1938 }
1939
1940 /* Add an integer value to temp prefs */
temp_prefs_set_int(TempPrefs * temp_prefs,const gchar * key,const gint value)1941 void temp_prefs_set_int(TempPrefs *temp_prefs, const gchar *key,
1942 const gint value)
1943 {
1944 gchar *strvalue; /* String value converted from integer */
1945
1946 g_return_if_fail (temp_prefs && temp_prefs->tree);
1947 g_return_if_fail (key);
1948
1949 strvalue = g_strdup_printf("%i", value);
1950 g_tree_insert(temp_prefs->tree, g_strdup(key), strvalue);
1951 }
1952
1953 /* Add an int64 to temp prefs */
temp_prefs_set_int64(TempPrefs * temp_prefs,const gchar * key,const gint64 value)1954 void temp_prefs_set_int64(TempPrefs *temp_prefs, const gchar *key,
1955 const gint64 value)
1956 {
1957 gchar *strvalue; /* String value converted from int64 */
1958
1959 g_return_if_fail (temp_prefs && temp_prefs->tree);
1960 g_return_if_fail (key);
1961
1962 strvalue = g_strdup_printf("%" G_GINT64_FORMAT, value);
1963 g_tree_insert(temp_prefs->tree, g_strdup(key), strvalue);
1964 }
1965
temp_prefs_set_double(TempPrefs * temp_prefs,const gchar * key,gdouble value)1966 void temp_prefs_set_double(TempPrefs *temp_prefs, const gchar *key,
1967 gdouble value)
1968 {
1969 gchar *strvalue; /* String value converted from int64 */
1970
1971 g_return_if_fail (temp_prefs && temp_prefs->tree);
1972 g_return_if_fail (key);
1973
1974 strvalue = g_strdup_printf("%fu", value);
1975 g_tree_insert(temp_prefs->tree, g_strdup(key), strvalue);
1976 }
1977
1978 /* Get a string value associated with a key. Free returned string. */
temp_prefs_get_string(TempPrefs * temp_prefs,const gchar * key)1979 gchar *temp_prefs_get_string(TempPrefs *temp_prefs, const gchar *key)
1980 {
1981 g_return_val_if_fail (temp_prefs && temp_prefs->tree, NULL);
1982 g_return_val_if_fail (key, NULL);
1983
1984 return g_strdup (g_tree_lookup (temp_prefs->tree, key));
1985 }
1986
1987 /* Use this if you need to know if the given key actually exists */
1988 /* The value parameter can be NULL if you don't need the value itself. */
temp_prefs_get_string_value(TempPrefs * temp_prefs,const gchar * key,gchar ** value)1989 gboolean temp_prefs_get_string_value(TempPrefs *temp_prefs,
1990 const gchar *key, gchar **value)
1991 {
1992 gchar *string; /* String value from prefs table */
1993
1994 g_return_val_if_fail (temp_prefs && temp_prefs->tree, FALSE);
1995 g_return_val_if_fail (key, FALSE);
1996
1997 string = g_tree_lookup (temp_prefs->tree, key);
1998
1999 if (value)
2000 *value = g_strdup (string);
2001
2002 if (string)
2003 return TRUE;
2004 else
2005 return FALSE;
2006 }
2007
2008 /* Get an integer value from a key */
temp_prefs_get_int(TempPrefs * temp_prefs,const gchar * key)2009 gint temp_prefs_get_int(TempPrefs *temp_prefs, const gchar *key)
2010 {
2011 gchar *string; /* Hash value string */
2012 gint value; /* Returned value */
2013
2014 g_return_val_if_fail (temp_prefs && temp_prefs->tree, 0);
2015 g_return_val_if_fail (key, 0);
2016
2017 value = 0;
2018
2019 string = g_tree_lookup (temp_prefs->tree, key);
2020
2021 if (string)
2022 value = atoi(string);
2023
2024 return value;
2025 }
2026
2027 /* Use this if you need to know if the given key actually exists */
2028 /* The value parameter can be NULL if you don't need the value itself. */
temp_prefs_get_int_value(TempPrefs * temp_prefs,const gchar * key,gint * value)2029 gboolean temp_prefs_get_int_value(TempPrefs *temp_prefs,
2030 const gchar *key, gint *value)
2031 {
2032 gchar *string; /* String value from prefs table */
2033
2034 g_return_val_if_fail (temp_prefs && temp_prefs->tree, FALSE);
2035 g_return_val_if_fail (key, FALSE);
2036
2037 string = g_tree_lookup (temp_prefs->tree, key);
2038
2039 if (value)
2040 {
2041 if (string)
2042 *value = atoi(string);
2043 else
2044 *value = 0;
2045 }
2046
2047 if (string)
2048 return TRUE;
2049 else
2050 return FALSE;
2051 }
2052
temp_prefs_get_double(TempPrefs * temp_prefs,const gchar * key)2053 gdouble temp_prefs_get_double(TempPrefs *temp_prefs,
2054 const gchar *key)
2055 {
2056 gchar *string; /* Hash value string */
2057 gdouble value; /* Returned value */
2058
2059 g_return_val_if_fail (temp_prefs && temp_prefs->tree, 0);
2060 g_return_val_if_fail (key, 0);
2061
2062 value = 0.0f;
2063
2064 string = g_tree_lookup (temp_prefs->tree, key);
2065
2066 if (string)
2067 value = g_ascii_strtod(string, NULL);
2068
2069 return value;
2070 }
2071
temp_prefs_get_double_value(TempPrefs * temp_prefs,const gchar * key,gdouble * value)2072 gboolean temp_prefs_get_double_value(TempPrefs *temp_prefs,
2073 const gchar *key, gdouble *value)
2074 {
2075 gchar *string; /* String value from prefs table */
2076
2077 g_return_val_if_fail (temp_prefs && temp_prefs->tree, FALSE);
2078 g_return_val_if_fail (key, FALSE);
2079
2080 string = g_tree_lookup (temp_prefs->tree, key);
2081
2082 if (value)
2083 {
2084 if (string)
2085 *value = g_ascii_strtod(string, NULL);
2086 else
2087 *value = 0;
2088 }
2089
2090 if (string)
2091 return TRUE;
2092 else
2093 return FALSE;
2094 }
2095
2096 /* Functions for numbered pref keys */
2097
2098 /* Set a string value with the given key */
temp_prefs_set_string_index(TempPrefs * temp_prefs,const gchar * key,const guint index,const gchar * value)2099 void temp_prefs_set_string_index(TempPrefs *temp_prefs, const gchar *key,
2100 const guint index, const gchar *value)
2101 {
2102 gchar *full_key; /* Complete numbered key */
2103
2104 g_return_if_fail (temp_prefs && temp_prefs->tree);
2105 g_return_if_fail (key);
2106
2107 full_key = create_full_key(key, index);
2108 temp_prefs_set_string(temp_prefs, full_key, value);
2109
2110 g_free(full_key);
2111 }
2112
2113 /* Set a key value to a given integer */
temp_prefs_set_int_index(TempPrefs * temp_prefs,const gchar * key,const guint index,const gint value)2114 void temp_prefs_set_int_index(TempPrefs *temp_prefs, const gchar *key,
2115 const guint index, const gint value)
2116 {
2117 gchar *full_key; /* Complete numbered key */
2118
2119 g_return_if_fail (temp_prefs && temp_prefs->tree);
2120 g_return_if_fail (key);
2121
2122 full_key = create_full_key(key, index);
2123 temp_prefs_set_int(temp_prefs, full_key, value);
2124
2125 g_free(full_key);
2126 }
2127
2128 /* Set a key to an int64 value */
temp_prefs_set_int64_index(TempPrefs * temp_prefs,const gchar * key,const guint index,const gint64 value)2129 void temp_prefs_set_int64_index(TempPrefs *temp_prefs, const gchar *key,
2130 const guint index, const gint64 value)
2131 {
2132 gchar *full_key; /* Complete numbered key */
2133
2134 g_return_if_fail (temp_prefs && temp_prefs->tree);
2135 g_return_if_fail (key);
2136
2137 full_key = create_full_key(key, index);
2138 temp_prefs_set_int64(temp_prefs, full_key, value);
2139
2140 g_free(full_key);
2141 }
2142
2143 /* Functions for variable-length lists */
2144
2145 /* Create a tree that contains lists that need to be rebuilt */
2146 /* Free the returned structure with destroy_temp_lists */
temp_lists_create()2147 TempLists *temp_lists_create()
2148 {
2149 TempLists *temp_lists; /* Allocated temp list structure */
2150
2151 temp_lists = (TempLists*)g_malloc(sizeof(TempLists));
2152
2153
2154 temp_lists->tree = g_tree_new_full((GCompareDataFunc)strcmp, NULL,
2155 g_free,
2156 (GDestroyNotify)prefs_free_list);
2157 return temp_lists;
2158 }
2159
2160 /* Destroys the list tree */
temp_lists_destroy(TempLists * temp_lists)2161 void temp_lists_destroy(TempLists *temp_lists)
2162 {
2163 if (temp_lists)
2164 {
2165 if (temp_lists->tree)
2166 g_tree_destroy(temp_lists->tree);
2167
2168 g_free(temp_lists);
2169 }
2170 }
2171
2172 /* Add a list with the given key prefix to a temp list tree */
temp_list_add(TempLists * temp_lists,const gchar * key,GList * list)2173 void temp_list_add(TempLists *temp_lists, const gchar *key, GList *list)
2174 {
2175 if (temp_lists)
2176 {
2177 if (temp_lists->tree)
2178 g_tree_insert(temp_lists->tree, g_strdup(key), list);
2179 }
2180 }
2181
2182 /* Copy the items of the lists in the given tree to the prefs table */
temp_lists_apply(TempLists * temp_lists)2183 void temp_lists_apply(TempLists *temp_lists)
2184 {
2185 if (temp_lists)
2186 {
2187 if (temp_lists->tree)
2188 g_tree_foreach(temp_lists->tree, copy_list, NULL);
2189 }
2190 }
2191
2192 /* Copy one list to the prefs table. Useful for lists not changed by a window */
prefs_apply_list(gchar * key,GList * list)2193 void prefs_apply_list(gchar *key, GList *list)
2194 {
2195 GList *node; /* Current list node */
2196 guint i; /* Counter */
2197
2198 i = 0;
2199
2200 if (prefs_table)
2201 {
2202 /* Clean the existing list */
2203 wipe_list(key);
2204
2205 node = list;
2206
2207 /* Add the new list items to the table */
2208 while (node)
2209 {
2210 g_hash_table_insert(prefs_table, create_full_key(key, i),
2211 g_strdup(node->data));
2212
2213 node = g_list_next(node);
2214 i++;
2215 }
2216
2217 /* Add the end marker */
2218 g_hash_table_insert(prefs_table, create_full_key(key, i),
2219 g_strdup(LIST_END_MARKER));
2220 }
2221 }
2222
2223 /* Get the items in a variable-length list from the prefs table */
prefs_get_list(const gchar * key)2224 GList *prefs_get_list(const gchar *key)
2225 {
2226 guint end_marker_hash; /* Hash value of the list end marker */
2227 guint item_hash; /* Hash value of current list string */
2228 gchar *item_string; /* List item string */
2229 guint i; /* Counter */
2230 GList *list; /* List that contains items */
2231
2232 /* Go through each key in the table until we find the end marker */
2233 end_marker_hash = g_str_hash(LIST_END_MARKER);
2234 list = NULL;
2235
2236 for (i = 0;;i++)
2237 {
2238 item_string = prefs_get_string_index(key, i);
2239
2240 if (item_string)
2241 {
2242 item_hash = g_str_hash(item_string);
2243
2244 if (item_hash != end_marker_hash)
2245 {
2246 list = g_list_append(list, item_string);
2247 continue;
2248 }
2249 else
2250 {
2251 g_free(item_string);
2252 break;
2253 }
2254 }
2255 }
2256
2257 return list;
2258 }
2259
2260 /* Free a list and its strings */
prefs_free_list(GList * list)2261 void prefs_free_list(GList *list)
2262 {
2263 GList *node; /* Current list node */
2264
2265 node = list;
2266
2267 /* Go through the list, freeing the strings */
2268
2269 while (node)
2270 {
2271 if (node->data)
2272 g_free(node->data);
2273
2274 node = g_list_next(node);
2275 }
2276
2277 g_list_free(list);
2278 }
2279
2280 /* Creates a list from lines in a GtkTextBuffer. Free the list when done. */
get_list_from_buffer(GtkTextBuffer * buffer)2281 GList *get_list_from_buffer(GtkTextBuffer *buffer)
2282 {
2283 GtkTextIter start_iter; /* Start of buffer text */
2284 GtkTextIter end_iter; /* End of buffer text */
2285 gchar *text_buffer; /* Raw text buffer */
2286 gchar **string_array; /* Contains each line of the buffer */
2287 gchar **string_iter; /* Pointer for iterating through the string vector */
2288 GList *list; /* List that contains each string */
2289
2290 list = NULL;
2291
2292 /* Grab the text from the buffer, and then split it up by lines */
2293 gtk_text_buffer_get_start_iter(buffer, &start_iter);
2294 gtk_text_buffer_get_end_iter(buffer, &end_iter);
2295
2296 text_buffer = gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, FALSE);
2297 string_array = g_strsplit(text_buffer, "\n", -1);
2298 string_iter = string_array;
2299
2300 /* Go through each string and put it in the list */
2301 while (*string_iter)
2302 {
2303 if (strlen(*string_iter) != 0)
2304 list = g_list_append(list, g_strdup(*string_iter));
2305
2306 string_iter++;
2307 }
2308
2309 g_free (text_buffer);
2310 g_strfreev (string_array);
2311
2312 return list;
2313 }
2314