aboutsummaryrefslogtreecommitdiffhomepage
path: root/parser.cpp
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 /parser.cpp
parentd0020c7f6faeff4b415f15884eea3270d306aff9 (diff)
downloadsciteco-b58893781bcb8feeba8c4743ae3d5e6083dc010e.tar.gz
insert (I) and <TAB> commands implemented
* StateExpectString does not yet handle string building chars
Diffstat (limited to 'parser.cpp')
-rw-r--r--parser.cpp108
1 files changed, 106 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;
+}