gliv-1.4.2
[gliv.git] / src / rcfile.c
blobeb490edb1ffb038b4c35a1a069cb125e796f8475
1 /*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License
4 * as published by the Free Software Foundation; either version 2
5 * of the License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 * See the COPYING file for license information.
18 * Guillaume Chazarain <booh@altern.org>
21 /***********************
22 * Configuration file. *
23 ***********************/
25 #include <unistd.h> /* R_OK */
26 #include <stdio.h> /* FILE, f*(), perror(), getline() */
27 #include <string.h> /* strlen(), memcpy() */
28 #include "gliv.h"
30 #ifndef HAVE_GETLINE
31 #include "../lib/getline.h"
32 #endif
34 static GHashTable *table = NULL;
36 /* The link between options and the rcfile. */
37 static options_struct opts = {
38 /* Default options */
39 .fullscreen = FALSE,
40 .maximize = FALSE,
41 .menu_bar = TRUE,
42 .status_bar = TRUE,
43 .zoom_pointer = FALSE,
44 .alpha_checks = TRUE,
45 .dither = FALSE,
46 .delay = 0,
47 .history_size = 1000
50 typedef struct {
51 const gchar *name;
52 gint *option;
53 const gchar *comment;
54 const gboolean is_bool;
55 } option_struct;
57 /* *INDENT-OFF* */
58 static option_struct option_names[] = {
59 /* To fill the hash table and the configuration file. */
60 { "full-screen", &opts.fullscreen, "Start in full screen mode", 1 },
61 { "maximize", &opts.maximize, "Maximize image to fit window", 1 },
62 { "menu", &opts.menu_bar, "Display the menu bar", 1 },
63 { "info", &opts.status_bar, "Show infos about current image", 1 },
64 { "zoom-pointer", &opts.zoom_pointer, "Zoom centered on pointer", 1 },
65 { "alpha_checks", &opts.alpha_checks, "Alpha checks in the background", 1 },
66 { "dither", &opts.dither, "Dithering", 1 },
67 { "delay", &opts.delay, "Delay before hiding the cursor", 0 },
68 { "history", &opts.history_size, "Length of history", 0 },
69 { NULL, NULL, NULL, 0 }
71 /* *INDENT-ON* */
74 * Maximum length of the option names, currently
75 * it is strlen("zoom-pointer") == 12.
76 * Used to indent the option file.
78 #define MAX_OPT_LEN 12
80 static gchar *find_rcfile(gboolean test)
82 gchar *path;
84 path = g_build_filename(g_get_home_dir(), ".glivrc", NULL);
86 if (test == FALSE || g_file_test(path, G_FILE_TEST_EXISTS) == TRUE)
87 /* When loading the file, we really try to access it. */
88 /* When saving, we just need the filename. */
89 return path;
91 g_free(path);
92 return NULL;
95 /*** Loading options. ***/
97 static void init_hash_table(void)
99 gint i;
101 table = g_hash_table_new(g_str_hash, g_str_equal);
103 /* (i + 1), because 0 is when no option is found, not the first option. */
104 for (i = 0; option_names[i].name != NULL; i++)
105 g_hash_table_insert(table, (gchar *) option_names[i].name,
106 GINT_TO_POINTER(i + 1));
109 /* Processes spaces and '#'. */
110 static gchar *clean_str(gchar * str)
112 gchar *new_str;
113 gchar *ptr;
115 new_str = g_new(gchar, strlen(str) + 1);
117 for (ptr = new_str; *str != '\n'; str++) {
118 if (*str == ' ')
119 continue;
121 if (*str == '#') {
122 g_free(new_str);
123 return NULL;
126 *ptr = *str;
127 ptr++;
129 *ptr = '\0';
131 new_str = g_renew(gchar, new_str, ptr - new_str + 1);
132 return new_str;
135 static void process_line(gchar * str)
137 gchar **res;
138 gint hash_index;
139 gchar *clean;
141 if (*str == '\n')
142 /* Skip this line. */
143 return;
145 clean = clean_str(str);
146 if (clean == NULL)
147 /* This line is a '#' comment. */
148 return;
150 /* res[0] : option name ; res[1] : value */
151 res = g_strsplit(clean, "=", 2);
153 g_free(clean);
155 if (res[0] != NULL && res[1] != NULL && res[2] == NULL) {
156 /* No error during split. */
157 hash_index = GPOINTER_TO_INT(g_hash_table_lookup(table, res[0]));
159 if (hash_index != 0) {
160 /* Option found. */
161 hash_index--;
163 if (option_names[hash_index].is_bool == TRUE) {
165 if (g_strcasecmp(res[1], "true") == 0)
166 *(option_names[hash_index].option) = TRUE;
168 else if (g_strcasecmp(res[1], "false") == 0)
169 *(option_names[hash_index].option) = FALSE;
171 } else
172 /* option_names[hash_index].is_bool == FALSE */
173 *(option_names[hash_index].option) =
174 (gint) g_strtod(res[1], NULL);
178 g_strfreev(res);
181 options_struct *load_rc(gboolean from_file)
183 gchar *filename;
184 FILE *file;
185 gchar *line = NULL;
186 size_t nb = 0;
188 if (from_file == FALSE)
189 return &opts;
191 init_hash_table();
193 filename = find_rcfile(TRUE);
194 if (filename == NULL)
195 return &opts;
197 file = fopen(filename, "r");
198 if (file == NULL) {
200 * Not very frequent because find_rcfile(TRUE)
201 * should have made us return.
203 perror(filename);
204 return &opts;
207 for (;;) {
208 getline(&line, &nb, file);
210 if (feof(file) == 0)
211 process_line(line);
212 else
213 /* End Of File. */
214 break;
217 g_free(line);
218 fclose(file);
219 g_free(filename);
220 g_hash_table_destroy(table);
222 return &opts;
225 /*** Saving options. ***/
227 static void write_option_line(FILE * f, gint index)
229 gint i;
230 gint value;
232 fputs(option_names[index].name, f);
234 for (i = strlen(option_names[index].name); i < MAX_OPT_LEN; i++)
235 fputc(' ', f);
237 value = *(option_names[index].option);
239 if (value != 0 && option_names[index].is_bool == FALSE)
240 fprintf(f, " = %d\n\n", value);
241 else
242 fprintf(f, " = %s\n\n", (value == TRUE ? "True" : "False"));
245 static void write_rc(gchar * filename)
247 FILE *file;
248 gint i;
250 file = fopen(filename, "w");
251 if (file == NULL) {
252 perror(filename);
253 return;
256 fprintf(file, "# Configuration file for GLiv %s\n\n", VERSION);
257 fputs("# Option names are case sensitive.\n", file);
258 fputs("# Option values are case insensitive.\n", file);
259 fputs("# Note : 'maximize = True' implies 'full-screen = True'.\n\n", file);
261 for (i = 0; option_names[i].name != NULL; i++) {
262 /* The comment line. */
263 fprintf(file, "# %s\n", option_names[i].comment);
265 /* The option line. */
266 write_option_line(file, i);
269 fclose(file);
270 g_free(filename);
273 void save_rc(options_struct * opt)
275 memcpy(&opts, opt, sizeof(options_struct));
276 write_rc(find_rcfile(FALSE));