r323: Improved pinboard support. Files can be dropped onto the pinboard
[rox-filer/ma.git] / ROX-Filer / src / options.c
bloba37da8b82c48bd8dc53941107c8873e8543e5a60
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, 4);
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);
155 /* Call this on init to register a handler for a key (thing before the = in
156 * the config file).
157 * The function returns a pointer to an error messages (which will
158 * NOT be free()d), or NULL on success.
160 void option_register(char *key, OptionFunc *func)
162 if (!option_hash)
163 option_hash = g_hash_table_new(g_str_hash, g_str_equal);
164 g_hash_table_insert(option_hash, key, func);
167 /* Process one line from the options file (\0 term'd).
168 * Returns NULL on success, or a pointer to an error message.
169 * The line is modified.
171 static char *process_option_line(guchar *line)
173 guchar *eq, *c;
174 OptionFunc *func;
176 g_return_val_if_fail(option_hash != NULL, "No registered functions!");
178 eq = strchr(line, '=');
179 if (!eq)
180 return _("Missing '='");
182 c = eq - 1;
183 while (c > line && (*c == ' ' || *c == '\t'))
184 c--;
185 c[1] = '\0';
186 c = eq + 1;
187 while (*c == ' ' || *c == '\t')
188 c++;
190 func = (OptionFunc *) g_hash_table_lookup(option_hash, line);
191 if (!func)
192 return _("Unknown option");
194 return func(c);
197 static void save_options(GtkWidget *widget, gpointer data)
199 int button = (int) data;
200 GSList *next = options_sections;
202 while (next)
204 OptionsSection *section = (OptionsSection *) next->data;
205 section->set();
206 next = next->next;
209 if (button == BUTTON_SAVE)
211 char *path;
213 path = choices_find_path_save("options", PROJECT, TRUE);
214 g_return_if_fail(path != NULL);
216 save_file = fopen(path, "wb");
217 if (!save_file)
219 char *str;
220 str = g_strdup_printf(
221 _("Unable to open '%s' for writing: %s"),
222 path, g_strerror(errno));
223 report_error(PROJECT, str);
224 g_free(str);
225 return;
228 next = options_sections;
229 while (next)
231 OptionsSection *section = (OptionsSection *) next->data;
232 section->save();
233 next = next->next;
236 if (save_file && fclose(save_file) == EOF)
238 report_error(PROJECT, g_strerror(errno));
239 return;
243 if (button != BUTTON_APPLY)
244 gtk_widget_hide(window);
247 void options_show(FilerWindow *filer_window)
249 GSList *next = options_sections;
251 if (GTK_WIDGET_MAPPED(window))
252 gtk_widget_hide(window);
254 while (next)
256 OptionsSection *section = (OptionsSection *) next->data;
257 section->update();
258 next = next->next;
261 gtk_widget_show_all(window);
264 void option_write(char *name, char *value)
266 char *string;
267 int len;
269 if (!save_file)
270 return; /* Error already reported hopefully */
272 string = g_strconcat(name, " = ", value, "\n", NULL);
273 len = strlen(string);
274 if (fwrite(string, sizeof(char), len, save_file) < len)
276 delayed_error(_("Saving options"), g_strerror(errno));
277 fclose(save_file);
278 save_file = NULL;
280 g_free(string);