diff options
| author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2012-12-04 17:29:01 +0100 |
|---|---|---|
| committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2012-12-04 22:07:08 +0100 |
| commit | d8a316514c03d85b771a9dce4a8a51b875d955b3 (patch) | |
| tree | 8966c29db767a155848f6d90f76771ce5b9de32e /ring.cpp | |
| parent | b120616b6da52e951097f69ad267de06081d218a (diff) | |
autoconf preparation: move everything into src/ subdir
Diffstat (limited to 'ring.cpp')
| -rw-r--r-- | ring.cpp | 539 |
1 files changed, 0 insertions, 539 deletions
diff --git a/ring.cpp b/ring.cpp deleted file mode 100644 index f1b051b..0000000 --- a/ring.cpp +++ /dev/null @@ -1,539 +0,0 @@ -#include <limits.h> -#include <stdlib.h> -#include <string.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 "undo.h" -#include "parser.h" -#include "expressions.h" -#include "ring.h" - -#ifdef G_OS_WIN32 -/* here it shouldn't cause conflicts with other headers */ -#include <windows.h> - -/* still need to clean up */ -#ifdef interface -#undef interface -#endif -#endif - -namespace States { - StateEditFile editfile; - StateSaveFile savefile; -} - -Ring ring; - -void -Buffer::UndoTokenClose::run(void) -{ - ring.close(buffer); - /* NOTE: the buffer is NOT deleted on Token destruction */ - delete buffer; -} - -bool -Buffer::load(const gchar *filename) -{ - gchar *contents; - gsize size; - - /* FIXME: prevent excessive allocations by reading file into buffer */ - if (!g_file_get_contents(filename, &contents, &size, NULL)) - return false; - - edit(); - - interface.ssm(SCI_BEGINUNDOACTION); - interface.ssm(SCI_CLEARALL); - interface.ssm(SCI_APPENDTEXT, size, (sptr_t)contents); - interface.ssm(SCI_ENDUNDOACTION); - - g_free(contents); - - /* NOTE: currently buffer cannot be dirty */ -#if 0 - interface.undo_info_update(this); - undo.push_var(dirty); - dirty = false; -#endif - - set_filename(filename); - - return true; -} - -void -Ring::UndoTokenEdit::run(void) -{ - /* - * assumes that buffer still has correct prev/next - * pointers - */ - if (buffer->next()) - TAILQ_INSERT_BEFORE(buffer->next(), buffer, buffers); - else - TAILQ_INSERT_TAIL(&ring->head, buffer, buffers); - - ring->current = buffer; - buffer->edit(); - buffer = NULL; -} - -Buffer * -Ring::find(const gchar *filename) -{ - gchar *resolved = get_absolute_path(filename); - Buffer *cur; - - TAILQ_FOREACH(cur, &head, buffers) - if (!g_strcmp0(cur->filename, resolved)) - break; - - g_free(resolved); - return cur; -} - -Buffer * -Ring::find(gint64 id) -{ - Buffer *cur; - - TAILQ_FOREACH(cur, &head, buffers) - if (!--id) - break; - - return cur; -} - -void -Ring::dirtify(void) -{ - if (!current || current->dirty) - return; - - interface.undo_info_update(current); - undo.push_var(current->dirty); - current->dirty = true; - interface.info_update(current); -} - -bool -Ring::is_any_dirty(void) -{ - Buffer *cur; - - TAILQ_FOREACH(cur, &head, buffers) - if (cur->dirty) - return true; - - return false; -} - -bool -Ring::edit(gint64 id) -{ - Buffer *buffer = find(id); - - if (!buffer) - return false; - - current_save_dot(); - - QRegisters::current = NULL; - current = buffer; - buffer->edit(); - - QRegisters::hook(QRegisters::HOOK_EDIT); - - return true; -} - -void -Ring::edit(const gchar *filename) -{ - Buffer *buffer = find(filename); - - current_save_dot(); - - QRegisters::current = NULL; - if (buffer) { - current = buffer; - buffer->edit(); - - QRegisters::hook(QRegisters::HOOK_EDIT); - } else { - buffer = new Buffer(); - TAILQ_INSERT_TAIL(&head, buffer, buffers); - - current = buffer; - undo_close(); - - if (filename && g_file_test(filename, G_FILE_TEST_IS_REGULAR)) { - buffer->load(filename); - - interface.msg(Interface::MSG_INFO, - "Added file \"%s\" to ring", filename); - } else { - buffer->edit(); - buffer->set_filename(filename); - - if (filename) - interface.msg(Interface::MSG_INFO, - "Added new file \"%s\" to ring", - filename); - else - interface.msg(Interface::MSG_INFO, - "Added new unnamed file to ring."); - } - - QRegisters::hook(QRegisters::HOOK_ADD); - } -} - -#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 { - interface.msg(Interface::MSG_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, - token->attributes | - FILE_ATTRIBUTE_HIDDEN); -#endif - undo.push(token); - } else { - interface.msg(Interface::MSG_WARNING, - "Unable to create save point file \"%s\"", - savepoint); - g_free(savepoint); - } -} - -#endif /* !G_OS_UNIX */ - -bool -Ring::save(const gchar *filename) -{ - const gchar *buffer; - gssize size; - - if (!current) - return false; - - 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)); - } - - /* FIXME: improve by writing before and after document gap */ - buffer = (const gchar *)interface.ssm(SCI_GETCHARACTERPOINTER); - size = interface.ssm(SCI_GETLENGTH); - - if (!g_file_set_contents(filename, buffer, size, NULL)) - return false; - - interface.undo_info_update(current); - undo.push_var(current->dirty); - 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) - */ - //if (filename) { - undo.push_str(current->filename); - current->set_filename(filename); - //} - - return true; -} - -void -Ring::close(Buffer *buffer) -{ - TAILQ_REMOVE(&head, buffer, buffers); - - if (buffer->filename) - interface.msg(Interface::MSG_INFO, - "Removed file \"%s\" from the ring", - buffer->filename); - else - interface.msg(Interface::MSG_INFO, - "Removed unnamed file from the ring."); -} - -void -Ring::close(void) -{ - Buffer *buffer = current; - - buffer->dot = interface.ssm(SCI_GETCURRENTPOS); - close(buffer); - current = buffer->next() ? : buffer->prev(); - /* transfer responsibility to UndoToken object */ - undo.push(new UndoTokenEdit(this, buffer)); - - if (current) { - current->edit(); - QRegisters::hook(QRegisters::HOOK_EDIT); - } else { - edit((const gchar *)NULL); - } -} - -Ring::~Ring() -{ - Buffer *buffer, *next; - - TAILQ_FOREACH_SAFE(buffer, &head, buffers, next) - delete buffer; -} - -/* - * 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, NULL); - 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 - */ - -void -StateEditFile::do_edit(const gchar *filename) throw (Error) -{ - if (ring.current) - ring.undo_edit(); - else /* QRegisters::current != NULL */ - QRegisters::undo_edit(); - ring.edit(filename); -} - -void -StateEditFile::do_edit(gint64 id) throw (Error) -{ - if (ring.current) - ring.undo_edit(); - else /* QRegisters::current != NULL */ - QRegisters::undo_edit(); - if (!ring.edit(id)) - throw Error("Invalid buffer id %" G_GINT64_FORMAT, id); -} - -void -StateEditFile::initial(void) throw (Error) -{ - gint64 id = expressions.pop_num_calc(1, -1); - - allowFilename = true; - - if (id == 0) { - for (Buffer *cur = ring.first(); cur; cur = cur->next()) - interface.popup_add(Interface::POPUP_FILE, - cur->filename ? : "(Unnamed)", - cur == ring.current); - - interface.popup_show(); - } else if (id > 0) { - allowFilename = false; - do_edit(id); - } -} - -State * -StateEditFile::done(const gchar *str) throw (Error) -{ - BEGIN_EXEC(&States::start); - - if (!allowFilename) { - if (*str) - throw Error("If a buffer is selected by id, the <EB> " - "string argument must be empty"); - - return &States::start; - } - - if (is_glob_pattern(str)) { - gchar *dirname; - GDir *dir; - - dirname = g_path_get_dirname(str); - dir = g_dir_open(dirname, 0, NULL); - - if (dir) { - const gchar *basename; - GPatternSpec *pattern; - - basename = g_path_get_basename(str); - pattern = g_pattern_spec_new(basename); - g_free((gchar *)basename); - - while ((basename = g_dir_read_name(dir))) { - if (g_pattern_match_string(pattern, basename)) { - gchar *filename; - - filename = g_build_filename(dirname, - basename, - NULL); - do_edit(filename); - g_free(filename); - } - } - - g_pattern_spec_free(pattern); - g_dir_close(dir); - } - - g_free(dirname); - } else { - do_edit(*str ? str : NULL); - } - - return &States::start; -} - -State * -StateSaveFile::done(const gchar *str) throw (Error) -{ - BEGIN_EXEC(&States::start); - - if (!ring.save(*str ? str : NULL)) - throw Error("Unable to save file"); - - return &States::start; -} |
