ref: e2add4185cf1e3639b7a320384098d63dc2f3d67
parent: 6c66e2b2de63b6a8159835516ee229bda3253bc2
author: Simon Tatham <anakin@pobox.com>
date: Sun Apr 23 07:00:58 EDT 2023
GTK: add a command-line --delete-prefs option. If you want to remove your saved preferences for a puzzle for any reason (perhaps because of one of those unsympathetic managers, or perhaps because it's become corrupted in some way), you can of course manually go and find the config file and delete it. But if you're not sure where it is, it's helpful to have a method of telling the puzzle itself to delete the config file. Perhaps it would be useful to expose this in the GUI as well, though I'm not quite sure where is the best place to put it. (_Perhaps_ it would also be useful to have a more thorough option that deleted _all_ puzzles' configurations - although that would involve telling every separate puzzle binary in this collection what all the other ones' names are, which would be an entirely new build headache.)
--- a/gtk.c
+++ b/gtk.c
@@ -3102,6 +3102,70 @@
return err;
}
+static bool delete_prefs(char **msg)
+{
+ char *dir_path = prefs_dir();
+ char *file_path = prefs_path();
+ char *tmp_path = prefs_tmp_path();
+ char *msgs[3];
+ int i, len, nmsgs = 0;
+ char *p;
+ bool ok = true;
+
+ if (unlink(file_path) == 0) {
+ sprintf(msgs[nmsgs++] = snewn(256 + strlen(file_path), char),
+ "Removed preferences file %s\n", file_path);
+ } else if (errno != ENOENT) {
+ const char *os_err = strerror(errno);
+ sprintf(msgs[nmsgs++] = snewn(256 + strlen(file_path) + strlen(os_err),
+ char),
+ "Failed to remove preferences file %s: %s\n",
+ file_path, os_err);
+ ok = false;
+ }
+
+ if (unlink(tmp_path) == 0) {
+ sprintf(msgs[nmsgs++] = snewn(256 + strlen(tmp_path), char),
+ "Removed temporary file %s\n", tmp_path);
+ } else if (errno != ENOENT) {
+ const char *os_err = strerror(errno);
+ sprintf(msgs[nmsgs++] = snewn(256 + strlen(tmp_path) + strlen(os_err),
+ char),
+ "Failed to remove temporary file %s: %s\n", tmp_path, os_err);
+ ok = false;
+ }
+
+ if (rmdir(dir_path) == 0) {
+ sprintf(msgs[nmsgs++] = snewn(256 + strlen(dir_path), char),
+ "Removed empty preferences directory %s\n", dir_path);
+ } else if (errno != ENOENT && errno != ENOTEMPTY) {
+ const char *os_err = strerror(errno);
+ sprintf(msgs[nmsgs++] = snewn(256 + strlen(dir_path) + strlen(os_err),
+ char),
+ "Failed to remove preferences directory %s: %s\n",
+ dir_path, os_err);
+ ok = false;
+ }
+
+ for (i = len = 0; i < nmsgs; i++)
+ len += strlen(msgs[i]);
+ *msg = snewn(len + 1, char);
+ p = *msg;
+ for (i = len = 0; i < nmsgs; i++) {
+ size_t len = strlen(msgs[i]);
+ memcpy(p, msgs[i], len);
+ p += len;
+ sfree(msgs[i]);
+ }
+ *p = '\0';
+
+ sfree(dir_path);
+ sfree(file_path);
+ sfree(tmp_path);
+
+ return ok;
+}
+
#ifdef USE_PRINTING
static void menu_print_event(GtkMenuItem *menuitem, gpointer data)
{
@@ -3863,6 +3927,7 @@
int ngenerate = 0, px = 1, py = 1;
bool print = false;
bool time_generation = false, test_solve = false, list_presets = false;
+ bool delete_prefs_action = false;
bool soln = false, colour = false;
float scale = 1.0F;
float redo_proportion = 0.0F;
@@ -3921,6 +3986,9 @@
test_solve = true;
} else if (doing_opts && !strcmp(p, "--list-presets")) {
list_presets = true;
+ } else if (doing_opts && (!strcmp(p, "--delete-prefs") ||
+ !strcmp(p, "--delete-preferences"))) {
+ delete_prefs_action = true;
} else if (doing_opts && !strcmp(p, "--save")) {
if (--ac > 0) {
savefile = *++av;
@@ -4269,6 +4337,16 @@
list_presets_from_menu(menu);
midend_free(me);
return 0;
+ } else if (delete_prefs_action) {
+ char *msg = NULL;
+ bool ok = delete_prefs(&msg);
+ if (!ok) {
+ fputs(msg, stderr);
+ return 1;
+ } else {
+ fputs(msg, stdout);
+ return 0;
+ }
} else {
frontend *fe;
bool headless = screenshot_file != NULL;
--- a/puzzles.but
+++ b/puzzles.but
@@ -364,6 +364,11 @@
}
+\dt \cw{--delete-prefs}
+
+\dd This option causes the puzzle to delete the configuration file in
+which its user preferences were stored, if there is one.
+
\dt \I{printing, on Unix}\cw{--print }\e{w}\cw{x}\e{h}
\dd If this option is specified, instead of a puzzle being displayed,