diff options
-rw-r--r-- | parser.cpp | 3 | ||||
-rw-r--r-- | qbuffers.cpp | 121 | ||||
-rw-r--r-- | qbuffers.h | 100 | ||||
-rwxr-xr-x | teco.ini | 49 |
4 files changed, 230 insertions, 43 deletions
@@ -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); @@ -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; @@ -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 |