1 /* gAlan - Graphical Audio Language
2 * Copyright (C) 1999 Tony Garnock-Jones
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <sys/types.h>
36 #define HOMEDIR_GALANDIR "/.galan"
37 #define HOMEDIR_SUFFIX "/.galan/prefs"
38 #define SITE_PREFS_PATH SITE_PKGLIB_DIR "/prefs"
40 typedef struct PrefEntry
{
48 PRIVATE GHashTable
*prefs
= NULL
;
49 PRIVATE GHashTable
*options
= NULL
;
51 PRIVATE
void clone_prefs_entry(gpointer key
, gpointer value
, gpointer user_data
) {
52 GHashTable
*newtab
= user_data
;
53 PrefEntry
*entry
= value
;
54 PrefEntry
*newentry
= safe_malloc(sizeof(PrefEntry
));
56 newentry
->key
= safe_string_dup(entry
->key
);
57 newentry
->d
.value
= safe_string_dup(entry
->d
.value
);
58 g_hash_table_insert(newtab
, newentry
->key
, newentry
);
61 PRIVATE GHashTable
*clone_prefs_table(GHashTable
*tab
) {
62 GHashTable
*newtab
= g_hash_table_new(g_str_hash
, g_str_equal
);
64 g_hash_table_foreach(tab
, clone_prefs_entry
, newtab
);
68 PRIVATE
void free_prefs_entry(gpointer key
, gpointer value
, gpointer user_data
) {
69 PrefEntry
*entry
= value
;
75 PRIVATE
void kill_prefs_table(GHashTable
*tab
) {
76 g_hash_table_foreach(tab
, free_prefs_entry
, NULL
);
79 PUBLIC
char *prefs_get_item(const char *key
) {
80 PrefEntry
*entry
= g_hash_table_lookup(prefs
, key
);
81 return entry
? entry
->d
.value
: NULL
;
84 PUBLIC
void prefs_set_item(const char *key
, const char *value
) {
85 PrefEntry
*entry
= safe_malloc(sizeof(PrefEntry
));
86 entry
->key
= safe_string_dup(key
);
87 entry
->d
.value
= safe_string_dup(value
);
88 prefs_clear_item(key
);
89 g_hash_table_insert(prefs
, entry
->key
, entry
);
92 PUBLIC
void prefs_clear_item(const char *key
) {
93 PrefEntry
*entry
= g_hash_table_lookup(prefs
, key
);
96 g_hash_table_remove(prefs
, key
);
103 PUBLIC
void prefs_register_option(const char *key
, const char *value
) {
104 PrefEntry
*entry
= g_hash_table_lookup(options
, key
);
107 entry
= safe_malloc(sizeof(PrefEntry
));
108 entry
->key
= safe_string_dup(key
);
109 entry
->d
.list
= NULL
;
112 entry
->d
.list
= g_list_append(entry
->d
.list
, safe_string_dup(value
));
113 g_hash_table_insert(options
, entry
->key
, entry
);
116 PRIVATE
void add_option_to_optlist(gpointer key
, gpointer value
, gpointer user_data
) {
117 PrefEntry
*entry
= value
;
118 GtkCList
*list
= user_data
;
119 char *texts
[2] = { NULL
, NULL
};
121 texts
[0] = entry
->key
;
122 gtk_clist_append(list
, texts
);
125 PRIVATE gboolean
optlist_row_selected(GtkCList
*optlist
, gint row
, gint column
,
126 GdkEventButton
*event
, gpointer user_data
) {
127 GtkCombo
*droplist
= gtk_object_get_data(GTK_OBJECT(optlist
), "droplist");
131 gtk_clist_get_text(optlist
, row
, column
, &option_name
);
132 entry
= g_hash_table_lookup(options
, option_name
);
135 gchar
*current_value
= prefs_get_item(option_name
);
137 /* Remove the data so that setting the text doesn't update the variable */
138 gtk_object_remove_data(GTK_OBJECT(droplist
->entry
), "option_name");
139 gtk_combo_set_popdown_strings(droplist
, entry
->d
.list
);
140 gtk_entry_set_text(GTK_ENTRY(droplist
->entry
), current_value
? current_value
: "");
142 /* Reinstate it so that changes from now on take effect */
143 gtk_object_set_data(GTK_OBJECT(droplist
->entry
), "option_name", option_name
);
148 PRIVATE gboolean
droplist_entry_changed(GtkEntry
*entry
, gpointer data
) {
149 gchar
*option_name
= gtk_object_get_data(GTK_OBJECT(entry
), "option_name");
151 if (option_name
!= NULL
) {
152 const gchar
*value_text
= gtk_entry_get_text(entry
);
154 if (value_text
[0] == '\0')
155 prefs_clear_item(option_name
);
157 prefs_set_item(option_name
, value_text
);
162 PUBLIC
void prefs_edit_prefs(void) {
163 GHashTable
*backup_prefs
= clone_prefs_table(prefs
);
164 GtkWidget
*ob
= gtk_vbox_new(FALSE
, 5);
165 GtkWidget
*ib
= gtk_vbox_new(FALSE
, 5);
167 GtkWidget
*label
= gtk_label_new("[Note: Quit and restart to put changes into effect]");
168 GtkWidget
*frame
= gtk_frame_new("Options");
169 GtkWidget
*optlist
= gtk_clist_new(1);
170 GtkWidget
*droplist
= gtk_combo_new();
171 GtkWidget
*scrollwin
= gtk_scrolled_window_new(NULL
,NULL
);
173 /* Configure the widgets */
174 //gtk_widget_set_usize(optlist, 200, 100);
175 gtk_clist_set_selection_mode(GTK_CLIST(optlist
), GTK_SELECTION_SINGLE
);
176 gtk_clist_column_titles_hide(GTK_CLIST(optlist
));
177 gtk_clist_set_column_width(GTK_CLIST(optlist
), 0, 200);
178 g_hash_table_foreach(options
, add_option_to_optlist
, optlist
);
180 gtk_box_pack_start(GTK_BOX(ob
), label
, FALSE
, FALSE
, 5);
181 gtk_box_pack_start(GTK_BOX(ob
), frame
, TRUE
, TRUE
, 0);
182 gtk_widget_show(label
);
183 gtk_widget_show(frame
);
185 /* Nest and display the widgets */
186 gtk_container_add(GTK_CONTAINER(frame
), ib
);
189 gtk_container_add( GTK_CONTAINER( scrollwin
), optlist
);
190 gtk_box_pack_start(GTK_BOX(ib
), scrollwin
, TRUE
, TRUE
, 0);
191 gtk_widget_show(optlist
);
192 gtk_widget_show(scrollwin
);
194 hb
= gtk_hbox_new(FALSE
, 5);
195 gtk_box_pack_start(GTK_BOX(ib
), hb
, FALSE
, FALSE
, 0);
198 label
= gtk_label_new("Value:");
199 gtk_label_set_justify(GTK_LABEL(label
), GTK_JUSTIFY_LEFT
);
200 gtk_box_pack_start(GTK_BOX(hb
), label
, FALSE
, TRUE
, 0);
201 gtk_widget_show(label
);
203 gtk_box_pack_start(GTK_BOX(hb
), droplist
, FALSE
, FALSE
, 0);
204 gtk_widget_show(droplist
);
206 /* Configure the data and signals */
207 gtk_object_set_data(GTK_OBJECT(optlist
), "droplist", droplist
);
209 gtk_signal_connect(GTK_OBJECT(optlist
), "select_row",
210 GTK_SIGNAL_FUNC(optlist_row_selected
), NULL
);
211 gtk_signal_connect(GTK_OBJECT(GTK_COMBO(droplist
)->entry
), "changed",
212 GTK_SIGNAL_FUNC(droplist_entry_changed
), NULL
);
214 if (popup_dialog("Adjust Preferences", MSGBOX_ACCEPT
| MSGBOX_DISMISS
, 0, MSGBOX_NONE
,
215 ob
, NULL
, NULL
) != MSGBOX_ACCEPT
) {
216 kill_prefs_table(prefs
);
217 prefs
= backup_prefs
;
222 PRIVATE
void load_prefs_from(char *filename
) {
223 FILE *f
= fopen(filename
, "rt");
224 char line
[LINELEN
]; /* %%% Yuck, a fixed size buffer */
230 if (fgets(line
, LINELEN
, f
) != NULL
) {
231 char *valpos
= strchr(line
, '=');
234 if (line
[0] == '#' || valpos
== NULL
)
237 /* Extract value string + trim leading whitespace */
241 } while (isspace(*valpos
) && *valpos
!= '\0');
243 /* Trim trailing whitespace */
244 len
= strlen(valpos
);
245 while (isspace(valpos
[len
-1])) {
246 valpos
[len
-1] = '\0';
250 prefs_set_item(line
, valpos
);
257 PRIVATE
void save_pref_entry(gpointer key
, gpointer value
, gpointer user_data
) {
259 PrefEntry
*entry
= value
;
261 fprintf(f
, "%s=%s\n", entry
->key
, entry
->d
.value
);
264 PRIVATE gboolean
save_prefs_to(char *filename
) {
265 FILE *f
= fopen(filename
, "wt");
270 g_hash_table_foreach(prefs
, save_pref_entry
, f
);
274 PRIVATE
char *build_userprefs_path(char *homedir
) {
275 char *userprefs
= safe_malloc(strlen(homedir
) + strlen(HOMEDIR_SUFFIX
) + 1);
277 strcpy(userprefs
, homedir
);
278 strcat(userprefs
, HOMEDIR_SUFFIX
);
282 PRIVATE
void load_prefs(void) {
283 char *homedir
= getenv("HOME");
285 load_prefs_from(SITE_PREFS_PATH
);
287 if (homedir
!= NULL
) {
288 char *userprefs
= build_userprefs_path(homedir
);
289 load_prefs_from(userprefs
);
294 PRIVATE
void save_prefs(void) {
296 if (!save_prefs_to(SITE_PREFS_PATH
))
297 g_warning("Could not save preferences to %s", SITE_PREFS_PATH
);
299 char *homedir
= getenv("HOME");
301 if (homedir
!= NULL
) {
302 char *userprefs
= build_userprefs_path(homedir
);
304 if (!save_prefs_to(userprefs
)) {
305 char *usergalandir
= safe_malloc(strlen(homedir
) + strlen(HOMEDIR_GALANDIR
) + 1);
306 strcpy(usergalandir
, homedir
);
307 strcat(usergalandir
, HOMEDIR_GALANDIR
);
308 mkdir(usergalandir
, 0777);
310 if (!save_prefs_to(userprefs
))
311 g_warning("Could not save preferences to %s", userprefs
);
319 PUBLIC
void init_prefs(void) {
320 prefs
= g_hash_table_new(g_str_hash
, g_str_equal
);
321 options
= g_hash_table_new(g_str_hash
, g_str_equal
);
326 PRIVATE
void free_options_entry(gpointer key
, gpointer value
, gpointer user_data
) {
327 PrefEntry
*entry
= value
;
329 g_list_foreach(entry
->d
.list
, (GFunc
) free
, NULL
);
330 g_list_free(entry
->d
.list
);
334 PUBLIC
void done_prefs(void) {
337 g_hash_table_foreach(options
, free_options_entry
, NULL
);
338 kill_prefs_table(prefs
);
340 g_hash_table_destroy(options
);
341 g_hash_table_destroy(prefs
);