shithub: puzzles

Download patch

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,