From f7b82e3f6b07445cb2156a1a834c0c4830014c38 Mon Sep 17 00:00:00 2001 From: twanvl Date: Sun, 26 Aug 2007 19:39:23 +0000 Subject: [PATCH] Implemented auto replace, including GUI git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@631 0fc631ac-6414-0410-93d0-97cfa31319b6 --- data/en.mse-locale/locale | 21 + src/data/game.cpp | 3 +- src/data/game.hpp | 6 +- src/data/settings.cpp | 38 +- src/data/settings.hpp | 8 + src/data/symbol.cpp | 7 + src/data/word_list.cpp | 15 + src/data/word_list.hpp | 18 + src/gui/set/window.cpp | 13 +- src/gui/set/window.hpp | 1 + src/gui/value/text.cpp | 111 ++- src/gui/value/text.hpp | 13 +- src/mse.vcproj | 6 + src/resource/common/expected_locale_keys | 1006 +++++++++++----------- src/util/io/writer.cpp | 4 +- src/util/window_id.hpp | 11 +- tools/gen.pl | 2 +- 17 files changed, 742 insertions(+), 541 deletions(-) diff --git a/data/en.mse-locale/locale b/data/en.mse-locale/locale index 8b548a34..7ab18988 100644 --- a/data/en.mse-locale/locale +++ b/data/en.mse-locale/locale @@ -29,6 +29,7 @@ menu: find: &Find Ctrl+F find next: Find &Next F3 replace: R&eplace Ctrl+H + auto replace: Auto Rep&lace... preferences: &Preferences... cards: &Cards @@ -125,6 +126,10 @@ help: paste: Inserts the text from the clipboard paste card: Inserts the card from the clipboard paste keyword: Inserts the keyword from the clipboard + find: Search the card texts + find next: Find the next match + replace: Replace in the card texts + auto replace: What text should automatically be replaced? preferences: Change the configuration of Magic Set Editor cards: @@ -435,6 +440,10 @@ label: zoom: Zoom filter: Filter + # Auto replace + auto match: Match + auto replace: Replace + # Symbol editor sides: sides @@ -484,6 +493,14 @@ button: # Update checker close: &Close + + # Auto replace + use auto replace: Use auto replace + add item: &Add + remove item: &Remove + defaults: Reset to &Defaults + enabled: Enabled + whole word: Match whole word only ############################################################## Titles in the GUI title: @@ -519,6 +536,8 @@ title: export cancelled: Export Cancelled export html: Export to HTML save html: Export to HTML + # auto replace + auto replaces: Auto Replace # Package Update Window package list: Package Updates @@ -537,6 +556,7 @@ action: delete: Delete cut: Cut paste: Paste + auto replace: Auto Replace # Choice/color editors change: Change %s @@ -623,6 +643,7 @@ error: When you open it, some aspects of the file may be lost. It is recommended that you upgrade to the latest version. Visit http:://magicseteditor.sourceforge.net/ + word list type not found: The word list type %s was not found (from a tag) # Update checking checking updates failed: Checking updates failed. diff --git a/src/data/game.cpp b/src/data/game.cpp index 7f244c3e..20e9ea78 100644 --- a/src/data/game.cpp +++ b/src/data/game.cpp @@ -57,7 +57,8 @@ IMPLEMENT_REFLECTION(Game) { REFLECT(keyword_modes); REFLECT(keyword_parameter_types); REFLECT_NO_SCRIPT(keywords); - REFLECT(word_lists); + REFLECT_NO_SCRIPT(word_lists); + REFLECT_NO_SCRIPT(auto_replaces); } void Game::validate(Version v) { diff --git a/src/data/game.hpp b/src/data/game.hpp index 3c0fd45d..22dd0d73 100644 --- a/src/data/game.hpp +++ b/src/data/game.hpp @@ -25,6 +25,7 @@ DECLARE_POINTER_TYPE(KeywordParam); DECLARE_POINTER_TYPE(KeywordMode); DECLARE_POINTER_TYPE(Keyword); DECLARE_POINTER_TYPE(WordList); +DECLARE_POINTER_TYPE(AutoReplace); // ----------------------------------------------------------------------------- : Game @@ -45,13 +46,14 @@ class Game : public Packaged { vector statistics_categories; ///< (Additional) statistics categories vector pack_types; ///< Types of random card packs to generate vector word_lists; ///< Word lists for editing with a drop down list - + vector auto_replaces; ///< Things to autoreplace in textboxes + bool has_keywords; ///< Does this game use keywords? OptionalScript keyword_match_script; ///< For the keyword editor vector keyword_parameter_types;///< Types of keyword parameters vector keyword_modes; ///< Modes of keywords vector keywords; ///< Keywords for use in text - + Dependencies dependent_scripts_cards; ///< scripts that depend on the card list Dependencies dependent_scripts_keywords; ///< scripts that depend on the keywords bool dependencies_initialized; ///< are the script dependencies comming from this game all initialized? diff --git a/src/data/settings.cpp b/src/data/settings.cpp index 55476bec..76d20dac 100644 --- a/src/data/settings.cpp +++ b/src/data/settings.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,8 @@ #include #include +DECLARE_TYPEOF_COLLECTION(AutoReplaceP); + // ----------------------------------------------------------------------------- : Extra types IMPLEMENT_REFLECTION_ENUM(CheckUpdates) { @@ -43,7 +46,7 @@ ColumnSettings::ColumnSettings() // dummy for ColumnSettings reflection ScriptValueP to_script(const ColumnSettings&) { return script_nil; } -IMPLEMENT_REFLECTION(ColumnSettings) { +IMPLEMENT_REFLECTION_NO_SCRIPT(ColumnSettings) { REFLECT(width); REFLECT(position); REFLECT(visible); @@ -53,9 +56,33 @@ GameSettings::GameSettings() : sort_cards_ascending(true) , images_export_filename(_("{card.name}.jpg")) , images_export_conflicts(CONFLICT_NUMBER_OVERWRITE) + , use_auto_replace(true) + , initialized(false) {} -IMPLEMENT_REFLECTION(GameSettings) { +void GameSettings::initDefaults(const Game& game) { + if (initialized) return; + initialized = true; + // init auto_replaces, copy from game file + FOR_EACH_CONST(ar, game.auto_replaces) { + // do we have this one? + bool already_have = false; + FOR_EACH(ar2, auto_replaces) { + if (ar->match == ar2->match) { + ar2->custom = false; + already_have = true; + break; + } + } + if (!already_have) { + // TODO: when we start saving games, clone here + ar->custom = false; + auto_replaces.push_back(ar); + } + } +} + +IMPLEMENT_REFLECTION_NO_SCRIPT(GameSettings) { REFLECT(default_stylesheet); REFLECT(default_export); REFLECT_N("cardlist columns", columns); @@ -63,6 +90,8 @@ IMPLEMENT_REFLECTION(GameSettings) { REFLECT(sort_cards_ascending); REFLECT(images_export_filename); REFLECT(images_export_conflicts); + REFLECT(use_auto_replace); + REFLECT(auto_replaces); } @@ -82,7 +111,7 @@ void StyleSheetSettings::useDefault(const StyleSheetSettings& ss) { if (card_normal_export.isDefault()) card_normal_export.assignDefault(ss.card_normal_export); } -IMPLEMENT_REFLECTION(StyleSheetSettings) { +IMPLEMENT_REFLECTION_NO_SCRIPT(StyleSheetSettings) { REFLECT(card_zoom); REFLECT(card_angle); REFLECT(card_anti_alias); @@ -127,6 +156,7 @@ void Settings::addRecentFile(const String& filename) { GameSettings& Settings::gameSettingsFor(const Game& game) { GameSettingsP& gs = game_settings[game.name()]; if (!gs) gs = new_intrusive(); + gs->initDefaults(game); return *gs; } ColumnSettings& Settings::columnSettingsFor(const Game& game, const Field& field) { @@ -165,7 +195,7 @@ String Settings::settingsFile() { return user_settings_dir() + _("mse8.config"); // use different file during development of C++ port } -IMPLEMENT_REFLECTION(Settings) { +IMPLEMENT_REFLECTION_NO_SCRIPT(Settings) { REFLECT_ALIAS(300, "style settings", "stylesheet settings"); REFLECT_ALIAS(300, "default style settings", "default stylesheet settings"); REFLECT(locale); diff --git a/src/data/settings.hpp b/src/data/settings.hpp index ad111fac..b4124e21 100644 --- a/src/data/settings.hpp +++ b/src/data/settings.hpp @@ -22,6 +22,7 @@ DECLARE_POINTER_TYPE(GameSettings); DECLARE_POINTER_TYPE(StyleSheetSettings); DECLARE_POINTER_TYPE(Field); DECLARE_POINTER_TYPE(Value); +DECLARE_POINTER_TYPE(AutoReplace); // ----------------------------------------------------------------------------- : Extra data structures @@ -56,6 +57,9 @@ class GameSettings : public IntrusivePtrBase { public: GameSettings(); + /// Where the settings have defaults, initialize with the values from the game + void initDefaults(const Game& g); + String default_stylesheet; String default_export; map columns; @@ -63,8 +67,12 @@ class GameSettings : public IntrusivePtrBase { bool sort_cards_ascending; String images_export_filename; FilenameConflicts images_export_conflicts; + bool use_auto_replace; + vector auto_replaces; ///< Things to autoreplace in textboxes DECLARE_REFLECTION(); + private: + bool initialized; }; /// Settings for a StyleSheet diff --git a/src/data/symbol.cpp b/src/data/symbol.cpp index 388999d1..4b562b4a 100644 --- a/src/data/symbol.cpp +++ b/src/data/symbol.cpp @@ -281,9 +281,16 @@ IMPLEMENT_REFLECTION(Symbol) { } double Symbol::aspectRatio() const { + // Margin between the edges and the symbol. + // In each direction take the lowest one + // This is at most 0.5 (if the symbol is just a line in the middle) + // Multiply by 2 (below) to give something in the range [0...1] i.e. [touches the edge...only in the middle] double margin_x = min(0.4999, max(0., min(min_pos.x, 1-max_pos.x))); double margin_y = min(0.4999, max(0., min(min_pos.y, 1-max_pos.y))); + // The difference between these two, + // e.g. if the vertical margin is more then the horizontal one, the symbol is 'flat' double delta = 2 * (margin_y - margin_x); + // The aspect ratio, i.e. width/height if (delta > 0) { return 1 / (1 - delta); } else { diff --git a/src/data/word_list.cpp b/src/data/word_list.cpp index 0cb5049f..2837ac1e 100644 --- a/src/data/word_list.cpp +++ b/src/data/word_list.cpp @@ -32,3 +32,18 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(WordList) { REFLECT(words); } + +// ----------------------------------------------------------------------------- : Auto replace words + +AutoReplace::AutoReplace() + : enabled(true) + , whole_word(true) + , custom(true) +{} + +IMPLEMENT_REFLECTION_NO_SCRIPT(AutoReplace) { + REFLECT(enabled); + REFLECT(whole_word); + REFLECT(match); + REFLECT(replace); +} diff --git a/src/data/word_list.hpp b/src/data/word_list.hpp index c2a34326..f60a24d9 100644 --- a/src/data/word_list.hpp +++ b/src/data/word_list.hpp @@ -14,6 +14,7 @@ DECLARE_POINTER_TYPE(WordListWord); DECLARE_POINTER_TYPE(WordList); +DECLARE_POINTER_TYPE(AutoReplace); // ----------------------------------------------------------------------------- : WordList @@ -38,6 +39,23 @@ class WordList : public WordListWord { DECLARE_REFLECTION(); }; +// ----------------------------------------------------------------------------- : Auto replace words + +/// Autoreplace specific shortcut words +class AutoReplace : public IntrusivePtrVirtualBase { + public: + AutoReplace(); + + bool enabled; + bool whole_word; + bool custom; ///< Is this a custom auto replace? + String match; + String replace; + + inline AutoReplaceP clone() const { return new_intrusive1(*this); } + + DECLARE_REFLECTION(); +}; // ----------------------------------------------------------------------------- : EOF #endif diff --git a/src/gui/set/window.cpp b/src/gui/set/window.cpp index 884c100d..f22463a7 100644 --- a/src/gui/set/window.cpp +++ b/src/gui/set/window.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -86,9 +87,10 @@ SetWindow::SetWindow(Window* parent, const SetP& set) menuEdit->Append(ID_EDIT_COPY, _("copy"), _MENU_("copy"), _HELP_("copy")); menuEdit->Append(ID_EDIT_PASTE, _("paste"), _MENU_("paste"), _HELP_("paste")); menuEdit->AppendSeparator(); - menuEdit->Append(ID_EDIT_FIND, _("find"), _MENU_("find"), _("")); - menuEdit->Append(ID_EDIT_FIND_NEXT, _MENU_("find next"), _("")); - menuEdit->Append(ID_EDIT_REPLACE, _MENU_("replace"), _("")); + menuEdit->Append(ID_EDIT_FIND, _("find"), _MENU_("find"), _HELP_("find")); + menuEdit->Append(ID_EDIT_FIND_NEXT, _MENU_("find next"), _HELP_("find next")); + menuEdit->Append(ID_EDIT_REPLACE, _MENU_("replace"), _HELP_("replace")); + menuEdit->Append(ID_EDIT_AUTO_REPLACE, _MENU_("auto replace"), _HELP_("auto replace")); menuEdit->AppendSeparator(); menuEdit->Append(ID_EDIT_PREFERENCES, _MENU_("preferences"), _HELP_("preferences")); menuBar->Append(menuEdit, _MENU_("edit")); @@ -619,6 +621,10 @@ void SetWindow::onReplaceAll(wxFindDialogEvent&) { current_panel->doReplaceAll(find_data); } +void SetWindow::onEditAutoReplace(wxCommandEvent&) { + (new AutoReplaceWindow(this, *set->game))->Show(); +} + void SetWindow::onEditPreferences(wxCommandEvent&) { PreferencesWindow wnd(this); if (wnd.ShowModal() == wxID_OK) { @@ -697,6 +703,7 @@ BEGIN_EVENT_TABLE(SetWindow, wxFrame) EVT_MENU (ID_EDIT_FIND, SetWindow::onEditFind) EVT_MENU (ID_EDIT_FIND_NEXT, SetWindow::onEditFindNext) EVT_MENU (ID_EDIT_REPLACE, SetWindow::onEditReplace) + EVT_MENU (ID_EDIT_AUTO_REPLACE, SetWindow::onEditAutoReplace) EVT_MENU (ID_EDIT_PREFERENCES, SetWindow::onEditPreferences) EVT_MENU (ID_WINDOW_NEW, SetWindow::onWindowNewWindow) EVT_TOOL_RANGE (ID_WINDOW_MIN, ID_WINDOW_MAX, SetWindow::onWindowSelect) diff --git a/src/gui/set/window.hpp b/src/gui/set/window.hpp index 9caaf02a..7d77c49a 100644 --- a/src/gui/set/window.hpp +++ b/src/gui/set/window.hpp @@ -131,6 +131,7 @@ class SetWindow : public wxFrame, public SetView { void onEditFind (wxCommandEvent&); void onEditFindNext (wxCommandEvent&); void onEditReplace (wxCommandEvent&); + void onEditAutoReplace (wxCommandEvent&); void onEditPreferences (wxCommandEvent&); void onFind (wxFindDialogEvent&); diff --git a/src/gui/value/text.cpp b/src/gui/value/text.cpp index 92080f76..b927e9de 100644 --- a/src/gui/value/text.cpp +++ b/src/gui/value/text.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,7 @@ DECLARE_SHARED_POINTER_TYPE(DropDownList); DECLARE_TYPEOF_COLLECTION(WordListP); DECLARE_TYPEOF_COLLECTION(WordListWordP); DECLARE_TYPEOF_COLLECTION(WordListPosP); +DECLARE_TYPEOF_COLLECTION(AutoReplaceP); // ----------------------------------------------------------------------------- : TextValueEditorScrollBar @@ -273,8 +275,8 @@ bool TextValueEditor::onMotion(const RealPoint& pos, wxMouseEvent& ev) { if (select_words) { // on the left, swap start and end bool left = selection_end_i < selection_start_i; - size_t next = nextWordBoundry(index); - size_t prev = prevWordBoundry(index); + size_t next = nextWordBoundary(index); + size_t prev = prevWordBoundary(index); if (( left && next > max(selection_start_i, selection_end_i)) || (!left && prev < min(selection_start_i, selection_end_i))) { left = !left; @@ -294,8 +296,8 @@ bool TextValueEditor::onLeftDClick(const RealPoint& pos, wxMouseEvent& ev) { select_words = true; selecting = true; size_t index = v.indexAt(style().getRotation().trInv(pos)); - moveSelection(TYPE_INDEX, prevWordBoundry(index), true, MOVE_MID); - moveSelection(TYPE_INDEX, nextWordBoundry(index), false, MOVE_MID); + moveSelection(TYPE_INDEX, prevWordBoundary(index), true, MOVE_MID); + moveSelection(TYPE_INDEX, nextWordBoundary(index), false, MOVE_MID); return true; } @@ -323,17 +325,17 @@ bool TextValueEditor::onChar(wxKeyEvent& ev) { case WXK_LEFT: // move left (selection?) if (ev.ControlDown()) { - moveSelection(TYPE_INDEX, prevWordBoundry(selection_end_i),!ev.ShiftDown(), MOVE_LEFT); + moveSelection(TYPE_INDEX, prevWordBoundary(selection_end_i),!ev.ShiftDown(), MOVE_LEFT); } else { - moveSelection(TYPE_CURSOR, prevCharBoundry(selection_end), !ev.ShiftDown(), MOVE_LEFT); + moveSelection(TYPE_CURSOR, prevCharBoundary(selection_end), !ev.ShiftDown(), MOVE_LEFT); } break; case WXK_RIGHT: // move left (selection?) if (ev.ControlDown()) { - moveSelection(TYPE_INDEX, nextWordBoundry(selection_end_i),!ev.ShiftDown(), MOVE_RIGHT); + moveSelection(TYPE_INDEX, nextWordBoundary(selection_end_i),!ev.ShiftDown(), MOVE_RIGHT); } else { - moveSelection(TYPE_CURSOR, nextCharBoundry(selection_end), !ev.ShiftDown(), MOVE_RIGHT); + moveSelection(TYPE_CURSOR, nextCharBoundary(selection_end), !ev.ShiftDown(), MOVE_RIGHT); } break; case WXK_UP: @@ -369,10 +371,10 @@ bool TextValueEditor::onChar(wxKeyEvent& ev) { case WXK_BACK: if (selection_start == selection_end) { // if no selection, select previous character - moveSelectionNoRedraw(TYPE_CURSOR, prevCharBoundry(selection_end), false); + moveSelectionNoRedraw(TYPE_CURSOR, prevCharBoundary(selection_end), false); if (selection_start == selection_end) { // Walk over a as if we are the LEFT key - moveSelection(TYPE_CURSOR, prevCharBoundry(selection_end), true, MOVE_LEFT); + moveSelection(TYPE_CURSOR, prevCharBoundary(selection_end), true, MOVE_LEFT); return true; } } @@ -381,10 +383,10 @@ bool TextValueEditor::onChar(wxKeyEvent& ev) { case WXK_DELETE: if (selection_start == selection_end) { // if no selection select next - moveSelectionNoRedraw(TYPE_CURSOR, nextCharBoundry(selection_end), false); + moveSelectionNoRedraw(TYPE_CURSOR, nextCharBoundary(selection_end), false); if (selection_start == selection_end) { // Walk over a as if we are the RIGHT key - moveSelection(TYPE_CURSOR, nextCharBoundry(selection_end), true, MOVE_RIGHT); + moveSelection(TYPE_CURSOR, nextCharBoundary(selection_end), true, MOVE_RIGHT); } } replaceSelection(wxEmptyString, _ACTION_("delete")); @@ -411,9 +413,9 @@ bool TextValueEditor::onChar(wxKeyEvent& ev) { // this might not work for internationalized input. // It might also not be portable! #ifdef UNICODE - replaceSelection(escape(String(ev.GetUnicodeKey(), 1)), _ACTION_("typing")); + replaceSelection(escape(String(ev.GetUnicodeKey(), 1)), _ACTION_("typing"), true); #else - replaceSelection(escape(String((Char)ev.GetKeyCode(), 1)), _ACTION_("typing")); + replaceSelection(escape(String((Char)ev.GetKeyCode(), 1)), _ACTION_("typing"), true); #endif } else { return false; @@ -775,7 +777,7 @@ size_t match_cursor_position(size_t pos1, const String& text1, size_t pos2, cons return 1000 * before + 2 * after - penalty; // matching 'before' is more important } -void TextValueEditor::replaceSelection(const String& replacement, const String& name) { +void TextValueEditor::replaceSelection(const String& replacement, const String& name, bool allow_auto_replace, bool select_on_undo) { if (replacement.empty() && selection_start == selection_end) { // no text selected, nothing to delete return; @@ -785,10 +787,10 @@ void TextValueEditor::replaceSelection(const String& replacement, const String& fixSelection(); // execute the action before adding it to the stack, // because we want to run scripts before action listeners see the action - TextValueAction* action = typing_action(valueP(), selection_start_i, selection_end_i, selection_start, selection_end, replacement, name); + TextValueAction* action = typing_action(valueP(), selection_start_i, selection_end_i, select_on_undo ? selection_start : selection_end, selection_end, replacement, name); if (!action) { // nothing changes, but move the selection anyway - moveSelection(TYPE_CURSOR, selection_start); + moveSelection(TYPE_CURSOR, selection_end); return; } // what we would expect if no scripts take place @@ -832,10 +834,31 @@ void TextValueEditor::replaceSelection(const String& replacement, const String& selection_end = selection_start = best_cursor; fixSelection(TYPE_CURSOR, MOVE_RIGHT); } + // auto replace after typing? + if (allow_auto_replace) tryAutoReplace(); // scroll with next update scroll_with_cursor = true; } +void TextValueEditor::tryAutoReplace() { + size_t end = selection_start_i; + GameSettings& gs = settings.gameSettingsFor(*getSet().game); + FOR_EACH(ar, gs.auto_replaces) { + if (ar->enabled && ar->match.size() <= end) { + size_t start = end - ar->match.size(); + if (is_substr(value().value(), start, ar->match) && + (!ar->whole_word || (isWordBoundary(start) && isWordBoundary(end))) + ) { + // replace + selection_start_i = start; + selection_end_i = end; + fixSelection(TYPE_INDEX); + replaceSelection(ar->replace, _ACTION_("auto replace"), false, false); + } + } + } +} + void TextValueEditor::moveSelection(IndexType t, size_t new_end, bool also_move_start, Movement dir) { size_t old_start = selection_start_i; size_t old_end = selection_end_i; @@ -891,28 +914,64 @@ void TextValueEditor::fixSelection(IndexType t, Movement dir) { } -size_t TextValueEditor::prevCharBoundry(size_t pos) const { +size_t TextValueEditor::prevCharBoundary(size_t pos) const { return max(0, (int)pos - 1); } -size_t TextValueEditor::nextCharBoundry(size_t pos) const { +size_t TextValueEditor::nextCharBoundary(size_t pos) const { return min(index_to_cursor(value().value(), String::npos), pos + 1); } -size_t TextValueEditor::prevWordBoundry(size_t pos_i) const { + +static const Char word_bound_chars[] = _(" ,.:;()\n"); +bool isWordBoundaryChar(Char c) { + return c == _(' ') || c == _(',') || c == _('.') || c == _(':') || c == _(';') || + c == _('(') || c == _(')') || c == _('\n') || isPunct(c); +} + +size_t TextValueEditor::prevWordBoundary(size_t pos_i) const { const String& val = value().value(); - size_t p = val.find_last_not_of(_(" ,.:;()\n"), max(0, (int)pos_i - 1)); + size_t p = val.find_last_not_of(word_bound_chars, max(0, (int)pos_i - 1)); if (p == String::npos) return 0; - p = val.find_last_of(_(" ,.:;()\n"), p); + p = val.find_last_of(word_bound_chars, p); if (p == String::npos) return 0; return p + 1; } -size_t TextValueEditor::nextWordBoundry(size_t pos_i) const { +size_t TextValueEditor::nextWordBoundary(size_t pos_i) const { const String& val = value().value(); - size_t p = val.find_first_of(_(" ,.:;()\n"), pos_i); + size_t p = val.find_first_of(word_bound_chars, pos_i); if (p == String::npos) return val.size(); - p = val.find_first_not_of(_(" ,.:;()\n"), p); + p = val.find_first_not_of(word_bound_chars, p); if (p == String::npos) return val.size(); return p; } +bool TextValueEditor::isWordBoundary(size_t pos_i) const { + const String& val = value().value(); + // boundary after? + size_t pos = pos_i; + while (true) { + if (pos >= val.size()) return true; + Char c = val.GetChar(pos); + if (c == _('<')) pos = skip_tag(val,pos); // skip tags + else if (isWordBoundaryChar(c)) return true; + else break; + } + // boundary before? + pos = pos_i; + while (true) { + if (pos == 0) return true; + Char c = val.GetChar(pos - 1); + if (c == _('>')) { + // (try to) skip tags in reverse + while (true) { + if (pos == 0) return false; // not a tag + --pos; + c = val.GetChar(pos - 1); + if (c == _('<')) { --pos; break; } // was a tag + else if (c == _('>')) return false; // was not a tag + } + } + else return isWordBoundaryChar(c); + } +} void TextValueEditor::select(size_t start, size_t end) { selection_start = start; @@ -1129,7 +1188,7 @@ void TextValueEditor::drawWordListIndicators(RotatedDC& dc) { if (current && wl->active) { dc.SetPen (Color(0, 128,255)); dc.SetBrush(Color(64, 160,255)); - } else if (current && selection_end_i >= wl->start && selection_end_i <= wl->end) { + } else if (current && selection_end_i >= wl->start && selection_end_i <= wl->end && !dropDownShown()) { dc.SetPen (Color(64, 160,255)); dc.SetBrush(Color(160,208,255)); } else { diff --git a/src/gui/value/text.hpp b/src/gui/value/text.hpp index b7ba49f1..5e01ff4e 100644 --- a/src/gui/value/text.hpp +++ b/src/gui/value/text.hpp @@ -116,7 +116,9 @@ class TextValueEditor : public TextValueViewer, public ValueEditor { /// Replace the current selection with 'replacement', name the action /** replacement should be a tagged string (i.e. already escaped) */ - void replaceSelection(const String& replacement, const String& name); + void replaceSelection(const String& replacement, const String& name, bool allow_auto_replace = false, bool select_on_undo = true); + /// Try to autoreplace at the position before the cursor + void tryAutoReplace(); /// Make sure the selection satisfies its constraints /** - selection_start and selection_end are inside the text @@ -135,12 +137,13 @@ class TextValueEditor : public TextValueViewer, public ValueEditor { /// Position of previous visible & selectable character /** Uses cursor positions */ - size_t prevCharBoundry(size_t pos) const; - size_t nextCharBoundry(size_t pos) const; + size_t prevCharBoundary(size_t pos) const; + size_t nextCharBoundary(size_t pos) const; /// Front of previous word, used witch Ctrl+Left/right /** Uses character indices */ - size_t prevWordBoundry(size_t pos_i) const; - size_t nextWordBoundry(size_t pos_i) const; + size_t prevWordBoundary(size_t pos_i) const; + size_t nextWordBoundary(size_t pos_i) const; + bool isWordBoundary(size_t pos_i) const; // --------------------------------------------------- : Scrolling diff --git a/src/mse.vcproj b/src/mse.vcproj index c3ebcdbc..8c2f38be 100644 --- a/src/mse.vcproj +++ b/src/mse.vcproj @@ -947,6 +947,12 @@ + + + + diff --git a/src/resource/common/expected_locale_keys b/src/resource/common/expected_locale_keys index 5de49511..d4184a60 100644 --- a/src/resource/common/expected_locale_keys +++ b/src/resource/common/expected_locale_keys @@ -1,495 +1,511 @@ -# This file contains the keys expected to be in MSE locales -# It was automatically generated by tools/locale/locale.pl -# Generated on Fri Aug 17 22:58:51 2007 - -action: - add control point: 0 - add part: 1 - add symmetry: 0 - backspace: 0 - change: 1 - change combine mode: 0 - change shape name: 0 - change symmetry copies: 0 - change symmetry type: 0 - convert to curve: 0 - convert to line: 0 - cut: 0 - delete: 0 - delete point: 0 - delete points: 0 - duplicate: 1 - enter: 0 - group parts: 0 - insert symbol: 0 - lock point: 0 - move: 1 - move curve: 0 - move handle: 0 - move symmetry center: 0 - move symmetry handle: 0 - paste: 0 - remove parts: 1 - reorder parts: 0 - rotate: 1 - scale: 1 - shear: 1 - soft line break: 0 - typing: 0 - ungroup parts: 0 -button: - always: 0 - browse: 0 - check now: 0 - close: 0 - edit symbol: 0 - hide: 0 - high quality: 0 - if internet connection exists: 0 - insert parameter: 0 - keep old: 0 - last opened set: 0 - move down: 0 - move up: 0 - never: 0 - new set: 0 - number: 0 - number overwrite: 0 - open set: 0 - overwrite: 0 - refer parameter: 0 - select: optional, 0 - select all: 0 - select none: 0 - show: 0 - show lines: 0 - symbol gallery: optional, 0 - use custom styling options: 0 - use for all cards: 0 - zoom export: 0 -error: - aborting parsing: 0 - can't convert: 2 - can't convert value: 3 - checking updates: 0 - checking updates failed: 0 - coordinates for blending overlap: 0 - dimension not found: 1 - expected key: 1 - file not found: 2 - file parse error: 2 - has no member: 2 - has no member value: 2 - images used for blending must have the same size: 0 - internal error: 1 - newer version: 2 - no game specified for the set: 0 - no packages: 0 - no stylesheet specified for the set: 0 - no updates: 0 - package not found: 1 - package out of date: 3 - stylesheet and set refer to different game: 0 - unable to open output file: 0 - unable to store file: 0 - unrecognized value: 1 - unsupported field type: 1 - unsupported fill type: 1 - unsupported format: 1 -help: - about: 0 - add card: 0 - add cards: 0 - add keyword: 0 - add symmetry: 0 - app language: 0 - basic shapes: 0 - bold: 0 - border: 0 - card list columns: 0 - cards tab: 0 - check updates: 0 - click to select shape: 0 - close symbol editor: 0 - copies: 0 - copy: 0 - copy card: 0 - copy keyword: 0 - curve segment: 0 - cut: 0 - cut card: 0 - cut keyword: 0 - difference: 0 - draft tab: optional, 0 - drag to draw shape: 0 - drag to move curve: 0 - drag to move line: 0 - drag to move point: 0 - drag to resize: 1 - drag to rotate: 1 - drag to shear: 1 - draw ellipse: 0 - draw polygon: 0 - draw rectangle: 0 - draw star: 0 - duplicate: 0 - ellipse: 0 - exit: 0 - export: 0 - export apprentice: 0 - export html: 0 - export image: 0 - export images: 0 - export mws: 0 - filename format: 0 - free point: 0 - grid: 0 - group: 0 - index: 0 - intersect: 0 - italic: 0 - keywords tab: 0 - last opened set: 1 - line segment: 0 - merge: 0 - new set: 0 - new symbol: 0 - new window: 0 - next card: 0 - next keyword: 0 - open set: 0 - open symbol: 0 - orientation: 0 - overlap: 0 - paint: 0 - paste: 0 - paste card: 0 - paste keyword: 0 - points: 0 - polygon: 0 - preferences: 0 - previous card: 0 - previous keyword: 0 - print: 0 - print preview: 0 - rectangle: 0 - redo: 0 - reflection: 0 - reload data: 0 - reminder text: 0 - remove card: 0 - remove keyword: 0 - remove symmetry: 0 - rotate: 0 - rotate 0: 0 - rotate 180: 0 - rotate 270: 0 - rotate 90: 0 - rotate card: 0 - rotation: 0 - save set: 0 - save set as: 0 - save symbol: 0 - save symbol as: 0 - select: 0 - set code: 0 - set info tab: 0 - sides: 0 - smooth point: 0 - snap: 0 - star: 0 - stats tab: 0 - store symbol: 0 - style tab: 0 - subtract: 0 - symbols: 0 - symmetric point: 0 - symmetry: 0 - undo: 0 - ungroup: 0 - website: 0 - welcome: 0 - zoom export: 0 -label: - app language: 0 - apprentice: 0 - apprentice exe: 0 - apprentice export cancelled: 0 - card display: 0 - card notes: 0 - cards to export: 0 - check at startup: 0 - checking requires internet: 0 - columns: 0 - export filenames: 0 - external programs: 0 - filename conflicts: 0 - filename format: 0 - filename is ignored: 0 - filter: 0 - game type: 0 - html export options: 0 - html template: 0 - keyword: 0 - language: 0 - match: 0 - mode: 0 - original: 0 - percent of normal: 0 - reminder: 0 - result: 0 - save changes: 1 - select cards print: 0 - select columns: 0 - selection: 0 - set code: 0 - sides: optional, 0 - size: 0 - standard keyword: 1 - style type: 0 - styling options: 0 - uses: 0 - zoom: 0 -menu: - about: 0 - add card: 0 - add cards: 0 - add keyword: 0 - basic shapes: 0 - bold: 0 - card list columns: 0 - cards: 0 - cards tab: 0 - check updates: 0 - close symbol editor: 0 - copy: 0 - cut: 0 - draft tab: optional, 0 - duplicate: 0 - edit: 0 - exit: 0 - export: 0 - export apprentice: 0 - export html: 0 - export image: 0 - export images: 0 - export mws: 0 - file: 0 - find: 0 - find next: 0 - format: 0 - group: 0 - help: 0 - index: 0 - insert symbol: 0 - italic: 0 - keywords: 0 - keywords tab: 0 - new set: 0 - new symbol: 0 - new window: 0 - next card: 0 - next keyword: 0 - open set: 0 - open symbol: 0 - orientation: 0 - paint: 0 - paste: 0 - points: 0 - preferences: 0 - previous card: 0 - previous keyword: 0 - print: 0 - print preview: 0 - redo: 1 - reload data: 0 - reminder text: 0 - remove card: 0 - remove keyword: 0 - replace: 0 - rotate: 0 - rotate 0: 0 - rotate 180: 0 - rotate 270: 0 - rotate 90: 0 - save set: 0 - save set as: 0 - save symbol: 0 - save symbol as: 0 - select: 0 - set info tab: 0 - stats tab: 0 - store symbol: 0 - style tab: 0 - symbols: 0 - symmetry: 0 - tool: 0 - undo: 1 - ungroup: 0 - website: 0 - window: 0 -title: - %s - magic set editor: 1 - about: 0 - directories: 0 - display: 0 - export cancelled: 0 - export html: 0 - export images: 0 - global: 0 - locate apprentice: 0 - magic set editor: 0 - new status: 0 - open set: 0 - package list: 0 - package name: 0 - package status: 0 - preferences: 0 - print preview: 0 - save changes: 0 - save html: 0 - save image: 0 - save set: 0 - select cards: 0 - select cards export: 0 - select columns: 0 - slice image: 0 - symbol editor: 0 - untitled: 0 - update check: 0 - updates: 0 - updates availible: 0 -tool: - add symmetry: 0 - basic shapes: 0 - border: 0 - cards tab: 0 - curve segment: 0 - difference: 0 - draft tab: optional, 0 - ellipse: 0 - free point: 0 - grid: 0 - intersect: 0 - keywords tab: 0 - line segment: 0 - merge: 0 - overlap: 0 - paint: optional, 0 - points: 0 - polygon: 0 - rectangle: 0 - redo: 0 - reflection: 0 - remove symmetry: 0 - rotate: 0 - rotation: 0 - select: 0 - set info tab: 0 - smooth point: 0 - snap: 0 - star: 0 - stats tab: 0 - store symbol: 0 - style tab: 0 - subtract: 0 - symmetric point: 0 - symmetry: 0 - undo: 0 -tooltip: - add card: 0 - add keyword: 0 - add symmetry: 0 - basic shapes: 0 - bold: 0 - border: 0 - cards tab: 0 - copy: 0 - curve segment: 0 - cut: 0 - difference: 0 - draft tab: optional, 0 - ellipse: 0 - export: 0 - free point: 0 - grid: 0 - intersect: 0 - italic: 0 - keywords tab: 0 - line segment: 0 - merge: 0 - new set: 0 - open set: 0 - overlap: 0 - paint: optional, 0 - paste: 0 - points: 0 - polygon: 0 - rectangle: 0 - redo: 1 - reflection: 0 - reminder text: 0 - remove card: 0 - remove keyword: 0 - remove symmetry: 0 - rotate: 0 - rotate card: 0 - rotation: 0 - save set: 0 - select: 0 - set info tab: 0 - smooth point: 0 - snap: 0 - star: 0 - stats tab: 0 - store symbol: 0 - style tab: 0 - subtract: 0 - symbols: 0 - symmetric point: 0 - symmetry: 0 - undo: 1 -type: - boolean: 0 - card: 0 - circle: 0 - collection: 0 - collection of: 1 - color: 0 - do nothing: 0 - double: 0 - ellipse: 0 - field: 0 - function: 0 - game: 0 - group: 0 - hexagon: 0 - image: 0 - install: 0 - installed: 0 - integer: 0 - new mse: 0 - nil: 0 - object: 0 - pentagon: 0 - point: 0 - points: 0 - polygon: 0 - rectangle: 0 - reflection: 0 - rhombus: 0 - rotation: 0 - set: 0 - shape: 0 - shapes: 0 - square: 0 - star: 0 - string: 0 - style: 0 - stylesheet: 0 - triangle: 0 - uninstall: 0 - uninstalled: 0 - upgrade: 0 - upgradeable: 0 - value: 0 +# This file contains the keys expected to be in MSE locales +# It was automatically generated by tools/locale/locale.pl +# Generated on Sun Aug 26 21:17:38 2007 + +action: + add control point: 0 + add part: 1 + add symmetry: 0 + auto replace: 0 + backspace: 0 + change: 1 + change combine mode: 0 + change shape name: 0 + change symmetry copies: 0 + change symmetry type: 0 + convert to curve: 0 + convert to line: 0 + cut: 0 + delete: 0 + delete point: 0 + delete points: 0 + duplicate: 1 + enter: 0 + group parts: 0 + insert symbol: 0 + lock point: 0 + move: 1 + move curve: 0 + move handle: 0 + move symmetry center: 0 + move symmetry handle: 0 + paste: 0 + remove parts: 1 + reorder parts: 0 + rotate: 1 + scale: 1 + shear: 1 + soft line break: 0 + typing: 0 + ungroup parts: 0 +button: + add item: 0 + always: 0 + browse: 0 + check now: 0 + close: 0 + defaults: 0 + edit symbol: 0 + enabled: 0 + hide: 0 + high quality: 0 + if internet connection exists: 0 + insert parameter: 0 + keep old: 0 + last opened set: 0 + move down: 0 + move up: 0 + never: 0 + new set: 0 + number: 0 + number overwrite: 0 + open set: 0 + overwrite: 0 + refer parameter: 0 + remove item: 0 + select: optional, 0 + select all: 0 + select none: 0 + show: 0 + show lines: 0 + symbol gallery: optional, 0 + use auto replace: 0 + use custom styling options: 0 + use for all cards: 0 + whole word: 0 + zoom export: 0 +error: + aborting parsing: 0 + can't convert: 2 + can't convert value: 3 + checking updates: 0 + checking updates failed: 0 + coordinates for blending overlap: 0 + dimension not found: 1 + expected key: 1 + file not found: 2 + file parse error: 2 + has no member: 2 + has no member value: 2 + images used for blending must have the same size: 0 + internal error: 1 + newer version: 2 + no game specified for the set: 0 + no packages: 0 + no stylesheet specified for the set: 0 + no updates: 0 + package not found: 1 + package out of date: 3 + stylesheet and set refer to different game: 0 + unable to open output file: 0 + unable to store file: 0 + unrecognized value: 1 + unsupported field type: 1 + unsupported fill type: 1 + unsupported format: 1 + word list type not found: 1 +help: + about: 0 + add card: 0 + add cards: 0 + add keyword: 0 + add symmetry: 0 + app language: 0 + auto replace: 0 + basic shapes: 0 + bold: 0 + border: 0 + card list columns: 0 + cards tab: 0 + check updates: 0 + click to select shape: 0 + close symbol editor: 0 + copies: 0 + copy: 0 + copy card: 0 + copy keyword: 0 + curve segment: 0 + cut: 0 + cut card: 0 + cut keyword: 0 + difference: 0 + draft tab: optional, 0 + drag to draw shape: 0 + drag to move curve: 0 + drag to move line: 0 + drag to move point: 0 + drag to resize: 1 + drag to rotate: 1 + drag to shear: 1 + draw ellipse: 0 + draw polygon: 0 + draw rectangle: 0 + draw star: 0 + duplicate: 0 + ellipse: 0 + exit: 0 + export: 0 + export apprentice: 0 + export html: 0 + export image: 0 + export images: 0 + export mws: 0 + filename format: 0 + find: 0 + find next: 0 + free point: 0 + grid: 0 + group: 0 + index: 0 + intersect: 0 + italic: 0 + keywords tab: 0 + last opened set: 1 + line segment: 0 + merge: 0 + new set: 0 + new symbol: 0 + new window: 0 + next card: 0 + next keyword: 0 + open set: 0 + open symbol: 0 + orientation: 0 + overlap: 0 + paint: 0 + paste: 0 + paste card: 0 + paste keyword: 0 + points: 0 + polygon: 0 + preferences: 0 + previous card: 0 + previous keyword: 0 + print: 0 + print preview: 0 + rectangle: 0 + redo: 0 + reflection: 0 + reload data: 0 + reminder text: 0 + remove card: 0 + remove keyword: 0 + remove symmetry: 0 + replace: 0 + rotate: 0 + rotate 0: 0 + rotate 180: 0 + rotate 270: 0 + rotate 90: 0 + rotate card: 0 + rotation: 0 + save set: 0 + save set as: 0 + save symbol: 0 + save symbol as: 0 + select: 0 + set code: 0 + set info tab: 0 + sides: 0 + smooth point: 0 + snap: 0 + star: 0 + stats tab: 0 + store symbol: 0 + style tab: 0 + subtract: 0 + symbols: 0 + symmetric point: 0 + symmetry: 0 + undo: 0 + ungroup: 0 + website: 0 + welcome: 0 + zoom export: 0 +label: + app language: 0 + apprentice: 0 + apprentice exe: 0 + apprentice export cancelled: 0 + auto match: 0 + auto replace: 0 + card display: 0 + card notes: 0 + cards to export: 0 + check at startup: 0 + checking requires internet: 0 + columns: 0 + export filenames: 0 + external programs: 0 + filename conflicts: 0 + filename format: 0 + filename is ignored: 0 + filter: 0 + game type: 0 + html export options: 0 + html template: 0 + keyword: 0 + language: 0 + match: 0 + mode: 0 + original: 0 + percent of normal: 0 + reminder: 0 + result: 0 + save changes: 1 + select cards print: 0 + select columns: 0 + selection: 0 + set code: 0 + sides: optional, 0 + size: 0 + standard keyword: 1 + style type: 0 + styling options: 0 + uses: 0 + zoom: 0 +menu: + about: 0 + add card: 0 + add cards: 0 + add keyword: 0 + auto replace: 0 + basic shapes: 0 + bold: 0 + card list columns: 0 + cards: 0 + cards tab: 0 + check updates: 0 + close symbol editor: 0 + copy: 0 + cut: 0 + draft tab: optional, 0 + duplicate: 0 + edit: 0 + exit: 0 + export: 0 + export apprentice: 0 + export html: 0 + export image: 0 + export images: 0 + export mws: 0 + file: 0 + find: 0 + find next: 0 + format: 0 + group: 0 + help: 0 + index: 0 + insert symbol: 0 + italic: 0 + keywords: 0 + keywords tab: 0 + new set: 0 + new symbol: 0 + new window: 0 + next card: 0 + next keyword: 0 + open set: 0 + open symbol: 0 + orientation: 0 + paint: 0 + paste: 0 + points: 0 + preferences: 0 + previous card: 0 + previous keyword: 0 + print: 0 + print preview: 0 + redo: 1 + reload data: 0 + reminder text: 0 + remove card: 0 + remove keyword: 0 + replace: 0 + rotate: 0 + rotate 0: 0 + rotate 180: 0 + rotate 270: 0 + rotate 90: 0 + save set: 0 + save set as: 0 + save symbol: 0 + save symbol as: 0 + select: 0 + set info tab: 0 + stats tab: 0 + store symbol: 0 + style tab: 0 + symbols: 0 + symmetry: 0 + tool: 0 + undo: 1 + ungroup: 0 + website: 0 + window: 0 +title: + %s - magic set editor: 1 + about: 0 + auto replaces: 0 + directories: 0 + display: 0 + export cancelled: 0 + export html: 0 + export images: 0 + global: 0 + locate apprentice: 0 + magic set editor: 0 + new status: 0 + open set: 0 + package list: 0 + package name: 0 + package status: 0 + preferences: 0 + print preview: 0 + save changes: 0 + save html: 0 + save image: 0 + save set: 0 + select cards: 0 + select cards export: 0 + select columns: 0 + slice image: 0 + symbol editor: 0 + untitled: 0 + update check: 0 + updates: 0 + updates availible: 0 +tool: + add symmetry: 0 + basic shapes: 0 + border: 0 + cards tab: 0 + curve segment: 0 + difference: 0 + draft tab: optional, 0 + ellipse: 0 + free point: 0 + grid: 0 + intersect: 0 + keywords tab: 0 + line segment: 0 + merge: 0 + overlap: 0 + paint: optional, 0 + points: 0 + polygon: 0 + rectangle: 0 + redo: 0 + reflection: 0 + remove symmetry: 0 + rotate: 0 + rotation: 0 + select: 0 + set info tab: 0 + smooth point: 0 + snap: 0 + star: 0 + stats tab: 0 + store symbol: 0 + style tab: 0 + subtract: 0 + symmetric point: 0 + symmetry: 0 + undo: 0 +tooltip: + add card: 0 + add keyword: 0 + add symmetry: 0 + basic shapes: 0 + bold: 0 + border: 0 + cards tab: 0 + copy: 0 + curve segment: 0 + cut: 0 + difference: 0 + draft tab: optional, 0 + ellipse: 0 + export: 0 + free point: 0 + grid: 0 + intersect: 0 + italic: 0 + keywords tab: 0 + line segment: 0 + merge: 0 + new set: 0 + open set: 0 + overlap: 0 + paint: optional, 0 + paste: 0 + points: 0 + polygon: 0 + rectangle: 0 + redo: 1 + reflection: 0 + reminder text: 0 + remove card: 0 + remove keyword: 0 + remove symmetry: 0 + rotate: 0 + rotate card: 0 + rotation: 0 + save set: 0 + select: 0 + set info tab: 0 + smooth point: 0 + snap: 0 + star: 0 + stats tab: 0 + store symbol: 0 + style tab: 0 + subtract: 0 + symbols: 0 + symmetric point: 0 + symmetry: 0 + undo: 1 +type: + boolean: 0 + card: 0 + circle: 0 + collection: 0 + collection of: 1 + color: 0 + do nothing: 0 + double: 0 + ellipse: 0 + field: 0 + function: 0 + game: 0 + group: 0 + hexagon: 0 + image: 0 + install: 0 + installed: 0 + integer: 0 + new mse: 0 + nil: 0 + object: 0 + pentagon: 0 + point: 0 + points: 0 + polygon: 0 + rectangle: 0 + reflection: 0 + rhombus: 0 + rotation: 0 + set: 0 + shape: 0 + shapes: 0 + square: 0 + star: 0 + string: 0 + style: 0 + stylesheet: 0 + triangle: 0 + uninstall: 0 + uninstalled: 0 + upgrade: 0 + upgradeable: 0 + value: 0 diff --git a/src/util/io/writer.cpp b/src/util/io/writer.cpp index 0905150b..b1ad9b84 100644 --- a/src/util/io/writer.cpp +++ b/src/util/io/writer.cpp @@ -64,8 +64,8 @@ void Writer::handle(const String& value) { // write indentation and key writeKey(); writeUTF8(stream, _(": ")); - if (value.find_first_of(_('\n')) != String::npos) { - // multiline string + if (value.find_first_of(_('\n')) != String::npos || (!value.empty() && isSpace(value.GetChar(0)))) { + // multiline string, or contains leading whitespace stream.PutChar(_('\n')); indentation += 1; // split lines, and write each line diff --git a/src/util/window_id.hpp b/src/util/window_id.hpp index 5315476c..c94eaf2c 100644 --- a/src/util/window_id.hpp +++ b/src/util/window_id.hpp @@ -53,7 +53,8 @@ enum MenuID { , ID_EDIT_FIND = wxID_FIND , ID_EDIT_FIND_NEXT = 103 , ID_EDIT_REPLACE = wxID_REPLACE -, ID_EDIT_PREFERENCES = 104 +, ID_EDIT_AUTO_REPLACE = 104 +, ID_EDIT_PREFERENCES = 105 // Window menu (MainWindow) , ID_WINDOW_NEW = 201 @@ -242,7 +243,13 @@ enum ControlID { , ID_INSTALL , ID_UPGRADE , ID_REMOVE -, ID_CANCEL +, ID_CANCEL = wxID_CANCEL + // Auto replace window +, ID_USE_AUTO_REPLACE +, ID_ITEM_VALUE +, ID_ADD_ITEM +, ID_REMOVE_ITEM +, ID_DEFAULTS }; // ----------------------------------------------------------------------------- : EOF diff --git a/tools/gen.pl b/tools/gen.pl index c4be239f..ea9fbf3b 100644 --- a/tools/gen.pl +++ b/tools/gen.pl @@ -16,7 +16,7 @@ close F; # insert stuff -$hpp =~ s/_\n/_$macro\n/g; +$hpp =~ s/_\r?\n/_$macro\n/g; $cpp =~ s@@<$file.hpp>@g;