correct bug in last commit
[claws.git] / src / prefs.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2002 Hiroyuki Yamamoto
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include <gtk/gtk.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <errno.h>
30
31 #include "intl.h"
32 #include "main.h"
33 #include "prefs.h"
34 #include "utils.h"
35 #include "gtkutils.h"
36
37 typedef enum
38 {
39         DUMMY_PARAM
40 } DummyEnum;
41
42 void prefs_read_config(PrefParam *param, const gchar *label,
43                        const gchar *rcfile)
44 {
45         FILE *fp;
46         gchar buf[PREFSBUFSIZE];
47         gchar *rcpath;
48         gchar *block_label;
49
50         g_return_if_fail(param != NULL);
51         g_return_if_fail(label != NULL);
52         g_return_if_fail(rcfile != NULL);
53
54         debug_print("Reading configuration...\n");
55
56         prefs_set_default(param);
57
58         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, rcfile, NULL);
59         if ((fp = fopen(rcpath, "rb")) == NULL) {
60                 if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
61                 g_free(rcpath);
62                 return;
63         }
64         g_free(rcpath);
65
66         block_label = g_strdup_printf("[%s]", label);
67
68         /* search aiming block */
69         while (fgets(buf, sizeof(buf), fp) != NULL) {
70                 gint val;
71
72                 val = strncmp(buf, block_label, strlen(block_label));
73                 if (val == 0) {
74                         debug_print("Found %s\n", block_label);
75                         break;
76                 }
77         }
78         g_free(block_label);
79
80         while (fgets(buf, sizeof(buf), fp) != NULL) {
81                 strretchomp(buf);
82                 /* reached next block */
83                 if (buf[0] == '[') break;
84
85                 prefs_config_parse_one_line(param, buf);
86         }
87
88         debug_print("Finished reading configuration.\n");
89         fclose(fp);
90 }
91
92 void prefs_config_parse_one_line(PrefParam *param, const gchar *buf)
93 {
94         gint i;
95         gint name_len;
96         const gchar *value;
97
98         for (i = 0; param[i].name != NULL; i++) {
99                 name_len = strlen(param[i].name);
100                 if (strncasecmp(buf, param[i].name, name_len))
101                         continue;
102                 if (buf[name_len] != '=')
103                         continue;
104                 value = buf + name_len + 1;
105                 /* debug_print("%s = %s\n", param[i].name, value); */
106
107                 switch (param[i].type) {
108                 case P_STRING:
109                         g_free(*((gchar **)param[i].data));
110                         *((gchar **)param[i].data) =
111                                 *value ? g_strdup(value) : NULL;
112                         break;
113                 case P_INT:
114                         *((gint *)param[i].data) =
115                                 (gint)atoi(value);
116                         break;
117                 case P_BOOL:
118                         *((gboolean *)param[i].data) =
119                                 (*value == '0' || *value == '\0')
120                                         ? FALSE : TRUE;
121                         break;
122                 case P_ENUM:
123                         *((DummyEnum *)param[i].data) =
124                                 (DummyEnum)atoi(value);
125                         break;
126                 case P_USHORT:
127                         *((gushort *)param[i].data) =
128                                 (gushort)atoi(value);
129                         break;
130                 default:
131                         break;
132                 }
133         }
134 }
135
136 #define TRY(func) \
137 if (!(func)) \
138 { \
139         g_warning(_("failed to write configuration to file\n")); \
140         if (orig_fp) fclose(orig_fp); \
141         prefs_write_close_revert(pfile); \
142         g_free(rcpath); \
143         g_free(block_label); \
144         return; \
145 } \
146
147 void prefs_save_config(PrefParam *param, const gchar *label,
148                        const gchar *rcfile)
149 {
150         FILE *orig_fp;
151         PrefFile *pfile;
152         gchar *rcpath;
153         gchar buf[PREFSBUFSIZE];
154         gchar *block_label = NULL;
155         gboolean block_matched = FALSE;
156
157         g_return_if_fail(param != NULL);
158         g_return_if_fail(label != NULL);
159         g_return_if_fail(rcfile != NULL);
160
161         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, rcfile, NULL);
162         if ((orig_fp = fopen(rcpath, "rb")) == NULL) {
163                 if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
164         }
165
166         if ((pfile = prefs_write_open(rcpath)) == NULL) {
167                 g_warning(_("failed to write configuration to file\n"));
168                 if (orig_fp) fclose(orig_fp);
169                 g_free(rcpath);
170                 return;
171         }
172
173         block_label = g_strdup_printf("[%s]", label);
174
175         /* search aiming block */
176         if (orig_fp) {
177                 while (fgets(buf, sizeof(buf), orig_fp) != NULL) {
178                         gint val;
179
180                         val = strncmp(buf, block_label, strlen(block_label));
181                         if (val == 0) {
182                                 debug_print("Found %s\n", block_label);
183                                 block_matched = TRUE;
184                                 break;
185                         } else
186                                 TRY(fputs(buf, pfile->fp) != EOF);
187                 }
188         }
189
190         TRY(fprintf(pfile->fp, "%s\n", block_label) > 0);
191         g_free(block_label);
192         block_label = NULL;
193
194         /* write all param data to file */
195         TRY(prefs_write_param(param, pfile->fp) == 0);
196
197         if (block_matched) {
198                 while (fgets(buf, sizeof(buf), orig_fp) != NULL) {
199                         /* next block */
200                         if (buf[0] == '[') {
201                                 TRY(fputc('\n', pfile->fp) != EOF &&
202                                     fputs(buf, pfile->fp)  != EOF);
203                                 break;
204                         }
205                 }
206                 while (fgets(buf, sizeof(buf), orig_fp) != NULL)
207                         TRY(fputs(buf, pfile->fp) != EOF);
208         }
209
210         if (orig_fp) fclose(orig_fp);
211         if (prefs_write_close(pfile) < 0)
212                 g_warning(_("failed to write configuration to file\n"));
213         g_free(rcpath);
214
215         debug_print("Configuration is saved.\n");
216 }
217
218 gint prefs_write_param(PrefParam *param, FILE *fp)
219 {
220         gint i;
221         gchar buf[PREFSBUFSIZE];
222
223         for (i = 0; param[i].name != NULL; i++) {
224                 switch (param[i].type) {
225                 case P_STRING:
226                         g_snprintf(buf, sizeof(buf), "%s=%s\n", param[i].name,
227                                    *((gchar **)param[i].data) ?
228                                    *((gchar **)param[i].data) : "");
229                         break;
230                 case P_INT:
231                         g_snprintf(buf, sizeof(buf), "%s=%d\n", param[i].name,
232                                    *((gint *)param[i].data));
233                         break;
234                 case P_BOOL:
235                         g_snprintf(buf, sizeof(buf), "%s=%d\n", param[i].name,
236                                    *((gboolean *)param[i].data));
237                         break;
238                 case P_ENUM:
239                         g_snprintf(buf, sizeof(buf), "%s=%d\n", param[i].name,
240                                    *((DummyEnum *)param[i].data));
241                         break;
242                 case P_USHORT:
243                         g_snprintf(buf, sizeof(buf), "%s=%d\n", param[i].name,
244                                    *((gushort *)param[i].data));
245                         break;
246                 default:
247                         buf[0] = '\0';
248                 }
249
250                 if (buf[0] != '\0') {
251                         if (fputs(buf, fp) == EOF) {
252                                 perror("fputs");
253                                 return -1;
254                         }
255                 }
256         }
257
258         return 0;
259 }
260
261 PrefFile *prefs_write_open(const gchar *path)
262 {
263         PrefFile *pfile;
264         gchar *tmppath;
265         FILE *fp;
266
267         g_return_val_if_fail(path != NULL, NULL);
268
269         if (prefs_is_readonly(path)) {
270                 g_warning(_("no permission - %s\n"), path);
271                 return NULL;
272         }
273
274         tmppath = g_strconcat(path, ".tmp", NULL);
275         if ((fp = fopen(tmppath, "wb")) == NULL) {
276                 FILE_OP_ERROR(tmppath, "fopen");
277                 g_free(tmppath);
278                 return NULL;
279         }
280
281         if (change_file_mode_rw(fp, tmppath) < 0)
282                 FILE_OP_ERROR(tmppath, "chmod");
283
284         g_free(tmppath);
285
286         pfile = g_new(PrefFile, 1);
287         pfile->fp = fp;
288         pfile->path = g_strdup(path);
289
290         return pfile;
291 }
292
293 gint prefs_write_close(PrefFile *pfile)
294 {
295         FILE *fp;
296         gchar *path;
297         gchar *tmppath;
298         gchar *bakpath = NULL;
299
300         g_return_val_if_fail(pfile != NULL, -1);
301
302         fp = pfile->fp;
303         path = pfile->path;
304         g_free(pfile);
305
306         tmppath = g_strconcat(path, ".tmp", NULL);
307         if (fclose(fp) == EOF) {
308                 FILE_OP_ERROR(tmppath, "fclose");
309                 unlink(tmppath);
310                 g_free(path);
311                 g_free(tmppath);
312                 return -1;
313         }
314
315         if (is_file_exist(path)) {
316                 bakpath = g_strconcat(path, ".bak", NULL);
317                 if (rename(path, bakpath) < 0) {
318                         FILE_OP_ERROR(path, "rename");
319                         unlink(tmppath);
320                         g_free(path);
321                         g_free(tmppath);
322                         g_free(bakpath);
323                         return -1;
324                 }
325         }
326
327         if (rename(tmppath, path) < 0) {
328                 FILE_OP_ERROR(tmppath, "rename");
329                 unlink(tmppath);
330                 g_free(path);
331                 g_free(tmppath);
332                 g_free(bakpath);
333                 return -1;
334         }
335
336         g_free(path);
337         g_free(tmppath);
338         g_free(bakpath);
339         return 0;
340 }
341
342 gint prefs_write_close_revert(PrefFile *pfile)
343 {
344         gchar *tmppath;
345
346         g_return_val_if_fail(pfile != NULL, -1);
347
348         tmppath = g_strconcat(pfile->path, ".tmp", NULL);
349         fclose(pfile->fp);
350         if (unlink(tmppath) < 0) FILE_OP_ERROR(tmppath, "unlink");
351         g_free(tmppath);
352         g_free(pfile->path);
353         g_free(pfile);
354
355         return 0;
356 }
357
358 void prefs_set_default(PrefParam *param)
359 {
360         gint i;
361
362         g_return_if_fail(param != NULL);
363
364         for (i = 0; param[i].name != NULL; i++) {
365                 if (!param[i].data) continue;
366
367                 switch (param[i].type) {
368                 case P_STRING:
369                         if (param[i].defval != NULL) {
370                                 if (!strncasecmp(param[i].defval, "ENV_", 4))
371                                         *((gchar **)param[i].data) =
372                                                 g_strdup(g_getenv(param[i].defval + 4));
373                                 else if (param[i].defval[0] == '~')
374                                         *((gchar **)param[i].data) =
375                                                 g_strconcat(get_home_dir(),
376                                                             param[i].defval + 1,
377                                                             NULL);
378                                 else if (param[i].defval[0] != '\0')
379                                         *((gchar **)param[i].data) =
380                                                 g_strdup(param[i].defval);
381                                 else
382                                         *((gchar **)param[i].data) = NULL;
383                         } else
384                                 *((gchar **)param[i].data) = NULL;
385                         break;
386                 case P_INT:
387                         if (param[i].defval != NULL)
388                                 *((gint *)param[i].data) =
389                                         (gint)atoi(param[i].defval);
390                         else
391                                 *((gint *)param[i].data) = 0;
392                         break;
393                 case P_BOOL:
394                         if (param[i].defval != NULL) {
395                                 if (!strcasecmp(param[i].defval, "TRUE"))
396                                         *((gboolean *)param[i].data) = TRUE;
397                                 else
398                                         *((gboolean *)param[i].data) =
399                                                 atoi(param[i].defval) ? TRUE : FALSE;
400                         } else
401                                 *((gboolean *)param[i].data) = FALSE;
402                         break;
403                 case P_ENUM:
404                         if (param[i].defval != NULL)
405                                 *((DummyEnum*)param[i].data) =
406                                         (DummyEnum)atoi(param[i].defval);
407                         else
408                                 *((DummyEnum *)param[i].data) = 0;
409                         break;
410                 case P_USHORT:
411                         if (param[i].defval != NULL)
412                                 *((gushort *)param[i].data) =
413                                         (gushort)atoi(param[i].defval);
414                         else
415                                 *((gushort *)param[i].data) = 0;
416                         break;
417                 default:
418                         break;
419                 }
420         }
421 }
422
423 void prefs_free(PrefParam *param)
424 {
425         gint i;
426
427         g_return_if_fail(param != NULL);
428
429         for (i = 0; param[i].name != NULL; i++) {
430                 if (!param[i].data) continue;
431
432                 switch (param[i].type) {
433                 case P_STRING:
434                         g_free(*((gchar **)param[i].data));
435                         break;
436                 default:
437                         break;
438                 }
439         }
440 }
441
442 void prefs_dialog_create(PrefsDialog *dialog)
443 {
444         GtkWidget *window;
445         GtkWidget *vbox;
446         GtkWidget *notebook;
447
448         GtkWidget *confirm_area;
449         GtkWidget *ok_btn;
450         GtkWidget *cancel_btn;
451         GtkWidget *apply_btn;
452
453         g_return_if_fail(dialog != NULL);
454
455         window = gtk_window_new (GTK_WINDOW_DIALOG);
456         gtk_container_set_border_width (GTK_CONTAINER (window), 8);
457         gtk_window_position (GTK_WINDOW(window), GTK_WIN_POS_CENTER);
458         gtk_window_set_modal (GTK_WINDOW (window), TRUE);
459         gtk_window_set_policy (GTK_WINDOW(window), FALSE, TRUE, FALSE);
460
461         vbox = gtk_vbox_new (FALSE, 6);
462         gtk_widget_show(vbox);
463         gtk_container_add (GTK_CONTAINER (window), vbox);
464
465         notebook = gtk_notebook_new ();
466         gtk_widget_show(notebook);
467         gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
468         gtk_container_set_border_width (GTK_CONTAINER (notebook), 2);
469         /* GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS); */
470         gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE);
471         
472         gtk_notebook_popup_enable (GTK_NOTEBOOK (notebook));
473         
474         gtkut_button_set_create(&confirm_area,
475                                 &ok_btn,        _("OK"),
476                                 &cancel_btn,    _("Cancel"),
477                                 &apply_btn,     _("Apply"));
478         gtk_widget_show(confirm_area);
479         gtk_box_pack_end (GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
480         gtk_widget_grab_default(ok_btn);
481
482         dialog->window     = window;
483         dialog->notebook   = notebook;
484         dialog->ok_btn     = ok_btn;
485         dialog->cancel_btn = cancel_btn;
486         dialog->apply_btn  = apply_btn;
487 }
488
489 void prefs_dialog_destroy(PrefsDialog *dialog)
490 {
491         gtk_widget_destroy(dialog->window);
492         dialog->window     = NULL;
493         dialog->notebook   = NULL;
494         dialog->ok_btn     = NULL;
495         dialog->cancel_btn = NULL;
496         dialog->apply_btn  = NULL;
497 }
498
499 void prefs_button_toggled(GtkToggleButton *toggle_btn, GtkWidget *widget)
500 {
501         gboolean is_active;
502
503         is_active = gtk_toggle_button_get_active(toggle_btn);
504         gtk_widget_set_sensitive(widget, is_active);
505 }
506
507 void prefs_set_dialog(PrefParam *param)
508 {
509         gint i;
510
511         for (i = 0; param[i].name != NULL; i++) {
512                 if (param[i].widget_set_func)
513                         param[i].widget_set_func(&param[i]);
514         }
515 }
516
517 void prefs_set_data_from_dialog(PrefParam *param)
518 {
519         gint i;
520
521         for (i = 0; param[i].name != NULL; i++) {
522                 if (param[i].data_set_func)
523                         param[i].data_set_func(&param[i]);
524         }
525 }
526
527 void prefs_set_dialog_to_default(PrefParam *param)
528 {
529         gint       i;
530         PrefParam  tmpparam;
531         gchar     *str_data = NULL;
532         gint       int_data;
533         gushort    ushort_data;
534         gboolean   bool_data;
535         DummyEnum  enum_data;
536
537         for (i = 0; param[i].name != NULL; i++) {
538                 if (!param[i].widget_set_func) continue;
539
540                 tmpparam = param[i];
541
542                 switch (tmpparam.type) {
543                 case P_STRING:
544                         if (tmpparam.defval) {
545                                 if (!strncasecmp(tmpparam.defval, "ENV_", 4)) {
546                                         str_data = g_strdup(g_getenv(param[i].defval + 4));
547                                         tmpparam.data = &str_data;
548                                         break;
549                                 } else if (tmpparam.defval[0] == '~') {
550                                         str_data =
551                                                 g_strconcat(get_home_dir(),
552                                                             param[i].defval + 1,
553                                                             NULL);
554                                         tmpparam.data = &str_data;
555                                         break;
556                                 }
557                         }
558                         tmpparam.data = &tmpparam.defval;
559                         break;
560                 case P_INT:
561                         if (tmpparam.defval)
562                                 int_data = atoi(tmpparam.defval);
563                         else
564                                 int_data = 0;
565                         tmpparam.data = &int_data;
566                         break;
567                 case P_USHORT:
568                         if (tmpparam.defval)
569                                 ushort_data = atoi(tmpparam.defval);
570                         else
571                                 ushort_data = 0;
572                         tmpparam.data = &ushort_data;
573                         break;
574                 case P_BOOL:
575                         if (tmpparam.defval) {
576                                 if (!strcasecmp(tmpparam.defval, "TRUE"))
577                                         bool_data = TRUE;
578                                 else
579                                         bool_data = atoi(tmpparam.defval)
580                                                 ? TRUE : FALSE;
581                         } else
582                                 bool_data = FALSE;
583                         tmpparam.data = &bool_data;
584                         break;
585                 case P_ENUM:
586                         if (tmpparam.defval)
587                                 enum_data = (DummyEnum)atoi(tmpparam.defval);
588                         else
589                                 enum_data = 0;
590                         tmpparam.data = &enum_data;
591                         break;
592                 case P_OTHER:
593                         break;
594                 }
595                 tmpparam.widget_set_func(&tmpparam);
596                 g_free(str_data);
597                 str_data = NULL;
598         }
599 }
600
601 void prefs_set_data_from_entry(PrefParam *pparam)
602 {
603         gchar **str, *entry_str;
604
605         g_return_if_fail(*pparam->widget != NULL);
606
607         entry_str = gtk_entry_get_text(GTK_ENTRY(*pparam->widget));
608
609         switch (pparam->type) {
610         case P_STRING:
611                 str = (gchar **)pparam->data;
612                 g_free(*str);
613                 *str = entry_str[0] ? g_strdup(entry_str) : NULL;
614                 break;
615         case P_USHORT:
616                 *((gushort *)pparam->data) = atoi(entry_str);
617                 break;
618         case P_INT:
619                 *((gint *)pparam->data) = atoi(entry_str);
620                 break;
621         default:
622                 g_warning("Invalid PrefType for GtkEntry widget: %d\n",
623                           pparam->type);
624         }
625 }
626
627 void prefs_set_entry(PrefParam *pparam)
628 {
629         gchar **str;
630
631         g_return_if_fail(*pparam->widget != NULL);
632
633         switch (pparam->type) {
634         case P_STRING:
635                 str = (gchar **)pparam->data;
636                 gtk_entry_set_text(GTK_ENTRY(*pparam->widget),
637                                    *str ? *str : "");
638                 break;
639         case P_INT:
640                 gtk_entry_set_text(GTK_ENTRY(*pparam->widget),
641                                    itos(*((gint *)pparam->data)));
642                 break;
643         case P_USHORT:
644                 gtk_entry_set_text(GTK_ENTRY(*pparam->widget),
645                                    itos(*((gushort *)pparam->data)));
646                 break;
647         default:
648                 g_warning("Invalid PrefType for GtkEntry widget: %d\n",
649                           pparam->type);
650         }
651 }
652
653 void prefs_set_data_from_text(PrefParam *pparam)
654 {
655         gchar **str;
656         gchar *text, *tp;
657         gchar *tmp, *tmpp;
658
659         g_return_if_fail(*pparam->widget != NULL);
660
661         switch (pparam->type) {
662         case P_STRING:
663                 str = (gchar **)pparam->data;
664                 g_free(*str);
665                 tp = text = gtk_editable_get_chars
666                         (GTK_EDITABLE(*pparam->widget), 0, -1);
667                 if (text[0] == '\0') {
668                         *str = NULL;
669                         g_free(text);
670                         break;
671                 }
672
673                 Xalloca(tmpp = tmp, strlen(text) * 2 + 1,
674                         { *str = NULL; break; });
675                 while (*tp) {
676                         if (*tp == '\n') {
677                                 *tmpp++ = '\\';
678                                 *tmpp++ = 'n';
679                                 tp++;
680                         } else
681                                 *tmpp++ = *tp++;
682                 }
683                 *tmpp = '\0';
684                 *str = g_strdup(tmp);
685                 g_free(text);
686                 break;
687         default:
688                 g_warning("Invalid PrefType for GtkText widget: %d\n",
689                           pparam->type);
690         }
691 }
692
693 void prefs_set_text(PrefParam *pparam)
694 {
695         gchar *buf, *sp, *bufp;
696         gchar **str;
697         GtkText *text;
698
699         g_return_if_fail(*pparam->widget != NULL);
700
701         switch (pparam->type) {
702         case P_STRING:
703                 str = (gchar **)pparam->data;
704                 if (*str) {
705                         bufp = buf = alloca(strlen(*str) + 1);
706                         if (!buf) buf = "";
707                         else {
708                                 sp = *str;
709                                 while (*sp) {
710                                         if (*sp == '\\' && *(sp + 1) == 'n') {
711                                                 *bufp++ = '\n';
712                                                 sp += 2;
713                                         } else
714                                                 *bufp++ = *sp++;
715                                 }
716                                 *bufp = '\0';
717                         }
718                 } else
719                         buf = "";
720
721                 text = GTK_TEXT(*pparam->widget);
722                 gtk_text_set_point(text, 0);
723                 gtk_text_forward_delete(text, gtk_text_get_length(text));
724                 gtk_text_set_point(text, 0);
725                 gtk_text_insert(text, NULL, NULL, NULL, buf, -1);
726                 break;
727         default:
728                 g_warning("Invalid PrefType for GtkText widget: %d\n",
729                           pparam->type);
730         }
731 }
732
733 void prefs_set_data_from_toggle(PrefParam *pparam)
734 {
735         g_return_if_fail(pparam->type == P_BOOL);
736         g_return_if_fail(*pparam->widget != NULL);
737         
738         *((gboolean *)pparam->data) =
739                 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(*pparam->widget));
740 }
741
742 void prefs_set_toggle(PrefParam *pparam)
743 {
744         g_return_if_fail(pparam->type == P_BOOL);
745         g_return_if_fail(*pparam->widget != NULL);
746
747         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(*pparam->widget),
748                                      *((gboolean *)pparam->data));
749 }
750
751 void prefs_set_data_from_spinbtn(PrefParam *pparam)
752 {
753         g_return_if_fail(*pparam->widget != NULL);
754
755         switch (pparam->type) {
756         case P_INT:
757                 *((gint *)pparam->data) =
758                         gtk_spin_button_get_value_as_int
759                         (GTK_SPIN_BUTTON(*pparam->widget));
760                 break;
761         case P_USHORT:
762                 *((gushort *)pparam->data) =
763                         (gushort)gtk_spin_button_get_value_as_int
764                         (GTK_SPIN_BUTTON(*pparam->widget));
765                 break;
766         default:
767                 g_warning("Invalid PrefType for GtkSpinButton widget: %d\n",
768                           pparam->type);
769         }
770 }
771
772 void prefs_set_spinbtn(PrefParam *pparam)
773 {
774         g_return_if_fail(*pparam->widget != NULL);
775
776         switch (pparam->type) {
777         case P_INT:
778                 gtk_spin_button_set_value(GTK_SPIN_BUTTON(*pparam->widget),
779                                           (gfloat)*((gint *)pparam->data));
780                 break;
781         case P_USHORT:
782                 gtk_spin_button_set_value(GTK_SPIN_BUTTON(*pparam->widget),
783                                           (gfloat)*((gushort *)pparam->data));
784                 break;
785         default:
786                 g_warning("Invalid PrefType for GtkSpinButton widget: %d\n",
787                           pparam->type);
788         }
789 }
790
791 gboolean prefs_is_readonly(const gchar * path)
792 {
793         if (path == NULL)
794                 return TRUE;
795
796         return (access(path, W_OK) != 0 && access(path, F_OK) == 0);
797 }
798
799 gboolean prefs_rc_is_readonly(const gchar * rcfile)
800 {
801         gboolean result;
802         gchar * rcpath;
803
804         if (rcfile == NULL)
805                 return TRUE;
806
807         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, rcfile, NULL);
808         result = prefs_is_readonly(rcpath);
809         g_free(rcpath);
810
811         return result;
812 }