aboutsummaryrefslogtreecommitdiffhomepage
path: root/ring.cpp
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2012-12-04 17:29:01 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2012-12-04 22:07:08 +0100
commitd8a316514c03d85b771a9dce4a8a51b875d955b3 (patch)
tree8966c29db767a155848f6d90f76771ce5b9de32e /ring.cpp
parentb120616b6da52e951097f69ad267de06081d218a (diff)
autoconf preparation: move everything into src/ subdir
Diffstat (limited to 'ring.cpp')
-rw-r--r--ring.cpp539
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;
-}