Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2018-03-19 16:17:59 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-03-31 21:40:37 +0300
commit651b8fb14eb6ee5cbfa98bffe80a966a0753b14e (patch)
tree2281978509d82a25fb5fbf586f34335e3606442d /source/blender/blenloader
parent91d0825b5556150c017dad767f7971bb6a731aec (diff)
Undo: unified undo system w/ linear history
- Use a single undo history for all operations. - UndoType's are registered and poll the context to check if they should be used when performing an undo push. - Mode switching is used to ensure the state is correct before undo data is restored. - Some undo types accumulate changes (image & text editing) others store the state multiple times (with de-duplication). This is supported by checking UndoStack.mode `ACCUMULATE` / `STORE`. - Each undo step stores ID datablocks they use with utilities to help manage restoring correct ID's. Needed since global undo is now mixed with other modes undo. - Currently performs each undo step when going up/down history Previously this wasn't done, making history fail in some cases. This can be optimized to skip some combinations of undo steps. grease-pencil is an exception which has not been updated since it integrates undo into the draw-session. See D3113
Diffstat (limited to 'source/blender/blenloader')
-rw-r--r--source/blender/blenloader/BLO_readfile.h2
-rw-r--r--source/blender/blenloader/BLO_undofile.h14
-rw-r--r--source/blender/blenloader/intern/readfile.c3
-rw-r--r--source/blender/blenloader/intern/undofile.c78
4 files changed, 95 insertions, 2 deletions
diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h
index 4fd2e227bc5..0b4ff13c7bd 100644
--- a/source/blender/blenloader/BLO_readfile.h
+++ b/source/blender/blenloader/BLO_readfile.h
@@ -147,6 +147,8 @@ void BLO_update_defaults_startup_blend(struct Main *mainvar);
struct BlendThumbnail *BLO_thumbnail_from_file(const char *filepath);
+struct Main *BLO_main_from_memfile(struct MemFile *memfile, struct Main *bmain, struct Scene **r_scene);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenloader/BLO_undofile.h b/source/blender/blenloader/BLO_undofile.h
index d3c0130a63b..b713b963056 100644
--- a/source/blender/blenloader/BLO_undofile.h
+++ b/source/blender/blenloader/BLO_undofile.h
@@ -33,6 +33,8 @@
* \ingroup blenloader
*/
+struct Scene;
+
typedef struct {
void *next, *prev;
const char *buf;
@@ -47,6 +49,12 @@ typedef struct MemFile {
size_t size;
} MemFile;
+typedef struct MemFileUndoData {
+ char filename[1024]; /* FILE_MAX */
+ MemFile memfile;
+ size_t undo_size;
+} MemFileUndoData;
+
/* actually only used writefile.c */
extern void memfile_chunk_add(MemFile *compare, MemFile *current, const char *buf, unsigned int size);
@@ -54,5 +62,9 @@ extern void memfile_chunk_add(MemFile *compare, MemFile *current, const char *bu
extern void BLO_memfile_free(MemFile *memfile);
extern void BLO_memfile_merge(MemFile *first, MemFile *second);
-#endif
+/* utilities */
+extern struct Main *BLO_memfile_main_get(struct MemFile *memfile, struct Main *bmain, struct Scene **r_scene);
+extern bool BLO_memfile_write_file(struct MemFile *memfile, const char *filename);
+
+#endif /* __BLO_UNDOFILE_H__ */
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index e85af67b105..7b51ddcce92 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -6300,7 +6300,8 @@ static void direct_link_windowmanager(FileData *fd, wmWindowManager *wm)
wm->defaultconf = NULL;
wm->addonconf = NULL;
wm->userconf = NULL;
-
+ wm->undo_stack = NULL;
+
BLI_listbase_clear(&wm->jobs);
BLI_listbase_clear(&wm->drags);
diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c
index ffc7d7c83f5..287936e276e 100644
--- a/source/blender/blenloader/intern/undofile.c
+++ b/source/blender/blenloader/intern/undofile.c
@@ -34,6 +34,15 @@
#include <string.h>
#include <stdio.h>
#include <math.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* open/close */
+#ifndef _WIN32
+# include <unistd.h>
+#else
+# include <io.h>
+#endif
#include "MEM_guardedalloc.h"
@@ -42,6 +51,9 @@
#include "BLI_blenlib.h"
#include "BLO_undofile.h"
+#include "BLO_readfile.h"
+
+#include "BKE_main.h"
/* keep last */
#include "BLI_strict_flags.h"
@@ -124,3 +136,69 @@ void memfile_chunk_add(MemFile *compare, MemFile *current, const char *buf, unsi
current->size += size;
}
}
+
+struct Main *BLO_memfile_main_get(struct MemFile *memfile, struct Main *oldmain, struct Scene **r_scene)
+{
+ struct Main *bmain_undo = NULL;
+ BlendFileData *bfd = BLO_read_from_memfile(oldmain, oldmain->name, memfile, NULL, BLO_READ_SKIP_NONE);
+
+ if (bfd) {
+ bmain_undo = bfd->main;
+ if (r_scene) {
+ *r_scene = bfd->curscene;
+ }
+
+ MEM_freeN(bfd);
+ }
+
+ return bmain_undo;
+}
+
+
+/**
+ * Saves .blend using undo buffer.
+ *
+ * \return success.
+ */
+bool BLO_memfile_write_file(struct MemFile *memfile, const char *filename)
+{
+ MemFileChunk *chunk;
+ int file, oflags;
+
+ /* note: This is currently used for autosave and 'quit.blend', where _not_ following symlinks is OK,
+ * however if this is ever executed explicitly by the user, we may want to allow writing to symlinks.
+ */
+
+ oflags = O_BINARY | O_WRONLY | O_CREAT | O_TRUNC;
+#ifdef O_NOFOLLOW
+ /* use O_NOFOLLOW to avoid writing to a symlink - use 'O_EXCL' (CVE-2008-1103) */
+ oflags |= O_NOFOLLOW;
+#else
+ /* TODO(sergey): How to deal with symlinks on windows? */
+# ifndef _MSC_VER
+# warning "Symbolic links will be followed on undo save, possibly causing CVE-2008-1103"
+# endif
+#endif
+ file = BLI_open(filename, oflags, 0666);
+
+ if (file == -1) {
+ fprintf(stderr, "Unable to save '%s': %s\n",
+ filename, errno ? strerror(errno) : "Unknown error opening file");
+ return false;
+ }
+
+ for (chunk = memfile->chunks.first; chunk; chunk = chunk->next) {
+ if (write(file, chunk->buf, chunk->size) != chunk->size) {
+ break;
+ }
+ }
+
+ close(file);
+
+ if (chunk) {
+ fprintf(stderr, "Unable to save '%s': %s\n",
+ filename, errno ? strerror(errno) : "Unknown error writing file");
+ return false;
+ }
+ return true;
+}