mirror of
https://git.do.srb2.org/STJr/UltimateZoneBuilder.git
synced 2024-11-23 04:12:12 +00:00
Fixed: Find&Replace in Script Editor would go into an infinite loop if replacement contains the searched text
This commit is contained in:
parent
db1db76b4b
commit
123145085f
2 changed files with 103 additions and 8 deletions
|
@ -404,6 +404,100 @@ namespace CodeImp.DoomBuilder.Controls
|
||||||
|
|
||||||
#region ================== Methods
|
#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<ScriptDocumentTab> rtabs = new List<ScriptDocumentTab>();
|
||||||
|
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<ScriptType>(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
|
// Find Next
|
||||||
public bool FindNext(FindReplaceOptions options)
|
public bool FindNext(FindReplaceOptions options)
|
||||||
{
|
{
|
||||||
|
|
|
@ -313,17 +313,18 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
AddComboboxText(replacebox, options.ReplaceWith);
|
AddComboboxText(replacebox, options.ReplaceWith);
|
||||||
|
|
||||||
// Find next match
|
// Find next match
|
||||||
|
// [ZZ] why are we doing this? we aren't limited to the current tab.....
|
||||||
|
/*
|
||||||
ScriptDocumentTab curtab = editor.ActiveTab;
|
ScriptDocumentTab curtab = editor.ActiveTab;
|
||||||
if(curtab == null || !curtab.FindNext(options, true))
|
if(curtab == null || !curtab.FindNext(options, true))
|
||||||
{
|
{
|
||||||
editor.DisplayStatus(ScriptStatusType.Warning, "Can't find any occurrence of \"" + options.FindText + "\".");
|
editor.DisplayStatus(ScriptStatusType.Warning, "Can't find any occurrence of \"" + options.FindText + "\".");
|
||||||
return;
|
return;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// Replace loop
|
// Replace loop
|
||||||
int replacements = 0;
|
// We don't really want to do this outside of the script editor.
|
||||||
while(editor.FindNext(options) && editor.Replace(options))
|
int replacements = editor.FindReplace(options);
|
||||||
replacements++;
|
|
||||||
|
|
||||||
// Show result
|
// Show result
|
||||||
if(replacements == 0)
|
if(replacements == 0)
|
||||||
|
@ -333,9 +334,9 @@ namespace CodeImp.DoomBuilder.Windows
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
editor.DisplayStatus(ScriptStatusType.Info, "Replaced " + replacements + " occurrences of \"" + options.FindText + "\" with \"" + options.ReplaceWith + "\".");
|
editor.DisplayStatus(ScriptStatusType.Info, "Replaced " + replacements + " occurrences of \"" + options.FindText + "\" with \"" + options.ReplaceWith + "\".");
|
||||||
|
|
||||||
// Find & select the last match on the now-current tab
|
// Find & select the last match on the now-current tab
|
||||||
curtab = editor.ActiveTab;
|
ScriptDocumentTab curtab = editor.ActiveTab;
|
||||||
if(curtab != null)
|
if(curtab != null)
|
||||||
{
|
{
|
||||||
options.FindText = options.ReplaceWith;
|
options.FindText = options.ReplaceWith;
|
||||||
|
|
Loading…
Reference in a new issue