diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2014-11-24 02:51:31 +0100 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2014-11-24 05:07:06 +0100 |
commit | d503c3b07c2157658f699294c44ad5be244727a5 (patch) | |
tree | f25b9927f5bdcfca98a82f3bc917548cbec5962b /src | |
parent | 355cae277c29104b982f4dc7aa3e05fc06945325 (diff) | |
download | sciteco-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.am | 1 | ||||
-rw-r--r-- | src/ioview.cpp | 358 | ||||
-rw-r--r-- | src/ioview.h | 67 | ||||
-rw-r--r-- | src/ring.cpp | 367 | ||||
-rw-r--r-- | src/ring.h | 54 |
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; } @@ -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 |