#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<string>
{ 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<string>
{ 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<Lines> =
// 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-
Comments