aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--parser.cpp3
-rw-r--r--qbuffers.cpp121
-rw-r--r--qbuffers.h100
-rwxr-xr-xteco.ini49
4 files changed, 230 insertions, 43 deletions
diff --git a/parser.cpp b/parser.cpp
index 6c73d3e..4ba029b 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -338,6 +338,9 @@ StateStart::StateStart() : State()
transitions['E'] = &States::ecommand;
transitions['I'] = &States::insert;
transitions['S'] = &States::search;
+
+ transitions['['] = &States::pushqreg;
+ transitions[']'] = &States::popqreg;
transitions['Q'] = &States::getqreginteger;
transitions['U'] = &States::setqreginteger;
transitions['%'] = &States::increaseqreg;
diff --git a/qbuffers.cpp b/qbuffers.cpp
index 0711438..1ac06c7 100644
--- a/qbuffers.cpp
+++ b/qbuffers.cpp
@@ -24,6 +24,8 @@ namespace States {
StateEditFile editfile;
StateSaveFile savefile;
+ StatePushQReg pushqreg;
+ StatePopQReg popqreg;
StateEQCommand eqcommand;
StateLoadQReg loadqreg;
StateCtlUCommand ctlucommand;
@@ -35,11 +37,13 @@ namespace States {
StateCopyToQReg copytoqreg;
}
-Ring ring;
QRegisterTable qregisters;
+static QRegisterStack qregister_stack;
static QRegister *register_argument = NULL;
+Ring ring;
+
/* FIXME: clean up current_save_dot() usage */
static inline void
current_save_dot(void)
@@ -62,7 +66,7 @@ current_edit(void)
}
void
-QRegister::set_string(const gchar *str)
+QRegisterData::set_string(const gchar *str)
{
edit();
dot = 0;
@@ -75,7 +79,7 @@ QRegister::set_string(const gchar *str)
}
void
-QRegister::undo_set_string(void)
+QRegisterData::undo_set_string(void)
{
current_save_dot();
if (ring.current)
@@ -90,7 +94,7 @@ QRegister::undo_set_string(void)
}
gchar *
-QRegister::get_string(void)
+QRegisterData::get_string(void)
{
gint size;
gchar *str;
@@ -108,10 +112,23 @@ QRegister::get_string(void)
}
void
-QRegister::edit(void)
+QRegisterData::edit(void)
{
interface.ssm(SCI_SETDOCPOINTER, 0, (sptr_t)get_document());
interface.ssm(SCI_GOTOPOS, dot);
+}
+
+void
+QRegisterData::undo_edit(void)
+{
+ undo.push_msg(SCI_GOTOPOS, dot);
+ undo.push_msg(SCI_SETDOCPOINTER, 0, (sptr_t)get_document());
+}
+
+void
+QRegister::edit(void)
+{
+ QRegisterData::edit();
interface.info_update(this);
}
@@ -119,8 +136,7 @@ void
QRegister::undo_edit(void)
{
interface.undo_info_update(this);
- undo.push_msg(SCI_GOTOPOS, dot);
- undo.push_msg(SCI_SETDOCPOINTER, 0, (sptr_t)get_document());
+ QRegisterData::undo_edit();
}
void
@@ -237,6 +253,76 @@ execute_hook(Hook type)
qregisters["0"]->execute();
}
+void
+QRegisterStack::UndoTokenPush::run(void)
+{
+ SLIST_INSERT_HEAD(&stack->head, entry, entries);
+ entry = NULL;
+}
+
+void
+QRegisterStack::UndoTokenPop::run(void)
+{
+ Entry *entry = SLIST_FIRST(&stack->head);
+
+ SLIST_REMOVE_HEAD(&stack->head, entries);
+ delete entry;
+}
+
+void
+QRegisterStack::push(QRegister *reg)
+{
+ Entry *entry = new Entry();
+
+ entry->integer = reg->integer;
+ if (reg->string) {
+ gchar *str = reg->get_string();
+ entry->set_string(str);
+ g_free(str);
+ }
+ entry->dot = reg->dot;
+
+ SLIST_INSERT_HEAD(&head, entry, entries);
+ undo.push(new UndoTokenPop(this));
+}
+
+bool
+QRegisterStack::pop(QRegister *reg)
+{
+ Entry *entry = SLIST_FIRST(&head);
+ QRegisterData::document *string;
+
+ if (!entry)
+ return false;
+
+ undo.push_var(reg->integer);
+ reg->integer = entry->integer;
+
+ /* exchange document ownership between Stack entry and Q-Register */
+ string = reg->string;
+ undo.push_var(reg->string);
+ reg->string = entry->string;
+ undo.push_var(entry->string);
+ entry->string = string;
+
+ undo.push_var(reg->dot);
+ reg->dot = entry->dot;
+
+ SLIST_REMOVE_HEAD(&head, entries);
+ /* pass entry ownership to undo stack */
+ undo.push(new UndoTokenPush(this, entry));
+
+ return true;
+}
+
+QRegisterStack::~QRegisterStack()
+{
+ Entry *entry, *next;
+
+ SLIST_FOREACH_SAFE(entry, &head, entries, next)
+ delete entry;
+}
+
bool
Buffer::load(const gchar *filename)
{
@@ -668,6 +754,27 @@ StateSaveFile::done(const gchar *str) throw (Error)
}
State *
+StatePushQReg::got_register(QRegister *reg) throw (Error)
+{
+ BEGIN_EXEC(&States::start);
+
+ qregister_stack.push(reg);
+
+ return &States::start;
+}
+
+State *
+StatePopQReg::got_register(QRegister *reg) throw (Error)
+{
+ BEGIN_EXEC(&States::start);
+
+ if (!qregister_stack.pop(reg))
+ throw Error("Q-Register stack is empty");
+
+ return &States::start;
+}
+
+State *
StateEQCommand::got_register(QRegister *reg) throw (Error)
{
BEGIN_EXEC(&States::loadqreg);
diff --git a/qbuffers.h b/qbuffers.h
index c2bb8ab..b11d53d 100644
--- a/qbuffers.h
+++ b/qbuffers.h
@@ -29,30 +29,21 @@ gchar *get_absolute_path(const gchar *path);
/*
* Classes
*/
-class QRegister : public RBTree::RBEntry {
-public:
- gchar *name;
+class QRegisterData {
+public:
gint64 integer;
typedef void document;
document *string;
gint dot;
- QRegister(const gchar *_name)
- : name(g_strdup(_name)), integer(0), string(NULL), dot(0) {}
+ QRegisterData() : integer(0), string(NULL), dot(0) {}
virtual
- ~QRegister()
+ ~QRegisterData()
{
if (string)
interface.ssm(SCI_RELEASEDOCUMENT, 0, (sptr_t)string);
- g_free(name);
- }
-
- int
- operator <(RBEntry &entry)
- {
- return g_strcmp0(name, ((QRegister &)entry).name);
}
inline document *
@@ -69,6 +60,28 @@ public:
virtual void edit(void);
virtual void undo_edit(void);
+};
+
+class QRegister : public RBTree::RBEntry, public QRegisterData {
+public:
+ gchar *name;
+
+ QRegister(const gchar *_name)
+ : QRegisterData(), name(g_strdup(_name)) {}
+ virtual
+ ~QRegister()
+ {
+ g_free(name);
+ }
+
+ int
+ operator <(RBEntry &entry)
+ {
+ return g_strcmp0(name, ((QRegister &)entry).name);
+ }
+
+ virtual void edit(void);
+ virtual void undo_edit(void);
void execute(void) throw (State::Error);
@@ -144,6 +157,55 @@ public:
}
} qregisters;
+class QRegisterStack {
+ class Entry : public QRegisterData {
+ public:
+ SLIST_ENTRY(Entry) entries;
+
+ Entry() : QRegisterData() {}
+ };
+
+ class UndoTokenPush : public UndoToken {
+ QRegisterStack *stack;
+ /* only remaining reference to stack entry */
+ Entry *entry;
+
+ public:
+ UndoTokenPush(QRegisterStack *_stack, Entry *_entry)
+ : UndoToken(), stack(_stack), entry(_entry) {}
+
+ ~UndoTokenPush()
+ {
+ if (entry)
+ delete entry;
+ }
+
+ void run(void);
+ };
+
+ class UndoTokenPop : public UndoToken {
+ QRegisterStack *stack;
+
+ public:
+ UndoTokenPop(QRegisterStack *_stack)
+ : UndoToken(), stack(_stack) {}
+
+ void run(void);
+ };
+
+ SLIST_HEAD(Head, Entry) head;
+
+public:
+ QRegisterStack()
+ {
+ SLIST_INIT(&head);
+ }
+ ~QRegisterStack();
+
+ void push(QRegister *reg);
+ bool pop(QRegister *reg);
+};
+
class Buffer {
class UndoTokenClose : public UndoToken {
Buffer *buffer;
@@ -323,6 +385,16 @@ private:
State *done(const gchar *str) throw (Error);
};
+class StatePushQReg : public StateExpectQReg {
+private:
+ State *got_register(QRegister *reg) throw (Error);
+};
+
+class StatePopQReg : public StateExpectQReg {
+private:
+ State *got_register(QRegister *reg) throw (Error);
+};
+
class StateEQCommand : public StateExpectQReg {
private:
State *got_register(QRegister *reg) throw (Error);
@@ -372,6 +444,8 @@ namespace States {
extern StateEditFile editfile;
extern StateSaveFile savefile;
+ extern StatePushQReg pushqreg;
+ extern StatePopQReg popqreg;
extern StateEQCommand eqcommand;
extern StateLoadQReg loadqreg;
extern StateCtlUCommand ctlucommand;
diff --git a/teco.ini b/teco.ini
index a104968..6f81323 100755
--- a/teco.ini
+++ b/teco.ini
@@ -2,41 +2,42 @@
! TECO.INI !
-@R/
- U3U2U1
- (Q1*256 + Q2)*256 + Q3
-/
-
@0/
@O"add,edit,close,quit"
-!add!
+!add! [f[r[0[1[2
f^QQ* EQf
- ZJ -:@S".^Q^E[cpp,c,h]""S Z-."= @EB"^Q^EQf"
- 3,4001ES^[
- 0,4005@ES"break case continue default do else for goto if return switch while"^[
- 0,255,0MR,0,2051@ES""^[
- 0,255,0MR,1,2051ES^[ 0,255,0MR,2,2051ES^[
- 255,255,0MR,4,2051ES^[ 255,0,0MR,5,2051ES^[
- 255,0,255MR,6,2051ES^[
- Oend
+ r
+ U2U1U0 (Q0*256 + Q1)*256 + Q2
+
+ ZJ -:@S".^Q^E[cpp,c,h]""S Z-."=
+ EB^QQf
+ 3,4001ES
+ 0,4005ESbreak case continue default do else for goto if return switch while
+ 0,255,0Mr,0,2051ES
+ 0,255,0Mr,1,2051ES 0,255,0Mr,2,2051ES
+ 255,255,0Mr,4,2051ES 255,0,0Mr,5,2051ES
+ 255,0,255Mr,6,2051ES
+ Oadd.end
''
- ZJ -:Smakefile"S Z-."= @EB"^Q^EQf"
- 11,4001ES^[
- 0,255,0MR,1,2051ES^[
- Oend
+ ZJ -:Smakefile"S Z-."=
+ EB^QQf
+ 11,4001ES
+ 0,255,0Mr,1,2051ES
+ Oadd.end
''
- @EB"^Q^EQf"
- @O"end"
+ EB^QQf
+!add.end!
+ ]2]1]0]r]f Oend
!edit!
- @O"end"
+ Oend
!close!
- @O"end"
+ Oend
!quit!
! fall through !
@@ -45,5 +46,7 @@
ED#32ED
! open all files specified on the commandline !
-<:L;R 0Xf EBQf EB L>
+[f
+ <:L;R 0Xf EBQf EB L>
+]f
-EF