aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2013-02-18 23:17:18 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2013-02-22 01:18:05 +0100
commit753dacacbcc2d45d35a044bfe2512fc4cd564b5c (patch)
tree0836f965a306b33449d60c4c7b579eab06f6bc2b
parente0a47e8fcd592585030384faf6d42a2bf74f43ad (diff)
downloadsciteco-753dacacbcc2d45d35a044bfe2512fc4cd564b5c.tar.gz
clean up QRegister vs. Buffer redundancies using TECODocument class
* also encapsulates data properly (previously there were many public attributes to avoid permission issues) * new class also cares about saving/and restoring scroll state. now, buffer/q-reg edits and temporary accesses do not reset the scroll state anymore.
-rw-r--r--src/Makefile.am1
-rw-r--r--src/document.cpp81
-rw-r--r--src/document.h99
-rw-r--r--src/qregisters.cpp58
-rw-r--r--src/qregisters.h41
-rw-r--r--src/ring.cpp6
-rw-r--r--src/ring.h36
7 files changed, 234 insertions, 88 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 787d941..bd945e1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,6 +17,7 @@ libsciteco_base_a_SOURCES = sciteco.h \
cmdline.cpp cmdline.h \
undo.cpp undo.h \
expressions.cpp expressions.h \
+ document.cpp document.h \
qregisters.cpp qregisters.h \
ring.cpp ring.h \
parser.cpp parser.h \
diff --git a/src/document.cpp b/src/document.cpp
new file mode 100644
index 0000000..b6a99f5
--- /dev/null
+++ b/src/document.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2012-2013 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 <glib.h>
+
+#include <Scintilla.h>
+
+#include "sciteco.h"
+#include "interface.h"
+#include "undo.h"
+#include "document.h"
+
+void
+TECODocument::edit(void)
+{
+ if (!is_initialized())
+ doc = (SciDoc)interface.ssm(SCI_CREATEDOCUMENT);
+
+ interface.ssm(SCI_SETDOCPOINTER, 0, (sptr_t)doc);
+ interface.ssm(SCI_SETFIRSTVISIBLELINE, first_line);
+ interface.ssm(SCI_SETXOFFSET, xoffset);
+ interface.ssm(SCI_GOTOPOS, dot);
+}
+
+void
+TECODocument::undo_edit(void)
+{
+ undo.push_msg(SCI_GOTOPOS, dot);
+ undo.push_msg(SCI_SETXOFFSET, xoffset);
+ undo.push_msg(SCI_SETFIRSTVISIBLELINE, first_line);
+ undo.push_msg(SCI_SETDOCPOINTER, 0, (sptr_t)doc);
+}
+
+void
+TECODocument::update(void)
+{
+ dot = interface.ssm(SCI_GETCURRENTPOS);
+ first_line = interface.ssm(SCI_GETFIRSTVISIBLELINE);
+ xoffset = interface.ssm(SCI_GETXOFFSET);
+}
+
+/*
+ * Only for QRegisterStack::pop() which does some clever
+ * exchanging of document data (without any deep copying)
+ */
+void
+TECODocument::exchange(TECODocument &other)
+{
+ SciDoc temp_doc = doc;
+ gint temp_dot = dot;
+ gint temp_first_line = first_line;
+ gint temp_xoffset = xoffset;
+
+ doc = other.doc;
+ dot = other.dot;
+ first_line = other.first_line;
+ xoffset = other.xoffset;
+
+ other.doc = temp_doc;
+ other.dot = temp_dot;
+ other.first_line = temp_first_line;
+ other.xoffset = temp_xoffset;
+}
diff --git a/src/document.h b/src/document.h
new file mode 100644
index 0000000..2ef71ba
--- /dev/null
+++ b/src/document.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2012-2013 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 __DOCUMENT_H
+#define __DOCUMENT_H
+
+#include <glib.h>
+
+#include <Scintilla.h>
+
+#include "sciteco.h"
+#include "interface.h"
+#include "undo.h"
+
+/*
+ * Classes
+ */
+
+/*
+ * NOTE: The only reason this is called TECODocument
+ * is to prevent a nameclash with Scintilla which
+ * does not use a proper namespace for its public
+ * symbols...
+ */
+class TECODocument {
+ typedef const void *SciDoc;
+ SciDoc doc;
+
+ /* updated/restored only when required */
+ gint dot;
+ gint first_line;
+ gint xoffset;
+
+public:
+ TECODocument() : doc(NULL)
+ {
+ reset();
+ }
+ virtual ~TECODocument()
+ {
+ if (is_initialized())
+ interface.ssm(SCI_RELEASEDOCUMENT, 0, (sptr_t)doc);
+ }
+
+ inline bool
+ is_initialized(void)
+ {
+ return doc != NULL;
+ }
+
+ void edit(void);
+ void undo_edit(void);
+
+ void update(void);
+ inline void
+ update(const TECODocument &from)
+ {
+ dot = from.dot;
+ first_line = from.first_line;
+ xoffset = from.xoffset;
+ }
+
+ inline void
+ reset(void)
+ {
+ dot = first_line = xoffset = 0;
+ }
+ inline void
+ undo_reset(void)
+ {
+ undo.push_var(dot);
+ undo.push_var(first_line);
+ undo.push_var(xoffset);
+ }
+
+ void exchange(TECODocument &other);
+ inline void
+ undo_exchange(void)
+ {
+ undo.push_var(doc);
+ undo_reset();
+ }
+};
+
+#endif
diff --git a/src/qregisters.cpp b/src/qregisters.cpp
index a46b4da..df75679 100644
--- a/src/qregisters.cpp
+++ b/src/qregisters.cpp
@@ -33,6 +33,7 @@
#include "undo.h"
#include "parser.h"
#include "expressions.h"
+#include "document.h"
#include "ring.h"
#include "qregisters.h"
@@ -59,7 +60,7 @@ namespace QRegisters {
void
undo_edit(void)
{
- current->dot = interface.ssm(SCI_GETCURRENTPOS);
+ current->update_string();
undo.push_var(ring.current);
undo.push_var(current)->undo_edit();
}
@@ -82,7 +83,7 @@ void
QRegisterData::set_string(const gchar *str)
{
edit();
- dot = 0;
+ string.reset();
interface.ssm(SCI_BEGINUNDOACTION);
interface.ssm(SCI_SETTEXT, 0, (sptr_t)(str ? : ""));
@@ -94,8 +95,8 @@ QRegisterData::set_string(const gchar *str)
void
QRegisterData::undo_set_string(void)
{
- /* set_string() assumes that dot has been saved */
- current_save_dot();
+ /* set_string() assumes that parameters have been saved */
+ current_doc_update();
if (!must_undo)
return;
@@ -105,7 +106,7 @@ QRegisterData::undo_set_string(void)
else if (QRegisters::current)
QRegisters::current->undo_edit();
- undo.push_var<gint>(dot);
+ string.undo_reset();
undo.push_msg(SCI_UNDO);
undo_edit();
@@ -132,7 +133,10 @@ QRegisterData::get_string(void)
gint size;
gchar *str;
- current_save_dot();
+ if (!string.is_initialized())
+ return g_strdup("");
+
+ current_doc_update();
edit();
size = interface.ssm(SCI_GETLENGTH) + 1;
@@ -147,24 +151,20 @@ QRegisterData::get_string(void)
void
QRegisterData::edit(void)
{
- interface.ssm(SCI_SETDOCPOINTER, 0, (sptr_t)get_document());
- interface.ssm(SCI_GOTOPOS, dot);
+ string.edit();
}
void
QRegisterData::undo_edit(void)
{
- if (!must_undo)
- return;
-
- undo.push_msg(SCI_GOTOPOS, dot);
- undo.push_msg(SCI_SETDOCPOINTER, 0, (sptr_t)get_document());
+ if (must_undo)
+ string.undo_edit();
}
void
QRegister::edit(void)
{
- QRegisterData::edit();
+ string.edit();
interface.info_update(this);
}
@@ -175,7 +175,7 @@ QRegister::undo_edit(void)
return;
interface.undo_info_update(this);
- QRegisterData::undo_edit();
+ string.undo_edit();
}
void
@@ -204,7 +204,7 @@ QRegister::load(const gchar *filename)
return false;
edit();
- dot = 0;
+ string.reset();
interface.ssm(SCI_BEGINUNDOACTION);
interface.ssm(SCI_CLEARALL);
@@ -268,7 +268,7 @@ QRegisterTable::QRegisterTable(bool _undo) : RBTree(), must_undo(_undo)
void
QRegisterTable::edit(QRegister *reg)
{
- current_save_dot();
+ current_doc_update();
reg->edit();
ring.current = NULL;
@@ -296,13 +296,12 @@ QRegisterStack::push(QRegister &reg)
{
Entry *entry = new Entry();
- entry->set_integer(reg.get_integer());
- if (reg.string) {
- gchar *str = reg.get_string();
+ gchar *str = reg.get_string();
+ if (*str)
entry->set_string(str);
- g_free(str);
- }
- entry->dot = reg.dot;
+ g_free(str);
+ entry->string.update(reg.string);
+ entry->set_integer(reg.get_integer());
SLIST_INSERT_HEAD(&head, entry, entries);
undo.push(new UndoTokenPop(this));
@@ -312,7 +311,6 @@ bool
QRegisterStack::pop(QRegister &reg)
{
Entry *entry = SLIST_FIRST(&head);
- QRegisterData::document *string;
if (!entry)
return false;
@@ -321,16 +319,10 @@ QRegisterStack::pop(QRegister &reg)
reg.set_integer(entry->get_integer());
/* exchange document ownership between Stack entry and Q-Register */
- string = reg.string;
- if (reg.must_undo)
- undo.push_var(reg.string);
- reg.string = entry->string;
- undo.push_var(entry->string);
- entry->string = string;
-
if (reg.must_undo)
- undo.push_var(reg.dot);
- reg.dot = entry->dot;
+ reg.string.undo_exchange();
+ entry->string.undo_exchange();
+ entry->string.exchange(reg.string);
SLIST_REMOVE_HEAD(&head, entries);
/* pass entry ownership to undo stack */
diff --git a/src/qregisters.h b/src/qregisters.h
index 15acd86..7e126fd 100644
--- a/src/qregisters.h
+++ b/src/qregisters.h
@@ -30,39 +30,24 @@
#include "undo.h"
#include "rbtree.h"
#include "parser.h"
+#include "document.h"
/*
* Classes
*/
class QRegisterData {
+protected:
gint64 integer;
+ TECODocument string;
public:
- typedef void document;
- document *string;
- gint dot;
-
/*
* whether to generate UndoTokens (unnecessary in macro invocations)
*/
bool must_undo;
- QRegisterData() : integer(0), string(NULL), dot(0), must_undo(true) {}
- virtual
- ~QRegisterData()
- {
- if (string)
- interface.ssm(SCI_RELEASEDOCUMENT, 0, (sptr_t)string);
- }
-
- inline document *
- get_document(void)
- {
- if (!string)
- string = (document *)interface.ssm(SCI_CREATEDOCUMENT);
- return string;
- }
+ QRegisterData() : integer(0), must_undo(true) {}
virtual gint64
set_integer(gint64 i)
@@ -81,6 +66,12 @@ public:
return integer;
}
+ inline void
+ update_string(void)
+ {
+ string.update();
+ }
+
virtual void set_string(const gchar *str);
virtual void undo_set_string(void);
virtual void append_string(const gchar *str);
@@ -93,6 +84,8 @@ public:
virtual void edit(void);
virtual void undo_edit(void);
+
+ friend class QRegisterStack;
};
class QRegister : public RBTree::RBEntry, public QRegisterData {
@@ -128,10 +121,7 @@ public:
class QRegisterBufferInfo : public QRegister {
public:
- QRegisterBufferInfo() : QRegister("*")
- {
- get_document();
- }
+ QRegisterBufferInfo() : QRegister("*") {}
gint64
set_integer(gint64 v)
@@ -191,10 +181,7 @@ public:
inline void
initialize(const gchar *name)
{
- QRegister *reg = new QRegister(name);
- insert(reg);
- /* make sure document is initialized */
- reg->get_document();
+ insert(new QRegister(name));
}
inline void
initialize(gchar name)
diff --git a/src/ring.cpp b/src/ring.cpp
index 8654686..138714f 100644
--- a/src/ring.cpp
+++ b/src/ring.cpp
@@ -233,7 +233,7 @@ Ring::edit(gint64 id)
if (!buffer)
return false;
- current_save_dot();
+ current_doc_update();
QRegisters::current = NULL;
current = buffer;
@@ -249,7 +249,7 @@ Ring::edit(const gchar *filename)
{
Buffer *buffer = find(filename);
- current_save_dot();
+ current_doc_update();
QRegisters::current = NULL;
if (buffer) {
@@ -488,7 +488,7 @@ Ring::close(void)
{
Buffer *buffer = current;
- buffer->dot = interface.ssm(SCI_GETCURRENTPOS);
+ buffer->update();
close(buffer);
current = buffer->next() ? : buffer->prev();
/* transfer responsibility to UndoToken object */
diff --git a/src/ring.h b/src/ring.h
index 608b752..4ca7a5d 100644
--- a/src/ring.h
+++ b/src/ring.h
@@ -30,6 +30,7 @@
#include "sciteco.h"
#include "interface.h"
#include "undo.h"
+#include "document.h"
#include "qregisters.h"
#include "parser.h"
@@ -53,7 +54,7 @@ gchar *get_absolute_path(const gchar *path);
* Classes
*/
-class Buffer {
+class Buffer : public TECODocument {
class UndoTokenClose : public UndoToken {
Buffer *buffer;
@@ -68,24 +69,13 @@ public:
TAILQ_ENTRY(Buffer) buffers;
gchar *filename;
- gint dot;
-
gint savepoint_id;
-
bool dirty;
-private:
- typedef void document;
- document *doc;
-
-public:
- Buffer() : filename(NULL), dot(0), savepoint_id(0), dirty(false)
- {
- doc = (document *)interface.ssm(SCI_CREATEDOCUMENT);
- }
+ Buffer() : TECODocument(),
+ filename(NULL), savepoint_id(0), dirty(false) {}
~Buffer()
{
- interface.ssm(SCI_RELEASEDOCUMENT, 0, (sptr_t)doc);
g_free(filename);
}
@@ -114,16 +104,14 @@ public:
inline void
edit(void)
{
- interface.ssm(SCI_SETDOCPOINTER, 0, (sptr_t)doc);
- interface.ssm(SCI_GOTOPOS, dot);
+ TECODocument::edit();
interface.info_update(this);
}
inline void
undo_edit(void)
{
interface.undo_info_update(this);
- undo.push_msg(SCI_GOTOPOS, dot);
- undo.push_msg(SCI_SETDOCPOINTER, 0, (sptr_t)doc);
+ TECODocument::undo_edit();
}
bool load(const gchar *filename);
@@ -207,7 +195,7 @@ public:
inline void
undo_edit(void)
{
- current->dot = interface.ssm(SCI_GETCURRENTPOS);
+ current->update();
undo.push_var(QRegisters::current);
undo.push_var(current)->undo_edit();
}
@@ -248,16 +236,14 @@ namespace States {
extern StateSaveFile savefile;
}
-/* FIXME: clean up current_save_dot() usage */
+/* FIXME: clean up current_doc_update() usage */
static inline void
-current_save_dot(void)
+current_doc_update(void)
{
- gint dot = interface.ssm(SCI_GETCURRENTPOS);
-
if (ring.current)
- ring.current->dot = dot;
+ ring.current->update();
else if (QRegisters::current)
- QRegisters::current->dot = dot;
+ QRegisters::current->update_string();
}
#endif