diff --git a/src/data/keyword.hpp b/src/data/keyword.hpp index 801589e6..0201bdf6 100644 --- a/src/data/keyword.hpp +++ b/src/data/keyword.hpp @@ -111,8 +111,6 @@ class KeywordDatabase { void add(const vector&); /// Add a keyword to be matched void add(const Keyword&); - /// Remove a keyword from the database - void remove(const Keyword&); /// Prepare the parameters and match regex for a list of keywords static void prepare_parameters(const vector&, const vector&); diff --git a/src/gui/control/card_editor.cpp b/src/gui/control/card_editor.cpp index c94b792c..1d564249 100644 --- a/src/gui/control/card_editor.cpp +++ b/src/gui/control/card_editor.cpp @@ -161,6 +161,10 @@ void DataEditor::onCommand(int id) { } } +void DataEditor::insert(const String& text, const String& action_name) { + if (current_editor) current_editor->insert(text, action_name); +} + // ----------------------------------------------------------------------------- : Mouse events void DataEditor::onLeftDown(wxMouseEvent& ev) { diff --git a/src/gui/control/card_editor.hpp b/src/gui/control/card_editor.hpp index 474c5ee3..cb934a5f 100644 --- a/src/gui/control/card_editor.hpp +++ b/src/gui/control/card_editor.hpp @@ -70,6 +70,11 @@ class DataEditor : public CardViewer { */ bool search(FindInfo& find, bool from_start); + // --------------------------------------------------- : Selection in editor + + /// Insert 'text' into the current editor, using an action with the given name + void insert(const String& text, const String& action_name); + // --------------------------------------------------- : ValueViewers protected: diff --git a/src/gui/control/text_ctrl.cpp b/src/gui/control/text_ctrl.cpp index affe0e6b..7c9e36d2 100644 --- a/src/gui/control/text_ctrl.cpp +++ b/src/gui/control/text_ctrl.cpp @@ -91,6 +91,9 @@ void TextCtrl::onChangeSet() { } else { setValue(nullptr); } + // select the one and only editor + current_viewer = viewers.front().get(); + current_editor = current_viewer->getEditor(); } void TextCtrl::onInit() { diff --git a/src/gui/set/keywords_panel.cpp b/src/gui/set/keywords_panel.cpp index d4b8cfbe..96787f71 100644 --- a/src/gui/set/keywords_panel.cpp +++ b/src/gui/set/keywords_panel.cpp @@ -138,8 +138,6 @@ void KeywordsPanel::onUpdateUI(wxUpdateUIEvent& ev) { case ID_KEYWORD_PREV: ev.Enable(list->canSelectPrevious()); break; case ID_KEYWORD_NEXT: ev.Enable(list->canSelectNext()); break; case ID_KEYWORD_REMOVE: ev.Enable(list->getKeyword() && !list->getKeyword()->fixed); break; - case ID_KEYWORD_ADD_PARAM: - break; } } @@ -192,26 +190,37 @@ void KeywordsPanel::onCommand(int id) { if (id >= ID_PARAM_TYPE_MIN && id < ID_PARAM_TYPE_MAX) { // add parameter KeywordParamP param = set->game->keyword_parameter_types.at(id - ID_PARAM_TYPE_MIN); - String to_insert = _("") + param->name + _(""); - // TODO + String to_insert = _("") + param->name + _(""); + match->insert(to_insert, _("Insert parameter")); } else if (id >= ID_PARAM_REF_MIN && id < ID_PARAM_REF_MAX) { - /* - int i = ID_PARAM_REF_MIN; - FOR_EACH(p, list->getKeyword()->parameters) { - if (p->refer_scripts.empty()) { - if (i == id) { - // found it - } else { - } - } - } - String to_insert = list->getKeyword()->run_ref_script(id - ID_PARAM_REF_MIN, set->getContext()); - */ - // TODO + String to_insert = runRefScript(id - ID_PARAM_REF_MIN); + reminder->insert(to_insert, _("Use parameter")); } } } +String KeywordsPanel::runRefScript(int find_i) { + int param = 0; + int i = 0; + FOR_EACH(p, list->getKeyword()->parameters) { + String param_s = String(_("param")) << ++param; + if (p->refer_scripts.empty()) { + if (i++ == find_i) { + // found it + return _("{") + param_s + _("}"); + } + } else { + FOR_EACH(r, p->refer_scripts) { + if (i++ == find_i) { + Context& ctx = set->getContext(); + ctx.setVariable(_("input"), to_script(param_s)); + return r->script.invoke(ctx)->toString(); + } + } + } + } + return wxEmptyString; +} // ----------------------------------------------------------------------------- : Events @@ -250,10 +259,19 @@ void KeywordsPanel::onChangeSet() { void KeywordsPanel::onAction(const Action& action, bool undone) { TYPE_CASE(action, ValueAction) { - KeywordReminderTextValue* value = dynamic_cast(action.valueP.get()); - if (value && &value->keyword == list->getKeyword().get()) { - // the current keyword's reminder text changed - errors->SetLabel(value->errors); + { + KeywordReminderTextValue* value = dynamic_cast(action.valueP.get()); + if (value && &value->keyword == list->getKeyword().get()) { + // the current keyword's reminder text changed + errors->SetLabel(value->errors); + } + } + { + KeywordTextValue* value = dynamic_cast(action.valueP.get()); + if (value && value->underlying == &list->getKeyword()->match) { + // match string changes, maybe there are parameters now + ref_param->Enable(!value->keyword.fixed && !value->keyword.parameters.empty()); + } } } TYPE_CASE(action, ChangeKeywordModeAction) { diff --git a/src/gui/set/keywords_panel.hpp b/src/gui/set/keywords_panel.hpp index 43d07aac..bae10d48 100644 --- a/src/gui/set/keywords_panel.hpp +++ b/src/gui/set/keywords_panel.hpp @@ -39,6 +39,9 @@ class KeywordsPanel : public SetWindowPanel { private: DECLARE_EVENT_TABLE(); + /// Find the code to insert based on the ref_scripts for the parameters of the current keyword + String runRefScript(int i); + // --------------------------------------------------- : Controls wxSplitterWindow* splitter; wxPanel* panel; diff --git a/src/gui/value/editor.hpp b/src/gui/value/editor.hpp index ddb139fe..997a1637 100644 --- a/src/gui/value/editor.hpp +++ b/src/gui/value/editor.hpp @@ -69,11 +69,11 @@ class ValueEditor { /// This editor can be pasted to right now /** this function should also check the data on the clipboard has the right format */ virtual bool canPaste() const { return false; } - // Copies from this field editor, returns success + /// Copies from this field editor, returns success virtual bool doCopy() { return false; } - // Deletes the selection from this field editor, cut = copy + delete, returns success + /// Deletes the selection from this field editor, cut = copy + delete, returns success virtual bool doDelete() { return false; } - // Cuts the selection from this field editor + /// Cuts the selection from this field editor bool doCut() { return doCopy() && doDelete(); } /// Initiate pasting in this field editor, /** should again check if pasting is possible and fail silently if not, returns success */ @@ -96,6 +96,9 @@ class ValueEditor { virtual size_t selectionStart() const { return 0; } virtual size_t selectionEnd() const { return 0; } + /// Insert the given text (replacing the current selection) + virtual void insert(const String& text, const String& action_name) {}; + // --------------------------------------------------- : Search / replace /// Do a search or replace action for the given FindInfo diff --git a/src/gui/value/text.cpp b/src/gui/value/text.cpp index 7cf47b3f..ac1a3ca4 100644 --- a/src/gui/value/text.cpp +++ b/src/gui/value/text.cpp @@ -218,8 +218,8 @@ void TextValueEditor::onLoseFocus() { assert(caret); if (caret->IsVisible()) caret->Hide(); // hide selection - selection_start = selection_end = 0; - selection_start_i = selection_end_i = 0; + //selection_start = selection_end = 0; + //selection_start_i = selection_end_i = 0; } bool TextValueEditor::onContextMenu(IconMenu& m, wxContextMenuEvent& ev) { @@ -478,6 +478,9 @@ void TextValueEditor::showCaret() { if (!caret->IsVisible()) caret->Show(); } +void TextValueEditor::insert(const String& text, const String& action_name) { + replaceSelection(text, action_name); +} void TextValueEditor::replaceSelection(const String& replacement, const String& name) { if (replacement.empty() && selection_start == selection_end) { // no text selected, nothing to delete diff --git a/src/gui/value/text.hpp b/src/gui/value/text.hpp index 9208d20c..6e0eb2aa 100644 --- a/src/gui/value/text.hpp +++ b/src/gui/value/text.hpp @@ -92,6 +92,8 @@ class TextValueEditor : public TextValueViewer, public ValueEditor { virtual size_t selectionStart() const { return selection_start; } virtual size_t selectionEnd() const { return selection_end; } + virtual void insert(const String& text, const String& action_name); + // --------------------------------------------------- : Other virtual wxCursor cursor() const; diff --git a/src/util/tagged_string.cpp b/src/util/tagged_string.cpp index f472f73c..ca41dc27 100644 --- a/src/util/tagged_string.cpp +++ b/src/util/tagged_string.cpp @@ -390,7 +390,10 @@ String get_tags(const String& str, size_t start, size_t end, bool close_tags) { } } if (intag && keeptag) ret += c; - if (c == _('>')) intag = false; + if (c == _('>')) { + intag = false; + keeptag = false; + } } return ret; } @@ -399,12 +402,21 @@ String tagged_substr_replace(const String& input, size_t start, size_t end, cons assert(start <= end); size_t size = input.size(); String ret; ret.reserve(size + replacement.size() - (end - start)); // estimated size - return simplify_tagged( - substr_replace(input, start, end, - get_tags(input, start, end, true) + // close tags - replacement + - get_tags(input, start, end, false) // open tags - )); + if (replacement.empty()) { + return simplify_tagged( + substr_replace(input, start, end, + get_tags(input, start, end, false) + // open tags + replacement + + get_tags(input, start, end, true) // close tags + )); + } else { + return simplify_tagged( + substr_replace(input, start, end, + get_tags(input, start, end, true) + // close tags + replacement + + get_tags(input, start, end, false) // open tags + )); + } } @@ -419,15 +431,24 @@ String simplify_tagged(const String& str) { // otherwise appends and returns fales // (where is the negation of tag) bool add_or_cancel_tag(const String& tag, String& stack) { - String anti = anti_tag(tag); - size_t pos = stack.find(anti); - if (pos == String::npos) { + if (starts_with(tag, _("b")) || starts_with(tag, _("i")) || starts_with(tag, _("sym")) || + starts_with(tag, _("/"))) { + // cancel out all close tags, but not all open tags, + // so is always removed + // but is not + String anti = anti_tag(tag); + size_t pos = stack.find(anti); + if (pos == String::npos) { + stack += _("<") + tag + _(">"); + return false; + } else { + // cancel out with anti tag + stack = stack.substr(0, pos) + stack.substr(pos + anti.size()); + return true; + } + } else { stack += _("<") + tag + _(">"); return false; - } else { - // cancel out with anti tag - stack = stack.substr(0, pos) + stack.substr(pos + anti.size()); - return true; } }