aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2012-11-08 18:18:11 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2012-11-08 18:18:11 +0100
commit049d75520a89fb081ff8b3c0de8dc65c20e1db70 (patch)
treefddfa5d9ad145582b649aae93b6e1e17c199d018
parent16614be0a5dea0613fedb6bbbb9f0dd8879905a2 (diff)
downloadsciteco-049d75520a89fb081ff8b3c0de8dc65c20e1db70.tar.gz
added buffer ring and preliminary EB...$ implementation
* undoing supported * does not yet support globbing
-rw-r--r--Makefile2
-rw-r--r--main.cpp12
-rw-r--r--parser.cpp1
-rw-r--r--parser.h2
-rw-r--r--qbuffers.cpp144
-rw-r--r--qbuffers.h122
6 files changed, 277 insertions, 6 deletions
diff --git a/Makefile b/Makefile
index 9f380eb..49cf315 100644
--- a/Makefile
+++ b/Makefile
@@ -10,7 +10,7 @@ LDFLAGS:=$(GTK_LDFLAGS) $(SCI_LDFLAGS)
all : sciteco
-sciteco : main.o cmdline.o undo.o expressions.o \
+sciteco : main.o cmdline.o undo.o expressions.o qbuffers.o \
parser.o goto.o
$(CXX) -o $@ $^ $(LDFLAGS)
diff --git a/main.cpp b/main.cpp
index f17ef1b..761fa96 100644
--- a/main.cpp
+++ b/main.cpp
@@ -13,6 +13,9 @@
#include <ScintillaWidget.h>
#include "sciteco.h"
+#include "parser.h"
+#include "qbuffers.h"
+#include "undo.h"
static GtkWidget *editor_widget;
static GtkWidget *cmdline_widget;
@@ -143,11 +146,10 @@ main(int argc, char **argv)
editor_msg(SCI_STYLESETFORE, SCE_C_WORD, 0x800000);
editor_msg(SCI_STYLESETFORE, SCE_C_STRING, 0x800080);
editor_msg(SCI_STYLESETBOLD, SCE_C_OPERATOR, 1);
- editor_msg(SCI_INSERTTEXT, 0, (sptr_t)
- "int main(int argc, char **argv) {\n"
- " // Start up the gnome\n"
- " gnome_init(\"stest\", \"1.0\", argc, argv);\n}"
- );
+
+ ring.edit(NULL);
+
+ undo.enabled = true;
cmdline_display("*");
gtk_widget_grab_focus(cmdline_widget);
diff --git a/parser.cpp b/parser.cpp
index 61e1398..f4abac4 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -556,6 +556,7 @@ StateControl::custom(gchar chr)
StateECommand::StateECommand() : State()
{
transitions['\0'] = this;
+ transitions['B'] = &states.file;
}
State *
diff --git a/parser.h b/parser.h
index edcece7..61eb433 100644
--- a/parser.h
+++ b/parser.h
@@ -92,6 +92,7 @@ private:
};
#include "goto.h"
+#include "qbuffers.h"
extern gint macro_pc;
@@ -100,6 +101,7 @@ extern struct States {
StateLabel label;
StateControl control;
StateECommand ecommand;
+ StateFile file;
StateInsert insert;
} states;
diff --git a/qbuffers.cpp b/qbuffers.cpp
new file mode 100644
index 0000000..03f9562
--- /dev/null
+++ b/qbuffers.cpp
@@ -0,0 +1,144 @@
+#include <bsd/sys/queue.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+#include <glib/gstdio.h>
+
+#include <Scintilla.h>
+
+#include "sciteco.h"
+#include "undo.h"
+#include "parser.h"
+#include "qbuffers.h"
+
+Ring ring;
+
+bool
+Buffer::load(const gchar *filename)
+{
+ gchar *contents;
+ gsize size;
+
+ edit();
+ editor_msg(SCI_CLEARALL);
+
+ /* FIXME: prevent excessive allocations by reading file into buffer */
+ if (!g_file_get_contents(filename, &contents, &size, NULL))
+ return false;
+ editor_msg(SCI_APPENDTEXT, size, (sptr_t)contents);
+ g_free(contents);
+
+ editor_msg(SCI_GOTOPOS, 0);
+ editor_msg(SCI_SETSAVEPOINT);
+
+ set_filename(filename);
+
+ return true;
+}
+
+void
+Buffer::close(void)
+{
+ LIST_REMOVE(this, buffers);
+
+ if (filename)
+ message_display(GTK_MESSAGE_INFO,
+ "Removed file \"%s\" from the ring",
+ filename);
+ else
+ message_display(GTK_MESSAGE_INFO,
+ "Removed unnamed file from the ring.");
+}
+
+Buffer *
+Ring::find(const gchar *filename)
+{
+ Buffer *cur;
+
+ LIST_FOREACH(cur, &head, buffers)
+ if (!g_strcmp0(cur->filename, filename))
+ return cur;
+
+ return NULL;
+}
+
+bool
+Ring::edit(const gchar *filename)
+{
+ bool new_in_ring = false;
+ Buffer *buffer = find(filename);
+
+ if (current)
+ current->dot = editor_msg(SCI_GETCURRENTPOS);
+
+ if (buffer) {
+ buffer->edit();
+ } else {
+ new_in_ring = true;
+
+ buffer = new Buffer();
+ LIST_INSERT_HEAD(&head, buffer, buffers);
+
+ if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {
+ buffer->load(filename);
+
+ message_display(GTK_MESSAGE_INFO,
+ "Added file \"%s\" to ring", filename);
+ } else {
+ buffer->edit();
+ buffer->set_filename(filename);
+
+ if (filename)
+ message_display(GTK_MESSAGE_INFO,
+ "Added new file \"%s\" to ring",
+ filename);
+ else
+ message_display(GTK_MESSAGE_INFO,
+ "Added new unnamed file to ring.");
+ }
+ }
+
+ current = buffer;
+
+ return new_in_ring;
+}
+
+void
+Ring::close(void)
+{
+ Buffer *buffer = current;
+
+ buffer->close();
+ current = LIST_NEXT(buffer, buffers) ? : LIST_FIRST(&head);
+ if (!current)
+ edit(NULL);
+
+ delete buffer;
+}
+
+Ring::~Ring()
+{
+ Buffer *buffer, *next;
+
+ LIST_FOREACH_SAFE(buffer, &head, buffers, next)
+ delete buffer;
+}
+
+/*
+ * Command states
+ */
+
+State *
+StateFile::done(const gchar *str)
+{
+ bool new_in_ring;
+
+ BEGIN_EXEC(&states.start);
+
+ ring.undo_edit();
+ new_in_ring = ring.edit(*str ? str : NULL);
+ if (new_in_ring)
+ ring.undo_close();
+
+ return &states.start;
+}
diff --git a/qbuffers.h b/qbuffers.h
new file mode 100644
index 0000000..88e5f8f
--- /dev/null
+++ b/qbuffers.h
@@ -0,0 +1,122 @@
+#ifndef __QBUFFERS_H
+#define __QBUFFERS_H
+
+#include <bsd/sys/queue.h>
+
+#include <glib.h>
+#include <glib/gprintf.h>
+
+#include <Scintilla.h>
+
+#include "sciteco.h"
+#include "undo.h"
+#include "parser.h"
+
+class Buffer {
+ class UndoTokenClose : public UndoToken {
+ Buffer *buffer;
+
+ public:
+ UndoTokenClose(Buffer *_buffer)
+ : UndoToken(), buffer(_buffer) {}
+
+ void
+ run(void)
+ {
+ buffer->close();
+ delete buffer;
+ }
+ };
+
+public:
+ LIST_ENTRY(Buffer) buffers;
+
+ gchar *filename;
+ gint dot;
+
+private:
+ typedef void document;
+ document *doc;
+
+public:
+ Buffer() : filename(NULL), dot(0)
+ {
+ doc = (document *)editor_msg(SCI_CREATEDOCUMENT);
+ }
+ ~Buffer()
+ {
+ editor_msg(SCI_RELEASEDOCUMENT, 0, (sptr_t)doc);
+ g_free(filename);
+ }
+
+ inline void
+ set_filename(const gchar *filename)
+ {
+ g_free(Buffer::filename);
+ Buffer::filename = filename ? g_strdup(filename) : NULL;
+ }
+
+ inline void
+ edit(void)
+ {
+ editor_msg(SCI_SETDOCPOINTER, 0, (sptr_t)doc);
+ editor_msg(SCI_GOTOPOS, dot);
+ }
+ inline void
+ undo_edit(void)
+ {
+ undo.push_msg(SCI_GOTOPOS, dot);
+ undo.push_msg(SCI_SETDOCPOINTER, 0, (sptr_t)doc);
+ }
+
+ bool load(const gchar *filename);
+
+ void close(void);
+ inline void
+ undo_close(void)
+ {
+ undo.push(new UndoTokenClose(this));
+ }
+};
+
+extern class Ring {
+ LIST_HEAD(Head, Buffer) head;
+ Buffer *current;
+
+public:
+ Ring() : current(NULL)
+ {
+ LIST_INIT(&head);
+ }
+ ~Ring();
+
+ Buffer *find(const gchar *filename);
+
+ bool edit(const gchar *filename);
+ inline void
+ undo_edit(void)
+ {
+ current->dot = editor_msg(SCI_GETCURRENTPOS);
+
+ undo.push_var<Buffer*>(current);
+ current->undo_edit();
+ }
+
+ void close(void);
+ inline void
+ undo_close(void)
+ {
+ current->undo_close();
+ }
+} ring;
+
+/*
+ * Command states
+ */
+
+class StateFile : public StateExpectString {
+private:
+ State *done(const gchar *str);
+};
+
+#endif