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)
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
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 */
32 #include "gui_support.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
);
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("...", "ROX-Filer", FALSE
);
85 string
= g_strconcat("Choices will be saved as ",
88 label
= gtk_label_new(string
);
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);
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
;
130 GSList
*next
= options_sections
;
134 OptionsSection
*section
= (OptionsSection
*) next
->data
;
136 group
= gtk_frame_new(_(section
->name
));
137 gtk_box_pack_start(GTK_BOX(sections_vbox
), group
,
139 gtk_container_add(GTK_CONTAINER(group
),
147 path
= choices_find_path_load("options", "ROX-Filer");
149 return; /* Nothing to load */
151 parse_file(path
, process_option_line
);
154 void parse_file(char *path
, ParseFunc
*parse_line
)
158 gboolean seen_error
= FALSE
;
160 if (load_file(path
, &data
, &length
))
166 while (line
&& *line
)
168 eol
= strchr(line
, '\n');
172 error
= parse_line(line
);
174 if (error
&& !seen_error
)
178 message
= g_string_new(NULL
);
179 g_string_sprintf(message
,
180 "Error in options file at line %d: "
182 "This may be due to upgrading from "
183 "a previous version of ROX-Filer. "
184 "Open the Options window and click "
186 "Further errors will be ignored.",
189 delayed_error("ROX-Filer", message
->str
);
190 g_string_free(message
, TRUE
);
203 /* Call this on init to register a handler for a key (thing before the = in
205 * The function returns a pointer to an error messages (which will
206 * NOT be free()d), or NULL on success.
208 void option_register(char *key
, OptionFunc
*func
)
211 option_hash
= g_hash_table_new(g_str_hash
, g_str_equal
);
212 g_hash_table_insert(option_hash
, key
, func
);
215 /* Process one line from the options file (\0 term'd).
216 * Returns NULL on success, or a pointer to an error message.
217 * The line is modified.
219 static char *process_option_line(guchar
*line
)
224 g_return_val_if_fail(option_hash
!= NULL
, "No registered functions!");
226 eq
= strchr(line
, '=');
228 return "Missing '='";
231 while (c
> line
&& (*c
== ' ' || *c
== '\t'))
235 while (*c
== ' ' || *c
== '\t')
238 func
= (OptionFunc
*) g_hash_table_lookup(option_hash
, line
);
240 return "Unknown option";
245 static void save_options(GtkWidget
*widget
, gpointer data
)
247 int button
= (int) data
;
248 GSList
*next
= options_sections
;
252 OptionsSection
*section
= (OptionsSection
*) next
->data
;
257 if (button
== BUTTON_SAVE
)
261 path
= choices_find_path_save("options", "ROX-Filer", TRUE
);
262 g_return_if_fail(path
!= NULL
);
264 save_file
= fopen(path
, "wb");
268 str
= g_strconcat("Unable to open '", path
,
272 report_error("ROX-Filer", str
);
277 next
= options_sections
;
280 OptionsSection
*section
= (OptionsSection
*) next
->data
;
285 if (save_file
&& fclose(save_file
) == EOF
)
287 report_error("ROX-Filer", g_strerror(errno
));
292 if (button
!= BUTTON_APPLY
)
293 gtk_widget_hide(window
);
296 void options_show(FilerWindow
*filer_window
)
298 GSList
*next
= options_sections
;
300 if (GTK_WIDGET_MAPPED(window
))
301 gtk_widget_hide(window
);
305 OptionsSection
*section
= (OptionsSection
*) next
->data
;
310 gtk_widget_show_all(window
);
313 void option_write(char *name
, char *value
)
319 return; /* Error already reported hopefully */
321 string
= g_strconcat(name
, " = ", value
, "\n", NULL
);
322 len
= strlen(string
);
323 if (fwrite(string
, sizeof(char), len
, save_file
) < len
)
325 delayed_error("Saving options", g_strerror(errno
));