diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2013-02-18 23:17:18 +0100 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2013-02-22 01:18:05 +0100 |
commit | 753dacacbcc2d45d35a044bfe2512fc4cd564b5c (patch) | |
tree | 0836f965a306b33449d60c4c7b579eab06f6bc2b | |
parent | e0a47e8fcd592585030384faf6d42a2bf74f43ad (diff) | |
download | sciteco-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.am | 1 | ||||
-rw-r--r-- | src/document.cpp | 81 | ||||
-rw-r--r-- | src/document.h | 99 | ||||
-rw-r--r-- | src/qregisters.cpp | 58 | ||||
-rw-r--r-- | src/qregisters.h | 41 | ||||
-rw-r--r-- | src/ring.cpp | 6 | ||||
-rw-r--r-- | src/ring.h | 36 |
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 ®) { 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 ®) { Entry *entry = SLIST_FIRST(&head); - QRegisterData::document *string; if (!entry) return false; @@ -321,16 +319,10 @@ QRegisterStack::pop(QRegister ®) 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 */ @@ -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 |