diff --git a/Source/Core/Controls/Scripting/ScriptEditorPanel.cs b/Source/Core/Controls/Scripting/ScriptEditorPanel.cs index 0df47275..12a10d77 100755 --- a/Source/Core/Controls/Scripting/ScriptEditorPanel.cs +++ b/Source/Core/Controls/Scripting/ScriptEditorPanel.cs @@ -404,6 +404,100 @@ namespace CodeImp.DoomBuilder.Controls #region ================== Methods + // [ZZ] Find and Replace + // This needs to be done in the script editor class, because we don't want to loop over the same value + // And for this, we need to know the context properly, not just "while FindNext && Replace". + // Which means there should be a function that does both find and replace manually. + public int FindReplace(FindReplaceOptions options) + { + // [ZZ] why do we require current tab for "find everywhere" and "replace everywhere"? + // todo: understand and refactor + // + // [ZZ] note: if we want CURRENT_*, error out if no active tab. + FindReplaceOptions singlesearchoptions = new FindReplaceOptions(options) { SearchMode = FindReplaceSearchMode.CURRENT_FILE }; + List rtabs = new List(); + switch (options.SearchMode) + { + // we really need a bitfield here. Whatever. + case FindReplaceSearchMode.CURRENT_FILE: + if (ActiveTab == null) + return 0; + rtabs.Add(ActiveTab); + break; + + case FindReplaceSearchMode.OPENED_TABS_CURRENT_SCRIPT_TYPE: + if (ActiveTab == null) + return 0; + // .NET is heavily retarded + goto case FindReplaceSearchMode.OPENED_TABS_ALL_SCRIPT_TYPES; + case FindReplaceSearchMode.OPENED_TABS_ALL_SCRIPT_TYPES: + foreach (ScriptDocumentTab tab in tabs.TabPages) + { + if (options.SearchMode == FindReplaceSearchMode.OPENED_TABS_ALL_SCRIPT_TYPES || + tab.Config.ScriptType == ActiveTab.Config.ScriptType) rtabs.Add(tab); + } + break; + + case FindReplaceSearchMode.CURRENT_PROJECT_CURRENT_SCRIPT_TYPE: + if (ActiveTab == null) + return 0; + // .NET is heavily retarded + goto case FindReplaceSearchMode.CURRENT_PROJECT_ALL_SCRIPT_TYPES; + case FindReplaceSearchMode.CURRENT_PROJECT_ALL_SCRIPT_TYPES: + // Just search among all resources + var usedscripttypes = new List(General.Map.Data.ScriptResources.Keys); + for (int i = 0; i < usedscripttypes.Count; i++) + { + if (options.SearchMode != FindReplaceSearchMode.CURRENT_PROJECT_ALL_SCRIPT_TYPES && + usedscripttypes[i] != ActiveTab.Config.ScriptType) continue; // [ZZ] skip irrelevant script types + foreach (ScriptResource sr in General.Map.Data.ScriptResources[usedscripttypes[i]]) + { + if (!sr.IsReadOnly && sr.ContainsText(singlesearchoptions)) + { + // open this tab + var newtab = OpenResource(sr); + rtabs.Add(newtab); + } + } + } + break; + } + + int replacements = 0; + foreach (ScriptDocumentTab tab in rtabs) + { + // do find/replace in the current tab. + // make sure that we don't find the same thing twice in case replacement has part of it's value. + int firstPosition = -1; + int lengthDifference = options.ReplaceWith.Length - options.FindText.Length; + int lastSelectionStart = -1; + int lastSelectionEnd = -1; + while (true) + { + if (!tab.FindNext(singlesearchoptions)) + break; + if (firstPosition < 0) + firstPosition = tab.SelectionStart; + else if (tab.SelectionStart == firstPosition) // found the first + { + tab.SelectionStart = lastSelectionStart; + tab.SelectionEnd = lastSelectionEnd; + break; + } + if (tab.SelectionStart < firstPosition) // offset the first position with string length difference if we are replacing before it. + firstPosition += lengthDifference; + // do replacement + tab.ReplaceSelection(options.ReplaceWith); + // + lastSelectionStart = tab.SelectionStart; + lastSelectionEnd = tab.SelectionEnd; + replacements++; + } + } + + return replacements; + } + // Find Next public bool FindNext(FindReplaceOptions options) { diff --git a/Source/Core/Windows/ScriptFindReplaceForm.cs b/Source/Core/Windows/ScriptFindReplaceForm.cs index cb9c540c..a67a34d3 100755 --- a/Source/Core/Windows/ScriptFindReplaceForm.cs +++ b/Source/Core/Windows/ScriptFindReplaceForm.cs @@ -313,17 +313,18 @@ namespace CodeImp.DoomBuilder.Windows AddComboboxText(replacebox, options.ReplaceWith); // Find next match + // [ZZ] why are we doing this? we aren't limited to the current tab..... + /* ScriptDocumentTab curtab = editor.ActiveTab; if(curtab == null || !curtab.FindNext(options, true)) { editor.DisplayStatus(ScriptStatusType.Warning, "Can't find any occurrence of \"" + options.FindText + "\"."); return; - } + }*/ - // Replace loop - int replacements = 0; - while(editor.FindNext(options) && editor.Replace(options)) - replacements++; + // Replace loop + // We don't really want to do this outside of the script editor. + int replacements = editor.FindReplace(options); // Show result if(replacements == 0) @@ -333,9 +334,9 @@ namespace CodeImp.DoomBuilder.Windows else { editor.DisplayStatus(ScriptStatusType.Info, "Replaced " + replacements + " occurrences of \"" + options.FindText + "\" with \"" + options.ReplaceWith + "\"."); - - // Find & select the last match on the now-current tab - curtab = editor.ActiveTab; + + // Find & select the last match on the now-current tab + ScriptDocumentTab curtab = editor.ActiveTab; if(curtab != null) { options.FindText = options.ReplaceWith;