2 * ROX-Filer, filer for the ROX desktop project
3 * Copyright (C) 2006, Thomas Leonard and others (see changelog for details).
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17 * Place, Suite 330, Boston, MA 02111-1307 USA
19 /* choices.c - code for handling loading and saving of user choices */
25 #include <sys/param.h>
31 #include "gui_support.h"
35 static gboolean saving_disabled
= TRUE
;
36 static gchar
**dir_list
= NULL
;
37 static gchar
**xdg_dir_list
= NULL
;
38 static int xdg_dir_count
= 0 ;
40 static struct migration
{
45 {"ROX-Filer", SITE
, TRUE
},
46 {"SendTo", SITE
, TRUE
},
47 {"Templates", SITE
, TRUE
},
48 {"MIME-types", SITE
, TRUE
},
49 {"MIME-icons", SITE
, TRUE
},
50 {"MIME-thumb", SITE
, TRUE
},
55 /* Static prototypes */
56 static gboolean
exists(char *path
);
57 static void migrate_choices(void);
59 /****************************************************************
60 * EXTERNAL INTERFACE *
61 ****************************************************************/
64 /* Reads in CHOICESPATH and constructs the directory list table.
65 * You must call this before using any other choices_* functions.
67 * If CHOICESPATH does not exist then a suitable default is used.
69 void choices_init(void)
76 g_return_if_fail(dir_list
== NULL
);
78 /* Initialize old system */
79 choices
= getenv("CHOICESPATH");
83 if (*choices
!= ':' && *choices
!= '\0')
84 saving_disabled
= FALSE
;
86 while (*choices
== ':')
91 dir_list
= g_new(char *, 1);
95 dir_list
= g_strsplit(choices
, ":", 0);
99 saving_disabled
= FALSE
;
101 dir_list
= g_new(gchar
*, 4);
102 dir_list
[0] = g_build_filename(g_get_home_dir(), "Choices",
104 dir_list
[1] = g_strdup("/usr/local/share/Choices");
105 dir_list
[2] = g_strdup("/usr/share/Choices");
109 /* Initialize new system */
110 env
= getenv("XDG_CONFIG_DIRS");
113 dirs
= g_strsplit(env
, ":", 0);
114 g_return_if_fail(dirs
!= NULL
);
115 for (n
= 0; dirs
[n
]; n
++)
117 for (i
= n
; i
> 0; i
--)
118 dirs
[i
] = dirs
[i
- 1];
119 env
= getenv("XDG_CONFIG_HOME");
121 dirs
[0] = g_strdup(env
);
123 dirs
[0] = g_build_filename(g_get_home_dir(), ".config", NULL
);
126 xdg_dir_count
= n
+ 1;
130 gchar
**cdir
= dir_list
;
132 for(i
=0; i
<xdg_dir_count
; i
++)
133 g_print("[ XDG dir '%s' ]\n", xdg_dir_list
[i
]);
137 g_print("[ choices dir '%s' ]\n", *cdir
);
141 g_print("[ saving is %s ]\n", saving_disabled
? "disabled"
148 /* If our XDG choices directory does not yet exist, offer to move the
151 void choices_migrate(void)
155 /* Attempt migration */
156 newpath
=choices_find_xdg_path_save(".", PROJECT
, SITE
, FALSE
);
157 if(!exists(newpath
) && !saving_disabled
)
162 void choices_free_list(GPtrArray
*list
)
166 g_return_if_fail(list
!= NULL
);
168 for (i
= 0; i
< list
->len
; i
++)
169 g_free(g_ptr_array_index(list
, i
));
171 g_ptr_array_free(list
, TRUE
);
174 /* Get the pathname of a choices file to load. Eg:
176 * choices_find_path_load("menus", "ROX-Filer")
177 * -> "/usr/local/share/Choices/ROX-Filer/menus".
179 * The return values may be NULL - use built-in defaults.
180 * g_free() the result.
182 static gchar
*choices_find_path_load(const char *leaf
, const char *dir
)
184 gchar
**cdir
= dir_list
;
186 g_return_val_if_fail(dir_list
!= NULL
, NULL
);
188 for (; *cdir
; cdir
++)
192 path
= g_build_filename(*cdir
, dir
, leaf
, NULL
);
203 /* Get the pathname of a choices file to load, using the XDG paths. Eg:
205 * choices_find_xdg_path_load("menus", "ROX-Filer", "rox.sourceforge.net")
206 * -> "/etc/xdg/rox.sourceforge.net/ROX-Filer/menus".
208 * Falls back on choices_find_path_load(leaf, dir) if it fails
209 * The return values may be NULL - use built-in defaults.
210 * g_free() the result.
212 gchar
*choices_find_xdg_path_load(const char *leaf
, const char *dir
,
217 g_return_val_if_fail(dir_list
!= NULL
, NULL
);
219 for (i
=0; i
<xdg_dir_count
; i
++)
224 path
= g_build_filename(xdg_dir_list
[i
], site
,
227 path
= g_build_filename(xdg_dir_list
[i
], dir
,
236 return choices_find_path_load(leaf
, dir
);
239 /* Returns the pathname of a file to save to, or NULL if saving is
240 * disabled. If 'create' is TRUE then intermediate directories will
241 * be created (set this to FALSE if you just want to find out where
242 * a saved file would go without actually altering the filesystem).
244 * g_free() the result.
246 static gchar
*choices_find_path_save(const char *leaf
, const char *dir
,
249 gchar
*path
, *retval
;
251 g_return_val_if_fail(dir_list
!= NULL
, NULL
);
256 if (create
&& !exists(dir_list
[0]))
258 if (mkdir(dir_list
[0], 0777))
259 g_warning("mkdir(%s): %s\n", dir_list
[0],
263 path
= g_build_filename(dir_list
[0], dir
, NULL
);
264 if (create
&& !exists(path
))
266 if (mkdir(path
, 0777))
267 g_warning("mkdir(%s): %s\n", path
, g_strerror(errno
));
270 retval
= g_build_filename(path
, leaf
, NULL
);
276 /* Returns the pathname of a file to save to, or NULL if saving is
277 * disabled. If 'create' is TRUE then intermediate directories will
278 * be created (set this to FALSE if you just want to find out where
279 * a saved file would go without actually altering the filesystem).
281 * g_free() the result.
283 gchar
*choices_find_xdg_path_save(const char *leaf
, const char *dir
,
284 const char *site
, gboolean create
)
286 gchar
*path
, *retval
, *tmp
;
288 g_return_val_if_fail(xdg_dir_list
!= NULL
, NULL
);
290 if (create
&& !exists(xdg_dir_list
[0]))
292 if (mkdir(xdg_dir_list
[0], 0777))
293 g_warning("mkdir(%s): %s\n", xdg_dir_list
[0],
299 path
= g_build_filename(xdg_dir_list
[0], site
, NULL
);
300 if (create
&& !exists(path
))
302 if (mkdir(path
, 0777))
303 g_warning("mkdir(%s): %s\n", path
,
308 tmp
=g_strdup(xdg_dir_list
[0]);
311 path
= g_build_filename(tmp
, dir
, NULL
);
313 if (create
&& !exists(path
))
315 if (mkdir(path
, 0777))
316 g_warning("mkdir(%s): %s\n", path
, g_strerror(errno
));
319 retval
= g_build_filename(path
, leaf
, NULL
);
326 * Returns an array of the directories in XDG_CONFIG_HOME and XDG_CONFIG_DIRS
327 * which contain a subdirectory called 'dir' (optionally in a subdirectory
330 * Lower-indexed results should override higher-indexed ones.
332 * Free the list using choices_free_list().
334 GPtrArray
*choices_list_xdg_dirs(char *dir
, char *site
)
339 g_return_val_if_fail(xdg_dir_list
!= NULL
, NULL
);
341 list
= g_ptr_array_new();
343 for (i
=0; i
<xdg_dir_count
; i
++)
348 path
= g_build_filename(xdg_dir_list
[i
], site
,
351 path
= g_build_filename(xdg_dir_list
[i
], dir
, NULL
);
354 g_ptr_array_add(list
, path
);
362 /****************************************************************
363 * INTERNAL FUNCTIONS *
364 ****************************************************************/
367 /* Returns TRUE if the object exists, FALSE if it doesn't */
368 static gboolean
exists(char *path
)
372 return stat(path
, &info
) == 0;
378 static void migrate_choices(void)
380 gchar
*opath
, *npath
;
384 gboolean migrated_something
= FALSE
;
386 npath
=choices_find_xdg_path_save("...", PROJECT
, SITE
, FALSE
);
387 opath
=choices_find_path_save("...", PROJECT
,FALSE
);
390 dest=choices_find_xdg_path_save(".", PROJECT, SITE, TRUE);
394 for(i
=0; to_migrate
[i
].dir
; i
++) {
395 src
=g_build_filename(dir_list
[0], to_migrate
[i
].dir
, NULL
);
396 dest
=choices_find_xdg_path_save(NULL
, NULL
,
397 to_migrate
[i
].site
, TRUE
);
399 dest
=choices_find_xdg_path_save(NULL
,
405 if(rename(src
, dest
)==0) {
406 if(to_migrate
[i
].symlink
)
408 migrated_something
= TRUE
;
410 g_warning("rename(%s, %s): %s\n",
415 } else if(to_migrate
[i
].symlink
) {
417 if(!exists(dir_list[0])) {
418 if (mkdir(dir_list[0], 0777))
419 g_warning("mkdir(%s): %s\n",
430 if (migrated_something
)
432 gchar
*failed_msg
= NULL
;
434 failed_msg
= g_strdup_printf(_("%d directories could not be migrated"),
436 info_message(_("Choices have been moved from \n"
438 "to the new location \n"
440 opath
, npath
, failed_msg
? failed_msg
: "");