#region Top Part //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // Smesa > SearchReplace.cs from EditMenu //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // v5.2.8.19 31-May Search Actions Design. // v5.2.9.19 June 2019, Ready Mods ++ Search // v5.2.9.20 07-June Integration w/MyEditor! // v5.3.0.21 10-June Brought MySearchType & // SearchCom into SearchForm Class. // v5.3.0.21 15-June Getting Serious Now! // v5.3.0.22 22-Jun-2019 Almost Beyond PB // Search groups and back to Smesa side but // it's difficult to Debug w/ all the IPC // and auxiliary Apps interacting beyond // my Debugger's Focus. // v5.3.1.23 25-Jun Coming Together! Rev-1; // v5.3.1.24 02-Jul-2019 Search Integration. // v5.3.1.25 10-July SearchForm Features plus. // MajDesRev3: // v5.3.3.27 15-July-2019 (start MDR3) // v5.3.3.27 20-July-2019 4 way comms. // v5.3.3.28 21-July SmesaSearch.cs rockin' // -=[ Design Revision 4 ]=- My Custom Type. // v5.3.4.29 25-Jul-2019 Spelling things out // Class{in-Class{in-Class}}; Custom Types: // v5.3.5.30 30-July ReCoded4 WorkList2 // v5.3.5.31 03-Aug ReCoded4 WorkList2 // v5.4.5.32 07-Aug-2019 Search & Replace. // v5.4.5.34 18-Aug Cleanup & Move into SS2 // v5.4.6.36 29-Aug Work down testwells & // BreakPoints, Clean and Polish++ 7-Sept. // v5.4.6.37 08-Sep-2019 Special Methods. // v5.4.6.38 19-Sep-2019 Tiny Details // v5.4.7.39 25-Sep ButtonClick Relays Begin // v5.4.7.40 01-Oct-2019 Heavy Hacking S&R. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ using System; using System.Collections.ObjectModel; using System.IO; using System.Threading; using System.Windows.Forms; // Class Aliases using MyCustomLibrary; using MCD = MyCustomLibrary.Dialogs; using MMF = MyCustomLibrary.MemoryMapper; using MCT = MyCustomLibrary.MyToolbox; using MSF = MyCustomLibrary.SearchForm; // Property Aliases using SMR = MyEditor.Properties.Resources; using SMS = MyEditor.Properties.Settings; #endregion Pop Tart namespace MyEditor { public partial class Smesa { #region File Loading Messages void Special() { const bool reset = false; Special(reset); } void Special(bool reset) { if (reset) { Text = SMR.AddedText; ArrowCursor(); } else { WaitCursor(); Special(SMS.Default .FileNames.Count); } } void Special(int ct) { Text += SMR.WAIT; if (ct > 12) Text = string.Format( "{0} {1} Files.", SMR.Loading, ct); Show(); WaitCursor(); } #endregion File Loading Messages //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #region MyEditor Calling Search void SearchClickedEventHandler( object sender, EventArgs e) { var was = MCT.Skip; MCT.Skip = true; foreach (var i in CheckForSave()) SaveCurrentFile(i); MCT.Skip = was; var tab = TabControl.SelectedIndex; var cof = new Collection { SMS.Default.FileNames[tab] }; foreach (var fnm in SMS.Default .FileNames) cof.Add(fnm); var rtb = TabControl.TabPages[tab] .Controls[0] as RichTextBox; if (rtb == null ||cof.Count < 1) return; var cst = new Collection { SMS.Default.FileNames[tab] }; MCD.Search(GetSearchString1( rtb.SelectedText), cof, cst); } // Gets Either default or trims text. // Truncates the string at 256 chars. string GetSearchString1(string text) { if (!string.IsNullOrEmpty(text)) { var txt = text; var spacer = new[] {' '}; txt = txt.TrimEnd(spacer); if (!string.IsNullOrEmpty(txt)) text = GetSearchString2(txt); } return text; } string GetSearchString2(string txt) { var texter = txt; var tester = SMR.SearchText; var charer = tester.IndexOf( "text", StringComparison .OrdinalIgnoreCase); if (charer >= 0 && charer < tester.Length - txt.Length ) texter = GetSearchString3( txt, tester, charer); return texter; } string GetSearchString3(string text, string tester, int charer) { if (!string.IsNullOrEmpty(text)) { var txt = text; tester = tester.Insert( charer + "text".Length, string.Format(// ^ fixedwell! ": \"{0}\"\r\n", txt)); if (!string.IsNullOrEmpty(txt) && YesNoDialog(tester, SMR.SearchTitle, 1) ) text = GetSearchString4(txt); } return text; } static string GetSearchString4(string text) { var spacer = new[] {' '}; var txt = text.TrimEnd(spacer); while ( txt.Length > 256) txt = txt.Remove(256); if (!string.IsNullOrEmpty( txt)) text = txt; // if & ONLY if!^^^ return text; } #endregion MyEditor Calling Search //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #region Incoming Messages from SearchForm #region WorkList2 Custom DataType desRev4 FileSystemWatcher MatchesWatcher { get; set; } WorkList2 WorkList { get; set; } void SetupMatchesWatcher() { MatchesWatcher.NotifyFilter = NotifyFilters.FileName; MatchesWatcher .InternalBufferSize = 32768; MatchesWatcher .EnableRaisingEvents = false; MatchesWatcher.Path = Application.StartupPath; MatchesWatcher.Filter = Path.GetFileName(SMR.Matches); MatchesWatcher.Created += MatchesEventHandler; MatchesWatcher .EnableRaisingEvents = true; } // RedNum = 1; >>====> // // Collection of Lines. // return IList = // GetLines(rtb.Text); // // consider: Just do one file at a time on the fly for fresh Lines and Starts, Each FindButtonClicked (Which is called all button). void MatchesEventHandler( object sender, FileSystemEventArgs e) { Thread.CurrentThread.Name = "MatchesReceived"; if (RichTextBox1.InvokeRequired) try { Invoke(new Invoker1( SetupNewWorkList)); } catch (ObjectDisposedException) {} // breakpoint MatchesEventHandler else SetupNewWorkList(); } // REM: Back on U/I Thread Here. void SetupNewWorkList() { using (new Mutex(true, "SmesaMutex")) { Thread.CurrentThread.Name = "SetupWorkList"; var m = ReadMatches(); if ( m == null || m.File == null || m.File.Count < 1) { WorkList = null; Tracker = null; if (!MCT.Skip) MessageBox.Show(SMR.Work); return; } WorkList = m; FindFirst(); } } // This returns m ^ above; // Reads the Matches.sme MMF and puts // the converted data back together as // new WorkList2.File[] Collection. // v5.3.5.31 03-July-2019 static WorkList2 ReadMatches() { var f = MCT.GetRoot + SMR.Matches; if (string.IsNullOrEmpty(f) || !File.Exists(f)) return null; var t = MMF.ReadStrings( MCD.GetArgs(f,0)); var bools = t[0].Split(','); if (bools.Length < 2) return null; var txt = t[1].Split(','); if (txt.Length < 2) return null; return txt.Length < 2 ? null : GetFileData(bools, txt, t); } #endregion WorkList2 Custom DataType usages //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #region Remote Control Members FileSystemWatcher RemoteControl { get; set; } void SetupRemoteControl() { RemoteControl.NotifyFilter = NotifyFilters.FileName; RemoteControl .InternalBufferSize = 65536; RemoteControl .EnableRaisingEvents = false; RemoteControl.Path = Application.StartupPath; RemoteControl.Filter = Path.GetFileName(SMR.Remote); RemoteControl.Created += RemoteEventHandler; RemoteControl .EnableRaisingEvents = true; } // Buttons Clicked in SearchForm3 obj, // after original entry point above. // Meaning, on subsequent Event calls. void RemoteEventHandler( object sender, FileSystemEventArgs e) { Thread.CurrentThread.Name = "Remote Handler"; if (!TabControl.InvokeRequired) RemoteEventHandler(); #region Tiny Bubbles Coming Out of Invoked Circuitry! //An unhandled exception of type 'System //.InvalidOperationException' occurred in // System.Windows.Forms.dll //Additional information: This property has // already been set and cannot be modified. #endregion else // try { // fixwell REH Invoke(new Invoker1( RemoteEventHandler)); // } #region Catch Clause // catch (InvalidOperationException) // { // const string txt = // "Invalid Operation Exception in\r\n" + // "Remote Event Handler. Return from\r\n" + // "Invokation did not Exit Properly\r\n" + // "or That Object was pre-disposed."; // if (MCT.Testing) // MessageBox.Show(txt); // } #endregion } // Flow is back on the UI/Thread Now. void RemoteEventHandler() { Thread.CurrentThread.Name = "Remote Event Handler"; Enabled = true; // testwell Handle msgs from SF3! // Byte Messages from SearchForm var button = ReadRemoteByte(); if (button < 1 || button > 4) return; if (button.Equals(1)) FindNextClicked(); if (button.Equals(2)) ReplaceClicked(); if (button.Equals(3)) ReplaceAllClicked(); if (button > 3) CancelSearchClicked(); else SearchFormHandoff(1); // signals ^ SF2.LetsGo(); (CTS*) // *Clear To Send signal* } // Read byte from RemoteControl // MMF & return it. v5.3.3.28 static byte ReadRemoteByte() { byte byteNum = 0; var fn = Application .StartupPath + SMR.Remote; var from = MMF.ReadBytes( MCD.GetArgs(fn, 0)); if (from != null && from.Count > 0) byteNum = from[0]; return byteNum; } #endregion Remote Control Members //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #endregion Incoming Messages from Search3 //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #region Outgoing Messages back-to SearchForm // Alerts SF that ME is done with that 1 // Made ReUsable v5.3.1.25 4 use w/Done. // byte 0 = empty, // byte 1 = "Go!"; // byte 2 = "Done!"; // <-= // byte 3 = "Cancel"; // Don't confuse with Search to... // (Matches.sme or Remote.sme) // Editor; this is Editor to Search comm // (SearchTask.sme) void SearchFormHandoff(byte task) { // testwell SearchFormHandoff //Enabled = true; // non-static holder. Enabled = task > 1; // if 1, disable ME ^, else enable. // develop blocking mechanism or System Wide Mutex maybe? var fn = Application .StartupPath + SMR.Search; if (!MMF.WriteBytes( MCD.GetArgs(fn, task))) MessageBox.Show(SMR.Err5); } #endregion Outgoing Messages to SearchForm //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #region Button Click Relays from SearchForm: P3D GetTrackMax() { if (WorkList == null) return null; if (WorkList.File == null || WorkList.File.Count < 1 ) return null; var f = WorkList.File.Count -1; if (WorkList.File[f].Line == null || WorkList.File[f].Line.Count < 1 ) return null; var l = WorkList.File[f] .Line.Count -1; if (WorkList.File[f] .Line[l].Star == null || WorkList.File[f] .Line[l].Star.Count < 1 ) return null; var c = WorkList.File[f] .Line[l].Star.Count -1; return new P3D { Star = c, Line = l, File = f }; } /*^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v*/ // Custom Data Type P3D Doc: //^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v // C is WhereFound The Position in Line[Y] // L is Line Number in current FileName[Z] // F is File Number in current WorkList[N] /*^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v^v*/ P3D Tracker { get; set; } P3D TrackTo { get; set; } // Uses WorkList2 Find & highlight' // the first pair + Length // of searchBox.Text, etc. Called // right after MyWorkList is assembled. // This Method & most subs testswell now! void FindFirst() { TrackTo = GetTrackMax(); // ABOVE ^^ Tracker = new P3D // full reset. { File = 0, Line = 0, Star = 0 }; // No FindNext, ^ it's new data! SetSelectedText(); } // Comes in Set to this.Next Zero ^v // Based Record indice. Finds Next // after this & sets to it when // finished with Current. v5.4.5.33.3 void FindNextClicked()//byte 1; { // breakpoint FindNextClicked\dev if (Tracker.Equals(TrackTo)) { // Completed Successfully! CancelSearchClicked(); MessageBox.Show(SMR.Done); SearchFormHandoff(2); //signals SF2.All ^ Done(); return; } FindNextMatch(); // testcode FindNextClicked const string tx = "Find Next Clicked Hit! = "; MessageBox.Show(tx); } // Incoming ^v Messages from SearchForm. void ReplaceClicked()//byte 2; { // testwell ReplaceClicked ReplaceSelection(); FindNextClicked(); // testcode ReplaceClicked const string t = "Replace Clicked Hit!"; MessageBox.Show(t); } // Uses the rtb.Text.Replace(); // instead of rtb.Lines and such. // Much easier to write too & FAST! // v5.4.7.40 01-Oct-2019 by -JpE- void ReplaceAllClicked()//byte 3; { // testwell Replace All foreach (var f in WorkList.File) { var num = GetTabNum(f.Name); if (num < 0 || !SMS.Default .FileNames.Contains(f.Name) ) continue; var rtb = GetRtB(num); TabControl.SelectedIndex = num; rtb.Text = rtb.Text.Replace( WorkList.FindThis, WorkList.Change2); } } void CancelSearchClicked() // byte 4; { // breakpoint CancelSearchClicked(); #region release mode testcode //const string t = // (SF just closed) // "Cancel Search Event " + // "from Search Form,\n" + // " Handled in My Editor!\n\n"; //MessageBox.Show(t); #endregion WorkList = null; Tracker = null; // null or SearchFormHandoff(3); } #endregion Button Click Relays from Search //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ #region Island Vista Parking Only. #endregion Island Vista Parking. //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ } } // 100% By -JpE-