aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2012-11-14 02:50:17 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2012-11-14 02:50:17 +0100
commit56c58144b1ed4f0a145c5572944e1fb2a165a45a (patch)
tree5124204c4b09bdb8c9e7b4615cf02c11ef9a650a
parent66bde3c43d543cbadd617f68240f4bd8c22d10d9 (diff)
downloadsciteco-56c58144b1ed4f0a145c5572944e1fb2a165a45a.tar.gz
support rubout for EW command: if in undo mode, a save point is created so the file can be replaced or removed when rubbing out EW
-rw-r--r--qbuffers.cpp126
-rw-r--r--qbuffers.h22
2 files changed, 133 insertions, 15 deletions
diff --git a/qbuffers.cpp b/qbuffers.cpp
index f4212d7..b9afbd6 100644
--- a/qbuffers.cpp
+++ b/qbuffers.cpp
@@ -3,6 +3,10 @@
#include <string.h>
#include <bsd/sys/queue.h>
+#ifdef G_OS_WIN32
+#include <windows.h>
+#endif
+
#include <glib.h>
#include <glib/gprintf.h>
#include <glib/gstdio.h>
@@ -261,6 +265,91 @@ Ring::edit(const gchar *filename)
return new_in_ring;
}
+#if 0
+
+/*
+ * TODO: on UNIX it may be better to open() the current file, unlink() it
+ * and keep the file descriptor in the UndoToken.
+ * When the operation is undone, the file descriptor's contents are written to
+ * the file (which should be efficient enough because it is written to the same
+ * filesystem). This way we could avoid messing around with save point files.
+ */
+
+#else
+
+class UndoTokenRestoreSavePoint : public UndoToken {
+ gchar *savepoint;
+ Buffer *buffer;
+
+public:
+#ifdef G_OS_WIN32
+ DWORD attributes;
+#endif
+
+ UndoTokenRestoreSavePoint(gchar *_savepoint, Buffer *_buffer)
+ : savepoint(_savepoint), buffer(_buffer) {}
+ ~UndoTokenRestoreSavePoint()
+ {
+ if (savepoint)
+ g_unlink(savepoint);
+ g_free(savepoint);
+ buffer->savepoint_id--;
+ }
+
+ void
+ run(void)
+ {
+ if (!g_rename(savepoint, buffer->filename)) {
+ g_free(savepoint);
+ savepoint = NULL;
+#ifdef G_OS_WIN32
+ SetFileAttributes((LPCTSTR)buffer->filename,
+ attributes);
+#endif
+ } else {
+ message_display(GTK_MESSAGE_WARNING,
+ "Unable to restore save point file \"%s\"",
+ savepoint);
+ }
+ }
+};
+
+static inline void
+make_savepoint(Buffer *buffer)
+{
+ gchar *dirname, *basename, *savepoint;
+ gchar savepoint_basename[FILENAME_MAX];
+
+ basename = g_path_get_basename(buffer->filename);
+ g_snprintf(savepoint_basename, sizeof(savepoint_basename),
+ ".teco.%s.%d", basename, buffer->savepoint_id);
+ g_free(basename);
+ dirname = g_path_get_dirname(buffer->filename);
+ savepoint = g_build_filename(dirname, savepoint_basename, NULL);
+ g_free(dirname);
+
+ if (!g_rename(buffer->filename, savepoint)) {
+ UndoTokenRestoreSavePoint *token;
+
+ buffer->savepoint_id++;
+ token = new UndoTokenRestoreSavePoint(savepoint, buffer);
+#ifdef G_OS_WIN32
+ token->attributes = GetFileAttributes((LPCTSTR)savepoint);
+ if (token->attributes != INVALID_FILE_ATTRIBUTES)
+ SetFileAttributes((LPCTSTR)savepoint,
+ attrs | FILE_ATTRIBUTE_HIDDEN);
+#endif
+ undo.push(token);
+ } else {
+ message_display(GTK_MESSAGE_WARNING,
+ "Unable to create save point file \"%s\"",
+ savepoint);
+ g_free(savepoint);
+ }
+}
+
+#endif /* !G_OS_UNIX */
+
bool
Ring::save(const gchar *filename)
{
@@ -270,14 +359,23 @@ Ring::save(const gchar *filename)
if (!current)
return false;
- if (!filename && !current->filename)
+ if (!filename)
+ filename = current->filename;
+ if (!filename)
return false;
+ if (undo.enabled) {
+ if (current->filename &&
+ g_file_test(current->filename, G_FILE_TEST_IS_REGULAR))
+ make_savepoint(current);
+ else
+ undo.push(new UndoTokenRemoveFile(filename));
+ }
+
buffer = (const gchar *)editor_msg(SCI_GETCHARACTERPOINTER);
size = editor_msg(SCI_GETLENGTH);
- if (!g_file_set_contents(filename ? : current->filename,
- buffer, size, NULL))
+ if (!g_file_set_contents(filename, buffer, size, NULL))
return false;
/*
@@ -288,7 +386,7 @@ Ring::save(const gchar *filename)
*/
//if (filename) {
undo.push_str(current->filename);
- current->set_filename(filename ? : current->filename);
+ current->set_filename(filename);
//}
return true;
@@ -324,16 +422,7 @@ Ring::~Ring()
/*
* Auxiliary functions
*/
-#ifdef __WIN32__
-
-gchar *
-get_absolute_path(const gchar *path)
-{
- /* FIXME: see Unix implementation */
- return path ? g_file_read_link(path, NULL) : NULL;
-}
-
-#else
+#ifdef G_OS_UNIX
gchar *
get_absolute_path(const gchar *path)
@@ -359,6 +448,15 @@ get_absolute_path(const gchar *path)
return resolved;
}
+#else
+
+gchar *
+get_absolute_path(const gchar *path)
+{
+ /* FIXME: see Unix implementation */
+ return path ? g_file_read_link(path, NULL) : NULL;
+}
+
#endif
/*
diff --git a/qbuffers.h b/qbuffers.h
index 9f22ab1..f58ebda 100644
--- a/qbuffers.h
+++ b/qbuffers.h
@@ -154,12 +154,14 @@ public:
gchar *filename;
gint dot;
+ gint savepoint_id;
+
private:
typedef void document;
document *doc;
public:
- Buffer() : filename(NULL), dot(0)
+ Buffer() : filename(NULL), dot(0), savepoint_id(0)
{
doc = (document *)editor_msg(SCI_CREATEDOCUMENT);
}
@@ -227,6 +229,24 @@ extern class Ring {
void run(void);
};
+ class UndoTokenRemoveFile : public UndoToken {
+ gchar *filename;
+
+ public:
+ UndoTokenRemoveFile(const gchar *_filename)
+ : filename(g_strdup(_filename)) {}
+ ~UndoTokenRemoveFile()
+ {
+ g_free(filename);
+ }
+
+ void
+ run(void)
+ {
+ g_unlink(filename);
+ }
+ };
+
LIST_HEAD(Head, Buffer) head;
public: