r250: Completed marking translatable strings. Tested by reversing all the strings
[rox-filer/ma.git] / ROX-Filer / src / options.c
blob146464a1ac3ca0deb26f44a05f046f857994ff71
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2000, Thomas Leonard, <tal197@ecs.soton.ac.uk>.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* options.c - code for handling user choices */
24 #include "config.h"
26 #include <stdio.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <glib.h>
30 #include <gtk/gtk.h>
32 #include "gui_support.h"
33 #include "choices.h"
34 #include "options.h"
36 /* Add OptionsSection structs to this list in your _init() functions */
37 GSList *options_sections = NULL;
39 static GtkWidget *window, *sections_vbox;
40 static FILE *save_file = NULL;
41 static GHashTable *option_hash = NULL;
43 enum {BUTTON_SAVE, BUTTON_OK, BUTTON_APPLY};
45 /* Static prototypes */
46 static void save_options(GtkWidget *widget, gpointer data);
47 static char *process_option_line(guchar *line);
49 void options_init()
51 GtkWidget *tl_vbox, *scrolled_area;
52 GtkWidget *border, *label;
53 GtkWidget *actions, *button;
54 char *string, *save_path;
56 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
57 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
58 gtk_window_set_title(GTK_WINDOW(window), _("ROX-Filer options"));
59 gtk_signal_connect(GTK_OBJECT(window), "delete_event",
60 GTK_SIGNAL_FUNC(hide_dialog_event), window);
61 gtk_container_set_border_width(GTK_CONTAINER(window), 4);
62 gtk_window_set_default_size(GTK_WINDOW(window), 400, 400);
64 tl_vbox = gtk_vbox_new(FALSE, 4);
65 gtk_container_add(GTK_CONTAINER(window), tl_vbox);
67 scrolled_area = gtk_scrolled_window_new(NULL, NULL);
68 gtk_container_set_border_width(GTK_CONTAINER(scrolled_area), 4);
69 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_area),
70 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
71 gtk_box_pack_start(GTK_BOX(tl_vbox), scrolled_area, TRUE, TRUE, 0);
73 border = gtk_frame_new(NULL);
74 gtk_frame_set_shadow_type(GTK_FRAME(border), GTK_SHADOW_NONE);
75 gtk_container_set_border_width(GTK_CONTAINER(border), 4);
76 gtk_scrolled_window_add_with_viewport(
77 GTK_SCROLLED_WINDOW(scrolled_area), border);
79 sections_vbox = gtk_vbox_new(FALSE, 4);
80 gtk_container_add(GTK_CONTAINER(border), sections_vbox);
82 save_path = choices_find_path_save("...", PROJECT, FALSE);
83 if (save_path)
85 string = g_strconcat(_("Choices will be saved as "),
86 save_path,
87 NULL);
88 label = gtk_label_new(string);
89 g_free(string);
91 else
92 label = gtk_label_new(_("Choices saving is disabled by "
93 "CHOICESPATH variable"));
94 gtk_box_pack_start(GTK_BOX(tl_vbox), label, FALSE, TRUE, 0);
96 actions = gtk_hbox_new(TRUE, 16);
97 gtk_box_pack_start(GTK_BOX(tl_vbox), actions, FALSE, TRUE, 0);
99 button = gtk_button_new_with_label(_("Save"));
100 gtk_box_pack_start(GTK_BOX(actions), button, FALSE, TRUE, 0);
101 if (!save_path)
102 gtk_widget_set_sensitive(button, FALSE);
103 gtk_signal_connect(GTK_OBJECT(button), "clicked",
104 GTK_SIGNAL_FUNC(save_options), (gpointer) BUTTON_SAVE);
106 button = gtk_button_new_with_label(_("OK"));
107 gtk_box_pack_start(GTK_BOX(actions), button, FALSE, TRUE, 0);
108 gtk_signal_connect(GTK_OBJECT(button), "clicked",
109 GTK_SIGNAL_FUNC(save_options), (gpointer) BUTTON_OK);
111 button = gtk_button_new_with_label(_("Apply"));
112 gtk_box_pack_start(GTK_BOX(actions), button, FALSE, TRUE, 0);
113 gtk_signal_connect(GTK_OBJECT(button), "clicked",
114 GTK_SIGNAL_FUNC(save_options), (gpointer) BUTTON_APPLY);
116 button = gtk_button_new_with_label(_("Cancel"));
117 gtk_box_pack_start(GTK_BOX(actions), button, FALSE, TRUE, 0);
118 gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
119 GTK_SIGNAL_FUNC(gtk_widget_hide), GTK_OBJECT(window));
122 void options_load(void)
124 static gboolean need_init = TRUE;
125 char *path;
127 if (need_init)
129 GtkWidget *group;
130 GSList *next = options_sections;
132 while (next)
134 OptionsSection *section = (OptionsSection *) next->data;
136 group = gtk_frame_new(_(section->name));
137 gtk_box_pack_start(GTK_BOX(sections_vbox), group,
138 FALSE, TRUE, 0);
139 gtk_container_add(GTK_CONTAINER(group),
140 section->create());
141 next = next->next;
144 need_init = FALSE;
147 path = choices_find_path_load("options", PROJECT);
148 if (!path)
149 return; /* Nothing to load */
151 parse_file(path, process_option_line);
154 void parse_file(char *path, ParseFunc *parse_line)
156 char *data;
157 long length;
158 gboolean seen_error = FALSE;
160 if (load_file(path, &data, &length))
162 char *eol, *error;
163 char *line = data;
164 int line_number = 1;
166 while (line && *line)
168 eol = strchr(line, '\n');
169 if (eol)
170 *eol = '\0';
172 error = parse_line(line);
174 if (error && !seen_error)
176 GString *message;
178 message = g_string_new(NULL);
179 g_string_sprintf(message,
180 _("Error in options file at line %d: "
181 "\n\"%s\"\n"
182 "This may be due to upgrading from a previous version of "
183 "ROX-Filer. Open the Options window and click on Save.\n"
184 "Further errors will be ignored."),
185 line_number,
186 error);
187 delayed_error(PROJECT, message->str);
188 g_string_free(message, TRUE);
189 seen_error = TRUE;
192 if (!eol)
193 break;
194 line = eol + 1;
195 line_number++;
197 g_free(data);
201 /* Call this on init to register a handler for a key (thing before the = in
202 * the config file).
203 * The function returns a pointer to an error messages (which will
204 * NOT be free()d), or NULL on success.
206 void option_register(char *key, OptionFunc *func)
208 if (!option_hash)
209 option_hash = g_hash_table_new(g_str_hash, g_str_equal);
210 g_hash_table_insert(option_hash, key, func);
213 /* Process one line from the options file (\0 term'd).
214 * Returns NULL on success, or a pointer to an error message.
215 * The line is modified.
217 static char *process_option_line(guchar *line)
219 guchar *eq, *c;
220 OptionFunc *func;
222 g_return_val_if_fail(option_hash != NULL, "No registered functions!");
224 eq = strchr(line, '=');
225 if (!eq)
226 return _("Missing '='");
228 c = eq - 1;
229 while (c > line && (*c == ' ' || *c == '\t'))
230 c--;
231 c[1] = '\0';
232 c = eq + 1;
233 while (*c == ' ' || *c == '\t')
234 c++;
236 func = (OptionFunc *) g_hash_table_lookup(option_hash, line);
237 if (!func)
238 return _("Unknown option");
240 return func(c);
243 static void save_options(GtkWidget *widget, gpointer data)
245 int button = (int) data;
246 GSList *next = options_sections;
248 while (next)
250 OptionsSection *section = (OptionsSection *) next->data;
251 section->set();
252 next = next->next;
255 if (button == BUTTON_SAVE)
257 char *path;
259 path = choices_find_path_save("options", PROJECT, TRUE);
260 g_return_if_fail(path != NULL);
262 save_file = fopen(path, "wb");
263 if (!save_file)
265 char *str;
266 str = g_strdup_printf(
267 _("Unable to open '%s' for writing: %s"),
268 path, g_strerror(errno));
269 report_error(PROJECT, str);
270 g_free(str);
271 return;
274 next = options_sections;
275 while (next)
277 OptionsSection *section = (OptionsSection *) next->data;
278 section->save();
279 next = next->next;
282 if (save_file && fclose(save_file) == EOF)
284 report_error(PROJECT, g_strerror(errno));
285 return;
289 if (button != BUTTON_APPLY)
290 gtk_widget_hide(window);
293 void options_show(FilerWindow *filer_window)
295 GSList *next = options_sections;
297 if (GTK_WIDGET_MAPPED(window))
298 gtk_widget_hide(window);
300 while (next)
302 OptionsSection *section = (OptionsSection *) next->data;
303 section->update();
304 next = next->next;
307 gtk_widget_show_all(window);
310 void option_write(char *name, char *value)
312 char *string;
313 int len;
315 if (!save_file)
316 return; /* Error already reported hopefully */
318 string = g_strconcat(name, " = ", value, "\n", NULL);
319 len = strlen(string);
320 if (fwrite(string, sizeof(char), len, save_file) < len)
322 delayed_error(_("Saving options"), g_strerror(errno));
323 fclose(save_file);
324 save_file = NULL;
326 g_free(string);