commit fda5f458563c3fad93afcc03aec628dd94c1784f
parent 3d2eac4ae2429b93d694efda884f23e5648f104c
Author: hhvn <dev@hhvn.uk>
Date: Sun, 27 Nov 2022 13:16:51 +0000
Save deletion
Diffstat:
7 files changed, 148 insertions(+), 15 deletions(-)
diff --git a/src/file.c b/src/file.c
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include "main.h"
+
+int
+mkdirp(char *path) {
+ char *dup;
+ char *p[64];
+ int create;
+ int i, max;
+ int ret = 0;
+
+ dup = estrdup(path);
+ max = strsplit(dup, "/", p, ELEMS(p));
+
+ for (i = 0, create = 0; i < max; i++) {
+ if (create || access(path, F_OK) == -1) {
+ if (mkdir(dup, 0777 & ~umask(0)) == -1) {
+ ret = -1;
+ goto end;
+ }
+ create = 1;
+ }
+ if (i + 1 != max)
+ *(p[i + 1] - 1) = '/';
+ }
+
+end:
+ free(dup);
+ return ret;
+}
+
+int
+rmdirp(char *dir) {
+ struct dirent **dirent;
+ struct stat st;
+ char path[PATH_MAX];
+ int ret = 0;
+ int n, i;
+
+ n = scandir(dir, &dirent, NULL, alphasort);
+ if (n < 0) return 0;
+
+ for (i = 0; i < n; i++) {
+ snprintf(path, sizeof(path), "%s/%s", dir, dirent[i]->d_name);
+ stat(path, &st);
+ if (!streq(dirent[i]->d_name, ".") && !streq(dirent[i]->d_name, "..")) {
+ if (S_ISDIR(st.st_mode)) {
+ if (rmdirp(path) == -1)
+ ret = -1;
+ } else {
+ if (unlink(path) == -1)
+ ret = -1;
+ }
+ }
+ free(dirent[i]);
+ }
+ free(dirent);
+
+ if (rmdir(dir) == -1)
+ ret = -1;
+
+ return ret;
+}
diff --git a/src/main.h b/src/main.h
@@ -211,10 +211,15 @@ char * bodytype_strify(Body *body);
Body * body_init(char *name);
void body_free(Body *b);
+/* file.c */
+int mkdirp(char *path);
+int rmdirp(char *dir);
+
/* save.c */
void save_read(char *dir);
int save_changed(void);
void save_write(void);
+int save_delete(char *name);
int save_exists(char *name);
int save_create(char *name);
@@ -249,11 +254,6 @@ int dbgetf(char *dir, char *group, char *key, char *fmt, ...);
int dbgettree(char *dir, Tree *t, Treegetter func);
int dbsettree(char *dir, Tree *t, Treesetter func);
-/* loading.c */
-Loader *loading_open(int steps, char *initstr);
-void loading_update(Loader *hand, char *str);
-void loading_close(Loader *hand);
-
/* maths.c */
float cosf_d(float x);
float sinf_d(float x);
diff --git a/src/save.c b/src/save.c
@@ -64,6 +64,14 @@ save_write(void) {
}
int
+save_delete(char *name) {
+ char dir[PATH_MAX];
+
+ snprintf(dir, sizeof(dir), "%s/%s", SAVEDIR, name);
+ return rmdirp(dir);
+}
+
+int
save_exists(char *name) {
char dir[PATH_MAX];
diff --git a/src/tree.c b/src/tree.c
@@ -82,6 +82,8 @@ tree_delete(Tree **t, Treefree freedata) {
freedata(e);
free(e);
+ *t = NULL;
+
return 0;
}
@@ -125,6 +127,9 @@ tree_delete_r(Tree **t, Treefree freedata) {
e->n->p = e->p;
tree_delete_r_sub(e, freedata);
+
+ *t = NULL;
+
return 0;
}
diff --git a/src/views/smenu.c b/src/views/smenu.c
@@ -27,6 +27,7 @@ static int loadhandler_actual(int type, void *elem);
static void loadprinter(int x, int y, Treeview *tv, Tree *t);
static void loadadd(char *dir, time_t mod);
static void loadinit(char *sdir);
+static void loadfree(Tree *t);
static View_smenu *v = &view_smenu;
View_smenu view_smenu = {
@@ -76,6 +77,7 @@ View_smenu view_smenu = {
.print = loadprinter,
.dclick = loadhandler_actual,
},
+ .delete = {0, "Delete", loadhandler_actual, 1 },
.load = {0, "Load", loadhandler_actual, 0 },
}
};
@@ -170,18 +172,30 @@ quithandler(void) {
static void
loadhandler(void) {
v->load.disp = 1;
- /* strcpy(v->cont.label, CONTCUR); */
- /* v->b[SMENU_CONT].enabled = 1; */
}
static int
loadhandler_actual(int type, void *elem) {
struct Loadable *l;
+ Button *b;
+ int delete;
+
+
+ if (type == GUI_BUTTON) {
+ b = elem;
+ delete = b->arg == 1;
+ } else delete = 0;
l = v->load.savelist.sel->data;
- save_read(l->name);
- view_tabs.sel = VIEW_MAIN;
- v->load.disp = 0;
+
+ if (delete) {
+ save_delete(l->name);
+ tree_delete(&v->load.savelist.sel, loadfree);
+ } else {
+ save_read(l->name);
+ view_tabs.sel = VIEW_MAIN;
+ v->load.disp = 0;
+ }
return 0;
}
@@ -211,6 +225,14 @@ loadadd(char *dir, time_t mod) {
tree_add_child(&v->load.saves, p->name, 1, p, NULL);
}
+static void
+loadfree(Tree *t) {
+ struct Loadable *p = t->data;
+
+ free(p->name);
+ free(p);
+}
+
void
checkbeforequit(void) {
if (save_changed()) {
@@ -268,9 +290,9 @@ view_smenu_handle(int nowsel) {
}
if (v->load.disp && v->load.savelist.sel)
- v->load.load.enabled = 1;
+ v->load.load.enabled = v->load.delete.enabled = 1;
else
- v->load.load.enabled = 0;
+ v->load.load.enabled = v->load.delete.enabled = 0;
v->b[SMENU_SAVE].enabled = save ? 1 : 0;
}
@@ -336,9 +358,13 @@ view_smenu_draw(void) {
y += PAD;
gui_treeview(x, y, LOAD_W, LOAD_H, &v->load.savelist);
- gui_button(x + w - BUTTON_W - PAD * 2,
- y + h - PAD * 2 - BUTTON_HEIGHT,
- BUTTON_W, &v->load.load);
+
+ x += w - BUTTON_W - PAD * 2;
+ y += h - PAD * 2 - BUTTON_HEIGHT;
+ gui_button(x, y, BUTTON_W, &v->load.load);
+
+ x -= BUTTON_W + PAD;
+ gui_button(x, y, BUTTON_W, &v->load.delete);
} else {
ui_draw_rect(EXPLODE_RECT(v->main), bg);
ui_draw_border_around(EXPLODE_RECT(v->main), 1);
diff --git a/src/views/struct.h b/src/views/struct.h
@@ -110,6 +110,7 @@ typedef struct {
int disp;
Tree saves;
Treeview savelist;
+ Button delete;
Button load;
} load;
} View_smenu;
diff --git a/tests/file.test b/tests/file.test
@@ -0,0 +1,24 @@
+/* vim: set filetype=c : */
+#include <unistd.h>
+#include <stdio.h>
+#include "../src/main.h"
+
+%{
+ FILE *f;
+ int ret;
+
+ mkdirp("a/b/c");
+ ck_assert(access("a", F_OK) == 0);
+ ck_assert(access("a/b", F_OK) == 0);
+ ck_assert(access("a/b/c", F_OK) == 0);
+
+ f = fopen("a/b/d", "w");
+ fclose(f);
+
+ ret = rmdirp("a");
+ ck_assert(access("a", F_OK) != 0);
+ ck_assert(access("a/b", F_OK) != 0);
+ ck_assert(access("a/b/c", F_OK) != 0);
+ ck_assert(access("a/b/d", F_OK) != 0);
+ ck_assert(ret == 0);
+}