aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2012-11-08 04:28:54 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2012-11-08 04:28:54 +0100
commitb58893781bcb8feeba8c4743ae3d5e6083dc010e (patch)
tree2fc9c98fa2f7fadf67508536be8c2c08843422e4
parentd0020c7f6faeff4b415f15884eea3270d306aff9 (diff)
downloadsciteco-b58893781bcb8feeba8c4743ae3d5e6083dc010e.tar.gz
insert (I) and <TAB> commands implemented
* StateExpectString does not yet handle string building chars
-rw-r--r--parser.cpp108
-rw-r--r--parser.h26
2 files changed, 132 insertions, 2 deletions
diff --git a/parser.cpp b/parser.cpp
index 68062eb..df87b32 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -1,3 +1,5 @@
+#include <string.h>
+
#include <glib.h>
#include <glib/gprintf.h>
@@ -26,6 +28,8 @@ static gint nest_level = 0;
gchar *strings[2] = {NULL, NULL};
+static gchar escape_char = '\x1B';
+
bool
macro_execute(const gchar *macro)
{
@@ -101,6 +105,63 @@ State::get_next_state(gchar chr)
return next;
}
+State *
+StateExpectString::custom(gchar chr)
+{
+ gchar insert[255];
+ gchar *new_str;
+
+ if (chr == '\0') {
+ BEGIN_EXEC(this);
+ initial();
+ return this;
+ }
+
+ /*
+ * String termination handling
+ */
+ if (modifiers.at) {
+ undo.push_var<bool>(modifiers.at);
+ modifiers.at = false;
+ undo.push_var<gchar>(escape_char);
+ escape_char = g_ascii_toupper(chr);
+
+ return this;
+ }
+
+ if (g_ascii_toupper(chr) == escape_char) {
+ State *next = done(strings[0]);
+
+ undo.push_var<gchar>(escape_char);
+ escape_char = '\x1B';
+ undo.push_str(strings[0]);
+ g_free(strings[0]);
+ strings[0] = NULL;
+ /* TODO: save and reset string building machine state */
+
+ return next;
+ }
+
+ /*
+ * String building characters
+ */
+ /* TODO */
+ insert[0] = chr;
+ insert[1] = '\0';
+
+ /*
+ * String accumulation
+ */
+ undo.push_str(strings[0]);
+ new_str = g_strconcat(strings[0] ? : "", insert, NULL);
+ g_free(strings[0]);
+ strings[0] = new_str;
+
+ BEGIN_EXEC(this);
+ process(strings[0], strlen(insert));
+ return this;
+}
+
StateStart::StateStart() : State()
{
transitions['\0'] = this;
@@ -108,6 +169,7 @@ StateStart::StateStart() : State()
transitions['!'] = &states.label;
transitions['^'] = &states.control;
+ transitions['I'] = &states.insert;
}
void
@@ -448,7 +510,6 @@ StateControl::custom(gchar chr)
expressions.set_radix(expressions.pop_num_calc());
break;
-#if 0
/*
* Alternatives: ^i, ^I, <CTRL/I>, <TAB>
*/
@@ -457,7 +518,6 @@ StateControl::custom(gchar chr)
expressions.eval();
expressions.push('\t');
return &states.insert;
-#endif
/*
* Alternatives: ^[, <CTRL/[>, <ESC>
@@ -491,3 +551,47 @@ StateControl::custom(gchar chr)
return &states.start;
}
+
+/*
+ * NOTE: cannot support VideoTECO's <n>I because
+ * beginning and end of strings must be determined
+ * syntactically
+ */
+void
+StateInsert::initial(void)
+{
+ int args;
+
+ expressions.eval();
+ args = expressions.args();
+ if (!args)
+ return;
+
+ editor_msg(SCI_BEGINUNDOACTION);
+ for (int i = args; i > 0; i--) {
+ /* FIXME: if possible prevent pops with index != 1 */
+ gchar chr = (gchar)expressions.pop_num_calc(i);
+ editor_msg(SCI_ADDTEXT, 1, (sptr_t)&chr);
+ }
+ editor_msg(SCI_ENDUNDOACTION);
+
+ undo.push_msg(SCI_UNDO);
+}
+
+void
+StateInsert::process(const gchar *str, gint new_chars)
+{
+ editor_msg(SCI_BEGINUNDOACTION);
+ editor_msg(SCI_ADDTEXT, new_chars,
+ (sptr_t)str + strlen(str) - new_chars);
+ editor_msg(SCI_ENDUNDOACTION);
+
+ undo.push_msg(SCI_UNDO);
+}
+
+State *
+StateInsert::done(const gchar *str __attribute__((unused)))
+{
+ /* nothing to be done when done */
+ return &states.start;
+}
diff --git a/parser.h b/parser.h
index 8ceb3e2..2798469 100644
--- a/parser.h
+++ b/parser.h
@@ -39,6 +39,24 @@ protected:
}
};
+/*
+ * Super-class for states accepting string arguments
+ * Opaquely cares about alternative-escape characters,
+ * string building commands and accumulation into a string
+ */
+class StateExpectString : public State {
+public:
+ StateExpectString() : State() {}
+
+private:
+ virtual State *custom(gchar chr);
+
+protected:
+ virtual void initial(void) {}
+ virtual void process(const gchar *str, gint new_chars) {}
+ virtual State *done(const gchar *str) = 0;
+};
+
class StateStart : public State {
public:
StateStart();
@@ -58,6 +76,13 @@ private:
State *custom(gchar chr);
};
+class StateInsert : public StateExpectString {
+private:
+ void initial(void);
+ void process(const gchar *str, gint new_chars);
+ State *done(const gchar *str);
+};
+
#include "goto.h"
extern gint macro_pc;
@@ -66,6 +91,7 @@ extern struct States {
StateStart start;
StateLabel label;
StateControl control;
+ StateInsert insert;
} states;
extern enum Mode {