aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2012-11-11 10:23:39 +0100
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2012-11-11 10:23:39 +0100
commit8c6c6afe144adca0635edd0438b9889b3c3df6e4 (patch)
tree09d486b60b130861211e5cb42a4d7c8d9b9514f1
parent54c58efbcdef773475508d982431a0a8ae215e3d (diff)
downloadsciteco-8c6c6afe144adca0635edd0438b9889b3c3df6e4.tar.gz
automatic support for string building characters
* also improved <n>I...$ insertion of chars from stack
-rw-r--r--parser.cpp121
-rw-r--r--parser.h24
2 files changed, 135 insertions, 10 deletions
diff --git a/parser.cpp b/parser.cpp
index 8ae51f3..83a94d5 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -121,11 +121,104 @@ State::get_next_state(gchar chr)
return next;
}
+gchar *
+StateExpectString::machine_input(gchar chr)
+{
+ switch (machine.mode) {
+ case Machine::MODE_UPPER:
+ chr = g_ascii_toupper(chr);
+ break;
+ case Machine::MODE_LOWER:
+ chr = g_ascii_tolower(chr);
+ break;
+ default:
+ break;
+ }
+
+ if (machine.toctl) {
+ chr = CTL_KEY(g_ascii_toupper(chr));
+ machine.toctl = false;
+ }
+
+ if (machine.state == Machine::STATE_ESCAPED) {
+ machine.state = Machine::STATE_START;
+ goto original;
+ }
+
+ if (chr == '^') {
+ machine.toctl = true;
+ return NULL;
+ }
+
+ switch (machine.state) {
+ case Machine::STATE_START:
+ switch (chr) {
+ case CTL_KEY('Q'):
+ case CTL_KEY('R'): machine.state = Machine::STATE_ESCAPED; break;
+ case CTL_KEY('V'): machine.state = Machine::STATE_LOWER; break;
+ case CTL_KEY('W'): machine.state = Machine::STATE_UPPER; break;
+ case CTL_KEY('E'): machine.state = Machine::STATE_CTL_E; break;
+ default:
+ goto original;
+ }
+ break;
+
+ case Machine::STATE_LOWER:
+ machine.state = Machine::STATE_START;
+ if (chr != CTL_KEY('V'))
+ return g_strdup((gchar []){g_ascii_tolower(chr), '\0'});
+ machine.mode = Machine::MODE_LOWER;
+ break;
+
+ case Machine::STATE_UPPER:
+ machine.state = Machine::STATE_START;
+ if (chr != CTL_KEY('W'))
+ return g_strdup((gchar []){g_ascii_toupper(chr), '\0'});
+ machine.mode = Machine::MODE_UPPER;
+ break;
+
+ case Machine::STATE_CTL_E:
+ switch (g_ascii_toupper(chr)) {
+ case 'Q': machine.state = Machine::STATE_CTL_EQ; break;
+ case 'U': machine.state = Machine::STATE_CTL_EU; break;
+ default:
+ machine.state = Machine::STATE_START;
+ return g_strdup((gchar []){CTL_KEY('E'), chr, '\0'});
+ }
+ break;
+
+ /*
+ * FIXME: Q-Register specifications might get more complicated
+ */
+ case Machine::STATE_CTL_EU:
+ case Machine::STATE_CTL_EQ: {
+ QRegister *reg;
+ Machine::State state = machine.state;
+ machine.state = Machine::STATE_START;
+
+ reg = qregisters[(gchar []){g_ascii_toupper(chr), '\0'}];
+ if (!reg)
+ return NULL;
+
+ return state == Machine::STATE_CTL_EQ
+ ? reg->get_string()
+ : g_strdup((gchar []){(gchar)reg->integer, '\0'});
+ }
+
+ default:
+ g_assert(TRUE);
+ }
+
+ return NULL;
+
+original:
+ return g_strdup((gchar []){chr, '\0'});
+}
+
State *
StateExpectString::custom(gchar chr)
{
- gchar insert[255];
- gchar *new_str;
+ gchar *insert, *new_str;
if (chr == '\0') {
BEGIN_EXEC(this);
@@ -153,17 +246,24 @@ StateExpectString::custom(gchar chr)
undo.push_str(strings[0]);
g_free(strings[0]);
strings[0] = NULL;
- /* TODO: save and reset string building machine state */
+
+ undo.push_var<Machine>(machine);
+ machine.state = Machine::STATE_START;
+ machine.mode = Machine::MODE_NORMAL;
+ machine.toctl = false;
return next;
}
+ BEGIN_EXEC(this);
+
/*
* String building characters
*/
- /* TODO */
- insert[0] = chr;
- insert[1] = '\0';
+ undo.push_var<Machine>(machine);
+ insert = machine_input(chr);
+ if (!insert)
+ return this;
/*
* String accumulation
@@ -173,8 +273,8 @@ StateExpectString::custom(gchar chr)
g_free(strings[0]);
strings[0] = new_str;
- BEGIN_EXEC(this);
process(strings[0], strlen(insert));
+ g_free(insert);
return this;
}
@@ -787,10 +887,11 @@ StateInsert::initial(void)
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);
+ gchar chr = (gchar)expressions.peek_num(i);
editor_msg(SCI_ADDTEXT, 1, (sptr_t)&chr);
}
+ for (int i = args; i > 0; i--)
+ expressions.pop_num_calc();
editor_msg(SCI_ENDUNDOACTION);
undo.push_msg(SCI_UNDO);
@@ -801,7 +902,7 @@ 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);
+ (sptr_t)(str + strlen(str) - new_chars));
editor_msg(SCI_ENDUNDOACTION);
undo.push_msg(SCI_UNDO);
diff --git a/parser.h b/parser.h
index 940dbd5..bff15c7 100644
--- a/parser.h
+++ b/parser.h
@@ -45,10 +45,34 @@ protected:
* string building commands and accumulation into a string
*/
class StateExpectString : public State {
+ struct Machine {
+ enum State {
+ STATE_START,
+ STATE_ESCAPED,
+ STATE_LOWER,
+ STATE_UPPER,
+ STATE_CTL_E,
+ STATE_CTL_EQ,
+ STATE_CTL_EU
+ } state;
+
+ enum Mode {
+ MODE_NORMAL,
+ MODE_UPPER,
+ MODE_LOWER
+ } mode;
+
+ bool toctl;
+
+ Machine() : state(STATE_START),
+ mode(MODE_NORMAL), toctl(false) {}
+ } machine;
+
public:
StateExpectString() : State() {}
private:
+ gchar *machine_input(gchar key);
State *custom(gchar chr);
protected: