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
|
||||
|
||||
// [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
|
||||
public bool FindNext(FindReplaceOptions options)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
@ -334,8 +335,8 @@ namespace CodeImp.DoomBuilder.Windows
|
|||
{
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue