aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2014-11-24 02:51:31 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2014-11-24 05:07:06 +0100
commitd503c3b07c2157658f699294c44ad5be244727a5 (patch)
treef25b9927f5bdcfca98a82f3bc917548cbec5962b /src
parent355cae277c29104b982f4dc7aa3e05fc06945325 (diff)
downloadsciteco-d503c3b07c2157658f699294c44ad5be244727a5.tar.gz
factored out file loading and saving into the View specialisation IOView
this will allow us to use the same algorithms for loading and saving Q-Registers (from/to file). * Saving with EW when a Q-Reg is edited has been fixed (was broken earlier) * SciTECO save point files are now named .teco-X-BASENAME When using IOView for Q-Regs, there will be no way to sensible count the save points. Each write of a Q-Reg may be to another file. Therefore, we number save-points globally. If the sequence of writes has to be reconstructed manually, one can still look at the save point files' modification dates * give more informative error messages when saving a file fails
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am1
-rw-r--r--src/ioview.cpp358
-rw-r--r--src/ioview.h67
-rw-r--r--src/ring.cpp367
-rw-r--r--src/ring.h54
5 files changed, 467 insertions, 380 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index d02c0b5..9972f71 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -25,6 +25,7 @@ libsciteco_base_a_SOURCES = main.cpp sciteco.h \
undo.cpp undo.h \
expressions.cpp expressions.h \
document.cpp document.h \
+ ioview.cpp ioview.h \
qregisters.cpp qregisters.h \
ring.cpp ring.h \
parser.cpp parser.h \
diff --git a/src/ioview.cpp b/src/ioview.cpp
new file mode 100644
index 0000000..c9d147c
--- /dev/null
+++ b/src/ioview.cpp
@@ -0,0 +1,358 @@
+/*
+ * Copyright (C) 2012-2014 Robin Haberkorn
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <glib/gstdio.h>
+
+#include <Scintilla.h>
+
+#include "sciteco.h"
+#include "interface.h"
+#include "undo.h"
+#include "error.h"
+#include "ioview.h"
+
+#ifdef HAVE_WINDOWS_H
+/* here it shouldn't cause conflicts with other headers */
+#include <windows.h>
+
+/* still need to clean up */
+#undef interface
+#endif
+
+namespace SciTECO {
+
+#ifdef G_OS_WIN32
+
+typedef DWORD FileAttributes;
+/* INVALID_FILE_ATTRIBUTES already defined */
+
+static inline FileAttributes
+get_file_attributes(const gchar *filename)
+{
+ return GetFileAttributes((LPCTSTR)filename);
+}
+
+static inline void
+set_file_attributes(const gchar *filename, FileAttributes attrs)
+{
+ SetFileAttributes((LPCTSTR)filename, attrs);
+}
+
+#else
+
+typedef int FileAttributes;
+#define INVALID_FILE_ATTRIBUTES (-1)
+
+static inline FileAttributes
+get_file_attributes(const gchar *filename)
+{
+ struct stat buf;
+
+ return g_stat(filename, &buf) ? INVALID_FILE_ATTRIBUTES : buf.st_mode;
+}
+
+static inline void
+set_file_attributes(const gchar *filename, FileAttributes attrs)
+{
+ g_chmod(filename, attrs);
+}
+
+#endif /* !G_OS_WIN32 */
+
+/*
+ * The following simple implementation of file reading is actually the
+ * most efficient and useful in the common case of editing small files,
+ * since
+ * a) it works with minimal number of syscalls and
+ * b) small files cause little temporary memory overhead.
+ * Reading large files however could be very inefficient since the file
+ * must first be read into memory and then copied in-memory. Also it could
+ * result in thrashing.
+ * Alternatively we could iteratively read into a smaller buffer trading
+ * in speed against (temporary) memory consumption.
+ * The best way to do it could be memory mapping the file as we could
+ * let Scintilla copy from the file's virtual memory directly.
+ * Unfortunately since every page of the mapped file is
+ * only touched once by Scintilla TLB caching is useless and the TLB is
+ * effectively thrashed with entries of the mapped file.
+ * This results in the doubling of page faults and weighs out the other
+ * advantages of memory mapping (has been benchmarked).
+ *
+ * So in the future, the following approach could be implemented:
+ * 1.) On Unix/Posix, mmap() one page at a time, hopefully preventing
+ * TLB thrashing.
+ * 2.) On other platforms read into and copy from a statically sized buffer
+ * (perhaps page-sized)
+ */
+void
+IOView::load(const gchar *filename)
+{
+ gchar *contents;
+ gsize size;
+
+ GError *gerror = NULL;
+
+ if (!g_file_get_contents(filename, &contents, &size, &gerror))
+ throw GlibError(gerror);
+
+ ssm(SCI_BEGINUNDOACTION);
+ ssm(SCI_CLEARALL);
+ ssm(SCI_APPENDTEXT, size, (sptr_t)contents);
+ ssm(SCI_ENDUNDOACTION);
+
+ g_free(contents);
+}
+
+#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
+
+static gint savepoint_id = 0;
+
+class UndoTokenRestoreSavePoint : public UndoToken {
+ gchar *savepoint;
+ gchar *filename;
+
+#ifdef G_OS_WIN32
+ FileAttributes orig_attrs;
+#endif
+
+public:
+ UndoTokenRestoreSavePoint(gchar *_savepoint, const gchar *_filename)
+ : savepoint(_savepoint), filename(g_strdup(_filename))
+ {
+#ifdef G_OS_WIN32
+ orig_attrs = get_file_attributes(filename);
+ if (orig_attrs != INVALID_FILE_ATTRIBUTES)
+ set_file_attributes(savepoint,
+ orig_attrs | FILE_ATTRIBUTE_HIDDEN);
+#endif
+ }
+
+ ~UndoTokenRestoreSavePoint()
+ {
+ if (savepoint) {
+ g_unlink(savepoint);
+ g_free(savepoint);
+ }
+ g_free(filename);
+
+ savepoint_id--;
+ }
+
+ void
+ run(void)
+ {
+ if (!g_rename(savepoint, filename)) {
+ g_free(savepoint);
+ savepoint = NULL;
+#ifdef G_OS_WIN32
+ if (orig_attrs != INVALID_FILE_ATTRIBUTES)
+ set_file_attributes(filename,
+ orig_attrs);
+#endif
+ } else {
+ interface.msg(InterfaceCurrent::MSG_WARNING,
+ "Unable to restore save point file \"%s\"",
+ savepoint);
+ }
+ }
+};
+
+static void
+make_savepoint(const gchar *filename)
+{
+ gchar *dirname, *basename, *savepoint;
+ gchar savepoint_basename[FILENAME_MAX];
+
+ basename = g_path_get_basename(filename);
+ g_snprintf(savepoint_basename, sizeof(savepoint_basename),
+ ".teco-%d-%s", savepoint_id, basename);
+ g_free(basename);
+ dirname = g_path_get_dirname(filename);
+ savepoint = g_build_filename(dirname, savepoint_basename, NIL);
+ g_free(dirname);
+
+ if (g_rename(filename, savepoint)) {
+ interface.msg(InterfaceCurrent::MSG_WARNING,
+ "Unable to create save point file \"%s\"",
+ savepoint);
+ g_free(savepoint);
+ return;
+ }
+ savepoint_id++;
+
+ /* NOTE: passes ownership of savepoint string to undo token */
+ undo.push(new UndoTokenRestoreSavePoint(savepoint, filename));
+}
+
+#endif /* !G_OS_UNIX */
+
+void
+IOView::save(const gchar *filename)
+{
+ const void *buffer;
+ sptr_t gap;
+ size_t size;
+ FILE *file;
+
+#ifdef G_OS_UNIX
+ GStatBuf file_stat;
+ file_stat.st_uid = -1;
+ file_stat.st_gid = -1;
+#endif
+ FileAttributes attributes = INVALID_FILE_ATTRIBUTES;
+
+ if (undo.enabled) {
+ if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {
+#ifdef G_OS_UNIX
+ g_stat(filename, &file_stat);
+#endif
+ attributes = get_file_attributes(filename);
+ make_savepoint(filename);
+ } else {
+ undo.push(new UndoTokenRemoveFile(filename));
+ }
+ }
+
+ /* leaves access mode intact if file still exists */
+ file = g_fopen(filename, "w");
+ if (!file)
+ /* hopefully, errno is also always set on Windows */
+ throw Error("Error opening file \"%s\": %s",
+ filename, strerror(errno));
+
+ /* write part of buffer before gap */
+ gap = ssm(SCI_GETGAPPOSITION);
+ if (gap > 0) {
+ buffer = (const void *)ssm(SCI_GETRANGEPOINTER,
+ 0, gap);
+ if (!fwrite(buffer, (size_t)gap, 1, file)) {
+ fclose(file);
+ throw Error("Error writing file \"%s\"",
+ filename);
+ }
+ }
+
+ /* write part of buffer after gap */
+ size = ssm(SCI_GETLENGTH) - gap;
+ if (size > 0) {
+ buffer = (const void *)ssm(SCI_GETRANGEPOINTER,
+ gap, size);
+ if (!fwrite(buffer, size, 1, file)) {
+ fclose(file);
+ throw Error("Error writing file \"%s\"",
+ filename);
+ }
+ }
+
+ /* if file existed but has been renamed, restore attributes */
+ if (attributes != INVALID_FILE_ATTRIBUTES)
+ set_file_attributes(filename, attributes);
+#ifdef G_OS_UNIX
+ /*
+ * only a good try to inherit owner since process user must have
+ * CHOWN capability traditionally reserved to root only.
+ * That's why we don't handle the return value and are spammed
+ * with unused-result warnings by GCC. There is NO sane way to avoid
+ * this warning except, adding -Wno-unused-result which disabled all
+ * such warnings.
+ */
+ fchown(fileno(file), file_stat.st_uid, file_stat.st_gid);
+#endif
+
+ fclose(file);
+}
+
+/*
+ * Auxiliary functions
+ */
+#ifdef G_OS_UNIX
+
+gchar *
+get_absolute_path(const gchar *path)
+{
+ gchar buf[PATH_MAX];
+ gchar *resolved;
+
+ if (!path)
+ return NULL;
+
+ if (!realpath(path, buf)) {
+ if (g_path_is_absolute(path)) {
+ resolved = g_strdup(path);
+ } else {
+ gchar *cwd = g_get_current_dir();
+ resolved = g_build_filename(cwd, path, NIL);
+ g_free(cwd);
+ }
+ } else {
+ resolved = g_strdup(buf);
+ }
+
+ return resolved;
+}
+
+#elif defined(G_OS_WIN32)
+
+gchar *
+get_absolute_path(const gchar *path)
+{
+ TCHAR buf[MAX_PATH];
+ gchar *resolved = NULL;
+
+ if (path && GetFullPathName(path, sizeof(buf), buf, NULL))
+ resolved = g_strdup(buf);
+
+ return resolved;
+}
+
+#else
+
+/*
+ * FIXME: I doubt that works on any platform...
+ */
+gchar *
+get_absolute_path(const gchar *path)
+{
+ return path ? g_file_read_link(path, NULL) : NULL;
+}
+
+#endif /* !G_OS_UNIX && !G_OS_WIN32 */
+
+} /* namespace SciTECO */
diff --git a/src/ioview.h b/src/ioview.h
new file mode 100644
index 0000000..0c1e653
--- /dev/null
+++ b/src/ioview.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012-2014 Robin Haberkorn
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __IOVIEW_H
+#define __IOVIEW_H
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include "sciteco.h"
+#include "interface.h"
+#include "undo.h"
+
+namespace SciTECO {
+
+/*
+ * Auxiliary functions
+ */
+
+/*
+ * Get absolute/full version of a possibly relative path.
+ * Works with existing and non-existing paths (in the latter case,
+ * heuristics may be applied.)
+ */
+gchar *get_absolute_path(const gchar *path);
+
+class IOView : public ViewCurrent {
+ 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);
+ }
+ };
+
+public:
+ void load(const gchar *filename);
+ void save(const gchar *filename);
+};
+
+} /* namespace SciTECO */
+
+#endif
diff --git a/src/ring.cpp b/src/ring.cpp
index fdd8206..e7f7d75 100644
--- a/src/ring.cpp
+++ b/src/ring.cpp
@@ -19,21 +19,16 @@
#include "config.h"
#endif
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdio.h>
#include <bsd/sys/queue.h>
#include <glib.h>
#include <glib/gprintf.h>
-#include <glib/gstdio.h>
#include <Scintilla.h>
#include "sciteco.h"
#include "interface.h"
+#include "ioview.h"
#include "undo.h"
#include "parser.h"
#include "expressions.h"
@@ -42,14 +37,6 @@
#include "error.h"
#include "ring.h"
-#ifdef HAVE_WINDOWS_H
-/* here it shouldn't cause conflicts with other headers */
-#include <windows.h>
-
-/* still need to clean up */
-#undef interface
-#endif
-
namespace SciTECO {
namespace States {
@@ -57,44 +44,6 @@ namespace States {
StateSaveFile savefile;
}
-#ifdef G_OS_WIN32
-
-typedef DWORD FileAttributes;
-/* INVALID_FILE_ATTRIBUTES already defined */
-
-static inline FileAttributes
-get_file_attributes(const gchar *filename)
-{
- return GetFileAttributes((LPCTSTR)filename);
-}
-
-static inline void
-set_file_attributes(const gchar *filename, FileAttributes attrs)
-{
- SetFileAttributes((LPCTSTR)filename, attrs);
-}
-
-#else
-
-typedef int FileAttributes;
-#define INVALID_FILE_ATTRIBUTES (-1)
-
-static inline FileAttributes
-get_file_attributes(const gchar *filename)
-{
- struct stat buf;
-
- return g_stat(filename, &buf) ? INVALID_FILE_ATTRIBUTES : buf.st_mode;
-}
-
-static inline void
-set_file_attributes(const gchar *filename, FileAttributes attrs)
-{
- g_chmod(filename, attrs);
-}
-
-#endif /* !G_OS_WIN32 */
-
void
Buffer::UndoTokenClose::run(void)
{
@@ -103,57 +52,30 @@ Buffer::UndoTokenClose::run(void)
delete buffer;
}
-/*
- * The following simple implementation of file reading is actually the
- * most efficient and useful in the common case of editing small files,
- * since
- * a) it works with minimal number of syscalls and
- * b) small files cause little temporary memory overhead.
- * Reading large files however could be very inefficient since the file
- * must first be read into memory and then copied in-memory. Also it could
- * result in thrashing.
- * Alternatively we could iteratively read into a smaller buffer trading
- * in speed against (temporary) memory consumption.
- * The best way to do it could be memory mapping the file as we could
- * let Scintilla copy from the file's virtual memory directly.
- * Unfortunately since every page of the mapped file is
- * only touched once by Scintilla TLB caching is useless and the TLB is
- * effectively thrashed with entries of the mapped file.
- * This results in the doubling of page faults and weighs out the other
- * advantages of memory mapping (has been benchmarked).
- *
- * So in the future, the following approach could be implemented:
- * 1.) On Unix/Posix, mmap() one page at a time, hopefully preventing
- * TLB thrashing.
- * 2.) On other platforms read into and copy from a statically sized buffer
- * (perhaps page-sized)
- */
void
-Buffer::load(const gchar *filename)
+Buffer::save(const gchar *filename)
{
- gchar *contents;
- gsize size;
-
- GError *gerror = NULL;
+ if (!filename && !Buffer::filename)
+ throw Error("File name expected");
- if (!g_file_get_contents(filename, &contents, &size, &gerror))
- throw GlibError(gerror);
+ IOView::save(filename ? : Buffer::filename);
- ssm(SCI_BEGINUNDOACTION);
- ssm(SCI_CLEARALL);
- ssm(SCI_APPENDTEXT, size, (sptr_t)contents);
- ssm(SCI_ENDUNDOACTION);
-
- g_free(contents);
-
- /* NOTE: currently buffer cannot be dirty */
-#if 0
+ /*
+ * Undirtify
+ * NOTE: info update is performed by set_filename()
+ */
interface.undo_info_update(this);
- undo.push_var(dirty);
- dirty = false;
-#endif
+ undo.push_var(dirty) = false;
- set_filename(filename);
+ /*
+ * FIXME: necessary also if the filename was not specified but the file
+ * is (was) new, in order to canonicalize the filename.
+ * May be circumvented by cananonicalizing without requiring the file
+ * name to exist (like readlink -f)
+ * NOTE: undo_info_update is already called above
+ */
+ undo.push_str(Buffer::filename);
+ set_filename(filename ? : Buffer::filename);
}
void
@@ -296,192 +218,6 @@ Ring::edit(const gchar *filename)
}
}
-#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
- FileAttributes orig_attrs;
-#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
- if (orig_attrs != INVALID_FILE_ATTRIBUTES)
- set_file_attributes(buffer->filename,
- orig_attrs);
-#endif
- } else {
- interface.msg(InterfaceCurrent::MSG_WARNING,
- "Unable to restore save point file \"%s\"",
- savepoint);
- }
- }
-};
-
-static inline FileAttributes
-make_savepoint(Buffer *buffer)
-{
- gchar *dirname, *basename, *savepoint;
- gchar savepoint_basename[FILENAME_MAX];
-
- FileAttributes attributes = get_file_attributes(buffer->filename);
-
- 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, NIL);
- g_free(dirname);
-
- if (!g_rename(buffer->filename, savepoint)) {
- UndoTokenRestoreSavePoint *token;
-
- buffer->savepoint_id++;
- token = new UndoTokenRestoreSavePoint(savepoint, buffer);
-#ifdef G_OS_WIN32
- token->orig_attrs = attributes;
- if (attributes != INVALID_FILE_ATTRIBUTES)
- set_file_attributes(savepoint,
- attributes | FILE_ATTRIBUTE_HIDDEN);
-#endif
- undo.push(token);
- } else {
- interface.msg(InterfaceCurrent::MSG_WARNING,
- "Unable to create save point file \"%s\"",
- savepoint);
- g_free(savepoint);
- }
-
- return attributes;
-}
-
-#endif /* !G_OS_UNIX */
-
-bool
-Ring::save(const gchar *filename)
-{
- const void *buffer;
- sptr_t gap;
- size_t size;
- FILE *file;
-
-#ifdef G_OS_UNIX
- struct stat file_stat;
- file_stat.st_uid = -1;
- file_stat.st_gid = -1;
-#endif
- FileAttributes attributes = INVALID_FILE_ATTRIBUTES;
-
- if (!current)
- return false;
-
- if (!filename && !current->filename)
- return false;
-
- /*
- * Undirtify
- * NOTE: info update is performed by current->set_filename()
- */
- interface.undo_info_update(current);
- undo.push_var(current->dirty) = false;
-
- /*
- * FIXME: necessary also if the filename was not specified but the file
- * is (was) new, in order to canonicalize the filename.
- * May be circumvented by cananonicalizing without requiring the file
- * name to exist (like readlink -f)
- * NOTE: undo_info_update is already called above
- */
- undo.push_str(current->filename);
- current->set_filename(filename ? : current->filename);
-
- if (undo.enabled) {
- if (g_file_test(current->filename, G_FILE_TEST_IS_REGULAR)) {
-#ifdef G_OS_UNIX
- g_stat(current->filename, &file_stat);
-#endif
- attributes = make_savepoint(current);
- } else {
- undo.push(new UndoTokenRemoveFile(current->filename));
- }
- }
-
- /* leaves mode intact if file exists */
- file = g_fopen(current->filename, "w");
- if (!file)
- return false;
-
- /* write part of buffer before gap */
- gap = interface.ssm(SCI_GETGAPPOSITION);
- if (gap > 0) {
- buffer = (const void *)interface.ssm(SCI_GETRANGEPOINTER,
- 0, gap);
- if (!fwrite(buffer, (size_t)gap, 1, file)) {
- fclose(file);
- return false;
- }
- }
-
- /* write part of buffer after gap */
- size = interface.ssm(SCI_GETLENGTH) - gap;
- if (size > 0) {
- buffer = (const void *)interface.ssm(SCI_GETRANGEPOINTER,
- gap, size);
- if (!fwrite(buffer, size, 1, file)) {
- fclose(file);
- return false;
- }
- }
-
- /* if file existed but has been renamed, restore attributes */
- if (attributes != INVALID_FILE_ATTRIBUTES)
- set_file_attributes(current->filename, attributes);
-#ifdef G_OS_UNIX
- /*
- * only a good try to inherit owner since process user must have
- * CHOWN capability traditionally reserved to root only.
- * That's why we don't handle the return value and are spammed
- * with unused-result warnings by GCC. There is NO sane way to avoid
- * this warning except, adding -Wno-unused-result which disabled all
- * such warnings.
- */
- fchown(fileno(file), file_stat.st_uid, file_stat.st_gid);
-#endif
-
- fclose(file);
-
- return true;
-}
-
void
Ring::close(Buffer *buffer)
{
@@ -524,62 +260,6 @@ Ring::~Ring()
}
/*
- * Auxiliary functions
- */
-#ifdef G_OS_UNIX
-
-gchar *
-get_absolute_path(const gchar *path)
-{
- gchar buf[PATH_MAX];
- gchar *resolved;
-
- if (!path)
- return NULL;
-
- if (!realpath(path, buf)) {
- if (g_path_is_absolute(path)) {
- resolved = g_strdup(path);
- } else {
- gchar *cwd = g_get_current_dir();
- resolved = g_build_filename(cwd, path, NIL);
- g_free(cwd);
- }
- } else {
- resolved = g_strdup(buf);
- }
-
- return resolved;
-}
-
-#elif defined(G_OS_WIN32)
-
-gchar *
-get_absolute_path(const gchar *path)
-{
- TCHAR buf[MAX_PATH];
- gchar *resolved = NULL;
-
- if (path && GetFullPathName(path, sizeof(buf), buf, NULL))
- resolved = g_strdup(buf);
-
- return resolved;
-}
-
-#else
-
-/*
- * FIXME: I doubt that works on any platform...
- */
-gchar *
-get_absolute_path(const gchar *path)
-{
- return path ? g_file_read_link(path, NULL) : NULL;
-}
-
-#endif /* !G_OS_UNIX && !G_OS_WIN32 */
-
-/*
* Command states
*/
@@ -707,7 +387,7 @@ StateEditFile::done(const gchar *str)
* save point files.
* It does not merely overwrite existing files when saving
* but moves them to save point files instead.
- * Save point files are called \(lq.teco-<filename>-<n>\(rq
+ * Save point files are called \(lq.teco-\fIn\fP-\fIfilename\fP\(rq,
* where <filename> is the name of the saved file and <n> is
* a number that is increased with every save operation.
* Save point files are always created in the same directory
@@ -730,8 +410,11 @@ StateSaveFile::done(const gchar *str)
{
BEGIN_EXEC(&States::start);
- if (!ring.save(*str ? str : NULL))
- throw Error("Unable to save file");
+ if (QRegisters::current)
+ throw Error("Cannot save Q-Register");
+// QRegisters::current->save(str);
+ else
+ ring.current->save(*str ? str : NULL);
return &States::start;
}
diff --git a/src/ring.h b/src/ring.h
index 7aa4f27..1fc135f 100644
--- a/src/ring.h
+++ b/src/ring.h
@@ -21,8 +21,6 @@
#include <bsd/sys/queue.h>
#include <glib.h>
-#include <glib/gprintf.h>
-#include <glib/gstdio.h>
#include <Scintilla.h>
@@ -31,25 +29,15 @@
#include "undo.h"
#include "qregisters.h"
#include "parser.h"
+#include "ioview.h"
namespace SciTECO {
/*
- * Auxiliary functions
- */
-
-/*
- * Get absolute/full version of a possibly relative path.
- * Works with existing and non-existing paths (in the latter case,
- * heuristics may be applied.)
- */
-gchar *get_absolute_path(const gchar *path);
-
-/*
* Classes
*/
-class Buffer : private ViewCurrent {
+class Buffer : private IOView {
class UndoTokenClose : public UndoToken {
Buffer *buffer;
@@ -64,11 +52,9 @@ public:
TAILQ_ENTRY(Buffer) buffers;
gchar *filename;
- gint savepoint_id;
bool dirty;
- Buffer() : ViewCurrent(),
- filename(NULL), savepoint_id(0), dirty(false)
+ Buffer() : filename(NULL), dirty(false)
{
initialize();
/* only have to do this once: */
@@ -115,7 +101,19 @@ public:
interface.undo_show_view(this);
}
- void load(const gchar *filename);
+ inline void
+ load(const gchar *filename)
+ {
+ IOView::load(filename);
+
+#if 0 /* NOTE: currently buffer cannot be dirty */
+ interface.undo_info_update(this);
+ undo.push_var(dirty) = false;
+#endif
+
+ set_filename(filename);
+ }
+ void save(const gchar *filename = NULL);
inline void
undo_close(void)
@@ -146,24 +144,6 @@ 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);
- }
- };
-
TAILQ_HEAD(Head, Buffer) head;
public:
@@ -208,8 +188,6 @@ public:
undo.push_var(current)->undo_edit();
}
- bool save(const gchar *filename);
-
void close(Buffer *buffer);
void close(void);
inline void