diff options
-rw-r--r-- | TODO | 13 | ||||
-rw-r--r-- | src/cmdline.cpp | 755 | ||||
-rw-r--r-- | src/cmdline.h | 18 | ||||
-rw-r--r-- | src/goto.h | 4 | ||||
-rw-r--r-- | src/help.h | 4 | ||||
-rw-r--r-- | src/parser.h | 106 | ||||
-rw-r--r-- | src/qregisters.h | 16 | ||||
-rw-r--r-- | src/spawn.h | 4 |
8 files changed, 528 insertions, 392 deletions
@@ -254,15 +254,6 @@ Optimizations: using _msize() to measure the memory required by individual chunks. This must be benchmarked. * Add G_UNLIKELY to all error throws. - * Instead of using RTTI to implement the immediate editing command - behaviours in Cmdline::process_edit_cmd() depending on the current - state, this could be modelled via virtual methods in State. - This would almost eradicate Cmdline::process_edit_cmd() and the - huge switch-case statement, would be more efficient (but who cares - in this case?) and would allow us to -fno-rtti saving a few bytes. - However, this would mean to make some more Cmdline methods public. - The implementations of the States' commandline editing handlers - could all be concentrated in cmdline.cpp. * String::append() could be optimized by ORing a padding into the realloc() size (e.g. 0xFF). However, this has not proven effective on Linux/glibc @@ -294,6 +285,10 @@ Optimizations: exception types. By adding an error code to the error object (which we will need anyway for supporting error handling in SciTECO macros), we may even avoid RTTI. + Should also allow us to completely disable exceptions via -fno-exceptions. + * RTTI could be disabled (-fno-rtti). It's only still required + because of StdError() for handling arbitrary C++ exceptions. + This is probably not required. * The position can be eliminated from UndoTokens by rewriting the UndoStack into a stack of UndoToken lists. Should be a significant memory reduction in interactive mode. 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) @@ -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 { @@ -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 { |