aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmdline.cpp755
-rw-r--r--src/cmdline.h18
-rw-r--r--src/goto.h4
-rw-r--r--src/help.h4
-rw-r--r--src/parser.h106
-rw-r--r--src/qregisters.h16
-rw-r--r--src/spawn.h4
7 files changed, 524 insertions, 383 deletions
diff --git a/src/cmdline.cpp b/src/cmdline.cpp
index ffe44d6..55d63d7 100644
--- a/src/cmdline.cpp
+++ b/src/cmdline.cpp
@@ -231,7 +231,7 @@ Cmdline::keypress(gchar key)
* characters as necessary into the command line.
*/
try {
- process_edit_cmd(key);
+ States::current->process_edit_cmd(key);
} catch (Return) {
/*
* Return from top-level macro, results
@@ -295,318 +295,10 @@ Cmdline::keypress(gchar key)
}
void
-Cmdline::process_edit_cmd(gchar key)
-{
- switch (key) {
- case '\n': /* insert EOL sequence */
- interface.popup_clear();
-
- if (Flags::ed & Flags::ED_AUTOEOL)
- insert("\n");
- else
- insert(get_eol_seq(interface.ssm(SCI_GETEOLMODE)));
- break;
-
- case CTL_KEY('G'): /* toggle immediate editing modifier */
- interface.popup_clear();
-
- modifier_enabled = !modifier_enabled;
- interface.msg(InterfaceCurrent::MSG_INFO,
- "Immediate editing modifier is now %s.",
- modifier_enabled ? "enabled" : "disabled");
- break;
-
- case CTL_KEY('H'): /* rubout/reinsert character */
- interface.popup_clear();
-
- if (modifier_enabled)
- /* re-insert character */
- insert();
- else
- /* rubout character */
- rubout();
- break;
-
- case CTL_KEY('W'): /* rubout/reinsert word/command */
- interface.popup_clear();
-
- if (States::is_file()) {
- /* File names, including directories */
- if (modifier_enabled) {
- /* reinsert one level of file name */
- while (States::is_file() && rubout_len &&
- !G_IS_DIR_SEPARATOR(str[len]))
- insert();
-
- /* reinsert final directory separator */
- if (States::is_file() && rubout_len &&
- G_IS_DIR_SEPARATOR(str[len]))
- insert();
- } else if (strings[0] && *strings[0]) {
- /* rubout directory separator */
- if (strings[0] && *strings[0] &&
- G_IS_DIR_SEPARATOR(str[len-1]))
- rubout();
-
- /* rubout one level of file name */
- while (strings[0] && *strings[0] &&
- !G_IS_DIR_SEPARATOR(str[len-1]))
- rubout();
- } else {
- /*
- * Rub out entire command instead of
- * rubbing out nothing.
- */
- rubout_command();
- }
- } else if (States::is_string()) {
- gchar wchars[interface.ssm(SCI_GETWORDCHARS)];
- interface.ssm(SCI_GETWORDCHARS, 0, (sptr_t)wchars);
-
- if (modifier_enabled) {
- /* reinsert word chars */
- while (States::is_string() && rubout_len &&
- strchr(wchars, str[len]))
- insert();
-
- /* reinsert non-word chars */
- while (States::is_string() && rubout_len &&
- !strchr(wchars, str[len]))
- insert();
- } else if (strings[0] && *strings[0]) {
- /* rubout non-word chars */
- while (strings[0] && *strings[0] &&
- !strchr(wchars, str[len-1]))
- rubout();
-
- /* rubout word chars */
- while (strings[0] && *strings[0] &&
- strchr(wchars, str[len-1]))
- rubout();
- } else {
- /*
- * Rub out entire command instead of
- * rubbing out nothing.
- */
- rubout_command();
- }
- } else if (modifier_enabled) {
- /* reinsert command */
- do
- insert();
- while (!States::is_start() && rubout_len);
- } else {
- /* rubout command */
- rubout_command();
- }
- break;
-
- case CTL_KEY('U'): /* rubout/reinsert string */
- interface.popup_clear();
-
- if (States::is_string()) {
- if (modifier_enabled) {
- /* reinsert string */
- while (States::is_string() && rubout_len)
- insert();
- } else {
- /* rubout string */
- while (strings[0] && *strings[0])
- rubout();
- }
- } else {
- insert(key);
- }
- break;
-
- case '\t': /* autocomplete symbol or file name */
- if (modifier_enabled) {
- /*
- * TODO: In insertion commands, we can autocomplete
- * the string at the buffer cursor.
- */
- if (States::is_string()) {
- /* autocomplete filename using string argument */
- if (interface.popup_is_shown()) {
- /* cycle through popup pages */
- interface.popup_show();
- break;
- }
-
- const gchar *filename = last_occurrence(strings[0]);
- gchar *new_chars = filename_complete(filename);
-
- if (new_chars)
- insert(new_chars);
- g_free(new_chars);
-
- /* may be reset if there was a rubbed out command line */
- modifier_enabled = true;
- } else {
- interface.popup_clear();
- insert(key);
- }
- } else if (States::is_qreg()) {
- if (interface.popup_is_shown()) {
- /* cycle through popup pages */
- interface.popup_show();
- break;
- }
-
- QRegSpecMachine &machine = ((StateExpectQReg *)States::current)->machine;
- gchar *new_chars = machine.auto_complete();
-
- if (new_chars)
- insert(new_chars);
- g_free(new_chars);
- } else if (States::is_string() &&
- ((StateExpectString *)States::current)->machine.qregspec_machine) {
- if (interface.popup_is_shown()) {
- /* cycle through popup pages */
- interface.popup_show();
- break;
- }
-
- QRegSpecMachine *machine =
- ((StateExpectString *)States::current)->machine.qregspec_machine;
- gchar *new_chars = machine->auto_complete();
-
- if (new_chars)
- insert(new_chars);
- g_free(new_chars);
- } else if (States::is_insertion() && !interface.ssm(SCI_GETUSETABS)) {
- interface.popup_clear();
-
- /* insert soft tabs */
- gint spaces = interface.ssm(SCI_GETTABWIDTH);
-
- spaces -= interface.ssm(SCI_GETCOLUMN,
- interface.ssm(SCI_GETCURRENTPOS)) % spaces;
-
- while (spaces--)
- insert(' ');
- } else if (States::is_dir()) {
- if (interface.popup_is_shown()) {
- /* cycle through popup pages */
- interface.popup_show();
- break;
- }
-
- gchar *new_chars = filename_complete(strings[0], '\0',
- G_FILE_TEST_IS_DIR);
-
- if (new_chars)
- insert(new_chars);
- g_free(new_chars);
- } else if (States::is_file()) {
- if (interface.popup_is_shown()) {
- /* cycle through popup pages */
- interface.popup_show();
- break;
- }
-
- gchar complete = escape_char == '{' ? '\0' : escape_char;
- gchar *new_chars = filename_complete(strings[0], complete);
-
- if (new_chars)
- insert(new_chars);
- g_free(new_chars);
- } else if (States::current == &States::executecommand) {
- /*
- * In the EC command, <TAB> completes files just like ^T
- * TODO: Implement shell-command completion by iterating
- * executables in $PATH
- */
- if (interface.popup_is_shown()) {
- /* cycle through popup pages */
- interface.popup_show();
- break;
- }
-
- const gchar *filename = last_occurrence(strings[0]);
- gchar *new_chars = filename_complete(filename);
-
- if (new_chars)
- insert(new_chars);
- g_free(new_chars);
- } else if (States::current == &States::scintilla_symbols) {
- if (interface.popup_is_shown()) {
- /* cycle through popup pages */
- interface.popup_show();
- break;
- }
-
- const gchar *symbol = last_occurrence(strings[0], ",");
- SymbolList &list = symbol == strings[0]
- ? Symbols::scintilla
- : Symbols::scilexer;
- gchar *new_chars = symbol_complete(list, symbol, ',');
-
- if (new_chars)
- insert(new_chars);
- g_free(new_chars);
- } else if (States::current == &States::gotocmd) {
- if (interface.popup_is_shown()) {
- /* cycle through popup pages */
- interface.popup_show();
- break;
- }
-
- const gchar *label = last_occurrence(strings[0], ",");
- gchar *new_chars = Goto::table->auto_complete(label);
-
- if (new_chars)
- insert(new_chars);
- g_free(new_chars);
- } else if (States::current == &States::gethelp) {
- if (interface.popup_is_shown()) {
- /* cycle through popup pages */
- interface.popup_show();
- break;
- }
-
- gchar complete = escape_char == '{' ? '\0' : escape_char;
- gchar *new_chars = help_index.auto_complete(strings[0], complete);
-
- if (new_chars)
- insert(new_chars);
- g_free(new_chars);
- } else {
- interface.popup_clear();
- insert(key);
- }
- break;
-
-#ifdef SIGTSTP
- case CTL_KEY('Z'):
- /*
- * <CTL/Z> does not raise signal if handling of
- * special characters temporarily disabled in terminal
- * (Curses), or command-line is detached from
- * terminal (GTK+).
- * This does NOT change the state of the popup window.
- */
- raise(SIGTSTP);
- break;
-#endif
-
- default:
- interface.popup_clear();
- insert(key);
- }
-}
-
-void
Cmdline::fnmacro(const gchar *name)
{
- enum {
- FNMACRO_MASK_START = (1 << 0),
- FNMACRO_MASK_STRING = (1 << 1)
- };
-
gchar macro_name[1 + strlen(name) + 1];
QRegister *reg;
- tecoInt mask;
gchar *macro;
if (!(Flags::ed & Flags::ED_FNKEYS))
@@ -621,17 +313,8 @@ Cmdline::fnmacro(const gchar *name)
/* macro undefined */
goto default_action;
- mask = reg->get_integer();
- if (States::is_start()) {
- if (mask & FNMACRO_MASK_START)
- return;
- } else if (States::is_string()) {
- if (mask & FNMACRO_MASK_STRING)
- return;
- } else if (mask & ~(tecoInt)(FNMACRO_MASK_START | FNMACRO_MASK_STRING)) {
- /* all other bits refer to any other state */
+ if (reg->get_integer() & States::current->get_fnmacro_mask())
return;
- }
macro = reg->get_string();
try {
@@ -854,6 +537,440 @@ symbol_complete(SymbolList &list, const gchar *symbol, gchar completed)
}
/*
+ * Commandline key processing.
+ *
+ * These are all the implementations of State::process_edit_cmd().
+ * It makes sense to use virtual methods for key processing, as it is
+ * largely state-dependant; but it defines interactive-mode-only
+ * behaviour which can be kept isolated from the rest of the states'
+ * implementation.
+ */
+
+void
+State::process_edit_cmd(gchar key)
+{
+ switch (key) {
+ case '\n': /* insert EOL sequence */
+ interface.popup_clear();
+
+ if (Flags::ed & Flags::ED_AUTOEOL)
+ cmdline.insert("\n");
+ else
+ cmdline.insert(get_eol_seq(interface.ssm(SCI_GETEOLMODE)));
+ return;
+
+ case CTL_KEY('G'): /* toggle immediate editing modifier */
+ interface.popup_clear();
+
+ modifier_enabled = !modifier_enabled;
+ interface.msg(InterfaceCurrent::MSG_INFO,
+ "Immediate editing modifier is now %s.",
+ modifier_enabled ? "enabled" : "disabled");
+ return;
+
+ case CTL_KEY('H'): /* rubout/reinsert character */
+ interface.popup_clear();
+
+ if (modifier_enabled)
+ /* re-insert character */
+ cmdline.insert();
+ else
+ /* rubout character */
+ cmdline.rubout();
+ return;
+
+ case CTL_KEY('W'): /* rubout/reinsert command */
+ interface.popup_clear();
+
+ if (modifier_enabled) {
+ /* reinsert command */
+ do
+ cmdline.insert();
+ while (States::current != &States::start && cmdline.rubout_len);
+ } else {
+ /* rubout command */
+ do
+ cmdline.rubout();
+ while (States::current != &States::start);
+ }
+ return;
+
+#ifdef SIGTSTP
+ case CTL_KEY('Z'):
+ /*
+ * <CTL/Z> does not raise signal if handling of
+ * special characters temporarily disabled in terminal
+ * (Curses), or command-line is detached from
+ * terminal (GTK+).
+ * This does NOT change the state of the popup window.
+ */
+ raise(SIGTSTP);
+ return;
+#endif
+ }
+
+ interface.popup_clear();
+ cmdline.insert(key);
+}
+
+void
+StateExpectString::process_edit_cmd(gchar key)
+{
+ switch (key) {
+ case CTL_KEY('W'): { /* rubout/reinsert word */
+ interface.popup_clear();
+
+ gchar wchars[interface.ssm(SCI_GETWORDCHARS)];
+ interface.ssm(SCI_GETWORDCHARS, 0, (sptr_t)wchars);
+
+ if (modifier_enabled) {
+ /* reinsert word chars */
+ while (States::current == this && cmdline.rubout_len &&
+ strchr(wchars, cmdline.str[cmdline.len]))
+ cmdline.insert();
+
+ /* reinsert non-word chars */
+ while (States::current == this && cmdline.rubout_len &&
+ !strchr(wchars, cmdline.str[cmdline.len]))
+ cmdline.insert();
+ return;
+ }
+
+ if (strings[0] && *strings[0]) {
+ /* rubout non-word chars */
+ while (strings[0] && *strings[0] &&
+ !strchr(wchars, cmdline.str[cmdline.len-1]))
+ cmdline.rubout();
+
+ /* rubout word chars */
+ while (strings[0] && *strings[0] &&
+ strchr(wchars, cmdline.str[cmdline.len-1]))
+ cmdline.rubout();
+ return;
+ }
+
+ /*
+ * Otherwise, the entire command string will
+ * be rubbed out.
+ */
+ break;
+ }
+
+ case CTL_KEY('U'): /* rubout/reinsert string */
+ interface.popup_clear();
+
+ if (modifier_enabled) {
+ /* reinsert string */
+ while (States::current == this && cmdline.rubout_len)
+ cmdline.insert();
+ } else {
+ /* rubout string */
+ while (strings[0] && *strings[0])
+ cmdline.rubout();
+ }
+ return;
+
+ case '\t': /* autocomplete file name */
+ if (modifier_enabled) {
+ /*
+ * TODO: In insertion commands, we can autocomplete
+ * the string at the buffer cursor.
+ */
+ /* autocomplete filename using string argument */
+ if (interface.popup_is_shown()) {
+ /* cycle through popup pages */
+ interface.popup_show();
+ return;
+ }
+
+ const gchar *filename = last_occurrence(strings[0]);
+ gchar *new_chars = filename_complete(filename);
+
+ if (new_chars)
+ cmdline.insert(new_chars);
+ g_free(new_chars);
+
+ /* may be reset if there was a rubbed out command line */
+ modifier_enabled = true;
+ return;
+ }
+
+ if (machine.qregspec_machine) {
+ if (interface.popup_is_shown()) {
+ /* cycle through popup pages */
+ interface.popup_show();
+ return;
+ }
+
+ gchar *new_chars = machine.qregspec_machine->auto_complete();
+
+ if (new_chars)
+ cmdline.insert(new_chars);
+ g_free(new_chars);
+ return;
+ }
+ break;
+ }
+
+ State::process_edit_cmd(key);
+}
+
+void
+StateInsert::process_edit_cmd(gchar key)
+{
+ gint spaces;
+
+ switch (key) {
+ case '\t': /* insert <TAB> indention */
+ if (modifier_enabled || interface.ssm(SCI_GETUSETABS))
+ break;
+
+ interface.popup_clear();
+
+ /* insert soft tabs */
+ spaces = interface.ssm(SCI_GETTABWIDTH);
+ spaces -= interface.ssm(SCI_GETCOLUMN,
+ interface.ssm(SCI_GETCURRENTPOS)) % spaces;
+
+ while (spaces--)
+ cmdline.insert(' ');
+ return;
+ }
+
+ StateExpectString::process_edit_cmd(key);
+}
+
+void
+StateExpectFile::process_edit_cmd(gchar key)
+{
+ gchar *new_chars;
+
+ switch (key) {
+ case CTL_KEY('W'): /* rubout/reinsert file names including directories */
+ interface.popup_clear();
+
+ if (modifier_enabled) {
+ /* reinsert one level of file name */
+ while (States::current == this && cmdline.rubout_len &&
+ !G_IS_DIR_SEPARATOR(cmdline.str[cmdline.len]))
+ cmdline.insert();
+
+ /* reinsert final directory separator */
+ if (States::current == this && cmdline.rubout_len &&
+ G_IS_DIR_SEPARATOR(cmdline.str[cmdline.len]))
+ cmdline.insert();
+ return;
+ }
+
+ if (strings[0] && *strings[0]) {
+ /* rubout directory separator */
+ if (strings[0] && *strings[0] &&
+ G_IS_DIR_SEPARATOR(cmdline.str[cmdline.len-1]))
+ cmdline.rubout();
+
+ /* rubout one level of file name */
+ while (strings[0] && *strings[0] &&
+ !G_IS_DIR_SEPARATOR(cmdline.str[cmdline.len-1]))
+ cmdline.rubout();
+ return;
+ }
+
+ /*
+ * Rub out entire command instead of
+ * rubbing out nothing.
+ */
+ break;
+
+ case '\t': /* autocomplete file name */
+ if (modifier_enabled)
+ break;
+
+ if (interface.popup_is_shown()) {
+ /* cycle through popup pages */
+ interface.popup_show();
+ return;
+ }
+
+ new_chars = filename_complete(strings[0],
+ escape_char == '{' ? '\0' : escape_char);
+ if (new_chars)
+ cmdline.insert(new_chars);
+ g_free(new_chars);
+ return;
+ }
+
+ StateExpectString::process_edit_cmd(key);
+}
+
+void
+StateExpectDir::process_edit_cmd(gchar key)
+{
+ gchar *new_chars;
+
+ switch (key) {
+ case '\t': /* autocomplete directory */
+ if (modifier_enabled)
+ break;
+
+ if (interface.popup_is_shown()) {
+ /* cycle through popup pages */
+ interface.popup_show();
+ return;
+ }
+
+ new_chars = filename_complete(strings[0], '\0',
+ G_FILE_TEST_IS_DIR);
+ if (new_chars)
+ cmdline.insert(new_chars);
+ g_free(new_chars);
+ return;
+ }
+
+ StateExpectFile::process_edit_cmd(key);
+}
+
+void
+StateExpectQReg::process_edit_cmd(gchar key)
+{
+ gchar *new_chars;
+
+ switch (key) {
+ case '\t': /* autocomplete Q-Register name */
+ if (modifier_enabled)
+ break;
+
+ if (interface.popup_is_shown()) {
+ /* cycle through popup pages */
+ interface.popup_show();
+ return;
+ }
+
+ new_chars = machine.auto_complete();
+ if (new_chars)
+ cmdline.insert(new_chars);
+ g_free(new_chars);
+ return;
+ }
+
+ State::process_edit_cmd(key);
+}
+
+void
+StateExecuteCommand::process_edit_cmd(gchar key)
+{
+ gchar *new_chars;
+
+ switch (key) {
+ case '\t': /* autocomplete symbol or file name */
+ if (modifier_enabled)
+ break;
+
+ /*
+ * In the EC command, <TAB> completes files just like ^T
+ * TODO: Implement shell-command completion by iterating
+ * executables in $PATH
+ */
+ if (interface.popup_is_shown()) {
+ /* cycle through popup pages */
+ interface.popup_show();
+ return;
+ }
+
+ new_chars = filename_complete(last_occurrence(strings[0]));
+ if (new_chars)
+ cmdline.insert(new_chars);
+ g_free(new_chars);
+ return;
+ }
+
+ StateExpectString::process_edit_cmd(key);
+}
+
+void
+StateScintilla_symbols::process_edit_cmd(gchar key)
+{
+ switch (key) {
+ case '\t': { /* autocomplete Scintilla symbol */
+ if (modifier_enabled)
+ break;
+
+ if (interface.popup_is_shown()) {
+ /* cycle through popup pages */
+ interface.popup_show();
+ return;
+ }
+
+ const gchar *symbol = last_occurrence(strings[0], ",");
+ SymbolList &list = symbol == strings[0]
+ ? Symbols::scintilla
+ : Symbols::scilexer;
+ gchar *new_chars = symbol_complete(list, symbol, ',');
+
+ if (new_chars)
+ cmdline.insert(new_chars);
+ g_free(new_chars);
+ return;
+ }
+ }
+
+ StateExpectString::process_edit_cmd(key);
+}
+
+void
+StateGotoCmd::process_edit_cmd(gchar key)
+{
+ switch (key) {
+ case '\t': { /* autocomplete goto label */
+ if (modifier_enabled)
+ break;
+
+ if (interface.popup_is_shown()) {
+ /* cycle through popup pages */
+ interface.popup_show();
+ return;
+ }
+
+ const gchar *label = last_occurrence(strings[0], ",");
+ gchar *new_chars = Goto::table->auto_complete(label);
+
+ if (new_chars)
+ cmdline.insert(new_chars);
+ g_free(new_chars);
+ return;
+ }
+ }
+
+ StateExpectString::process_edit_cmd(key);
+}
+
+void
+StateGetHelp::process_edit_cmd(gchar key)
+{
+ switch (key) {
+ case '\t': { /* autocomplete help term */
+ if (modifier_enabled)
+ break;
+
+ if (interface.popup_is_shown()) {
+ /* cycle through popup pages */
+ interface.popup_show();
+ return;
+ }
+
+ gchar complete = escape_char == '{' ? '\0' : escape_char;
+ gchar *new_chars = help_index.auto_complete(strings[0], complete);
+
+ if (new_chars)
+ cmdline.insert(new_chars);
+ g_free(new_chars);
+ return;
+ }
+ }
+
+ StateExpectString::process_edit_cmd(key);
+}
+
+/*
* Command states
*/
diff --git a/src/cmdline.h b/src/cmdline.h
index 8b01df8..66e1829 100644
--- a/src/cmdline.h
+++ b/src/cmdline.h
@@ -27,6 +27,13 @@
namespace SciTECO {
+/*
+ * NOTE: Some of the members (esp. insert() and rubout())
+ * have to be public, so that State::process_edit_cmd()
+ * implementations can access it.
+ * Otherwise, we'd have to list all implementations as
+ * friend methods, which is inelegant.
+ */
extern class Cmdline : public Object {
public:
/**
@@ -68,9 +75,6 @@ public:
void replace(void) G_GNUC_NORETURN;
-private:
- void process_edit_cmd(gchar key);
-
inline void
rubout(void)
{
@@ -80,14 +84,6 @@ private:
}
}
- inline void
- rubout_command(void)
- {
- do
- rubout();
- while (States::current != &States::start);
- }
-
void insert(const gchar *src = NULL);
inline void
insert(gchar key)
diff --git a/src/goto.h b/src/goto.h
index 3365a79..78a9579 100644
--- a/src/goto.h
+++ b/src/goto.h
@@ -128,6 +128,10 @@ private:
class StateGotoCmd : public StateExpectString {
private:
State *done(const gchar *str);
+
+protected:
+ /* in cmdline.cpp */
+ void process_edit_cmd(gchar key);
};
namespace States {
diff --git a/src/help.h b/src/help.h
index 6695ae6..73eaa42 100644
--- a/src/help.h
+++ b/src/help.h
@@ -83,6 +83,10 @@ public:
private:
void initial(void);
State *done(const gchar *str);
+
+protected:
+ /* in cmdline.cpp */
+ void process_edit_cmd(gchar key);
};
namespace States {
diff --git a/src/parser.h b/src/parser.h
index 9aa13ad..700d25f 100644
--- a/src/parser.h
+++ b/src/parser.h
@@ -87,6 +87,41 @@ protected:
throw SyntaxError(chr);
return NULL;
}
+
+public:
+ /**
+ * Process editing command (or key press).
+ *
+ * This is part of command line handling in interactive
+ * mode and allows the definition of state-specific
+ * editing commands (behaviour on key press).
+ *
+ * By implementing this method, sub-states can either
+ * handle a key and return or chain to the
+ * parent's process_edit_cmd() implementation.
+ *
+ * All implementations of this method are defined in
+ * cmdline.cpp.
+ */
+ virtual void process_edit_cmd(gchar key);
+
+ enum fnmacroMask {
+ FNMACRO_MASK_START = (1 << 0),
+ FNMACRO_MASK_STRING = (1 << 1),
+ FNMACRO_MASK_DEFAULT = ~((1 << 2)-1)
+ };
+
+ /**
+ * Get the function key macro mask this
+ * state refers to.
+ *
+ * Could also be modelled as a State member.
+ */
+ virtual fnmacroMask
+ get_fnmacro_mask(void) const
+ {
+ return FNMACRO_MASK_DEFAULT;
+ }
};
template <typename Type>
@@ -166,14 +201,9 @@ class StateExpectString : public State {
bool string_building;
bool last;
-public:
- /*
- * FIXME: Only public as long as cmdline.cpp
- * needs to access it.
- * Can be avoided one process_edit_cmd() is in State.
- */
StringBuildingMachine machine;
+public:
StateExpectString(bool _building = true, bool _last = true)
: insert_len(0), nesting(1),
string_building(_building), last(_last) {}
@@ -182,10 +212,19 @@ private:
State *custom(gchar chr);
void refresh(void);
+ virtual fnmacroMask
+ get_fnmacro_mask(void) const
+ {
+ return FNMACRO_MASK_STRING;
+ }
+
protected:
virtual void initial(void) {}
virtual void process(const gchar *str, gint new_chars) {}
virtual State *done(const gchar *str) = 0;
+
+ /* in cmdline.cpp */
+ void process_edit_cmd(gchar key);
};
class StateExpectFile : public StateExpectString {
@@ -198,12 +237,19 @@ private:
protected:
virtual State *got_file(const gchar *filename) = 0;
+
+ /* in cmdline.cpp */
+ void process_edit_cmd(gchar key);
};
class StateExpectDir : public StateExpectFile {
public:
StateExpectDir(bool _building = true, bool _last = true)
: StateExpectFile(_building, _last) {}
+
+protected:
+ /* in cmdline.cpp */
+ void process_edit_cmd(gchar key);
};
class StateStart : public State {
@@ -222,6 +268,12 @@ private:
State *custom(gchar chr);
void end_of_macro(void) {}
+
+ fnmacroMask
+ get_fnmacro_mask(void) const
+ {
+ return FNMACRO_MASK_START;
+ }
};
class StateControl : public State {
@@ -304,6 +356,10 @@ public:
private:
State *done(const gchar *str);
+
+protected:
+ /* in cmdline.cpp */
+ void process_edit_cmd(gchar key);
};
class StateScintilla_lParam : public StateExpectString {
@@ -323,6 +379,9 @@ protected:
void initial(void);
void process(const gchar *str, gint new_chars);
State *done(const gchar *str);
+
+ /* in cmdline.cpp */
+ void process_edit_cmd(gchar key);
};
class StateInsertIndent : public StateInsert {
@@ -346,41 +405,6 @@ namespace States {
extern StateInsertIndent insert_indent;
extern State *current;
-
- static inline bool
- is_start()
- {
- /*
- * The "escape" state exists only as a hack,
- * to support $$. Otherwise it should behave
- * like the start state.
- */
- return current == &start || current == &escape;
- }
-
- static inline bool
- is_string()
- {
- return dynamic_cast<StateExpectString *>(current);
- }
-
- static inline bool
- is_insertion()
- {
- return dynamic_cast<StateInsert *>(current);
- }
-
- static inline bool
- is_file()
- {
- return dynamic_cast<StateExpectFile *>(current);
- }
-
- static inline bool
- is_dir()
- {
- return dynamic_cast<StateExpectDir *>(current);
- }
}
extern enum Mode {
diff --git a/src/qregisters.h b/src/qregisters.h
index f185f03..d57323a 100644
--- a/src/qregisters.h
+++ b/src/qregisters.h
@@ -489,14 +489,9 @@ public:
* Super class for states accepting Q-Register specifications
*/
class StateExpectQReg : public State {
-public:
- /*
- * FIXME: Only public, so we can access it from
- * cmdline.cpp. Will not be necessary if process_edit_cmd()
- * is a State method.
- */
QRegSpecMachine machine;
+public:
StateExpectQReg(QRegSpecType type = QREG_REQUIRED);
private:
@@ -504,6 +499,9 @@ private:
protected:
virtual State *got_register(QRegister *reg) = 0;
+
+ /* in cmdline.cpp */
+ void process_edit_cmd(gchar key);
};
class StatePushQReg : public StateExpectQReg {
@@ -637,12 +635,6 @@ namespace States {
extern StateMacro macro;
extern StateMacroFile macro_file;
extern StateCopyToQReg copytoqreg;
-
- static inline bool
- is_qreg()
- {
- return dynamic_cast<StateExpectQReg *>(current);
- }
}
namespace QRegisters {
diff --git a/src/spawn.h b/src/spawn.h
index 5ddc9dd..4d7403e 100644
--- a/src/spawn.h
+++ b/src/spawn.h
@@ -57,6 +57,10 @@ private:
void initial(void);
State *done(const gchar *str);
+
+protected:
+ /* in cmdline.cpp */
+ void process_edit_cmd(gchar key);
};
class StateEGCommand : public StateExpectQReg {