#region ================== Namespaces using System; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; using CodeImp.DoomBuilder.Config; using CodeImp.DoomBuilder.Controls; using CodeImp.DoomBuilder.Windows; #endregion namespace CodeImp.DoomBuilder.Data.Scripting { public sealed class ScriptResource { #region ================== Variables private string filename; private string filepathname; private string resourcedisplayname; private int lumpindex = -1; private DataReader resource; private string resourcepath; private HashSet entries; private ScriptType scripttype; private bool isreadonly; // Special cases... private string parentresourcelocation; #endregion #region ================== Properties public string Filename { get { return filename; } } // Path to text file inside of Resource public string FilePathName { get { return filepathname; } } // Resource location and file path inside resource combined public int LumpIndex { get { return lumpindex; } } // Text lump index if Resource is wad, -1 otherwise internal DataReader Resource { get { return GetResource(); } } public HashSet Entries { get { return entries; } } // Actors/models/sounds etc. public ScriptType ScriptType { get { return scripttype; } } public bool IsReadOnly { get { return isreadonly; } } #endregion #region ================== Constructor public ScriptResource(TextResourceData source, ScriptType type) { resource = source.Source; resourcepath = resource.Location.location; resourcedisplayname = resource.Location.GetDisplayName(); filename = source.Filename.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); filepathname = Path.Combine(resourcepath, filename); entries = new HashSet(StringComparer.OrdinalIgnoreCase); lumpindex = source.LumpIndex; scripttype = type; isreadonly = resource.IsReadOnly; // Embedded resources require additional tender loving care... if(resource is WADReader) { WADReader wr = (WADReader)resource; if(wr.ParentResource is PK3Reader) parentresourcelocation = wr.ParentResource.Location.location; } } #endregion #region ================== Methods internal bool ContainsText(FindReplaceOptions options) { // Get text DataReader res = GetResource(); if(res == null) return false; MemoryStream stream = res.LoadFile(filename, lumpindex); if(stream != null) { // Add word boundary delimiter? string findtext = (options.WholeWord ? "\\b" + options.FindText + "\\b" : options.FindText); RegexOptions ro = (options.CaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase); Regex regex = new Regex(findtext, ro); using(StreamReader reader = new StreamReader(stream, ScriptEditorControl.Encoding)) { while(!reader.EndOfStream) { if(regex.IsMatch(reader.ReadLine())) return true; } } } // No dice... return false; } // Finds text occurencies in the resource. Whole word / ignode case only. internal List FindUsages(FindReplaceOptions options) { var result = new List(); // Get text DataReader res = GetResource(); if(res == null) return result; MemoryStream stream = res.LoadFile(filename, lumpindex); if(stream != null) { // Add word boundary delimiter string findtext = (options.WholeWord ? "\\b" + options.FindText + "\\b" : options.FindText); Regex regex = new Regex(findtext, (options.CaseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase)); using(StreamReader reader = new StreamReader(stream, ScriptEditorControl.Encoding)) { int lineindex = 0; while(!reader.EndOfStream) { string line = reader.ReadLine(); foreach(Match match in regex.Matches(line)) result.Add(new FindUsagesResult(this, match, line, lineindex)); lineindex++; } } } return result; } private DataReader GetResource() { if(resource == null || resource.IsDisposed) { resource = null; // Try to re-aquire resource if(!string.IsNullOrEmpty(parentresourcelocation)) { // Special case: WAD resource inside of PK3 resource. // Resource resourcepath will be different after reloading resources, because it's randomly generated. // So resolve using displayname and parent resource location... foreach(DataReader reader in General.Map.Data.Containers) { // Found parent if(reader.Location.location == parentresourcelocation && reader is PK3Reader) { PK3Reader pr = (PK3Reader)reader; foreach(WADReader wr in pr.Wads) { if(wr.Location.GetDisplayName() == resourcedisplayname) { // Found it resource = reader; // Some paths need updating... resourcepath = resource.Location.location; filepathname = Path.Combine(resourcepath, filename); break; } } } } } else { foreach(DataReader reader in General.Map.Data.Containers) { if(reader.Location.location == resourcepath) { // Found it resource = reader; break; } } } } return resource; } // Used as tab and script navigator item title public override string ToString() { return (lumpindex != -1 ? lumpindex + ":" : "") + Path.GetFileName(filename); } #endregion } }