Text Filter

Post your working scripts, libraries and tools for AHK v1.1 and older
SundayProgrammer
Posts: 143
Joined: 25 Dec 2020, 12:26

Re: Text Filter

13 Jun 2021, 08:28

the script is updated. → viewtopic.php?p=404344#p404344 ← click this link

star-one-b added a new feature, a 3-tier search mechanism.
SundayProgrammer
Posts: 143
Joined: 25 Dec 2020, 12:26

Re: Text Filter

20 Jun 2021, 23:47

SundayProgrammer wrote:
07 Jun 2021, 13:09
hi @Kellyzkorner_NJ, thank you for letting me know the error. i myself did hit this a few times during testing, but can never repeat it immediately. are you having this problem consistently?

by the way, the _cwi_ (current window id) global variable is set by the wm_activate function via onmessage. the "other windows" message simply means the active window is other than those created from the "tf" object (the text filter and its associated windows).
i think i have found the "Oops..." problem of my "wm_activate" function, which requires myself or any developers using this to note about. that is, at the moment when a window is created, its title doesn't meet the "wm_activate" checking. and it only becomes "met" (the checking) thereafter by changing/updating its title which won't trigger "wm_activate" to update the global variable "_cwi_".

two ways to fix it: either make sure the window title meets the "wm_activate" checking at the moment when the window is born, or execute "wm_activate(1)" after its window title becomes "met".
SundayProgrammer
Posts: 143
Joined: 25 Dec 2020, 12:26

Re: Text Filter

20 Jun 2021, 23:56

star-two

added a "slim" gui, and it becomes the going one at the "start". you can nonetheless switch between slim and full-blown by a button click or selecting it from rightclick menu anytime.

people sometimes may want a light and clean interface for simple tasks, and the full-blown gui takes up almost the whole screen could be too much for that purpose.

this slim gui starts with a smaller footprint. all the checkboxes are removed, yet, "assorted matches", "treeview", and "context peeking" got their own button now. added a match count, and it can be used as a refresh button as well.

side note: the match count is not equivalent to the line count shown on the window title, they may show the same number when each line has one and only one match though.

although there is no "multi-level" thing in slim gui, the current level in full-blown will be brought forward when you switch over. and hence, you may work at different level in slim because of that.

2021-6-30: star-two-a made three tweaks:

(a) improved the indentation for the scenario when "assorted matches" shown with word wrapping.

although the 1st-step richedit indentation is already there since "matches highlighting" was implemented, "assorted matches" was not benefited as it requires 2nd-step indentation (due to its "grouped" layout).

as a legacy of the pre-richedit era, indentation for "assorted matches" relied on the "tab" character (which never worked well with word wrapping). now, the "tab" character is removed, and the 2nd-step richedit indentation is applied.

(b) extended the "doubleclick" to invoke "copy the line/selection".

it all depends on whether "context peeking" window exists or not when "doubleclick" is made. if exists, "context peeking" will be scrolled to show the line. otherwise, "copy the line/selection" is assumed.

(c) enabled user to specify new instance be created from which class object.

there are two ways to create new instance within the user interface. either through "paste into the base" or "open a file". however, both ways were set to create from the "tf" class object.

now, user can specify it explicitly. at the input box when "object instance identification" is popped for a response, you may enter like this: mytf=stf where "mytf" is the id and "stf" is the class object that "mytf" will be created from.

likewise, if you have your own extended class, say, named "abc", you may also enter it like udtf=abc to create the instance "udtf" from the class "abc".

this explicit specification of class object is optional. if it's not specified, class "tf" is assumed if the id is changed (otherwise, it's just a "replace" operation thus what class was the instance created from will remain unchanged), same as before.

2021-7-7: star-two-b added a feature to load the text in reverse order, by line.

at the input box when "object instance identification" is popped for a response, just append "/r" or "-r" to indicate the loading shall be in reverse order. examples, joy/r or joy=stf/r.

2021-7-11: star-two-c two adjustments are made.

(a) "reload the file" can cater "reversed" file now. that is, if the file was loaded in reversed order, its order will be preserved after "reload".

(b) a better fix (regarding the "doubleclick" feature) is crafted. and hence, all those dirty fixes (made recently) are removed.

besides, a new trivial feature is added.

long press the "yes" button of the msgbox for "copy" (the one triggered by "doubleclick") not only will copy the selected text but will also use it as the new search term.

if the msgbox did not pop up after the text is selected and you so happen wanting it, just place your mouse pointer on top of the selected text and give it a long press.

if this still doesn't bring up the msgbox you wanted, just select something else (to reset the memory) and get back to select it again.

that's it for now.

Code: Select all

SetWorkingDir %A_ScriptDir%
RE_Dll := DllCall("LoadLibrary", "Str", "Msftedit.dll", "Ptr")
thePoem=
(
The Road Not Taken
BY ROBERT FROST
Two roads diverged in a yellow wood,
And sorry I could not travel both
And be one traveler, long I stood
And looked down one as far as I could
To where it bent in the undergrowth;
Then took the other, as just as fair,
And having perhaps the better claim,
Because it was grassy and wanted wear;
Though as for that the passing there
Had worn them really about the same,
And both that morning equally lay
In leaves no step had trodden black.
Oh, I kept the first for another day!
Yet knowing how way leads on to way,
I doubted if I should ever come back.
I shall be telling this with a sigh
Somewhere ages and ages hence:
Two roads diverged in a wood, and I—
I took the one less traveled by,
And that has made all the difference.
)
; tf.start("Load Clipboard")
; msgbox
; tf.start("Load File log.txt")
; msgbox
tf.start(thePoem)
; msgbox
; tf.start()	;from what's leftoff in the object's memory

;multiple instances can be coexisting as below
; w1 := new tf, w1.start("Load Clipboard")
; w2 := new tf, w2.start("Load File log.txt")
; w3 := new tf, w3.start(thePoem)
; msgbox
; w3.start()	;from what's leftoff in the object's memory
Return

Class stf extends tf {
	FlexRxR(ByRef Hays, Nee) {
	 	v := this.ov
		If Resu := RegExReplace(Hays, this.Maker(Nee))
			Return (Resu, this[v].r := Nee)

		last_index := 0, s := Nee
		While, pos := RegExMatch(s, "\([^)]+\)|\[[^\]]+\]", m)
			s := SubStr(s, 1, pos - 1) Chr(168) Chr(168 + A_Index) Chr(168) SubStr(s, pos + StrLen(m)), s%A_Index% := m, last_index := A_Index
		Loop, Parse, s
		{	If A_Index > 1
				r .= t A_LoopField
			Else r := A_LoopField
			t := RegExMatch(A_LoopField, "[a-z]") ? "\w{0,3}" : ""
		}
		Loop, % last_index
			i := last_index - A_Index + 1, r := StrReplace(r, Chr(168) Chr(168 + i) Chr(168), s%i%)
		If Resu := RegExReplace(Hays, this.Maker(r))
			Return (Resu, this[v].r := r)

		Loop, Parse, Nee
		{	If A_Index > 1
				r .= t A_LoopField
			Else r := A_LoopField
			t := RegExMatch(A_LoopField, "\w") ? "[\w'\-+]*" : ""
		}
		If Resu := RegExReplace(Hays, this.Maker(r))
			Return (Resu, this[v].r := r)

		Loop, Parse, Nee, % ("", r := "")
			r .= RegExMatch(A_LoopField, "\w") ? "(?=[\w'\-+]*" A_LoopField ")" : ""
		If StrLen(r)
			r .= "\b[\w'\-+]*\b"
		Else Return ""
		If Resu := RegExReplace(Hays, this.Maker(r))
			Return (Resu, this[v].r := r)
		Else Return ("", this[v].r := "")
	}
}	;end of class

FocusedControl() {
	ControlGetFocus, foco, A
	Return foco
}
#If, WinActive("The Text Filter") and FocusedControl() = "Edit1"
	`::
	Tab::ControlFocus, RICHEDIT50W1, A
#If, WinActive("The Text Filter") and FocusedControl() = "RICHEDIT50W1"
	Tab::ControlFocus, Edit1, A
	Space::PgDn
	+Space::PgUp
	s::Home
	e::End
	t::^Home
	b::^End
	-::%_cwi_%.DecrFontSize()
	+::
	=::%_cwi_%.IncrFontSize()
	`::
	Enter::%_cwi_%.TakeThisLine()
	f::%_cwi_%.FindNextMatch()
	+f::%_cwi_%.FindNextMatch(1)
#If, WinActive("TreeView Of Assorted Matches") and FocusedControl() = "SysTreeView321"
	`::
	Enter::%_cwi_%.tvButtonEnter()
#If, WinActive("Context Peeking") and FocusedControl() = "RICHEDIT50W1"
	~WheelUp::
	~WheelDown::%_cwi_%.WheelSearchMode()
#IfWinActive, The Text Filter
	F1::%_cwi_%.ToggleHelpPage(_cwi_)
	~WheelUp::
	~WheelDown::%_cwi_%.WheelSearchMode()
	!a::%_cwi_%.ShowAssMatches()
	^t::%_cwi_%.AssTreeView(_cwi_)
	^p::%_cwi_%.ContextPeek(_cwi_)
	!v::Gosub, PasteHaySub
	^o::Gosub, OpenFileSub
	^r::%_cwi_%.ReloadFile()
#If, WinActive("The Text Filter") and (_bundledRB_ not = "disabled")
	~RButton::%_cwi_%.RClickMenu()
#IfWinActive, ahk_class #32770
	~LButton::EventHandler(0, 0, 0x201, 0)
	~LButton up::EventHandler(0, 0, 0x202, 0)
#IfWinActive

PasteHaySub:
	%_cwi_%[%_cwi_%.ov].eFlag := True
	If _uii_ := %_cwi_%.PasteIntoHaystack()
	{	If _rev_ := RegExMatch(_uii_, "^r\)")
			_uii_ := RegExReplace(_uii_, "^r\)")
		If RegExMatch(_uii_, "(\w+)=(\w+)", _uii_m) and IsObject(%_uii_m2%)
			%_uii_m1% := new %_uii_m2%, %_uii_m1%.start("Load Clipboard", _rev_)
		Else If not InStr(_uii_, "=")
			%_uii_% := new tf, %_uii_%.start("Load Clipboard", _rev_)
	}
	%_cwi_%[%_cwi_%.ov].eFlag := False
	Return

OpenFileSub:
	%_cwi_%[%_cwi_%.ov].eFlag := True
	If _OpFi_ := %_cwi_%.OpenFile()
	{	If _rev_ := RegExMatch(_OpFi_, "^r\)")
			_OpFi_ := RegExReplace(_OpFi_, "^r\)")
		RegExMatch(_OpFi_, "^[\w=]+(?=\t)", _uii_), RegExMatch(_OpFi_, "\t\K.+$", _usf_)
		If RegExMatch(_uii_, "(\w+)=(\w+)", _uii_m) and IsObject(%_uii_m2%)
			%_uii_m1% := new %_uii_m2%, %_uii_m1%.start("Load File " _usf_, _rev_)
		Else If not InStr(_uii_, "=")
			%_uii_% := new tf, %_uii_%.start("Load File " _usf_, _rev_)
	}
	%_cwi_%[%_cwi_%.ov].eFlag := False
	Return

WM_ACTIVATE(wParam) {
	global _cwi_
	If (wParam > 0)
		If WinActive("The Text Filter") or WinActive("TreeView Of Assorted Matches") or WinActive("Context Peeking") or WinActive("Edit Variables")
		{	WinGetTitle, t, A
			If RegExMatch(t, "\| *?(\w*?) *?\|", m) and StrLen(m1)
				_cwi_ := m1
			Else _cwi_ := "Oops..."
		}Else _cwi_ := "Other Windows"
}
EventHandler(wParam, lParam, msg, hwnd) {
	static lbdowntime := 0, dx, dy
	global lbduration := 0
	If msg = 0x201	;WM_LBUTTONDOWN
	{	MouseGetPos, dx, dy
		lbdowntime := A_TickCount
	}Else If msg = 0x202	;WM_LBUTTONUP
		If (lbduration := A_TickCount - lbdowntime) > 1000
		{	MouseGetPos, ux, uy,, moc
			If (moc = "RICHEDIT50W1") and Abs(ux - dx) < 10 and Abs(uy - dy) < 10
				MsgBox,, Prompt, Hang On..., 1
		}
	Return
}

Class tf {
	static o := {}
	v := {}

	start(Param := "", Reverse := 0) {
		OnMessage(0x6, "WM_ACTIVATE")
		OnMessage(0x201, "EventHandler")	;WM_LBUTTONDOWN
		OnMessage(0x202, "EventHandler")	;WM_LBUTTONUP
		this.id := this.GetObjVarNam(), v := this.ov := (this.id = this.__class ? "o" : "v")
		this[v].Version := "Star-Two-C"
		If StrLen(Param)
		{	this[v].SelectedFile := ""
			If Param = Load Clipboard
				this[v].Haystack := Clipboard
			Else If SubStr(Param, 1, 9) = "Load File"
				this[v].Haystack := this.FileRead((Reverse ? "<R>" : "") SubStr(Param, 11))
			Else this[v].Haystack := Param
			this[v].Haystack := StrReplace(this[v].Haystack, "`r`n", "`n")
			If Reverse
				theHays := this[v].Haystack, this.ReverseByLine(theHays), this[v].Haystack := theHays

			this[v].Fayt := this[v].Case := this[v].Wwrap := True, this[v].Whole := this[v].Linum := False, this[v].n := 1, this[v].Hs[0] := this[v].GetAddress("Haystack"), this[v].Hs[1] := this[v].Haystack
		}
		this.SlimGui(this.id), this.CleanUp(this.id)
	}
	FileRead(theFile) {
		FileRead, theHays, % (SubStr(theFile, 1, 3) = "<R>" ? SubStr(theFile, 4) : theFile, this[this.ov].SelectedFile := theFile)
		Return theHays
	}
	HsP(n) {
		If (n > 1)
			Return this[this.ov].Hs[n - 1]
		Else Return StrGet(this[this.ov].Hs[0])
	}
	NeeP(n) {
		If (n > 1)
			Return this[this.ov].Needle[n - 1]
		Else Return ""
	}
	GetObjVarNam() {
		r := "(\w+?):.+?\{address: " Format("0x{:X}", &this) "\}"
		Return RegExMatch(this.ListGlobalVars(), r, m) ? m1 : ""
	}

SlimGui(id) {
	static Fayt
	Gui, %id%:New, +Labeltf.sGui_On
	Gui, +Resize +MinSize +MaximizeBox
	Gui, Font, s18, Consolas
	Gui, Add, Edit, xm w280 vFayt
	OnSuch := this.Fayt_OnTyping.Bind(this)
	GuiControl +g, Edit1, % OnSuch
	Gui, Add, Button, x+10 ys h37 w85 Center, 0
	OnSuch := this.Refresh_OnClick.Bind(this)
	GuiControl +g, Button1, % OnSuch
	Gui, Font, s10, Arial
	Gui, Add, Button, x+10 w40 ys h37 Default, A
	OnSuch := this.A_OnClick.Bind(this)
	GuiControl +g, Button2, % OnSuch
	Gui, Add, Button, x+0 w40 ys h37, T
	OnSuch := this.T_OnClick.Bind(this)
	GuiControl +g, Button3, % OnSuch
	Gui, Add, Button, x+0 w40 ys h37, C
	OnSuch := this.C_OnClick.Bind(this)
	GuiControl +g, Button4, % OnSuch
	Gui, Add, Button, x+0 w40 ys h37, F
	OnSuch := this.F_OnClick.Bind(this)
	GuiControl +g, Button5, % OnSuch
	begWwrap := this[this.ov].Wwrap ? "+Wrap" : "+HScroll"
	Gui, Font, s18, Consolas
	Gui, Add, Custom, ClassRICHEDIT50W Section xm h300 w534 %begWwrap% +VScroll +hwndHRE +0x804	;ES_READONLY = 0x800, ES_MULTILINE = 0x4
	this.HRE := HRE, this.RE := this.GetTomDoc(HRE)
	OnSuch := this.RE_OnEvent.Bind(this)
	GuiControl +g, %HRE%, % OnSuch
	Gui, Show,, The Text Filter (Slim)

	this.RenewGui(), WM_ACTIVATE(1)	;show content
}

sGui_OnSize() {
	If A_EventInfo = 1
		Return
	GuiControl, Move, RICHEDIT50W1, % "h" (A_GuiHeight - 76) " w" (A_GuiWidth - 46)
	GuiControl, Move, Button5, % "x" (A_GuiWidth - 62)
	GuiControl, Move, Button4, % "x" (A_GuiWidth - 102)
	GuiControl, Move, Button3, % "x" (A_GuiWidth - 142)
	GuiControl, Move, Edit1, % "w" (A_GuiWidth - 309)
	GuiControl, Move, Button2, % "x" (A_GuiWidth - 182)
	GuiControl, Move, Button1, % "x" (A_GuiWidth - 277)
}

sGui_OnEscape() {
	%A_Gui%.GuiClose(A_Gui)
}

sGui_OnClose() {
	%A_Gui%.GuiClose(A_Gui)
}

Fayt_OnTyping() {
	v := this.ov, n := this[v].n
	If IsFunc(this.eciwbeg)
	{	this[v].Needle[n] := theNeedle := this.Fpat(), this.eciwbeg(theNeedle)
		If not theNeedle = this[v].Needle[n]
			ControlSetText, Edit1, % theNeedle
	}
	Gui, Submit, NoHide
	this[v].Needle[n] := theNeedle := this.Fpat()
	If StrLen(theNeedle)
		this[v].Hs[n] := IsFunc(this.FlexRxR) ? this.FlexRxR(this.HsP(n), theNeedle) : RegExReplace(this.HsP(n), this.Maker(theNeedle))
	Else this[v].Hs[n] := this.HsP(n)
	this.RenewGui(theNeedle)
}

A_OnClick() {
	this.ShowAssMatches()
	ControlFocus, Edit1, A
}

T_OnClick() {
	this.AssTreeView(this.id)
	ControlFocus, Edit1, A
}

C_OnClick() {
	v := this.ov
	If not this[v].Linum
	{	MsgBox, 4, Request Response, Context Peeking Needs Line Numbering`n`nTurn it on now ?
		IfMsgBox, No
			Goto, EndingThis
		this[v].Linum := True, this.Linum_Sub1(), this.Linum_Sub2(), this.RenewGui(this.Fpat())
	}
	this.ContextPeek(this.id)
	EndingThis:
	ControlFocus, Edit1, A
}

F_OnClick() {
	v := this.ov, n := this[v].n, this[v].Needle[n] := this.Fpat(), this[v].eFlag := True
	this.GuiClose(this.id)
	this.BuildGui(this.id)
	GuiControl,, NeedleCB, % "`n" this[v].NeedleHistory
	ControlSetText, Edit1, % this[v].Needle[n], A
	this.RenewGui(this[v].Needle[n]), this[v].eFlag := False
	Send, {End}
}

SwitchToSlim() {
	v := this.ov, n := this[v].n, this[v].Needle[n] := this.Fpat(), this[v].eFlag := True
	this.GuiClose(this.id)
	this.SlimGui(this.id)
	ControlSetText, Edit1, % this[v].Needle[n], A
	this.RenewGui(this[v].Needle[n]), this[v].eFlag := False
	Send, {End}
}

BuildGui(id) {
	global NeedleCB
	static Fayt, Case, Whole, Linum, Wwrap
	v := this.ov

	Gui, %id%:New, +Labeltf.Gui_On
	Gui, +Delimiter`n
	Gui, +Resize +MinSize +MaximizeBox
	Gui, Font, s10, Arial New
	Gui, Add, Text,, O p t i o n s:

	begFayt := this[v].Fayt ? "Checked" : ""
	Gui, Add, Checkbox, ym vFayt %begFayt% Tabstop, Instant Filter (aka Find As You Type)
	OnSuch := this.Fayt_OnToggle.Bind(this)
	GuiControl +g, Button1, % OnSuch

	begCase := this[v].Case ? "Checked" : ""
	Gui, Add, Checkbox, ym vCase %begCase% Tabstop, Case Insensitive
	OnSuch := this.Case_OnToggle.Bind(this)
	GuiControl +g, Button2, % OnSuch

	begWhole := this[v].Whole ? "Checked" : ""
	Gui, Add, Checkbox, ym vWhole %begWhole% Tabstop, Whole Word
	OnSuch := this.Whole_OnToggle.Bind(this)
	GuiControl +g, Button3, % OnSuch

	begLinum := this[v].Linum ? "Checked" : ""
	Gui, Add, Checkbox, ym vLinum %begLinum% Tabstop, Line Number
	OnSuch := this.Linum_OnToggle.Bind(this)
	GuiControl +g, Button4, % OnSuch

	beg_Wrap := this[v].Wwrap ? "Checked" : ""
	Gui, Add, Checkbox, ym vWwrap %beg_Wrap% Tabstop, Word Wrap
	OnSuch := this.Wwrap_OnToggle.Bind(this)
	GuiControl +g, Button5, % OnSuch

	Gui, Font, s18, Arial New
	Gui, Add, Text, xm Section, Filter:

	w := A_ScreenWidth - 330
	Gui, Add, ComboBox, w%w% ys vNeedleCB +hwndhEdit1
	OnSuch := this.Fpat_OnTyping.Bind(this)
	GuiControl +g, %hEdit1%, % OnSuch

	Gui, Add, Button, h38 ys Default, Go
	OnSuch := this.Go_OnClick.Bind(this)
	GuiControl +g, Button6, % OnSuch

	Gui, Font, s10, Arial New
	Gui, Add, Button, h38 ys, Refresh
	OnSuch := this.Refresh_OnClick.Bind(this)
	GuiControl +g, Button7, % OnSuch

	Gui, Font, s18, Arial New
	Gui, Add, Button, h38 ys, Back
	OnSuch := this.Back_OnClick.Bind(this)
	GuiControl +g, Button8, % OnSuch

	h := A_ScreenHeight - 143, w := A_ScreenWidth - 30, begWwrap := this[v].Wwrap ? "+Wrap" : "+HScroll"
	Gui, Font, s18, Consolas
	Gui, Add, Custom, ClassRICHEDIT50W x10 h%h% w%w% %begWwrap% +VScroll +hwndHRE +0x804	;ES_READONLY = 0x800, ES_MULTILINE = 0x4
	this.HRE := HRE, this.RE := this.GetTomDoc(HRE)
	OnSuch := this.RE_OnEvent.Bind(this)
	GuiControl +g, %HRE%, % OnSuch

	h := A_ScreenHeight - 64, w := A_ScreenWidth - 6
	Gui, Show, h%h% w%w%, The Text Filter

	this.RenewGui(), WM_ACTIVATE(1)	;show content
}

RE_OnEvent() {
	global lbduration
	v := this.ov
	If not WinExist("The Text Filter")
		Return
	If (this[v].REseleT = this.RE.Selection.Text)
		Return
	If GetKeyState("RButton", "P")
		Return
	Sleep, 500	;this "sleep" exists with reason
	If GetKeyState("LButton", "P") or GetKeyState("Shift", "P")
		Return
	If not this[v].eFlag and this[v].Linum and WinActive("The Text Filter") and WinExist("Context Peeking  |  " this.id) and StrLen(this.RE.Selection.Text)
	{	this[v].eFlag := True
		n := this[v].n
		slcs := this.RE.Selection.Start, slce := this.RE.Selection.End, SelBegChar := this.RE.Range(slcs, slcs + 1).Text, SelEndChar := this.RE.Range(slce - 1, slce).Text, Hays := this.RE.Range(0, 999999999).Text
		If InStr(A_Priorkey, "WheelUp")
			this.RE.Range(slcs, slcs).Select
		Else maybe := InStr("`r`n", SelEndChar) ? 1 : 0, this.RE.Range(slce - maybe, slce - maybe).Select
		Sleep, 500
		maybe := InStr("`r`n", SelBegChar) and (SelEndChar = A_Space) ? 2 : 1, mpos := this.ULoNLoCR(Hays, slcs + maybe)
		slcs := mpos, mpos := this.DLoNLoCR(Hays, slce + 1)
		this.RE_PeekContext(mpos > StrLen(Hays) ? SubStr(Hays, slcs) : SubStr(Hays, slcs, mpos - slcs))
		this[v].eFlag := False, this[v].REseleT := this.RE.Selection.Text
	}Else If not this[v].eFlag and WinActive("The Text Filter") and StrLen(this.RE.Selection.Text) and Clipboard not = this.RE.Selection.Text
	{	this[v].eFlag := True, slcs := this.RE.Selection.Start
		If InStr("`r`n", SubStr(this.RE.Selection.Text, 0))
			this.RE.Range(slcs, slcs).Select, this.TakeThisLine()
		Else
		{	MsgBox, 259, Request Response, "Yes" = To Copy The Selected Text`n`n"No" = To Take Entire Line
			IfMsgBox, Yes
			{	Clipboard := this.RE.Selection.Text
				Progress, zh0 w380 c10 fs18, `nSelection Copied`n,, Prompt, Segoe UI
				Sleep, 500
				Progress, Off
				If lbduration > 1000
				{	ControlSetText, Edit1, % Trim(Clipboard)
					ControlGetText, TextExists, Static1, % "ahk_id " WinExist("The Text Filter")
					If TextExists
						this.Fpat_OnTyping()
				}
			}IfMsgBox, No
				this.RE.Range(slcs, slcs).Select, this.TakeThisLine()
			Sleep, 500	;this "sleep" exists with reason
		}
		this[v].eFlag := False, this[v].REseleT := this.RE.Selection.Text
	}
}
RE_PeekContext(theOne) {
	cpLnum := RegExReplace(theOne, "^\t? *?(\d+?):.*$", "$1")
	If cpLnum is not digit
		Return
	v := this.ov, Hays := this[v].HaystackN, cpLend := RegExMatch(RegExReplace(Hays, "`n",,, cpLnum - 1), "`n") + cpLnum - 1, mpos := this.ULoNLoCR(Hays, cpLend), cpLbeg := mpos - 1, this[v].xFlag := True, this.CP.Range(cpLbeg, cpLend).Select, this.cpScroIntoView()
	timer := ObjBindMethod(this, "OffxFlag")
	SetTimer, % timer, -1000
}
OffxFlag() {
	this[this.ov].xFlag := False
}

Gui_OnSize() {
	If A_EventInfo = 1
		Return
	GuiControl, Move, RICHEDIT50W1, % "h" (A_GuiHeight - 95) " w" (A_GuiWidth - 14)
}

Gui_OnEscape() {
	%A_Gui%.GuiClose(A_Gui)
}

Gui_OnClose() {
	%A_Gui%.GuiClose(A_Gui)
}
GuiClose(id) {
	Gui, %id%:Destroy
	%id%.CleanUp(id)
}

CleanUp(id) {
	IfExist, tf_%id%Work.rtf
		FileDelete, tf_%id%Work.rtf
	IfExist, tfHelp.rtf
		FileDelete, tfHelp.rtf
}

GetTomDoc(HRE) {	;written by "@just me"
	Static IID_ITextDocument := "{8CC497C0-A1DF-11CE-8098-00AA0047BE5D}"
	DocObj := 0
	If DllCall("SendMessage", "Ptr", HRE, "UInt", 0x043C, "Ptr", 0, "PtrP", IRichEditOle, "UInt")	;EM_GETOLEINTERFACE
	{	DocObj := ComObject(9, ComObjQuery(IRichEditOle, IID_ITextDocument), 1)	; ITextDocument
		ObjRelease(IRichEditOle)
	}
	Return DocObj
}

Fayt_OnToggle() {
	v := this.ov, n := this[v].n
	If not (this[v].Fayt := this.Fayt())
		If (this[v].Hs[n] != this.HsP(n))
		{	this[v].Needle[n] := this.Fpat(), theHaystack := this[v].Hs[n]
			n := (this[v].n += 1), this[v].Hs[n] := theHaystack
			this.UpdateTitle()
		}
	ControlFocus, Edit1, A
	this.Fpat_OnTyping()
}

Case_OnToggle() {
	this[this.ov].Case := this.Case()
	ControlFocus, Edit1, A
	this.Fpat_OnTyping()
}

Whole_OnToggle() {
	this[this.ov].Whole := this.Whole()
	ControlFocus, Edit1, A
	this.Fpat_OnTyping()
}

Linum_OnToggle() {
	v := this.ov
	If this[v].Linum := this.Linum()
		this.Linum_Sub1()
	Else this[v].Hs[0] := this[v].GetAddress("Haystack")
	this.Linum_Sub2()
	this.RenewGui(this.Fpat())
}

Linum_Sub1() {
	v := this.ov
	Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Line Numbering, Segoe UI
	lsl := StrLen(this.LineCount())
	HsN =
	Loop, Parse, % this[v].Haystack, `n`r
		HsN .= SubStr(this.StrRepeat(A_Space, lsl) A_Index, 1 - lsl) ":" A_Space A_LoopField "`n"
	Progress, Off
	this[v].HaystackN := HsN, this[v].Hs[0] := this[v].GetAddress("HaystackN")
}

Linum_Sub2() {
	v := this.ov
	Loop, % this[v].n
		this[v].Hs[A_Index] := IsFunc(this.FlexRxR) ? this.FlexRxR(this.HsP(A_Index), this[v].Needle[A_Index]) : RegExReplace(this.HsP(A_Index), this.Maker(this[v].Needle[A_Index]))
}

Wwrap_OnToggle() {
	v := this.ov, this[v].Wwrap := this.Wwrap(), n := this[v].n, this[v].Needle[n] := this.Fpat()
	this.BuildGui(this.id)
	GuiControl,, NeedleCB, % "`n" this[v].NeedleHistory
	ControlSetText, Edit1, % this[v].Needle[n], A
	this.RenewGui(this[v].Needle[n])
	Send, {End}
}

Fpat_OnTyping() {
	v := this.ov, n := this[v].n
	If IsFunc(this.eciwbeg)
	{	this[v].Needle[n] := theNeedle := this.Fpat(), this.eciwbeg(theNeedle)
		If not theNeedle = this[v].Needle[n]
			ControlSetText, Edit1, % theNeedle
	}
	If not this[v].Fayt and not this[v].CommitLevel
		Return
	Gui, Submit, NoHide
	this[v].Needle[n] := theNeedle := this.Fpat()
	If not StrLen(theNeedle) and this[v].CommitLevel
	{	this[v].CommitLevel := False, this.Back_OnClick()
		Progress, Off
		Return
	}
	theHaystack := IsFunc(this.FlexRxR) ? this.FlexRxR(this.HsP(n), theNeedle) : RegExReplace(this.HsP(n), this.Maker(theNeedle))
	If this[v].CommitLevel
	{	If not StrLen(this[v].NeedleHistory)
			this[v].NeedleHistory := theNeedle, Added := True
		Else If not RegExMatch(this[v].NeedleHistory, (this[v].Case ? "i" : "") "m`a)^\Q" theNeedle "\E$")
			this[v].NeedleHistory := theNeedle "`n" this[v].NeedleHistory, Added := True
		Else Added := False
		If Added
		{	GuiControl,, NeedleCB, % "`n" this[v].NeedleHistory
			ControlSetText, Edit1, % theNeedle
		}
		If (theHaystack = this.HsP(n))
			Progress, zh0 w450 c10 fs18, `nResult No Change Thus Not Anew Level`n,, Prompt, Segoe UI
		Else
		{	If not this[v].Fayt
				this[v].Hs[n] := theHaystack
			If (this.LineCount(n) < 2) and not (theNeedle == this.NeeP(n))
				Progress, zh0 w450 c10 fs18, `nUltimate/Empty Result Reached`nThus Level Not Advanced`n,, Prompt, Segoe UI
			Else
			{	n := (this[v].n += 1), this[v].Hs[n] := theHaystack
				Send, ^a
			}
		}
		this[v].CommitLevel := False
		Sleep, 500
		Progress, Off
	}Else this[v].Hs[n] := theHaystack
	this.RenewGui(theNeedle)
	If not this[v].Fayt and not StrLen(this[v].Hs[n])
	{	Progress, zh0 w450 c10 fs18, `nEmpty Result Reached`n`nFalling Back Now`n,, Prompt, Segoe UI
		Sleep, 1000
		this[v].Hs[n] := this.HsP(n)
		ControlSetText, Edit1, % this.NeeP(n)
		this.RenewGui(this.Fpat())
		Send, ^a
		Progress, Off
	}
}
Maker(t) {
	v := this.ov, t := this.tw4sh(t), r := (this[v].Case ? "i" : "") "m`a)^(?!"
	Loop, Parse, t, % A_Space
		If SubStr(A_LoopField, 1, 1) = "-"
			r .= "(?!.*(" (this[v].Whole ? "\b" : "") SubStr(A_LoopField, 2) (this[v].Whole ? "\b" : "") "))"
		Else r .= "(?=.*(" (this[v].Whole ? "\b" : "") A_LoopField (this[v].Whole ? "\b" : "") "))"
	r .= ").*\R?"
	Return r
}

Go_OnClick() {
	ControlFocus, Edit1, A
	Progress, zh0 w380 c10 fs18, `nCommitting This Level`n,, Prompt, Segoe UI
	this[this.ov].CommitLevel := True, this.Fpat_OnTyping()
}

Refresh_OnClick() {
	this.RenewGui(this[this.ov].Needle[this[this.ov].n] := this.Fpat(), "retain")
}

Back_OnClick() {
	ControlFocus, Edit1, A
	v := this.ov, n := this[v].n, this[v].Needle[n] := this.Fpat()
	If (n = 1) and (this[v].Hs[n] != this.HsP(n))
		this[v].Hs[n] := this.HsP(n), this[v].Needle[n] := ""
	Else If (this[v].Hs[n] = this.HsP(n)) and (this[v].Needle[n] = this.NeeP(n))
		If (n > 2)
			n := (this[v].n -= 2)
		Else If (n = 2)
			n := this[v].n := 1, this[v].Hs[n] := this.HsP(n), this[v].Needle[n] := ""
		Else n := this[v].n := 0
	Else n := (this[v].n -= 1)
	If n
	{	ControlSetText, Edit1, % this[v].Needle[n]
		this.RenewGui(this[v].Needle[n])
		Send, ^a
		If (n = 1) and (this[v].Hs[n] = this.HsP(n))
		{	Progress, zh0 w380 c10 fs18, `nReturned To The Origin`n,, Prompt, Segoe UI
			Sleep, 500
			Progress, Off
		}Else
		{	Progress, zh0 w380 c10 fs18, `nReturned To Level %n%`n,, Prompt, Segoe UI
			Sleep, 500
			Progress, Off
		}
	}Else this.Gui_OnClose()
}

Fpat() {
	GuiControlGet, Fpat,, Edit1
	If not StrLen(Fpat)
		ControlGetText, Fpat, Edit1
	Return Fpat
}
Fayt() {
	GuiControlGet, Fayt,, Button1
	If not StrLen(Fayt)
		ControlGetText, Fayt, Button1
	Return Fayt
}
Case() {
	GuiControlGet, Case,, Button2
	If not StrLen(Case)
		ControlGetText, Case, Button2
	Return Case
}
Whole() {
	GuiControlGet, Whole,, Button3
	If not StrLen(Whole)
		ControlGetText, Whole, Button3
	Return Whole
}
Linum() {
	GuiControlGet, Linum,, Button4
	If not StrLen(Linum)
		ControlGetText, Linum, Button4
	Return Linum
}
Wwrap() {
	GuiControlGet, Wwrap,, Button5
	If not StrLen(Wwrap)
		ControlGetText, Wwrap, Button5
	Return Wwrap
}

RenewGui(theNee := "", AMt := "") {
	global lbduration
	v := this.ov, n := this[v].n
	If this.Fpat() not = theNee
		Goto, WorkInterrupt
	this.ToggleReadOnly(this.HRE, this[v].Wwrap)
	If not this[v].PriorRefreshTime is digit
		this[v].PriorRefreshTime := 0
	If (AMt = "retain") and lbduration < 1000 and A_TickCount - this[v].PriorRefreshTime > 1000
		theHays := this.RE.Range(0, 999999999).Text, this[v].PriorRefreshTime := A_TickCount, this[v].combed := False
	Else If StrLen(AMt) and (AMt not = "retain")
		theHays := this[v][AMt]
	Else If IsFunc(this.Comb) and this.LineCount(n) < 1000 and lbduration < 1000
		theHays := this.Comb(this[v].Hs[n]), this[v].combed := True
	Else theHays := this[v].Hs[n], this[v].combed := False
	ControlSetText, RICHEDIT50W1, %theHays%, A
	indent := (StrLen(this.LineCount()) + 2) * 10, this.RE.Range(0, StrLen(theHays)).SetIndents(-indent, indent, 0)
	If this.Fpat() not = theNee
		Goto, WIP_Interrupt
	r := this.MakerC(IsFunc(this.FlexRxR) ? (this[v].combed ? this[v].combed_r : this[v].r) : theNee)
	If StrLen(theNee) and StrLen(r) and RegExMatch(theHays, r)
	{	Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Matches Highlighting, Segoe UI
 		mpos := 1, mlen := 0
 		While, (mpos := RegExMatch(theHays, r, nm, mpos + mlen)) and (A_Index < 1000 or lbduration > 1000)
 			mlen := StrLen(nm), this.RE.Range(mpos - 1, mpos + mlen - 1).Font.BackColor := 0x00FFFF, npos := mpos
 		lbduration := 0
 		Progress, Off
	}
	If this.RE.Range(0, 19).Text = "Assorted Matches:`t("
	{	Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Assorted Matches Formatting, Segoe UI
 		mpos := 1, mlen := 0
		While, (mpos := RegExMatch(theHays, "\R\d+\. .+?\R\K.+?(?=\R\d+\. .+|\R*$)", nm, mpos + mlen))
 			mlen := StrLen(nm), this.RE.Range(mpos - 1, mpos + mlen - 1).SetIndents(-indent, indent * 2, 0), npos := mpos
 		Progress, Off
	}
	WIP_Interrupt:
	this.ToggleReadOnly(this.HRE, this[v].Wwrap)
	ControlFocus, Edit1, A
	this.UpdateTitle()
	WorkInterrupt:
	GuiControlGet, TextExists,, Static2
	If not TextExists
	{	If StrLen(theNee)and StrLen(r) and RegExMatch(theHays, r)
			RegExReplace(theHays, r,, mc)
		Else mc := 0
		ControlSetText, Button1, %mc%, A
	}
	If this.Fpat() not = theNee
		If TextExists
			this.Fpat_OnTyping()
		Else this.Fayt_OnTyping()
}

UpdateTitle() {
	WinSetTitle, The Text Filter, % ("", v := this.ov, Version := this[v].Version, id := this.id, n := this[v].n, lc := this.LineCount(n), SelectedFile := this[v].SelectedFile), The Text Filter (Version: %Version%)  |  %id%  |  Level %n%  |  Line Count: %lc%  |  %SelectedFile%
}

LineCount(n := 0) {
	If n is digit
		theHays := this.HsP(n + 1)
	Else theHays := n
	StrReplace(theHays, "`n",, lc), lc += StrLen(theHays) and SubStr(theHays, 0) != "`n" ? 1 : 0
	Return lc
}

ToggleReadOnly(HRE, Wwrap) {
	ControlGet, Style, Style,,, ahk_id %HRE%
	If not (Style & 0x800)
		SendMessage, 0x443, 0, 0xF0F0F0,, ahk_id %HRE%	;tune Down BackgroundColor
     SendMessage, 1101, 1, (Style & 0x800) ? (Wwrap ? 0x44 : 0xC4) : (Wwrap ? 0x844 : 0x8C4),, ahk_id %HRE%	;ES_READONLY = 0x800
	If (Style & 0x800)
		SendMessage, 0x443, 0, 0xEEFFFF,, ahk_id %HRE%	;light Up BackgroundColor
}

MakerC(theNee) {
	theNee := this.tw4sh(theNee), r := "", v := this.ov
	Loop, Parse, theNee, % A_Space
		If SubStr(A_LoopField, 1, 1) != "-"
			r .= "(" (this[v].Whole ? "\b" : "") A_LoopField (this[v].Whole ? "\b" : "") ")|"
	If StrLen(r)
	{	If SubStr(r, 0) = "|"
			r := SubStr(r, 1, StrLen(r) - 1)
		r := (this[v].Case ? "i" : "") "m`a)" r
	}
	Return r
}

IncrFontSize() {
	MouseGetPos, mpx, mpy,, moc
	If (moc not = "RICHEDIT50W1")
		MouseMove, 400, 200
	Send, ^{WheelUp}
	If (moc not = "RICHEDIT50W1")
		MouseMove, mpx, mpy
}

DecrFontSize() {
	MouseGetPos, mpx, mpy,, moc
	If (moc not = "RICHEDIT50W1")
		MouseMove, 400, 200
	Send, ^{WheelDown}
	If (moc not = "RICHEDIT50W1")
		MouseMove, mpx, mpy
}

TakeThisLine(id := "RE") {
	slcs := this[id].Selection.Start, slce := this[id].Selection.End, Hays := this[id].Range(0, 999999999).Text
	If (slce > slcs)
	{	Clipboard := this[id].Selection.Text
		Progress, zh0 w380 c10 fs18, `nSelection Copied`n,, Prompt, Segoe UI
		Sleep, 500
		Progress, Off
		Return
	}
	mpos := this.ULoNLoCR(Hays, slce + 1)
	slcs := mpos, mpos := this.DLoNLoCR(Hays, slce + 1)
	this.FinalTouch(mpos > StrLen(Hays) ? SubStr(Hays, slcs) : SubStr(Hays, slcs, mpos - slcs))
}
ULoNLoCR(hays, mpos) {
	While, mpos > 1 and not InStr("`r`n", SubStr(hays, mpos - 1, 1))
		mpos--
	Return mpos
}
DLoNLoCR(hays, mpos) {
	pmax := StrLen(hays)
	While, mpos <= pmax and not InStr("`r`n", SubStr(hays, mpos, 1))
		mpos++
	Return mpos
}

FinalTouch(theOne) {
	Clipboard := RegExReplace(theOne, "^\t?(?: *?\d+?: )?(.*)$", "$1")
	If IsFunc(this.altTakeThisLine)
		this.altTakeThisLine()
	Else MsgBox,,, Has Put This Line Into Clipboard, 3
}

FindNextMatch(Reverse := 0) {
	If StrLen(sPat := this.Fpat())
		r := this.MakerC(IsFunc(this.FlexRxR) ? this[this.ov].r : sPat)
	Else r := "nothing to be matched this"
	slcs := this.RE.Selection.Start, slce := this.RE.Selection.End
	If (slce > slcs) and (RegExMatch(A_ThisHotkey, "^\+?f$") and StrLen(sPat) ? False : not RegExMatch(this.RE.Selection.Text, r))
		r := this.MakerS(this.RE.Selection.Text)
	If StrLen(r) and RegExMatch(Hays := this.RE.Range(0, 999999999).Text, r)
	{	StartHere:
		slcs := this.RE.Selection.Start, slce := this.RE.Selection.End, slcs++, slce++
		cp := Reverse ? slcs : slce
		If Reverse
		{	If cp > 1
			{	mpos := 0, pmax := cp - 1
				Loop
				{	npos := RegExMatch(Hays, r, pm, mpos + 1)
					If npos between 1 and %pmax%
						mpos := npos, nm := pm
					Else Break
				}
				found := (npos > pmax) and mpos > 0
			}
			If not found
			{	mpos := cp - 1, pmax := StrLen(Hays)
				Loop
				{	npos := RegExMatch(Hays, r, pm, mpos + 1)
					If npos between %cp% and %pmax%
						mpos := npos, nm := pm
					Else Break
				}
			}
		}Else mpos := RegExMatch(Hays, r, nm, cp)
		mpos--
		If mpos >= 0
		{	cp := mpos + StrLen(nm)
			this.RE.Range(mpos, cp).Select
		}Else If (mpos < 0) and not Reverse
		{	this.RE.Range(0, 0).Select
			Goto, StartHere
		}
	}
}
MakerS(st) {
	Return (StrLen(st), v := this.ov) ? (this[v].Case ? "i)" : "") (this[v].Whole ? "\b" : "") this.escrx(st) (this[v].Whole ? "\b" : "") : ""
}

WheelSearchMode() {
	MouseGetPos,,,, moc
	If not StrLen(moc) or not InStr("Edit1|RICHEDIT50W1", moc)
	{	IfWinNotActive, The Text Filter
		{	WinActivate % "ahk_id " this[this.ov].ParWin
			WinWaitActive
		}
		ControlFocus, RICHEDIT50W1, A
		this.FindNextMatch(InStr(A_ThisHotkey, "WheelUp"))
	}
}

ShowAssMatches() {
	If this.RE.Range(0, 19).Text = "Assorted Matches:`t("
	{	sPat := this.Fpat()
		If this.RE.Range(19, 31).Text = "Alphabetical"
			this.RenewGui(sPat, "AssHays")
		Else this.RenewGui(sPat, "AAssHays")
		Return
	}
	z := this.ov, n := this[z].n
	If not StrLen(this[z].Hs[n]) or not StrLen(sPat := this.Fpat()) or not StrLen(r := this.MakerC(sPat))
		Return
	r := IsFunc(this.FlexRxR) ? this.MakerC(this[z].r) : r
	Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Assortment, Segoe UI
	UniqMatches := [], Seq := 0, this[z].combed := IsFunc(this.Comb) and this.LineCount(n) < 1000
	Loop, Parse, % this[z].Hs[n], `n`r
	{	mpos = 1
		worknm:
		npos := RegExMatch(A_LoopField, r, nm, mpos), C_LoopField := this[z].combed ? Trim(this.Comb(A_LoopField)) : ""
		If npos
		{	If UniqMatches.HasKey(nm)
				Ums := UniqMatches[nm], AssHays%Ums% .= InStr(AssHays%Ums%, A_LoopField) ? "" : ("`n" A_LoopField, cAssHays%Ums% .= this[z].combed ? "`n" C_LoopField : "")
			Else
				Seq++, UniqMatches[nm] := Seq, AssHays%Seq% := nm "`n" A_LoopField, cAssHays%Seq% := this[z].combed ? nm "`n" C_LoopField : ""
			mpos := npos + StrLen(nm)
			Goto, worknm
		}
	}
	If Seq
	{	UniqHays := tvAAssHays := cAAssHays := "", umNoSort := []
		For k, v in UniqMatches
			UniqHays .= "`n" this.StrRepeat(A_Space, 3) A_Index ".`t" k, tvAAssHays .= "`n" A_Index ". " AssHays%v%, cAAssHays .= this[z].combed ? "`n" A_Index ". " cAssHays%v% : "", umNoSort[v] ? umNoSort[v].Insert(k) : umNoSort[v] := k
		AAssHays := "Assorted Matches:`t(Alphabetical Order)" UniqHays "`n" this.StrRepeat("-", 50) (this[z].combed ? cAAssHays : tvAAssHays)
		UniqHays := tvAssHays := cAssHays := ""
		For k, v in umNoSort
			UniqHays .= "`n" this.StrRepeat(A_Space, 3) k ".`t" v, tvAssHays .= "`n" A_Index ". " AssHays%k%, cAssHays .= this[z].combed ? "`n" A_Index ". " cAssHays%k% : ""
		AssHays := "Assorted Matches:`t(Chronological Order)" UniqHays "`n" this.StrRepeat("-", 50) (this[z].combed ? cAssHays : tvAssHays)
		this[z].AssHays := AssHays, this[z].AAssHays := AAssHays, this[z].tvAssHays := tvAssHays, this[z].tvAAssHays := tvAAssHays
		this.RenewGui(sPat, "AssHays")
	}
	Progress, Off
}

AssTreeView(id) {
	If this.RE.Range(0, 19).Text not = "Assorted Matches:`t("
		Return
	parwin := this[v].ParWin := WinExist("A")
	Gui, tv%id%:New, +Owner%parwin%
	Gui, +Resize +MinSize +MaximizeBox
	Gui, +Labeltf.tvGui_On
	Gui, Font, s18, Consolas
	Gui, Add, Text,, % this.RE.Range(19, 31).Text = "Alphabetical" ? "Assorted Matches: (Alphabetical Order)" : "Assorted Matches: (Chronological Order)"
	;Gui, Add, Button, Hidden Default, Enter
	Gui, Add, TreeView, AltSubmit Section xm w545
	OnSuch := this.tvEventHdlr.Bind(this)
	GuiControl +g, SysTreeView321, % OnSuch
	Seq := 0, aHays := this.RE.Range(19, 31).Text = "Alphabetical" ? this[this.ov].tvAAssHays : this[this.ov].tvAssHays, lc := this.LineCount(aHays) - 1
	Loop, Parse, aHays, `n`r
		If StrLen(A_LoopField)
			If RegExMatch(A_LoopField, "^ *\d+\.[ \t]")
				Seq++, P%Seq% := TV_Add(A_LoopField), Num := 0
			Else Num++, P%Seq%C%Num% := TV_Add(A_LoopField, P%Seq%)
	Gui, Show, x97 y539 h283, TreeView Of Assorted Matches  |  %id%  |  Line Count: %lc%
	GuiControl, Focus, SysTreeView321
}

tvGui_OnSize() {
	If A_EventInfo = 1
		Return
	GuiControl, Move, SysTreeView321, % "h" (A_GuiHeight - 76) " w" (A_GuiWidth - 46)
}

tvGui_OnEscape() {
	Gui, %A_Gui%:Destroy
}

tvGui_OnClose() {
	Gui, %A_Gui%:Destroy
}

tvEventHdlr() {
	If InStr("DoubleClick|S|K|Normal", A_GuiEvent)
		TV_GetText(theOne, TV_GetSelection())
	this[this.ov].theOne := theOne
	If A_GuiEvent = DoubleClick
		IfWinExist, % "Context Peeking  |  " this.id
			this.RE_PeekContext(theOne)
		Else this.tvButtonEnter()
}

tvButtonEnter() {
	this.FinalTouch(this[this.ov].theOne)
}

PasteIntoHaystack() {
	global _cwi_
	If StrLen(Clipboard)
	{	InputBox, id, Object Instance Identification, No space is allowed and please keep it short. Accept the given ID means not to create a new window but replace the content of the current one.`nExample: "joy=stf" (in which`, "=stf" is optional. Enter it only when you need a specific class.),,,,,,,, % _cwi_
		If not ErrorLevel and StrLen(Trim(id))
		{	If Reverse := RegExMatch(id, "[-/]\s*[rR]$")
				id := RegExReplace(id, "[-/]\s*[rR]$")
			If RegExMatch(id, "[^\w=]")
				id := RegExReplace(id, "[^\w=]")
			If RegExMatch(id, "\w+=(\w+)", m) and IsObject(%m1%)
				Return (Reverse ? "r)" id : id)
			If InStr(id, "=")
				MsgBox, Invalid Input
			Else If (id = _cwi_)
				this.start("Load Clipboard", Reverse)
			Else Return (Reverse ? "r)" id : id)
		}
	}Else MsgBox, Clipboard is empty
}

OpenFile() {
	global _cwi_
	FileSelectFile, SelectedFile
	If StrLen(SelectedFile)
	{	InputBox, id, Object Instance Identification, No space is allowed and please keep it short. Accept the given ID means not to create a new window but replace the content of the current one.`nExample: "joy=stf" (in which`, "=stf" is optional. Enter it only when you need a specific class.),,,,,,,, % _cwi_
		If not ErrorLevel and StrLen(Trim(id))
		{	If Reverse := RegExMatch(id, "[-/]\s*[rR]$")
				id := RegExReplace(id, "[-/]\s*[rR]$")
			If RegExMatch(id, "[^\w=]")
				id := RegExReplace(id, "[^\w=]")
			ido := (Reverse ? "r)" id : id)
			If RegExMatch(id, "\w+=(\w+)", m) and IsObject(%m1%)
				Return ido "`t" SelectedFile
			If InStr(id, "=")
				MsgBox, Invalid Input
			Else If (id = _cwi_)
				this.start("Load File " SelectedFile, Reverse)
			Else Return ido "`t" SelectedFile
		}
	}
}

ReloadFile() {
	If StrLen(SelectedFile := this[this.ov].SelectedFile)
	{	If Reverse := (SubStr(SelectedFile, 1, 3) = "<R>")
			SelectedFile := SubStr(SelectedFile, 4)
		this.start("Load File " SelectedFile, Reverse)
	}
}

RClickMenu() {
	global lbduration
	MouseGetPos, xb4, yb4
	While, GetKeyState("RButton", "P")
		Continue
	MouseGetPos, rbx, rby, mow, moc
	If Abs(rbx - xb4) > 10 or Abs(rby - yb4) > 10
		Return
	If (mow = (HGUI := WinExist("A"))) and rby > 30
		If (moc = "Button8")
			this.ShowTrail()
		Else If (moc not = "Edit1")
		{	Menu, myMenu, Add
			Menu, myMenu, DeleteAll
			If IsFunc(this.EditVars)
			{	Menu, myMenu, Add, Edit Variables, MenuHandler
				Menu, myMenu, Add
			}
			Menu, myMenu, Add, Show Assorted Matches, MenuHandler
			If this.RE.Range(0, 19).Text = "Assorted Matches:`t("
				Menu, myMenu, Add, Put Assorted Matches In TreeView, MenuHandler
			If this[this.ov].Linum and not WinExist("Context Peeking  |  " this.id)
			{	Menu, myMenu, Add
				Menu, myMenu, Add, Context Peeking, MenuHandler
			}
			Menu, myMenu, Add
			Menu, myMenu, Add, Increase Font Size, MenuHandler
			Menu, myMenu, Add, Decrease Font Size, MenuHandler
			Menu, myMenu, Add
			Menu, myMenu, Add, Paste Into The Base, MenuHandler
			Menu, myMenu, Add, Open A File, MenuHandler
			Menu, myMenu, Add, Reload The File, MenuHandler
			Menu, myMenu, Add
			ControlGetText, TextExists, Static1, ahk_id %HGUI%
			If TextExists
				Menu, myMenu, Add, Switch To Slim Gui, MenuHandler
			Else Menu, myMenu, Add, Switch To Full-Blown Gui, MenuHandler
			Menu, myMenu, Add
			Menu, myMenu, Add, List Global Variables, MenuHandler
			If (moc = "RICHEDIT50W1")
			{	Menu, myMenu, Add
				Menu, myMenu, Add, Copy The Line/Selection, MenuHandler
				Menu, myMenu, Add, Go To Rightmost Of The Line, MenuHandler
				Menu, myMenu, Add, Go To Leftmost Of The Line, MenuHandler
				Menu, myMenu, Add, Go To The Bottom, MenuHandler
				Menu, myMenu, Add, Go To The Top, MenuHandler
				Menu, myMenu, Add, Page Down, MenuHandler
				Menu, myMenu, Add, Page Up, MenuHandler
			}
			Menu, myMenu, Add
			Menu, myMenu, Add, Downward Find Next Match, MenuHandler
			Menu, myMenu, Add, Upward Find Next Match, MenuHandler
			Menu, myMenu, Add
			Menu, myMenu, Add, Override The 1K Default, MenuHandler
			Menu, myMenu, Add
			Menu, myMenu, Add, Show/Hide Help Page, MenuHandler
			Menu, myMenu, Show
		}
	Return
	MenuHandler:
		WinWaitActive, ahk_id %HGUI%
		If A_ThisMenuItem = Edit Variables
			this.EditVars(this.id)	;basically for debugging purpose
		Else If A_ThisMenuItem = Show Assorted Matches
			this.ShowAssMatches()
		Else If A_ThisMenuItem = Put Assorted Matches In TreeView
			this.AssTreeView(this.id)
		Else If A_ThisMenuItem = Context Peeking
			this.ContextPeek(this.id)
		Else If A_ThisMenuItem = Increase Font Size
			this.IncrFontSize()
		Else If A_ThisMenuItem = Decrease Font Size
			this.DecrFontSize()
		Else If A_ThisMenuItem = Paste Into The Base
			Gosub, PasteHaySub
		Else If A_ThisMenuItem = Open A File
			Gosub, OpenFileSub
		Else If A_ThisMenuItem = Reload The File
			this.ReloadFile()
		Else If A_ThisMenuItem = Switch To Slim Gui
			this.SwitchToSlim()
		Else If A_ThisMenuItem = Switch To Full-Blown Gui
			this.F_OnClick()
		Else If A_ThisMenuItem = List Global Variables
			this.start(this.ListGlobalVars())
		Else If A_ThisMenuItem = Copy The Line/Selection
		{	If this.RE.Selection.End = this.RE.Selection.Start
				MouseClick, Left, rbx, rby
			this.TakeThisLine()
		}Else If A_ThisMenuItem = Go To Rightmost Of The Line
		{	MouseClick, Left, rbx, rby
			Send, {End}
		}Else If A_ThisMenuItem = Go To Leftmost Of The Line
		{	MouseClick, Left, rbx, rby
			Send, {Home}
		}Else If A_ThisMenuItem = Go To The Bottom
		{	MouseClick, Left, rbx, rby
			Send, ^{End}
		}Else If A_ThisMenuItem = Go To The Top
		{	MouseClick, Left, rbx, rby
			Send, ^{Home}
		}Else If A_ThisMenuItem = Page Down
		{	MouseClick, Left, rbx, rby
			Send, {PgDn}
		}Else If A_ThisMenuItem = Page Up
		{	MouseClick, Left, rbx, rby
			Send, {PgUp}
		}Else If A_ThisMenuItem = Downward Find Next Match
		{	ControlFocus, RICHEDIT50W1, A
			this.FindNextMatch()
		}Else If A_ThisMenuItem = Upward Find Next Match
		{	ControlFocus, RICHEDIT50W1, A
			this.FindNextMatch(1)
		}Else If A_ThisMenuItem = Override The 1K Default
			lbduration := 1234, this.RenewGui(this.Fpat(), "retain")
		Else If A_ThisMenuItem = Show/Hide Help Page
			this.ToggleHelpPage(this.id)
		Return
}

ShowTrail() {
	HGUI := WinExist("A"), v := this.ov, n := this[v].n
	Menu, myTrail, Add
	Menu, myTrail, DeleteAll
	While, A_Index < n
	{	tn := n - A_Index, theNeedle := this[v].Needle[tn], lc := this.LineCount(tn)
		Menu, myTrail, Add, Level &%tn% remains %lc% lines after this filter: %theNeedle%, BtsLevel
	}
	lc := this.LineCount()
	Menu, myTrail, Add, Origin %lc% lines (Level &0), BtsLevel
	Menu, myTrail, Show
	Return
	BtsLevel:
		WinWaitActive, ahk_id %HGUI%
		n -= A_ThisMenuItemPos
		If n < 1
			n := this[v].n := 1, this[v].Hs[n] := this.HsP(n), this[v].Needle[n] := ""
		Else this[v].n := n
		ControlSetText, Edit1, % this[v].Needle[n]
		this.RenewGui(this[v].Needle[n])
		Return
}

ToggleHelpPage(id) {
	theFile = tf_%id%Work.rtf
	If this.RE.Range(0, 17).Text = "H e l p _ P a g e"
		IfExist, %theFile%
			this.RE.Open(theFile, 0x01, 0)
		Else this.RenewGui(this.Fpat())
	Else
	{	IfExist, %theFile%
			this.RE.Save(0, 0, 0)
		Else this.RE.Save(theFile, 0x01, 0)
		helpfile = tfHelp.rtf
		IfExist, % helpfile
			FileDelete, % helpfile
		FileAppend, % this.HelpPage(), % helpfile
		this.RE.Open(helpfile, 0x01, 0)
	}
}

ContextPeek(id) {
	v := this.ov
	If not this[v].Linum
		Return
	parwin := this[v].ParWin := WinExist("A")
	Gui, cp%id%:New, +Owner%parwin%
	Gui, +Resize +MinSize +MaximizeBox
	Gui, +Labeltf.cpGui_On
	Gui, Font, s12, Arial New
	Gui, Add, Button,, Close
	OnSuch := this.cpBclose.Bind(this)
	GuiControl +g, Button1, % OnSuch
	Gui, Add, Button, ys, Maximize
	OnSuch := this.cpBmaxim.Bind(this)
	GuiControl +g, Button2, % OnSuch
	Gui, Add, Button, ys, Restore
	OnSuch := this.cpBresto.Bind(this)
	GuiControl +g, Button3, % OnSuch
	Gui, Add, Button, ys, Minimize
	OnSuch := this.cpBminim.Bind(this)
	GuiControl +g, Button4, % OnSuch
	Gui, Font, s18, Consolas
	Gui, Add, Custom, ClassRICHEDIT50W xm Section +Wrap +VScroll +hwndHCP +0x804	;ES_READONLY = 0x800, ES_MULTILINE = 0x4
	this.HCP := HCP, this.CP := this.GetTomDoc(HCP)
	OnSuch := this.cpEventHdlr.Bind(this)
	GuiControl +g, RICHEDIT50W1, % OnSuch
	x := A_ScreenWidth/2, h := A_ScreenHeight - 94, w := A_ScreenWidth - 6, lc := this.LineCount()
	Gui, Show, x%x% y51 h%h% w%w%, Context Peeking  |  %id%  |  Line Count: %lc%
	Progress, zh0 w300 c10 fs18, `nHang On...`n,, Loading Origin, Segoe UI
	GuiControl,, RICHEDIT50W1, % this[v].HaystackN
	GuiControl, Focus, RICHEDIT50W1
	this.ToggleReadOnly(this.HCP, this[v].Wwrap)
	indent := (StrLen(lc) + 2) * 10, this.CP.Range(0, StrLen(this[v].HaystackN)).SetIndents(-indent, indent, 0)
	SendMessage, 0x443, 0, 0xF0F0F0,, ahk_id %HCP%	;tune Down BackgroundColor
	this.ToggleReadOnly(this.HCP, this[v].Wwrap)
	Progress, Off
}

cpScroIntoView() {
	GuiControlGet, gCPg, Pos, % this.HCP
	this.CP.Selection.ScrollIntoView(0), slcs := this.CP.Selection.Start, slce := this.CP.Selection.End
	this.CP.Range(cp := this.CfromP(this.HCP, 1, this.PfromC(this.HCP, slcs) + gCPgH / 2), cp).Select
	WinActivate, % "Context Peeking  |  " this.id
	WinWaitActive
	this.CP.Range(slcs, slce).Select
	this[this.ov].CPseleT := this.CP.Selection.Text
}
CfromP(hE, x := -1, y := -1) {
	VarSetCapacity(RECT, 16, 0)
	SendMessage 0xB2,, &RECT,, ahk_id %hE%	;EM_GETRECT
	LefP := NumGet(RECT, 0, "Int"), TopP := NumGet(RECT, 4, "Int"), RigP := NumGet(RECT, 8, "Int"), BotP := NumGet(RECT, 12, "Int")
	VarSetCapacity(PoL, 8, 0), NumPut(x < 0 ? RigP : x, PoL,, "Int"), NumPut(y < 0 ? BotP : y, PoL, 4, "Int")
	SendMessage 0xD7,, &PoL,, ahk_id %hE%	;EM_CHARFROMPOS
	Return ErrorLevel
}
PfromC(hE, i) {
	VarSetCapacity(PoL, 8, 0)
	SendMessage 0xD6, &PoL, i,, ahk_id %hE%	;EM_POSFROMCHAR
	Return NumGet(PoL, 4, "Int")
}

cpGui_OnSize() {
	If A_EventInfo = 1
		Return
	GuiControl, Move, RICHEDIT50W1, % "h" (A_GuiHeight - 65) " w" (A_GuiWidth - 30)
}

cpGui_OnEscape() {
	Gui, %A_Gui%:Destroy
}

cpGui_OnClose() {
	Gui, %A_Gui%:Destroy
}

cpBclose() {
	Gui, %A_Gui%:Destroy
}

cpBmaxim() {
	WinGet, wMM, MinMax, A
	If wMM = 1	;already maximized
		WinRestore, A
	Else WinMaximize, A
	GuiControl, Focus, RICHEDIT50W1
}

cpBresto() {
	static x := A_ScreenWidth/2, h := A_ScreenHeight - 94, w := A_ScreenWidth - 6
	WinGet, wMM, MinMax, A
	If wMM = 0	;already restored
	{	WinGetPos, GuiX,,,, A
		If (GuiX + x >= A_ScreenWidth)
			Gui, Show, x-5 y51 h%h% w%w%
		Else Gui, Show, x%x% y51 h%h% w%w%
	}Else WinRestore, A
	GuiControl, Focus, RICHEDIT50W1
}

cpBminim() {
	WinMinimize, A
}

cpEventHdlr() {
	global lbduration
	IfWinActive, Context Peeking
	{	ControlGetFocus, foco, A
		If (foco not = "RICHEDIT50W1")
		{	MouseGetPos,,, mow, moc
			If not (mow = WinExist("Context Peeking") and InStr(moc, "Button"))
				GuiControl, Focus, RICHEDIT50W1
		}
	}
	v := this.ov
	If (this[v].CPseleT = this.CP.Selection.Text)
		Return
	If GetKeyState("RButton", "P")
		Return
	Sleep, 500	;this "sleep" exists with reason
	If GetKeyState("LButton", "P") or GetKeyState("Shift", "P")
		Return
	If not this[v].xFlag and WinActive("Context Peeking") and StrLen(this.CP.Selection.Text)
	{	this[v].xFlag := True, slcs := this.CP.Selection.Start
		If InStr("`r`n", SubStr(this.CP.Selection.Text, 0))
			this.CP.Range(slcs, slcs).Select, this.TakeThisLine("CP")
		Else
		{	MsgBox, 259, Request Response, "Yes" = To Copy The Selected Text`n`n"No" = To Take Entire Line
			IfMsgBox, Yes
			{	Clipboard := this[v].CPseleT := this.CP.Selection.Text
				Progress, zh0 w380 c10 fs18, `nSelection Copied`n,, Prompt, Segoe UI
				Sleep, 500
				Progress, Off
				If lbduration > 1000
				{	WinMinimize
					ControlSetText, Edit1, % Trim(Clipboard), % "ahk_id " this[v].ParWin
				}
			}IfMsgBox, No
				this.CP.Range(slcs, slcs).Select, this.TakeThisLine("CP")
			Sleep, 500	;this "sleep" exists with reason
		}
		this[v].xFlag := False, this[v].CPseleT := this.CP.Selection.Text
	}
}

tw4sh(t) {
	tog := "\/", va := "?\\'\w", ph := "[^" va "\n]", tar := "\" tog ph "*?\K[" va "]", ph := "[^\w\n]"
	If mpos:=RegExMatch(t, tar)	;contained toggle (on)
	{	pb := "[^\w\n]", sh := "((?<=^|" ph ")", st := "(?=(\W|$)))"
		skip_c := skip_w := yb := False
		r := StrReplace(SubStr(t, 1, mpos - 1), tog) sh, rr := xx := ""
		Loop
		{	c := SubStr(t, mpos, 1), cc := SubStr(t, mpos + 1, 1)
			If skip_c
				skip_c--
			Else If SubStr(t, mpos, StrLen(tog)) = tog	;toggle (off) encountered
			{	this.flush(r, xx, pb, yb, st), rr := xx := ""
				mpos += StrLen(tog), npos := mpos
				If mpos:=RegExMatch(t, tar,, npos)	;found next toggle (on)
					r .= StrReplace(SubStr(t, npos, mpos - npos), tog) sh, rr := xx := ""
				Else
				{	r .= SubStr(t, npos)
					Break
				}
				Continue
			}Else If RegExMatch(c, "\w") or (c = "?")	;valid character
			{	If rr
					If not skip_w and ((cc not = "/") or StrLen(xx))
						this.flush(r, xx, pb, yb)
					Else If (cc = "/") and not StrLen(xx)
					{	If SubStr(t, mpos + 2, 1) = "/"
							skip_w := skip_w ? skip_w : True, skip_c++
						skip_c++
					}Else{}
				Else If StrLen(rr)
					r .= xx sh, rr := xx := ""
				r .= (c = "?") ? (skip_w ? "\w" : ("\w+?", yb++)) : c (skip_w ? "" : ("\w*?", yb++)), skip_w -= skip_w ? 1 : 0, rr := True
			}Else If (c = A_Space) and rr
				this.flush(r, xx, pb, yb, st), xx := A_Space, rr := 0
			Else If (c = "'")
				xx .= "\W"
			Else If (c = "\") and skip_w not < 0
				If (cc == "Q")
					skip_c++, skip_w := -1, this.flush(r, xx, pb, yb)
				Else If (cc == "E")
					skip_c++, skip_w := False
				Else If (cc = c)
					xx .= c
				Else If RegExMatch(cc, "\w")
					skip_c++, xx .= cc
				Else skip_c++, xx .= c cc
			Else xx .= c
			mpos++
			If (mpos > StrLen(t))	;exceeded
			{	If rr
					this.flush(r, xx, pb, yb, st), rr := xx := ""
				Break
			}
		}
	}Else r := t
	Return r
}

flush(ByRef r, ByRef xx, pb, ByRef yb, st := "") {
	mb := "[^,;\w\n.?!]+?", ss := SubStr(xx, -1), sc := (ss == "\W") or (ss == "\s") or (ss == "\t") or (ss == "\r") or (ss == "\n"), r .= xx ? (RegExMatch(SubStr(xx, 1, 1), "\w") ? mb : pb "*?") xx (st ? ")" : (RegExMatch(ss, "\\?\w$") and not sc ? "" : pb "*?")) : (st ? st : (yb ? (mb, yb--) : "")), xx := ""
}

StrRepeat(string, times) {
	Loop, %times%
		output .= string
	Return output
}
escrx(h) {
	e := "\().[]*+?{}^$|"

	Loop, Parse, e
		If InStr(h, A_LoopField)
			h := StrReplace(h, A_LoopField, "\" A_LoopField)

	Return h
}
ReverseByLine(ByRef text, delimiter := "`n") {
	array := StrSplit(SubStr(text, 0) = delimiter ? SubStr(text, 1, StrLen(text) - 1) : text, delimiter), mi := array.MaxIndex()
	Loop, % mi
		If A_Index > 1
			text .= array[mi - A_Index + 1] delimiter
		Else text := array[mi] delimiter
}
ListGlobalVars() {	;written by Lexikos
	static hwndEdit, pSFW, pSW, bkpSFW, bkpSW

	If !hwndEdit
	{	dhw := A_DetectHiddenWindows
		DetectHiddenWindows, On
		Process, Exist
		ControlGet, hwndEdit, Hwnd,, Edit1, ahk_class AutoHotkey ahk_pid %ErrorLevel%
		DetectHiddenWindows, %dhw%

		astr := A_IsUnicode ? "astr":"str"
		ptr := A_PtrSize=8 ? "ptr":"uint"
		hmod := DllCall("GetModuleHandle", "str", "user32.dll")
		pSFW := DllCall("GetProcAddress", ptr, hmod, astr, "SetForegroundWindow")
		pSW := DllCall("GetProcAddress", ptr, hmod, astr, "ShowWindow")
		DllCall("VirtualProtect", ptr, pSFW, ptr, 8, "uint", 0x40, "uint*", 0)
		DllCall("VirtualProtect", ptr, pSW, ptr, 8, "uint", 0x40, "uint*", 0)
		bkpSFW := NumGet(pSFW+0, 0, "int64")
		bkpSW := NumGet(pSW+0, 0, "int64")
	}

	If (A_PtrSize=8)
	{	NumPut(0x0000C300000001B8, pSFW+0, 0, "int64")	;return TRUE
		NumPut(0x0000C300000001B8, pSW+0, 0, "int64")	;return TRUE
	}Else
	{	NumPut(0x0004C200000001B8, pSFW+0, 0, "int64")	;return TRUE
		NumPut(0x0008C200000001B8, pSW+0, 0, "int64")	;return TRUE
	}

	ListVars

	NumPut(bkpSFW, pSFW+0, 0, "int64")
	NumPut(bkpSW, pSW+0, 0, "int64")

	ControlGetText, text,, ahk_id %hwndEdit%

	RegExMatch(text, "sm)(?<=^Global Variables \(alphabetical\)`r`n-{50}`r`n).*", text)
	Return text
}
HelpPage() {
HelpPage=
(
{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Arial;}{\f1\fnil\fcharset0 Consolas;}}
{\colortbl ;\red255\green0\blue0;\red155\green0\blue211;\red0\green77\blue187;\red0\green176\blue80;\red0\green0\blue255;}
{\*\generator Riched20 10.0.19041}\viewkind4\uc1 
\pard\sa200\sl276\slmult1\b\fs36\lang9 H e l p _ P a g e\b0\par
\par
\cf1\b F1\cf0\b0  - to toggle this help page\par
\par
\b Basic syntax by example:\b0\par

\pard\li720\sa200\sl276\slmult1 coexisting words/strings/patterns -unwanted\par
for instance, \cf2\b\f1 d.*d -the and -oo \\ws\cf0\b0\f0\par
(the 5 segments (space separated) above can go all at once, and yet, they can also be entered one by one. that's the so-called multilevel approach, instead.)\par

\pard\sa200\sl276\slmult1\par
\b Feature keys:\b0\par

\pard\li720\sa200\sl276\slmult1\cf3\b Alt+a\cf0\b0  - to show assorted matches and toggle between chronological and alphabetical order.\par
\cf3\b Ctrl+t\cf0\b0  - to put assorted matches into a treeview gui which may ease the exploration when the list is long and involved multiple groups.\par
\cf3\b Ctrl+p\cf0\b0  - to bring up context peeking gui which provides an integrated way of reviewing the context of any lines in the shortlisted result.\par
\cf3\b WheelDown\cf0\b0  - to find the next match (downward) from the caret position (given that, the mouse pointer is currently outside both text/edit boxes.)\par
\cf3\b WheelUp\cf0\b0  - to find the next match (upward) from the caret position (given that, the mouse pointer is currently outside both text/edit boxes.)\par
\cf3\b Alt+v\cf0\b0  - to paste clipboard content into the big text/edit box.\par
\cf3\b Ctrl+o\cf0\b0  - to open a file.\par
\cf3\b Ctrl+r\cf0\b0  - to reload the file.\par
\cf3\b Rightclick\cf0\b0  "Back" button - to glance committed levels and select one to fall back to.\par
\cf3\b Esc\cf0\b0  - to quit/exit/leave. same as closing the window.\par
\cf3\b Tab\cf0\b0  - to change focus between the text/edit boxes (just try it.)\par
\par
these below only work when the \ul big\ulnone  text/edit box is in focus:\par

\pard\li1440\sa200\sl276\slmult1\cf3\b f\cf0\b0  - to find the next match (downward) from the caret position.\par
\cf3\b Shift+f\cf0\b0  - to find the next match (upward) from the caret position.\par
\i (note: "the line" refers to the current line, that's where the caret is on.)\i0\par
\cf3\b Doubleclick\cf0\b0  - to copy the line/selection.\par
\cf3\b Enter\cf0\b0  - to copy the line/selection.\par
\cf3\b Space\cf0\b0  - to page down\par
\cf3\b Shift+Space\cf0\b0  - to page up\par
\cf3\b s\cf0\b0  - to move the caret to the beginning/start of the line.\par
\cf3\b e\cf0\b0  - to move the caret to the end of the line.\par
\cf3\b t\cf0\b0  - to move the caret to the top of the text.\par
\cf3\b b\cf0\b0  - to move the caret to the bottom of the text.\par
\cf3\b + or =\cf0\b0  - to increase font size (same as \cf3\b Ctrl+WheelUp\cf0\b0 ).\par
\cf3\b minus "-"\cf0\b0  - to decrease font size (same as \cf3\b Ctrl+WheelDown\cf0\b0 ).\par
\i (side note: "caret" may be known as "cursor" to some people.)\i0\par

\pard\sa200\sl276\slmult1\par
\tab these below only work when the \ul small\ulnone  text/edit box is in focus:\par

\pard\li1440\sa200\sl276\slmult1\cf3\b Enter\cf0\b0  - to commit a level (which makes the current result becoming the base/source of the next level.) same as clicking the button Go.\par

\pard\sa200\sl276\slmult1\par

\pard\li720\sa200\sl276\slmult1\cf3\b Backtick (``)\cf0\b0  - since users mostly use this tool to locate the specific line of text and copy it for whatever subsequent actions to be taken, which typically involves Tab and then Enter (if the first line is the one wanted), backtick is an alternative which can supersede both keys by just hit backtick twice instead.\par

\pard\sa200\sl276\slmult1\par
The \b improvised shorthand\b0  feature:\par

\pard\li720\sa200\sl276\slmult1 this feature can be triggered through "\cf2\b\\/\cf0\b0 " (a \b backslash\b0  followed by a \b slash\b0 ), a "regex like" syntax style, which toggle it on or off. so, enter "\cf2\b\\/tr\cf0\b0 " will bring you those lines contained "\cf4\i the road\cf0\i0 ", "\cf4\i two roads\cf0\i0 ", as well as "\cf4\i them really\cf0\i0 " out of the poem, whereas enter "\cf2\b oo \\/a?a\cf0\b0 " or "\cf2\b\\/a?a\\/ oo\cf0\b0 " will return you these two lines "\cf4\i And looked down one as far as I could\cf0\i0 " and "\cf4\i Then took the other, as just as fair,\cf0\i0 " in which, the "\cf2\b ?\cf0\b0 " represents any valid character regex recognized it as "word" element. Besides, the space has been cared so that the toggle works across it. for instance, enter "\cf2\b\\/tr yw\cf0\b0 " or "\cf2\b\\/yw tr\cf0\b0 " will show this line "\cf4\i Two roads diverged in a yellow wood,\cf0\i0 " where the space is still a separator as always, even though the shorthand feature is toggled on.\par

\pard\sa200\sl276\slmult1\par
\tab three more elements of the shorthand syntax:\par
\par

\pard\fi-360\li1800\sa200\sl276\slmult1 1, \b extra qualifier\b0  (within a single word);\par
2, \b escape character\b0  (between words);\par
3, a single \b character\b0  representing any "\b non-word\b0 " one (between words).\par

\pard\sa200\sl276\slmult1\par

\pard\li720\sa200\sl276\slmult1 the most basic usage of improvised shorthand is to match the specific "phrase" by just entering the first letter of each word constituted it (for instance, "\cf2\b sameto\cf0\b0 " can match "\cf4\i some are more equal than others\cf0\i0 ") yet sometimes we may want to further narrow down the result. if "\cf2\b slh\cf0\b0 " brings you both "\cf4\i she likes him\cf0\i0 " and "\cf4\i she loves him\cf0\i0 ", an extra qualifier to pinpoint one may be useful. it could simply be a "v" for this example hence "\cf2\b slv/h\cf0\b0 " (in which, the "/" after the "v" tells the system that it's just an extra qualifier to the "l", not for a word starts with "v",) returns you "\cf4\i she loves him\cf0\i0 " only. likewise, you may sometimes want to tell the system exactly what the word should be ending with, for instance, if "\cf2\b ioy\cf0\b0 " brings you both "\cf4\i i owe you\cf0\i0 " and "\cf4\i i own you\cf0\i0 ", "\cf2\b ioe//y\cf0\b0 " (in which, the "//" after the "e" tells the system that it's a word ending character, that is, "oe//" represents a word starts with "o" and ends with "e") returns you "\cf4\i i owe you\cf0\i0 " only. and no matter how rare (and impractical) it may be, you may have multiple of these qualifiers for a word, such as, "\cf2\b cm/c/e//d//\cf0\b0 " can match the word "\cf4\i complicated\cf0\i0 " whereas "\cf2\b td/i/u//s//\cf0\b0 " can match the word "\cf4\i tedious\cf0\i0 ".\par
\par
a \b backslash\b0  "\cf2\b\\\cf0\b0 " may be used to escape a single character after it. its target should be a "word" character because you don't need to escape otherwise. for all "non-word" character, just enter them directly except "\\" itself which requires a \b double backslash\b0  "\cf2\b\\\\\cf0\b0 " for a single one. for regex syntax such as "\\s", it becomes "\\\\s" (not "\\\\\\s" you may presume.) in other words, all escaped character will only be matched barely itself. for \ul consecutive\ulnone  "word" characters that need to be escaped, enclose them in the \cf2\b\\Q\cf0\b0  \cf2\b\\E\cf0\b0  pair, similar idea as in regex. one thing to note though, escaped character may affect the word immediately after it, for instance, "\cf2\b z\\xy\cf0\b0 " may bring you "\cf4\i zebra xylophone\cf0\i0 " rather than "\cf4\i zombie x yesterday\cf0\i0 ".\par
\par
an \b apostrophe\b0  "\cf2\b\f1 '\cf0\b0\f0 " may be used to represent any "non-word" character. that is, same as "\\\\W" (the regex syntax "\\W" for a "non-word" character). it may be useful at the (beginning and/or ending) ends of the "phrase" if it can further narrow down the result or you simply want it to be a part of the match.\par

\pard\sa200\sl276\slmult1\par
The \b matches highlighting\b0  feature:\par

\pard\li720\sa200\sl276\slmult1 the \ul default behavior\ulnone  is to highlight no more than a thousand matches (which can improve the response time when too many matches are found.) it can nonetheless be overridden by a long press of your left mouse button on one of the available gui buttons (i.e. go or refresh or back), whereas long press means press it down and hold on for \ul one second or longer\ulnone . therefore, highlighting will cover the whole thing even if the total number of matches is over \ul one thousand\ulnone . this \ul long-press-to-override\ulnone  is not a toggle, it's just an \ul one-off\ulnone  thing, so do it every time you want more than the default.\par

\pard\sa200\sl276\slmult1\par
End of this help page.\par
}
)
	Return HelpPage
}
}	;end of class
Last edited by SundayProgrammer on 11 Jul 2021, 00:14, edited 4 times in total.
User avatar
Kellyzkorner_NJ
Posts: 84
Joined: 20 Oct 2017, 18:33

Re: Text Filter

23 Jun 2021, 15:24

SundayProgrammer wrote:
20 Jun 2021, 23:47
SundayProgrammer wrote:
07 Jun 2021, 13:09
hi @Kellyzkorner_NJ, thank you for letting me know the error. i myself did hit this a few times during testing, but can never repeat it immediately. are you having this problem consistently?

by the way, the _cwi_ (current window id) global variable is set by the wm_activate function via onmessage. the "other windows" message simply means the active window is other than those created from the "tf" object (the text filter and its associated windows).
i think i have found the "Oops..." problem of my "wm_activate" function, which requires myself or any developers using this to note about. that is, at the moment when a window is created, its title doesn't meet the "wm_activate" checking. and it only becomes "met" (the checking) thereafter by changing/updating its title which won't trigger "wm_activate" to update the global variable "_cwi_".

two ways to fix it: either make sure the window title meets the "wm_activate" checking at the moment when the window is born, or execute "wm_activate(1)" after its window title becomes "met".
Hi, that's great! Thanks for keeping an eye on out that.
SundayProgrammer
Posts: 143
Joined: 25 Dec 2020, 12:26

Re: Text Filter

30 Jun 2021, 20:46

the script is updated. → viewtopic.php?p=406242#p406242 ← click this link

star-two-a made three tweaks.
SundayProgrammer
Posts: 143
Joined: 25 Dec 2020, 12:26

Re: Text Filter

07 Jul 2021, 02:45

the script is updated. → viewtopic.php?p=406242#p406242 ← click this link

star-two-b added a feature to load the text in reverse order, by line.
SundayProgrammer
Posts: 143
Joined: 25 Dec 2020, 12:26

Re: Text Filter

11 Jul 2021, 00:18

the script is updated. → viewtopic.php?p=406242#p406242 ← click this link

star-two-c two adjustments are made, and a trivial feature is added.
fenchai
Posts: 292
Joined: 28 Mar 2016, 07:57

Re: Text Filter

12 Jul 2021, 16:46

I feel like this would be better if you could make a simple function or class to use this feature, also please update the initial post where the example script is still not updated.

I have also learned that not eveyone will enjoy the given GUI, they prefer to create their own one or just add a feature to their own GUIs.

that's just my 2 cents :) great work, I can see you are dedicated.
SundayProgrammer
Posts: 143
Joined: 25 Dec 2020, 12:26

Re: Text Filter

12 Jul 2021, 21:14

fenchai wrote:
12 Jul 2021, 16:46
that's just my 2 cents :) great work, I can see you are dedicated.
i'm not. very kind, thank you.
fenchai wrote:
12 Jul 2021, 16:46
I feel like this would be better if you could make a simple function or class to use this feature, also please update the initial post where the example script is still not updated.
not sure what exactly you referring to:

about "this feature" << the trivial one from star-two-c ?

about "initial post ... example script" << the one in the very first post of this topic/thread ?
fenchai wrote:
12 Jul 2021, 16:46
I have also learned that not eveyone will enjoy the given GUI, they prefer to create their own one or just add a feature to their own GUIs.
i'm actually interested to know what feature people like/dislike. (it will be a bonus to me.)

btw, i wonder where did you learn it from ? i wanted to learn it too.
fenchai wrote:
12 Jul 2021, 16:46
they prefer to create their own one or just add a feature to their own GUIs.
i will absolutely be delighted if people can share with me how their own gui looks like. (hoped people have the time and feel okay to do it.)
fenchai
Posts: 292
Joined: 28 Mar 2016, 07:57

Re: Text Filter

14 Jul 2021, 10:47

This is one of my projects I use frequently, I think I also posted a very simple example GUI here on the forum.
https://ibb.co/6t5ypyW

This search system is not very complex but not as simple as using If InStr() as you can see. It can also search via youtube, google, amazon just by typing a prefix (in my case: "y ", "g ", "a ") ofcourse this has nothing to do with your script, just making my point of why people prefer a simple function or class so that they can use as an add-on to their scripts.
SundayProgrammer
Posts: 143
Joined: 25 Dec 2020, 12:26

Re: Text Filter

14 Jul 2021, 13:59

fenchai wrote:
14 Jul 2021, 10:47
This is one of my projects I use frequently, I think I also posted a very simple example GUI here on the forum.
https://ibb.co/6t5ypyW

This search system is not very complex but not as simple as using If InStr() as you can see. It can also search via youtube, google, amazon just by typing a prefix (in my case: "y ", "g ", "a ") ofcourse this has nothing to do with your script, just making my point of why people prefer a simple function or class so that they can use as an add-on to their scripts.
thank you. although i did not click the link, my best guess is, it's a screenshot of your project. would you mind to paste/upload it directly ? anyhow, thank you.
fenchai
Posts: 292
Joined: 28 Mar 2016, 07:57

Re: Text Filter

14 Jul 2021, 18:08

sure,

Image

cool trick, thanks
Last edited by fenchai on 15 Jul 2021, 08:56, edited 1 time in total.
gregster
Posts: 8968
Joined: 30 Sep 2013, 06:48

Re: Text Filter

14 Jul 2021, 22:12

fenchai wrote:
14 Jul 2021, 18:08
Image

no idea why it's not showing.
Our img-tags won't work with links to html pages acting as a container. To use the img-tags, you have to use a direct link ending on .jpg or .png.
Often, right-clicking the picture and selecting 'open picture in separate tab', or alike, can get you the needed link. In this case, you'd get https://i.ibb.co/HPQKMKH/Snipaste-2021-07-14-10-42-41.png:

Image

Afaik, uploding pictures directly to the forum should work again, too.
SundayProgrammer
Posts: 143
Joined: 25 Dec 2020, 12:26

Re: Text Filter

25 Jul 2021, 04:38

star-three

added a feature for non-alphabetic language (such as 漢字) which enables users to directly enter ime code to search for its corresponding word(s). i call it "user defined matching".

as a consequence, an external file, the udmtable.txt is added (along with the script) for this feature.
currently, two sets of ime code are available in the udmtable. and i think it should not be too difficult for you to add your own/favorites.

the feature currently assumed the target word is all "one character" long. the script can nonetheless be easily adjusted to cater for variable length with a slight modification.

two consecutive apostrophe is the mark for the beginning/ending of any ime code search term. you may also use a single apostrophe in the middle to add extra search term for the same word.

examples:
- ''fung'' then ''fung4'' then ''fung''hei''
- ''leun4'' ''gong''
- ''sqf'' then ''imsqf''
[spoiler3=''sqf'']
egsqf.PNG
egsqf.PNG (244.69 KiB) Viewed 2664 times
[/spoiler3]
[spoiler3=''imsqf'']
egimsqf.PNG
egimsqf.PNG (126.29 KiB) Viewed 2664 times
[/spoiler3]
- ''si'' then ''si6'' then ''si6'a''
- e''hdr''f

i prepared 10 screenshots of the examples above, but it seems to me that there is a ceiling of 3 attachments only. so, may be i spread them in separate posts after this.

that's it for now.

Code: Select all

SetWorkingDir %A_ScriptDir%
RE_Dll := DllCall("LoadLibrary", "Str", "Msftedit.dll", "Ptr")
theArticle=
(
是新生,是醒覺,夢想永遠在世上

壹傳媒結業,評論人擱筆,專頁紛紛消失。七日內,香港萬馬齊喑,新聞千人一面,這時候,我們還可以做什麼?

前兩日,老朋友打電話來,也問我今後做什麼。寫專欄前,我其實有幾份工作,其一是兼職侍應洗碗——那時候,剛和朋友合資經營一間「另類」餐廳,一腳踢,故事說來話長,有機會再寫。

問我做什麼,我於是隨口答:「冇得寫,最多咪洗碗。」聰明的你,該看得出我是說笑,但朋友果然夠朋友,竟認真沉思片刻,然後鄭重回應:「洗碗呀⋯⋯er⋯⋯咁我都信你識洗碗嘅,不過嘥你時間囉。」

我馬上怒吼:「頂你,咩叫『咁我都信你嘅』?如果我話噚晚見到外星人,你答『咁我都信你嘅』就情有可原。但洗碗咋喎,你使唔使講個『信』字呀?你不如話『我可以大膽咁講,你係識洗碗嘅』吖笨。」

雖然反駁得字字鏗鏘,但我其實很心虛:我真是懂得洗碗嗎?記得幼稚園老師常向家母投訴,指控我連剪刀也不懂用,疑心我弱智。十多年前出於好奇,我到工聯會學開鎖,上到第二堂就把鎖弄壞,連老師也開不到。我真係識洗碗?其實我都唔可以咁大膽講。

「我可以做什麼?」除了我,相信最近很多人,不管是移民抑或留下的,都在問。其實我早有答案。二〇一九年我寫過一篇專欄,講方展博如何打敗丁蟹,參照《大時代》劇情,探討人在最壞的時代該做什麼,結論是三件事:

一、唔好死;二、等運到;三,找到自己的世界,投入其中,瘋狂做自己最擅長、最有興趣的事,令自己不斷進步、天天變強。方展博做到這三件事,所以活下來,得到最後勝利。

「唔好死」是本能,「等運到」是無為,大家很容易參透,不必細表。但怎樣才能「找到自己的世界」呢?這問題不是今天獨有,自從盤古初開,人生於世,就一直要面對這個涉及存在的難題。

方展博沒解釋怎知道哪裏是自己的世界,但觀眾可分析出來:他一踏足交易所,即兩眼放光,樂而忘返,彷彿有用不盡的精力——能帶給你無限熱情的,就是你的世界。躺平,什麼也不做,睡到自然醒,你可能覺得這種生活很寫意很ok,但聽過有人會為此興奮嗎?躺平只是眼光光,絕不會兩眼放光。

有熱情的人都很努力,但不知道自己在努力。如果你要很努力地努力,你並沒找到自己的世界。在自己的世界不知疲倦,除了因為熱血沸騰,也因為你在做自己擅長的事,即是說,你在發揮才華,做別人覺得艱難、你卻一蹴而就的事。

沒找到自己的世界,即沒發現自己的才華。這確是難題。我不想無底線地講勵志話,所以必須跟你說:人人都有才華,也可培養才華,但歸根究底,你還是需要一點運氣,方能發現才華。你有,不等於別人看到,甚至不等於你自己知道。

以我為例,在《蘋果日報》由零開始,天天筆耕,朋友問我:「怎可以這樣天天寫?有題材嗎?」都覺得不可思議,我也難以置信。我若說自己沒寫作才華,未免虛偽,但我可以誓神劈願說:寫專欄前,我完全沒發現自己有這能力。我是意外被拋進自己的世界的。

按常理,我不可能在一份香港最多人看的報紙,跟那些成名多年的作家一起寫專欄。我向來不投稿、不識人、甚至懶寫字,難道緣分來了,自然就會成為作家嗎?不是說笑,「緣分」確是關鍵。

我跟專欄結下不解緣,不在編輯或黎生找我寫稿的瞬間,而是在很多年前,我一個人手執稀奇古怪的書,在我家附近海濱公園度過的許多春朝秋夕。當時我瘋狂看課外書,一天十六小時也不倦,比看備考的教科書還認真得多。

黎智英先生曾問我怎學拉丁文,我不想解釋太多,就答在外國的大學唸過。這是事實,但不是事實全部,甚至不是重點。重點是:早在入大學前,我已對着大海學懂了。那段看海的日子,很輕狂,也是我最迷惘的歲月。我不知道將來做什麼,只想做那一刻我最想做的事。

聽來很怪,那時我最想做的事,就是由朝到晚看書,不問值得不值得。吸收知識,尤其是不受課程限制的知識,有種吃禁果的快感,那是我做得最快樂的事。正因年少瘋狂,讓我儲備不少知識,寫專欄時才能從不同維度切入,即使談論哪怕最無聊的時事,也能帶出一些稍有意思的道理。

要找到自己的世界,很難,要碰運氣。你不能控制運氣,但你可以控制自己,透過學習,提高找到那世界的機率。學習除了孜孜矻矻唸書考試,還有很多形式。看一本好書、一齣好戲、一首好詩,只要能啟發你,都是學習。

你的世界是什麼,就做什麼。以我估計,我的世界應該是寫作,不是洗碗或賣卜(雖然朋友都叫我「神棍」)。但在沒稿費的情況下,我不知能撐多久,所以必須開Patreon(Facebook專欄我會繼續公開寫,兩件事無關)。有讀者早已催促我開,但寫什麼呢?我不想分析時局(還有意義嗎?),只想分享知識。

我想起歌德說過:「我們應該每天至少聽一首短歌,唸一首好詩,看一幅好畫,可能的話,說幾句有道理的話。」(Man sollte alle Tage wenigstens ein kleines Lied hören, ein gutes Gedicht lesen, ein treffliches Gemälde sehen und, wenn es möglich zu machen wäre, einige vernünftige Worte sprechen.)

這就是我的宗旨,要給大家介紹美好的事,講些有理的話。從前在《蘋果》寫文,有框框限制,很多創新意念也沒法實現。比如說,我很想每日跟大家講一首古詩,可長可短,學中文之餘,可順勢培養審美能力,甚至邏輯推理能力——對,要賞析一首詩,需要推理。

我也想每星期介紹好看的電影和劇,可新可舊;想用一種有別於江湖術士的方式,有系統有根據地討論術數文化;想談佛理、講耶穌;想介紹精彩的西洋文學,由英文講到拉丁文;想用有趣的方法教文言文;想創作故事,甚至寫武俠小說⋯⋯我要寫十個專欄!

以上夢想,我希望在Patreon實現,但我更希望達成的,是大家在這個崩壞的時代,一起努力變成更好的人。

__________________

馮睎乾十三維度Patreon
)
; tf.start("Load Clipboard")
; msgbox
; tf.start("Load File log.txt")
; msgbox
stf.start(theArticle)
; msgbox
; tf.start()	;from what's leftoff in the object's memory

;multiple instances can be coexisting as below
; w1 := new tf, w1.start("Load Clipboard")
; w2 := new tf, w2.start("Load File log.txt")
; w3 := new tf, w3.start(theArticle)
; msgbox
; w3.start()	;from what's leftoff in the object's memory
Return

Class stf extends tf {
	FlexRxR(ByRef Hays, Nee) {
		global udmTable
	 	v := this.ov
		If Resu := RegExReplace(Hays, this.Maker(Nee))
			Return (Resu, this[v].r := Nee)

Loop, Parse, Nee, % (A_Space, r := "")
	If StrLen(A_LoopField)
	If aPos := RegExMatch(A_LoopField, "''.+''", m)
	{	r .= SubStr(A_LoopField, 1, aPos - 1), rr := SubStr(A_LoopField, aPos + StrLen(m)), tt := SubStr(A_LoopField, aPos + 2, StrLen(m) - 4)
		ss := StrReplace(tt, "''", "`n")
		Loop, Parse, ss, `n
		{	s := StrReplace(A_LoopField, "'", A_Space)
If Resu := RegExReplace(udmTable, this.Maker(s))
{	t := "["
	Loop, Parse, Resu, `n
		t .= SubStr(A_LoopField, 1, 1) ;RegExMatch(A_LoopField, "\s") - 1
	r .= t "]"
}Else r .= A_LoopField
		}r .= rr A_Space
	}Else r .= A_LoopField A_Space
If SubStr(r, 0) = A_Space
	r := SubStr(r, 1, StrLen(r) - 1)
If Resu := RegExReplace(Hays, this.Maker(r))
	Return (Resu, this[v].r := r)

		last_index := 0, s := Nee
		While, pos := RegExMatch(s, "\([^)]+\)|\[[^\]]+\]", m)
			s := SubStr(s, 1, pos - 1) Chr(168) Chr(168 + A_Index) Chr(168) SubStr(s, pos + StrLen(m)), s%A_Index% := m, last_index := A_Index
		Loop, Parse, s
		{	If A_Index > 1
				r .= t A_LoopField
			Else r := A_LoopField
			t := RegExMatch(A_LoopField, "[a-z]") ? "\w{0,3}" : ""
		}
		Loop, % last_index
			i := last_index - A_Index + 1, r := StrReplace(r, Chr(168) Chr(168 + i) Chr(168), s%i%)
		If Resu := RegExReplace(Hays, this.Maker(r))
			Return (Resu, this[v].r := r)

		Loop, Parse, Nee
		{	If A_Index > 1
				r .= t A_LoopField
			Else r := A_LoopField
			t := RegExMatch(A_LoopField, "\w") ? "[\w'\-+]*" : ""
		}
		If Resu := RegExReplace(Hays, this.Maker(r))
			Return (Resu, this[v].r := r)

		Loop, Parse, Nee, % ("", r := "")
			r .= RegExMatch(A_LoopField, "\w") ? "(?=[\w'\-+]*" A_LoopField ")" : ""
		If StrLen(r)
			r .= "\b[\w'\-+]*\b"
		Else Return ""
		If Resu := RegExReplace(Hays, this.Maker(r))
			Return (Resu, this[v].r := r)
		Else Return ("", this[v].r := "")
	}
}	;end of class

FocusedControl() {
	ControlGetFocus, foco, A
	Return foco
}
#If, WinActive("The Text Filter") and FocusedControl() = "Edit1"
	`::
	Tab::ControlFocus, RICHEDIT50W1, A
#If, WinActive("The Text Filter") and FocusedControl() = "RICHEDIT50W1"
	Tab::ControlFocus, Edit1, A
	Space::PgDn
	+Space::PgUp
	s::Home
	e::End
	t::^Home
	b::^End
	-::%_cwi_%.DecrFontSize()
	+::
	=::%_cwi_%.IncrFontSize()
	`::
	Enter::%_cwi_%.TakeThisLine()
	f::%_cwi_%.FindNextMatch()
	+f::%_cwi_%.FindNextMatch(1)
#If, WinActive("TreeView Of Assorted Matches") and FocusedControl() = "SysTreeView321"
	`::
	Enter::%_cwi_%.tvButtonEnter()
#If, WinActive("Context Peeking") and FocusedControl() = "RICHEDIT50W1"
	~WheelUp::
	~WheelDown::%_cwi_%.WheelSearchMode()
#IfWinActive, The Text Filter
	F1::%_cwi_%.ToggleHelpPage(_cwi_)
	~WheelUp::
	~WheelDown::%_cwi_%.WheelSearchMode()
	!a::%_cwi_%.ShowAssMatches()
	^t::%_cwi_%.AssTreeView(_cwi_)
	^p::%_cwi_%.ContextPeek(_cwi_)
	!v::Gosub, PasteHaySub
	^o::Gosub, OpenFileSub
	^r::%_cwi_%.ReloadFile()
#If, WinActive("The Text Filter") and (_bundledRB_ not = "disabled")
	~RButton::%_cwi_%.RClickMenu()
#IfWinActive, ahk_class #32770
	~LButton::EventHandler(0, 0, 0x201, 0)
	~LButton up::EventHandler(0, 0, 0x202, 0)
#IfWinActive

PasteHaySub:
	%_cwi_%[%_cwi_%.ov].eFlag := True
	If _uii_ := %_cwi_%.PasteIntoHaystack()
	{	If _rev_ := RegExMatch(_uii_, "^r\)")
			_uii_ := RegExReplace(_uii_, "^r\)")
		If RegExMatch(_uii_, "(\w+)=(\w+)", _uii_m) and IsObject(%_uii_m2%)
			%_uii_m1% := new %_uii_m2%, %_uii_m1%.start("Load Clipboard", _rev_)
		Else If not InStr(_uii_, "=")
			%_uii_% := new tf, %_uii_%.start("Load Clipboard", _rev_)
	}
	%_cwi_%[%_cwi_%.ov].eFlag := False
	Return

OpenFileSub:
	%_cwi_%[%_cwi_%.ov].eFlag := True
	If _OpFi_ := %_cwi_%.OpenFile()
	{	If _rev_ := RegExMatch(_OpFi_, "^r\)")
			_OpFi_ := RegExReplace(_OpFi_, "^r\)")
		RegExMatch(_OpFi_, "^[\w=]+(?=\t)", _uii_), RegExMatch(_OpFi_, "\t\K.+$", _usf_)
		If RegExMatch(_uii_, "(\w+)=(\w+)", _uii_m) and IsObject(%_uii_m2%)
			%_uii_m1% := new %_uii_m2%, %_uii_m1%.start("Load File " _usf_, _rev_)
		Else If not InStr(_uii_, "=")
			%_uii_% := new tf, %_uii_%.start("Load File " _usf_, _rev_)
	}
	%_cwi_%[%_cwi_%.ov].eFlag := False
	Return

WM_ACTIVATE(wParam) {
	global _cwi_
	If (wParam > 0)
		If WinActive("The Text Filter") or WinActive("TreeView Of Assorted Matches") or WinActive("Context Peeking") or WinActive("Edit Variables")
		{	WinGetTitle, t, A
			If RegExMatch(t, "\| *?(\w*?) *?\|", m) and StrLen(m1)
				_cwi_ := m1
			Else _cwi_ := "Oops..."
		}Else _cwi_ := "Other Windows"
}
EventHandler(wParam, lParam, msg, hwnd) {
	static lbdowntime := 0, dx, dy
	global lbduration := 0
	If msg = 0x201	;WM_LBUTTONDOWN
	{	MouseGetPos, dx, dy
		lbdowntime := A_TickCount
	}Else If msg = 0x202	;WM_LBUTTONUP
		If (lbduration := A_TickCount - lbdowntime) > 1000
		{	MouseGetPos, ux, uy,, moc
			If (moc = "RICHEDIT50W1") and Abs(ux - dx) < 10 and Abs(uy - dy) < 10
				MsgBox,, Prompt, Hang On..., 1
		}
	Return
}

Class tf {
	static o := {}
	v := {}

	start(Param := "", Reverse := 0) {
		global udmTable
		OnMessage(0x6, "WM_ACTIVATE")
		OnMessage(0x201, "EventHandler")	;WM_LBUTTONDOWN
		OnMessage(0x202, "EventHandler")	;WM_LBUTTONUP
		this.id := this.GetObjVarNam(), v := this.ov := (this.id = this.__class ? "o" : "v")
		this[v].Version := "Star-Three"
		If IsFunc(this.FlexRxR) and FileExist("udmTable.txt")
			FileRead, udmTable, udmTable.txt
		If StrLen(Param)
		{	this[v].SelectedFile := ""
			If Param = Load Clipboard
				this[v].Haystack := Clipboard
			Else If SubStr(Param, 1, 9) = "Load File"
				this[v].Haystack := this.FileRead((Reverse ? "<R>" : "") SubStr(Param, 11))
			Else this[v].Haystack := Param
			this[v].Haystack := StrReplace(this[v].Haystack, "`r`n", "`n")
			If Reverse
				theHays := this[v].Haystack, this.ReverseByLine(theHays), this[v].Haystack := theHays

			this[v].Fayt := this[v].Case := this[v].Wwrap := True, this[v].Whole := this[v].Linum := False, this[v].n := 1, this[v].Hs[0] := this[v].GetAddress("Haystack"), this[v].Hs[1] := this[v].Haystack
		}
		this.SlimGui(this.id), this.CleanUp(this.id)
	}
	FileRead(theFile) {
		FileRead, theHays, % (SubStr(theFile, 1, 3) = "<R>" ? SubStr(theFile, 4) : theFile, this[this.ov].SelectedFile := theFile)
		Return theHays
	}
	HsP(n) {
		If (n > 1)
			Return this[this.ov].Hs[n - 1]
		Else Return StrGet(this[this.ov].Hs[0])
	}
	NeeP(n) {
		If (n > 1)
			Return this[this.ov].Needle[n - 1]
		Else Return ""
	}
	GetObjVarNam() {
		r := "(\w+?):.+?\{address: " Format("0x{:X}", &this) "\}"
		Return RegExMatch(this.ListGlobalVars(), r, m) ? m1 : ""
	}

SlimGui(id) {
	static Fayt
	Gui, %id%:New, +Labeltf.sGui_On
	Gui, +Resize +MinSize +MaximizeBox
	Gui, Font, s18, Consolas
	Gui, Add, Edit, xm w280 vFayt
	OnSuch := this.Fayt_OnTyping.Bind(this)
	GuiControl +g, Edit1, % OnSuch
	Gui, Add, Button, x+10 ys h37 w85 Center, 0
	OnSuch := this.Refresh_OnClick.Bind(this)
	GuiControl +g, Button1, % OnSuch
	Gui, Font, s10, Arial
	Gui, Add, Button, x+10 w40 ys h37 Default, A
	OnSuch := this.A_OnClick.Bind(this)
	GuiControl +g, Button2, % OnSuch
	Gui, Add, Button, x+0 w40 ys h37, T
	OnSuch := this.T_OnClick.Bind(this)
	GuiControl +g, Button3, % OnSuch
	Gui, Add, Button, x+0 w40 ys h37, C
	OnSuch := this.C_OnClick.Bind(this)
	GuiControl +g, Button4, % OnSuch
	Gui, Add, Button, x+0 w40 ys h37, F
	OnSuch := this.F_OnClick.Bind(this)
	GuiControl +g, Button5, % OnSuch
	begWwrap := this[this.ov].Wwrap ? "+Wrap" : "+HScroll"
	Gui, Font, s18, Consolas
	Gui, Add, Custom, ClassRICHEDIT50W Section xm h300 w534 %begWwrap% +VScroll +hwndHRE +0x804	;ES_READONLY = 0x800, ES_MULTILINE = 0x4
	this.HRE := HRE, this.RE := this.GetTomDoc(HRE)
	OnSuch := this.RE_OnEvent.Bind(this)
	GuiControl +g, %HRE%, % OnSuch
	Gui, Show,, The Text Filter (Slim)

	this.RenewGui(), WM_ACTIVATE(1)	;show content
}

sGui_OnSize() {
	If A_EventInfo = 1
		Return
	GuiControl, Move, RICHEDIT50W1, % "h" (A_GuiHeight - 76) " w" (A_GuiWidth - 46)
	GuiControl, Move, Button5, % "x" (A_GuiWidth - 62)
	GuiControl, Move, Button4, % "x" (A_GuiWidth - 102)
	GuiControl, Move, Button3, % "x" (A_GuiWidth - 142)
	GuiControl, Move, Edit1, % "w" (A_GuiWidth - 309)
	GuiControl, Move, Button2, % "x" (A_GuiWidth - 182)
	GuiControl, Move, Button1, % "x" (A_GuiWidth - 277)
}

sGui_OnEscape() {
	%A_Gui%.GuiClose(A_Gui)
}

sGui_OnClose() {
	%A_Gui%.GuiClose(A_Gui)
}

Fayt_OnTyping() {
	v := this.ov, n := this[v].n
	If IsFunc(this.eciwbeg)
	{	this[v].Needle[n] := theNeedle := this.Fpat(), this.eciwbeg(theNeedle)
		If not theNeedle = this[v].Needle[n]
			ControlSetText, Edit1, % theNeedle
	}
	Gui, Submit, NoHide
	this[v].Needle[n] := theNeedle := this.Fpat()
	If StrLen(theNeedle)
		this[v].Hs[n] := IsFunc(this.FlexRxR) ? this.FlexRxR(this.HsP(n), theNeedle) : RegExReplace(this.HsP(n), this.Maker(theNeedle))
	Else this[v].Hs[n] := this.HsP(n)
	this.RenewGui(theNeedle)
}

A_OnClick() {
	this.ShowAssMatches()
	ControlFocus, Edit1, A
}

T_OnClick() {
	this.AssTreeView(this.id)
	ControlFocus, Edit1, A
}

C_OnClick() {
	v := this.ov
	If not this[v].Linum
	{	MsgBox, 4, Request Response, Context Peeking Needs Line Numbering`n`nTurn it on now ?
		IfMsgBox, No
			Goto, EndingThis
		this[v].Linum := True, this.Linum_Sub1(), this.Linum_Sub2(), this.RenewGui(this.Fpat())
	}
	this.ContextPeek(this.id)
	EndingThis:
	ControlFocus, Edit1, A
}

F_OnClick() {
	v := this.ov, n := this[v].n, this[v].Needle[n] := this.Fpat(), this[v].eFlag := True
	this.GuiClose(this.id)
	this.BuildGui(this.id)
	GuiControl,, NeedleCB, % "`n" this[v].NeedleHistory
	ControlSetText, Edit1, % this[v].Needle[n], A
	this.RenewGui(this[v].Needle[n]), this[v].eFlag := False
	Send, {End}
}

SwitchToSlim() {
	v := this.ov, n := this[v].n, this[v].Needle[n] := this.Fpat(), this[v].eFlag := True
	this.GuiClose(this.id)
	this.SlimGui(this.id)
	ControlSetText, Edit1, % this[v].Needle[n], A
	this.RenewGui(this[v].Needle[n]), this[v].eFlag := False
	Send, {End}
}

BuildGui(id) {
	global NeedleCB
	static Fayt, Case, Whole, Linum, Wwrap
	v := this.ov

	Gui, %id%:New, +Labeltf.Gui_On
	Gui, +Delimiter`n
	Gui, +Resize +MinSize +MaximizeBox
	Gui, Font, s10, Arial New
	Gui, Add, Text,, O p t i o n s:

	begFayt := this[v].Fayt ? "Checked" : ""
	Gui, Add, Checkbox, ym vFayt %begFayt% Tabstop, Instant Filter (aka Find As You Type)
	OnSuch := this.Fayt_OnToggle.Bind(this)
	GuiControl +g, Button1, % OnSuch

	begCase := this[v].Case ? "Checked" : ""
	Gui, Add, Checkbox, ym vCase %begCase% Tabstop, Case Insensitive
	OnSuch := this.Case_OnToggle.Bind(this)
	GuiControl +g, Button2, % OnSuch

	begWhole := this[v].Whole ? "Checked" : ""
	Gui, Add, Checkbox, ym vWhole %begWhole% Tabstop, Whole Word
	OnSuch := this.Whole_OnToggle.Bind(this)
	GuiControl +g, Button3, % OnSuch

	begLinum := this[v].Linum ? "Checked" : ""
	Gui, Add, Checkbox, ym vLinum %begLinum% Tabstop, Line Number
	OnSuch := this.Linum_OnToggle.Bind(this)
	GuiControl +g, Button4, % OnSuch

	beg_Wrap := this[v].Wwrap ? "Checked" : ""
	Gui, Add, Checkbox, ym vWwrap %beg_Wrap% Tabstop, Word Wrap
	OnSuch := this.Wwrap_OnToggle.Bind(this)
	GuiControl +g, Button5, % OnSuch

	Gui, Font, s18, Arial New
	Gui, Add, Text, xm Section, Filter:

	w := A_ScreenWidth - 330
	Gui, Add, ComboBox, w%w% ys vNeedleCB +hwndhEdit1
	OnSuch := this.Fpat_OnTyping.Bind(this)
	GuiControl +g, %hEdit1%, % OnSuch

	Gui, Add, Button, h38 ys Default, Go
	OnSuch := this.Go_OnClick.Bind(this)
	GuiControl +g, Button6, % OnSuch

	Gui, Font, s10, Arial New
	Gui, Add, Button, h38 ys, Refresh
	OnSuch := this.Refresh_OnClick.Bind(this)
	GuiControl +g, Button7, % OnSuch

	Gui, Font, s18, Arial New
	Gui, Add, Button, h38 ys, Back
	OnSuch := this.Back_OnClick.Bind(this)
	GuiControl +g, Button8, % OnSuch

	h := A_ScreenHeight - 143, w := A_ScreenWidth - 30, begWwrap := this[v].Wwrap ? "+Wrap" : "+HScroll"
	Gui, Font, s18, Consolas
	Gui, Add, Custom, ClassRICHEDIT50W x10 h%h% w%w% %begWwrap% +VScroll +hwndHRE +0x804	;ES_READONLY = 0x800, ES_MULTILINE = 0x4
	this.HRE := HRE, this.RE := this.GetTomDoc(HRE)
	OnSuch := this.RE_OnEvent.Bind(this)
	GuiControl +g, %HRE%, % OnSuch

	h := A_ScreenHeight - 64, w := A_ScreenWidth - 6
	Gui, Show, h%h% w%w%, The Text Filter

	this.RenewGui(), WM_ACTIVATE(1)	;show content
}

RE_OnEvent() {
	global lbduration
	v := this.ov
	If not WinExist("The Text Filter")
		Return
	If (this[v].REseleT = this.RE.Selection.Text)
		Return
	If GetKeyState("RButton", "P")
		Return
	Sleep, 500	;this "sleep" exists with reason
	If GetKeyState("LButton", "P") or GetKeyState("Shift", "P")
		Return
	If not this[v].eFlag and this[v].Linum and WinActive("The Text Filter") and WinExist("Context Peeking  |  " this.id) and StrLen(this.RE.Selection.Text)
	{	this[v].eFlag := True
		n := this[v].n
		slcs := this.RE.Selection.Start, slce := this.RE.Selection.End, SelBegChar := this.RE.Range(slcs, slcs + 1).Text, SelEndChar := this.RE.Range(slce - 1, slce).Text, Hays := this.RE.Range(0, 999999999).Text
		If InStr(A_Priorkey, "WheelUp")
			this.RE.Range(slcs, slcs).Select
		Else maybe := InStr("`r`n", SelEndChar) ? 1 : 0, this.RE.Range(slce - maybe, slce - maybe).Select
		Sleep, 500
		maybe := InStr("`r`n", SelBegChar) and (SelEndChar = A_Space) ? 2 : 1, mpos := this.ULoNLoCR(Hays, slcs + maybe)
		slcs := mpos, mpos := this.DLoNLoCR(Hays, slce + 1)
		this.RE_PeekContext(mpos > StrLen(Hays) ? SubStr(Hays, slcs) : SubStr(Hays, slcs, mpos - slcs))
		this[v].eFlag := False, this[v].REseleT := this.RE.Selection.Text
	}Else If not this[v].eFlag and WinActive("The Text Filter") and StrLen(this.RE.Selection.Text) and Clipboard not = this.RE.Selection.Text
	{	this[v].eFlag := True, slcs := this.RE.Selection.Start
		If InStr("`r`n", SubStr(this.RE.Selection.Text, 0))
			this.RE.Range(slcs, slcs).Select, this.TakeThisLine()
		Else
		{	MsgBox, 259, Request Response, "Yes" = To Copy The Selected Text`n`n"No" = To Take Entire Line
			IfMsgBox, Yes
			{	Clipboard := this.RE.Selection.Text
				Progress, zh0 w380 c10 fs18, `nSelection Copied`n,, Prompt, Segoe UI
				Sleep, 500
				Progress, Off
				If lbduration > 1000
				{	ControlSetText, Edit1, % Trim(Clipboard)
					ControlGetText, TextExists, Static1, % "ahk_id " WinExist("The Text Filter")
					If TextExists
						this.Fpat_OnTyping()
				}
			}IfMsgBox, No
				this.RE.Range(slcs, slcs).Select, this.TakeThisLine()
			Sleep, 500	;this "sleep" exists with reason
		}
		this[v].eFlag := False, this[v].REseleT := this.RE.Selection.Text
	}
}
RE_PeekContext(theOne) {
	cpLnum := RegExReplace(theOne, "^\t? *?(\d+?):.*$", "$1")
	If cpLnum is not digit
		Return
	v := this.ov, Hays := this[v].HaystackN, cpLend := RegExMatch(RegExReplace(Hays, "`n",,, cpLnum - 1), "`n") + cpLnum - 1, mpos := this.ULoNLoCR(Hays, cpLend), cpLbeg := mpos - 1, this[v].xFlag := True, this.CP.Range(cpLbeg, cpLend).Select, this.cpScroIntoView()
	timer := ObjBindMethod(this, "OffxFlag")
	SetTimer, % timer, -1000
}
OffxFlag() {
	this[this.ov].xFlag := False
}

Gui_OnSize() {
	If A_EventInfo = 1
		Return
	GuiControl, Move, RICHEDIT50W1, % "h" (A_GuiHeight - 95) " w" (A_GuiWidth - 14)
}

Gui_OnEscape() {
	%A_Gui%.GuiClose(A_Gui)
}

Gui_OnClose() {
	%A_Gui%.GuiClose(A_Gui)
}
GuiClose(id) {
	Gui, %id%:Destroy
	%id%.CleanUp(id)
}

CleanUp(id) {
	IfExist, tf_%id%Work.rtf
		FileDelete, tf_%id%Work.rtf
	IfExist, tfHelp.rtf
		FileDelete, tfHelp.rtf
}

GetTomDoc(HRE) {	;written by "@just me"
	Static IID_ITextDocument := "{8CC497C0-A1DF-11CE-8098-00AA0047BE5D}"
	DocObj := 0
	If DllCall("SendMessage", "Ptr", HRE, "UInt", 0x043C, "Ptr", 0, "PtrP", IRichEditOle, "UInt")	;EM_GETOLEINTERFACE
	{	DocObj := ComObject(9, ComObjQuery(IRichEditOle, IID_ITextDocument), 1)	; ITextDocument
		ObjRelease(IRichEditOle)
	}
	Return DocObj
}

Fayt_OnToggle() {
	v := this.ov, n := this[v].n
	If not (this[v].Fayt := this.Fayt())
		If (this[v].Hs[n] != this.HsP(n))
		{	this[v].Needle[n] := this.Fpat(), theHaystack := this[v].Hs[n]
			n := (this[v].n += 1), this[v].Hs[n] := theHaystack
			this.UpdateTitle()
		}
	ControlFocus, Edit1, A
	this.Fpat_OnTyping()
}

Case_OnToggle() {
	this[this.ov].Case := this.Case()
	ControlFocus, Edit1, A
	this.Fpat_OnTyping()
}

Whole_OnToggle() {
	this[this.ov].Whole := this.Whole()
	ControlFocus, Edit1, A
	this.Fpat_OnTyping()
}

Linum_OnToggle() {
	v := this.ov
	If this[v].Linum := this.Linum()
		this.Linum_Sub1()
	Else this[v].Hs[0] := this[v].GetAddress("Haystack")
	this.Linum_Sub2()
	this.RenewGui(this.Fpat())
}

Linum_Sub1() {
	v := this.ov
	Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Line Numbering, Segoe UI
	lsl := StrLen(this.LineCount())
	HsN =
	Loop, Parse, % this[v].Haystack, `n`r
		HsN .= SubStr(this.StrRepeat(A_Space, lsl) A_Index, 1 - lsl) ":" A_Space A_LoopField "`n"
	Progress, Off
	this[v].HaystackN := HsN, this[v].Hs[0] := this[v].GetAddress("HaystackN")
}

Linum_Sub2() {
	v := this.ov
	Loop, % this[v].n
		this[v].Hs[A_Index] := IsFunc(this.FlexRxR) ? this.FlexRxR(this.HsP(A_Index), this[v].Needle[A_Index]) : RegExReplace(this.HsP(A_Index), this.Maker(this[v].Needle[A_Index]))
}

Wwrap_OnToggle() {
	v := this.ov, this[v].Wwrap := this.Wwrap(), n := this[v].n, this[v].Needle[n] := this.Fpat()
	this.BuildGui(this.id)
	GuiControl,, NeedleCB, % "`n" this[v].NeedleHistory
	ControlSetText, Edit1, % this[v].Needle[n], A
	this.RenewGui(this[v].Needle[n])
	Send, {End}
}

Fpat_OnTyping() {
	v := this.ov, n := this[v].n
	If IsFunc(this.eciwbeg)
	{	this[v].Needle[n] := theNeedle := this.Fpat(), this.eciwbeg(theNeedle)
		If not theNeedle = this[v].Needle[n]
			ControlSetText, Edit1, % theNeedle
	}
	If not this[v].Fayt and not this[v].CommitLevel
		Return
	Gui, Submit, NoHide
	this[v].Needle[n] := theNeedle := this.Fpat()
	If not StrLen(theNeedle) and this[v].CommitLevel
	{	this[v].CommitLevel := False, this.Back_OnClick()
		Progress, Off
		Return
	}
	theHaystack := IsFunc(this.FlexRxR) ? this.FlexRxR(this.HsP(n), theNeedle) : RegExReplace(this.HsP(n), this.Maker(theNeedle))
	If this[v].CommitLevel
	{	If not StrLen(this[v].NeedleHistory)
			this[v].NeedleHistory := theNeedle, Added := True
		Else If not RegExMatch(this[v].NeedleHistory, (this[v].Case ? "i" : "") "m`a)^\Q" theNeedle "\E$")
			this[v].NeedleHistory := theNeedle "`n" this[v].NeedleHistory, Added := True
		Else Added := False
		If Added
		{	GuiControl,, NeedleCB, % "`n" this[v].NeedleHistory
			ControlSetText, Edit1, % theNeedle
		}
		If (theHaystack = this.HsP(n))
			Progress, zh0 w450 c10 fs18, `nResult No Change Thus Not Anew Level`n,, Prompt, Segoe UI
		Else
		{	If not this[v].Fayt
				this[v].Hs[n] := theHaystack
			If (this.LineCount(n) < 2) and not (theNeedle == this.NeeP(n))
				Progress, zh0 w450 c10 fs18, `nUltimate/Empty Result Reached`nThus Level Not Advanced`n,, Prompt, Segoe UI
			Else
			{	n := (this[v].n += 1), this[v].Hs[n] := theHaystack
				Send, ^a
			}
		}
		this[v].CommitLevel := False
		Sleep, 500
		Progress, Off
	}Else this[v].Hs[n] := theHaystack
	this.RenewGui(theNeedle)
	If not this[v].Fayt and not StrLen(this[v].Hs[n])
	{	Progress, zh0 w450 c10 fs18, `nEmpty Result Reached`n`nFalling Back Now`n,, Prompt, Segoe UI
		Sleep, 1000
		this[v].Hs[n] := this.HsP(n)
		ControlSetText, Edit1, % this.NeeP(n)
		this.RenewGui(this.Fpat())
		Send, ^a
		Progress, Off
	}
}
Maker(t) {
	v := this.ov, t := this.tw4sh(t), r := (this[v].Case ? "i" : "") "m`a)^(?!"
	Loop, Parse, t, % A_Space
		If SubStr(A_LoopField, 1, 1) = "-"
			r .= "(?!.*(" (this[v].Whole ? "\b" : "") SubStr(A_LoopField, 2) (this[v].Whole ? "\b" : "") "))"
		Else r .= "(?=.*(" (this[v].Whole ? "\b" : "") A_LoopField (this[v].Whole ? "\b" : "") "))"
	r .= ").*\R?"
	Return r
}

Go_OnClick() {
	ControlFocus, Edit1, A
	Progress, zh0 w380 c10 fs18, `nCommitting This Level`n,, Prompt, Segoe UI
	this[this.ov].CommitLevel := True, this.Fpat_OnTyping()
}

Refresh_OnClick() {
	this.RenewGui(this[this.ov].Needle[this[this.ov].n] := this.Fpat(), "retain")
}

Back_OnClick() {
	ControlFocus, Edit1, A
	v := this.ov, n := this[v].n, this[v].Needle[n] := this.Fpat()
	If (n = 1) and (this[v].Hs[n] != this.HsP(n))
		this[v].Hs[n] := this.HsP(n), this[v].Needle[n] := ""
	Else If (this[v].Hs[n] = this.HsP(n)) and (this[v].Needle[n] = this.NeeP(n))
		If (n > 2)
			n := (this[v].n -= 2)
		Else If (n = 2)
			n := this[v].n := 1, this[v].Hs[n] := this.HsP(n), this[v].Needle[n] := ""
		Else n := this[v].n := 0
	Else n := (this[v].n -= 1)
	If n
	{	ControlSetText, Edit1, % this[v].Needle[n]
		this.RenewGui(this[v].Needle[n])
		Send, ^a
		If (n = 1) and (this[v].Hs[n] = this.HsP(n))
		{	Progress, zh0 w380 c10 fs18, `nReturned To The Origin`n,, Prompt, Segoe UI
			Sleep, 500
			Progress, Off
		}Else
		{	Progress, zh0 w380 c10 fs18, `nReturned To Level %n%`n,, Prompt, Segoe UI
			Sleep, 500
			Progress, Off
		}
	}Else this.Gui_OnClose()
}

Fpat() {
	GuiControlGet, Fpat,, Edit1
	If not StrLen(Fpat)
		ControlGetText, Fpat, Edit1
	Return Fpat
}
Fayt() {
	GuiControlGet, Fayt,, Button1
	If not StrLen(Fayt)
		ControlGetText, Fayt, Button1
	Return Fayt
}
Case() {
	GuiControlGet, Case,, Button2
	If not StrLen(Case)
		ControlGetText, Case, Button2
	Return Case
}
Whole() {
	GuiControlGet, Whole,, Button3
	If not StrLen(Whole)
		ControlGetText, Whole, Button3
	Return Whole
}
Linum() {
	GuiControlGet, Linum,, Button4
	If not StrLen(Linum)
		ControlGetText, Linum, Button4
	Return Linum
}
Wwrap() {
	GuiControlGet, Wwrap,, Button5
	If not StrLen(Wwrap)
		ControlGetText, Wwrap, Button5
	Return Wwrap
}

RenewGui(theNee := "", AMt := "") {
	global lbduration
	v := this.ov, n := this[v].n
	If this.Fpat() not = theNee
		Goto, WorkInterrupt
	this.ToggleReadOnly(this.HRE, this[v].Wwrap)
	If not this[v].PriorRefreshTime is digit
		this[v].PriorRefreshTime := 0
	If (AMt = "retain") and lbduration < 1000 and A_TickCount - this[v].PriorRefreshTime > 1000
		theHays := this.RE.Range(0, 999999999).Text, this[v].PriorRefreshTime := A_TickCount, this[v].combed := False
	Else If StrLen(AMt) and (AMt not = "retain")
		theHays := this[v][AMt]
	Else If IsFunc(this.Comb) and this.LineCount(n) < 1000 and lbduration < 1000
		theHays := this.Comb(this[v].Hs[n]), this[v].combed := True
	Else theHays := this[v].Hs[n], this[v].combed := False
	ControlSetText, RICHEDIT50W1, %theHays%, A
	indent := (StrLen(this.LineCount()) + 2) * 10, this.RE.Range(0, StrLen(theHays)).SetIndents(-indent, indent, 0)
	If this.Fpat() not = theNee
		Goto, WIP_Interrupt
	r := this.MakerC(IsFunc(this.FlexRxR) ? (this[v].combed ? this[v].combed_r : this[v].r) : theNee)
	If StrLen(theNee) and StrLen(r) and RegExMatch(theHays, r)
	{	Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Matches Highlighting, Segoe UI
 		mpos := 1, mlen := 0
 		While, (mpos := RegExMatch(theHays, r, nm, mpos + mlen)) and (A_Index < 1000 or lbduration > 1000)
 			mlen := StrLen(nm), this.RE.Range(mpos - 1, mpos + mlen - 1).Font.BackColor := 0x00FFFF, npos := mpos
 		lbduration := 0
 		Progress, Off
	}
	If this.RE.Range(0, 19).Text = "Assorted Matches:`t("
	{	Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Assorted Matches Formatting, Segoe UI
 		mpos := 1, mlen := 0
		While, (mpos := RegExMatch(theHays, "\R\d+\. .+?\R\K.+?(?=\R\d+\. .+|\R*$)", nm, mpos + mlen))
 			mlen := StrLen(nm), this.RE.Range(mpos - 1, mpos + mlen - 1).SetIndents(-indent, indent * 2, 0), npos := mpos
 		Progress, Off
	}
	WIP_Interrupt:
	this.ToggleReadOnly(this.HRE, this[v].Wwrap)
	ControlFocus, Edit1, A
	this.UpdateTitle()
	WorkInterrupt:
	GuiControlGet, TextExists,, Static2
	If not TextExists
	{	If StrLen(theNee)and StrLen(r) and RegExMatch(theHays, r)
			RegExReplace(theHays, r,, mc)
		Else mc := 0
		ControlSetText, Button1, %mc%, A
	}
	If this.Fpat() not = theNee
		If TextExists
			this.Fpat_OnTyping()
		Else this.Fayt_OnTyping()
}

UpdateTitle() {
	WinSetTitle, The Text Filter, % ("", v := this.ov, Version := this[v].Version, id := this.id, n := this[v].n, lc := this.LineCount(n), SelectedFile := this[v].SelectedFile), The Text Filter (Version: %Version%)  |  %id%  |  Level %n%  |  Line Count: %lc%  |  %SelectedFile%
}

LineCount(n := 0) {
	If n is digit
		theHays := this.HsP(n + 1)
	Else theHays := n
	StrReplace(theHays, "`n",, lc), lc += StrLen(theHays) and SubStr(theHays, 0) != "`n" ? 1 : 0
	Return lc
}

ToggleReadOnly(HRE, Wwrap) {
	ControlGet, Style, Style,,, ahk_id %HRE%
	If not (Style & 0x800)
		SendMessage, 0x443, 0, 0xF0F0F0,, ahk_id %HRE%	;tune Down BackgroundColor
     SendMessage, 1101, 1, (Style & 0x800) ? (Wwrap ? 0x44 : 0xC4) : (Wwrap ? 0x844 : 0x8C4),, ahk_id %HRE%	;ES_READONLY = 0x800
	If (Style & 0x800)
		SendMessage, 0x443, 0, 0xEEFFFF,, ahk_id %HRE%	;light Up BackgroundColor
}

MakerC(theNee) {
	theNee := this.tw4sh(theNee), r := "", v := this.ov
	Loop, Parse, theNee, % A_Space
		If SubStr(A_LoopField, 1, 1) != "-"
			r .= "(" (this[v].Whole ? "\b" : "") A_LoopField (this[v].Whole ? "\b" : "") ")|"
	If StrLen(r)
	{	If SubStr(r, 0) = "|"
			r := SubStr(r, 1, StrLen(r) - 1)
		r := (this[v].Case ? "i" : "") "m`a)" r
	}
	Return r
}

IncrFontSize() {
	MouseGetPos, mpx, mpy,, moc
	If (moc not = "RICHEDIT50W1")
		MouseMove, 400, 200
	Send, ^{WheelUp}
	If (moc not = "RICHEDIT50W1")
		MouseMove, mpx, mpy
}

DecrFontSize() {
	MouseGetPos, mpx, mpy,, moc
	If (moc not = "RICHEDIT50W1")
		MouseMove, 400, 200
	Send, ^{WheelDown}
	If (moc not = "RICHEDIT50W1")
		MouseMove, mpx, mpy
}

TakeThisLine(id := "RE") {
	slcs := this[id].Selection.Start, slce := this[id].Selection.End, Hays := this[id].Range(0, 999999999).Text
	If (slce > slcs)
	{	Clipboard := this[id].Selection.Text
		Progress, zh0 w380 c10 fs18, `nSelection Copied`n,, Prompt, Segoe UI
		Sleep, 500
		Progress, Off
		Return
	}
	mpos := this.ULoNLoCR(Hays, slce + 1)
	slcs := mpos, mpos := this.DLoNLoCR(Hays, slce + 1)
	this.FinalTouch(mpos > StrLen(Hays) ? SubStr(Hays, slcs) : SubStr(Hays, slcs, mpos - slcs))
}
ULoNLoCR(hays, mpos) {
	While, mpos > 1 and not InStr("`r`n", SubStr(hays, mpos - 1, 1))
		mpos--
	Return mpos
}
DLoNLoCR(hays, mpos) {
	pmax := StrLen(hays)
	While, mpos <= pmax and not InStr("`r`n", SubStr(hays, mpos, 1))
		mpos++
	Return mpos
}

FinalTouch(theOne) {
	Clipboard := RegExReplace(theOne, "^\t?(?: *?\d+?: )?(.*)$", "$1")
	If IsFunc(this.altTakeThisLine)
		this.altTakeThisLine()
	Else MsgBox,,, Has Put This Line Into Clipboard, 3
}

FindNextMatch(Reverse := 0) {
	If StrLen(sPat := this.Fpat())
		r := this.MakerC(IsFunc(this.FlexRxR) ? this[this.ov].r : sPat)
	Else r := "nothing to be matched this"
	slcs := this.RE.Selection.Start, slce := this.RE.Selection.End
	If (slce > slcs) and (RegExMatch(A_ThisHotkey, "^\+?f$") and StrLen(sPat) ? False : not RegExMatch(this.RE.Selection.Text, r))
		r := this.MakerS(this.RE.Selection.Text)
	If StrLen(r) and RegExMatch(Hays := this.RE.Range(0, 999999999).Text, r)
	{	StartHere:
		slcs := this.RE.Selection.Start, slce := this.RE.Selection.End, slcs++, slce++
		cp := Reverse ? slcs : slce
		If Reverse
		{	If cp > 1
			{	mpos := 0, pmax := cp - 1
				Loop
				{	npos := RegExMatch(Hays, r, pm, mpos + 1)
					If npos between 1 and %pmax%
						mpos := npos, nm := pm
					Else Break
				}
				found := (npos > pmax) and mpos > 0
			}
			If not found
			{	mpos := cp - 1, pmax := StrLen(Hays)
				Loop
				{	npos := RegExMatch(Hays, r, pm, mpos + 1)
					If npos between %cp% and %pmax%
						mpos := npos, nm := pm
					Else Break
				}
			}
		}Else mpos := RegExMatch(Hays, r, nm, cp)
		mpos--
		If mpos >= 0
		{	cp := mpos + StrLen(nm)
			this.RE.Range(mpos, cp).Select
		}Else If (mpos < 0) and not Reverse
		{	this.RE.Range(0, 0).Select
			Goto, StartHere
		}
	}
}
MakerS(st) {
	Return (StrLen(st), v := this.ov) ? (this[v].Case ? "i)" : "") (this[v].Whole ? "\b" : "") this.escrx(st) (this[v].Whole ? "\b" : "") : ""
}

WheelSearchMode() {
	MouseGetPos,,,, moc
	If not StrLen(moc) or not InStr("Edit1|RICHEDIT50W1", moc)
	{	IfWinNotActive, The Text Filter
		{	WinActivate % "ahk_id " this[this.ov].ParWin
			WinWaitActive
		}
		ControlFocus, RICHEDIT50W1, A
		this.FindNextMatch(InStr(A_ThisHotkey, "WheelUp"))
	}
}

ShowAssMatches() {
	If this.RE.Range(0, 19).Text = "Assorted Matches:`t("
	{	sPat := this.Fpat()
		If this.RE.Range(19, 31).Text = "Alphabetical"
			this.RenewGui(sPat, "AssHays")
		Else this.RenewGui(sPat, "AAssHays")
		Return
	}
	z := this.ov, n := this[z].n
	If not StrLen(this[z].Hs[n]) or not StrLen(sPat := this.Fpat()) or not StrLen(r := this.MakerC(sPat))
		Return
	r := IsFunc(this.FlexRxR) ? this.MakerC(this[z].r) : r
	Progress, zh0 w300 c10 fs18, `nHang On...`n,, Working On Assortment, Segoe UI
	UniqMatches := [], Seq := 0, this[z].combed := IsFunc(this.Comb) and this.LineCount(n) < 1000
	Loop, Parse, % this[z].Hs[n], `n`r
	{	mpos = 1
		worknm:
		npos := RegExMatch(A_LoopField, r, nm, mpos), C_LoopField := this[z].combed ? Trim(this.Comb(A_LoopField)) : ""
		If npos
		{	If UniqMatches.HasKey(nm)
				Ums := UniqMatches[nm], AssHays%Ums% .= InStr(AssHays%Ums%, A_LoopField) ? "" : ("`n" A_LoopField, cAssHays%Ums% .= this[z].combed ? "`n" C_LoopField : "")
			Else
				Seq++, UniqMatches[nm] := Seq, AssHays%Seq% := nm "`n" A_LoopField, cAssHays%Seq% := this[z].combed ? nm "`n" C_LoopField : ""
			mpos := npos + StrLen(nm)
			Goto, worknm
		}
	}
	If Seq
	{	UniqHays := tvAAssHays := cAAssHays := "", umNoSort := []
		For k, v in UniqMatches
			UniqHays .= "`n" this.StrRepeat(A_Space, 3) A_Index ".`t" k, tvAAssHays .= "`n" A_Index ". " AssHays%v%, cAAssHays .= this[z].combed ? "`n" A_Index ". " cAssHays%v% : "", umNoSort[v] ? umNoSort[v].Insert(k) : umNoSort[v] := k
		AAssHays := "Assorted Matches:`t(Alphabetical Order)" UniqHays "`n" this.StrRepeat("-", 50) (this[z].combed ? cAAssHays : tvAAssHays)
		UniqHays := tvAssHays := cAssHays := ""
		For k, v in umNoSort
			UniqHays .= "`n" this.StrRepeat(A_Space, 3) k ".`t" v, tvAssHays .= "`n" A_Index ". " AssHays%k%, cAssHays .= this[z].combed ? "`n" A_Index ". " cAssHays%k% : ""
		AssHays := "Assorted Matches:`t(Chronological Order)" UniqHays "`n" this.StrRepeat("-", 50) (this[z].combed ? cAssHays : tvAssHays)
		this[z].AssHays := AssHays, this[z].AAssHays := AAssHays, this[z].tvAssHays := tvAssHays, this[z].tvAAssHays := tvAAssHays
		this.RenewGui(sPat, "AssHays")
	}
	Progress, Off
}

AssTreeView(id) {
	If this.RE.Range(0, 19).Text not = "Assorted Matches:`t("
		Return
	parwin := this[v].ParWin := WinExist("A")
	Gui, tv%id%:New, +Owner%parwin%
	Gui, +Resize +MinSize +MaximizeBox
	Gui, +Labeltf.tvGui_On
	Gui, Font, s18, Consolas
	Gui, Add, Text,, % this.RE.Range(19, 31).Text = "Alphabetical" ? "Assorted Matches: (Alphabetical Order)" : "Assorted Matches: (Chronological Order)"
	;Gui, Add, Button, Hidden Default, Enter
	Gui, Add, TreeView, AltSubmit Section xm w545
	OnSuch := this.tvEventHdlr.Bind(this)
	GuiControl +g, SysTreeView321, % OnSuch
	Seq := 0, aHays := this.RE.Range(19, 31).Text = "Alphabetical" ? this[this.ov].tvAAssHays : this[this.ov].tvAssHays, lc := this.LineCount(aHays) - 1
	Loop, Parse, aHays, `n`r
		If StrLen(A_LoopField)
			If RegExMatch(A_LoopField, "^ *\d+\.[ \t]")
				Seq++, P%Seq% := TV_Add(A_LoopField), Num := 0
			Else Num++, P%Seq%C%Num% := TV_Add(A_LoopField, P%Seq%)
	Gui, Show, x97 y539 h283, TreeView Of Assorted Matches  |  %id%  |  Line Count: %lc%
	GuiControl, Focus, SysTreeView321
}

tvGui_OnSize() {
	If A_EventInfo = 1
		Return
	GuiControl, Move, SysTreeView321, % "h" (A_GuiHeight - 76) " w" (A_GuiWidth - 46)
}

tvGui_OnEscape() {
	Gui, %A_Gui%:Destroy
}

tvGui_OnClose() {
	Gui, %A_Gui%:Destroy
}

tvEventHdlr() {
	If InStr("DoubleClick|S|K|Normal", A_GuiEvent)
		TV_GetText(theOne, TV_GetSelection())
	this[this.ov].theOne := theOne
	If A_GuiEvent = DoubleClick
		IfWinExist, % "Context Peeking  |  " this.id
			this.RE_PeekContext(theOne)
		Else this.tvButtonEnter()
}

tvButtonEnter() {
	this.FinalTouch(this[this.ov].theOne)
}

PasteIntoHaystack() {
	global _cwi_
	If StrLen(Clipboard)
	{	InputBox, id, Object Instance Identification, No space is allowed and please keep it short. Accept the given ID means not to create a new window but replace the content of the current one.`nExample: "joy=stf" (in which`, "=stf" is optional. Enter it only when you need a specific class.),,,,,,,, % _cwi_
		If not ErrorLevel and StrLen(Trim(id))
		{	If Reverse := RegExMatch(id, "[-/]\s*[rR]$")
				id := RegExReplace(id, "[-/]\s*[rR]$")
			If RegExMatch(id, "[^\w=]")
				id := RegExReplace(id, "[^\w=]")
			If RegExMatch(id, "\w+=(\w+)", m) and IsObject(%m1%)
				Return (Reverse ? "r)" id : id)
			If InStr(id, "=")
				MsgBox, Invalid Input
			Else If (id = _cwi_)
				this.start("Load Clipboard", Reverse)
			Else Return (Reverse ? "r)" id : id)
		}
	}Else MsgBox, Clipboard is empty
}

OpenFile() {
	global _cwi_
	FileSelectFile, SelectedFile
	If StrLen(SelectedFile)
	{	InputBox, id, Object Instance Identification, No space is allowed and please keep it short. Accept the given ID means not to create a new window but replace the content of the current one.`nExample: "joy=stf" (in which`, "=stf" is optional. Enter it only when you need a specific class.),,,,,,,, % _cwi_
		If not ErrorLevel and StrLen(Trim(id))
		{	If Reverse := RegExMatch(id, "[-/]\s*[rR]$")
				id := RegExReplace(id, "[-/]\s*[rR]$")
			If RegExMatch(id, "[^\w=]")
				id := RegExReplace(id, "[^\w=]")
			ido := (Reverse ? "r)" id : id)
			If RegExMatch(id, "\w+=(\w+)", m) and IsObject(%m1%)
				Return ido "`t" SelectedFile
			If InStr(id, "=")
				MsgBox, Invalid Input
			Else If (id = _cwi_)
				this.start("Load File " SelectedFile, Reverse)
			Else Return ido "`t" SelectedFile
		}
	}
}

ReloadFile() {
	If StrLen(SelectedFile := this[this.ov].SelectedFile)
	{	If Reverse := (SubStr(SelectedFile, 1, 3) = "<R>")
			SelectedFile := SubStr(SelectedFile, 4)
		this.start("Load File " SelectedFile, Reverse)
	}
}

RClickMenu() {
	global lbduration
	MouseGetPos, xb4, yb4
	While, GetKeyState("RButton", "P")
		Continue
	MouseGetPos, rbx, rby, mow, moc
	If Abs(rbx - xb4) > 10 or Abs(rby - yb4) > 10
		Return
	If (mow = (HGUI := WinExist("A"))) and rby > 30
		If (moc = "Button8")
			this.ShowTrail()
		Else If (moc not = "Edit1")
		{	Menu, myMenu, Add
			Menu, myMenu, DeleteAll
			If IsFunc(this.EditVars)
			{	Menu, myMenu, Add, Edit Variables, MenuHandler
				Menu, myMenu, Add
			}
			Menu, myMenu, Add, Show Assorted Matches, MenuHandler
			If this.RE.Range(0, 19).Text = "Assorted Matches:`t("
				Menu, myMenu, Add, Put Assorted Matches In TreeView, MenuHandler
			If this[this.ov].Linum and not WinExist("Context Peeking  |  " this.id)
			{	Menu, myMenu, Add
				Menu, myMenu, Add, Context Peeking, MenuHandler
			}
			Menu, myMenu, Add
			Menu, myMenu, Add, Increase Font Size, MenuHandler
			Menu, myMenu, Add, Decrease Font Size, MenuHandler
			Menu, myMenu, Add
			Menu, myMenu, Add, Paste Into The Base, MenuHandler
			Menu, myMenu, Add, Open A File, MenuHandler
			Menu, myMenu, Add, Reload The File, MenuHandler
			Menu, myMenu, Add
			ControlGetText, TextExists, Static1, ahk_id %HGUI%
			If TextExists
				Menu, myMenu, Add, Switch To Slim Gui, MenuHandler
			Else Menu, myMenu, Add, Switch To Full-Blown Gui, MenuHandler
			Menu, myMenu, Add
			Menu, myMenu, Add, List Global Variables, MenuHandler
			If (moc = "RICHEDIT50W1")
			{	Menu, myMenu, Add
				Menu, myMenu, Add, Copy The Line/Selection, MenuHandler
				Menu, myMenu, Add, Go To Rightmost Of The Line, MenuHandler
				Menu, myMenu, Add, Go To Leftmost Of The Line, MenuHandler
				Menu, myMenu, Add, Go To The Bottom, MenuHandler
				Menu, myMenu, Add, Go To The Top, MenuHandler
				Menu, myMenu, Add, Page Down, MenuHandler
				Menu, myMenu, Add, Page Up, MenuHandler
			}
			Menu, myMenu, Add
			Menu, myMenu, Add, Downward Find Next Match, MenuHandler
			Menu, myMenu, Add, Upward Find Next Match, MenuHandler
			Menu, myMenu, Add
			Menu, myMenu, Add, Override The 1K Default, MenuHandler
			Menu, myMenu, Add
			Menu, myMenu, Add, Show/Hide Help Page, MenuHandler
			Menu, myMenu, Show
		}
	Return
	MenuHandler:
		WinWaitActive, ahk_id %HGUI%
		If A_ThisMenuItem = Edit Variables
			this.EditVars(this.id)	;basically for debugging purpose
		Else If A_ThisMenuItem = Show Assorted Matches
			this.ShowAssMatches()
		Else If A_ThisMenuItem = Put Assorted Matches In TreeView
			this.AssTreeView(this.id)
		Else If A_ThisMenuItem = Context Peeking
			this.ContextPeek(this.id)
		Else If A_ThisMenuItem = Increase Font Size
			this.IncrFontSize()
		Else If A_ThisMenuItem = Decrease Font Size
			this.DecrFontSize()
		Else If A_ThisMenuItem = Paste Into The Base
			Gosub, PasteHaySub
		Else If A_ThisMenuItem = Open A File
			Gosub, OpenFileSub
		Else If A_ThisMenuItem = Reload The File
			this.ReloadFile()
		Else If A_ThisMenuItem = Switch To Slim Gui
			this.SwitchToSlim()
		Else If A_ThisMenuItem = Switch To Full-Blown Gui
			this.F_OnClick()
		Else If A_ThisMenuItem = List Global Variables
			this.start(this.ListGlobalVars())
		Else If A_ThisMenuItem = Copy The Line/Selection
		{	If this.RE.Selection.End = this.RE.Selection.Start
				MouseClick, Left, rbx, rby
			this.TakeThisLine()
		}Else If A_ThisMenuItem = Go To Rightmost Of The Line
		{	MouseClick, Left, rbx, rby
			Send, {End}
		}Else If A_ThisMenuItem = Go To Leftmost Of The Line
		{	MouseClick, Left, rbx, rby
			Send, {Home}
		}Else If A_ThisMenuItem = Go To The Bottom
		{	MouseClick, Left, rbx, rby
			Send, ^{End}
		}Else If A_ThisMenuItem = Go To The Top
		{	MouseClick, Left, rbx, rby
			Send, ^{Home}
		}Else If A_ThisMenuItem = Page Down
		{	MouseClick, Left, rbx, rby
			Send, {PgDn}
		}Else If A_ThisMenuItem = Page Up
		{	MouseClick, Left, rbx, rby
			Send, {PgUp}
		}Else If A_ThisMenuItem = Downward Find Next Match
		{	ControlFocus, RICHEDIT50W1, A
			this.FindNextMatch()
		}Else If A_ThisMenuItem = Upward Find Next Match
		{	ControlFocus, RICHEDIT50W1, A
			this.FindNextMatch(1)
		}Else If A_ThisMenuItem = Override The 1K Default
			lbduration := 1234, this.RenewGui(this.Fpat(), "retain")
		Else If A_ThisMenuItem = Show/Hide Help Page
			this.ToggleHelpPage(this.id)
		Return
}

ShowTrail() {
	HGUI := WinExist("A"), v := this.ov, n := this[v].n
	Menu, myTrail, Add
	Menu, myTrail, DeleteAll
	While, A_Index < n
	{	tn := n - A_Index, theNeedle := this[v].Needle[tn], lc := this.LineCount(tn)
		Menu, myTrail, Add, Level &%tn% remains %lc% lines after this filter: %theNeedle%, BtsLevel
	}
	lc := this.LineCount()
	Menu, myTrail, Add, Origin %lc% lines (Level &0), BtsLevel
	Menu, myTrail, Show
	Return
	BtsLevel:
		WinWaitActive, ahk_id %HGUI%
		n -= A_ThisMenuItemPos
		If n < 1
			n := this[v].n := 1, this[v].Hs[n] := this.HsP(n), this[v].Needle[n] := ""
		Else this[v].n := n
		ControlSetText, Edit1, % this[v].Needle[n]
		this.RenewGui(this[v].Needle[n])
		Return
}

ToggleHelpPage(id) {
	theFile = tf_%id%Work.rtf
	If this.RE.Range(0, 17).Text = "H e l p _ P a g e"
		IfExist, %theFile%
			this.RE.Open(theFile, 0x01, 0)
		Else this.RenewGui(this.Fpat())
	Else
	{	IfExist, %theFile%
			this.RE.Save(0, 0, 0)
		Else this.RE.Save(theFile, 0x01, 0)
		helpfile = tfHelp.rtf
		IfExist, % helpfile
			FileDelete, % helpfile
		FileAppend, % this.HelpPage(), % helpfile
		this.RE.Open(helpfile, 0x01, 0)
	}
}

ContextPeek(id) {
	v := this.ov
	If not this[v].Linum
		Return
	parwin := this[v].ParWin := WinExist("A")
	Gui, cp%id%:New, +Owner%parwin%
	Gui, +Resize +MinSize +MaximizeBox
	Gui, +Labeltf.cpGui_On
	Gui, Font, s12, Arial New
	Gui, Add, Button,, Close
	OnSuch := this.cpBclose.Bind(this)
	GuiControl +g, Button1, % OnSuch
	Gui, Add, Button, ys, Maximize
	OnSuch := this.cpBmaxim.Bind(this)
	GuiControl +g, Button2, % OnSuch
	Gui, Add, Button, ys, Restore
	OnSuch := this.cpBresto.Bind(this)
	GuiControl +g, Button3, % OnSuch
	Gui, Add, Button, ys, Minimize
	OnSuch := this.cpBminim.Bind(this)
	GuiControl +g, Button4, % OnSuch
	Gui, Font, s18, Consolas
	Gui, Add, Custom, ClassRICHEDIT50W xm Section +Wrap +VScroll +hwndHCP +0x804	;ES_READONLY = 0x800, ES_MULTILINE = 0x4
	this.HCP := HCP, this.CP := this.GetTomDoc(HCP)
	OnSuch := this.cpEventHdlr.Bind(this)
	GuiControl +g, RICHEDIT50W1, % OnSuch
	x := A_ScreenWidth/2, h := A_ScreenHeight - 94, w := A_ScreenWidth - 6, lc := this.LineCount()
	Gui, Show, x%x% y51 h%h% w%w%, Context Peeking  |  %id%  |  Line Count: %lc%
	Progress, zh0 w300 c10 fs18, `nHang On...`n,, Loading Origin, Segoe UI
	GuiControl,, RICHEDIT50W1, % this[v].HaystackN
	GuiControl, Focus, RICHEDIT50W1
	this.ToggleReadOnly(this.HCP, this[v].Wwrap)
	indent := (StrLen(lc) + 2) * 10, this.CP.Range(0, StrLen(this[v].HaystackN)).SetIndents(-indent, indent, 0)
	SendMessage, 0x443, 0, 0xF0F0F0,, ahk_id %HCP%	;tune Down BackgroundColor
	this.ToggleReadOnly(this.HCP, this[v].Wwrap)
	Progress, Off
}

cpScroIntoView() {
	GuiControlGet, gCPg, Pos, % this.HCP
	this.CP.Selection.ScrollIntoView(0), slcs := this.CP.Selection.Start, slce := this.CP.Selection.End
	this.CP.Range(cp := this.CfromP(this.HCP, 1, this.PfromC(this.HCP, slcs) + gCPgH / 2), cp).Select
	WinActivate, % "Context Peeking  |  " this.id
	WinWaitActive
	this.CP.Range(slcs, slce).Select
	this[this.ov].CPseleT := this.CP.Selection.Text
}
CfromP(hE, x := -1, y := -1) {
	VarSetCapacity(RECT, 16, 0)
	SendMessage 0xB2,, &RECT,, ahk_id %hE%	;EM_GETRECT
	LefP := NumGet(RECT, 0, "Int"), TopP := NumGet(RECT, 4, "Int"), RigP := NumGet(RECT, 8, "Int"), BotP := NumGet(RECT, 12, "Int")
	VarSetCapacity(PoL, 8, 0), NumPut(x < 0 ? RigP : x, PoL,, "Int"), NumPut(y < 0 ? BotP : y, PoL, 4, "Int")
	SendMessage 0xD7,, &PoL,, ahk_id %hE%	;EM_CHARFROMPOS
	Return ErrorLevel
}
PfromC(hE, i) {
	VarSetCapacity(PoL, 8, 0)
	SendMessage 0xD6, &PoL, i,, ahk_id %hE%	;EM_POSFROMCHAR
	Return NumGet(PoL, 4, "Int")
}

cpGui_OnSize() {
	If A_EventInfo = 1
		Return
	GuiControl, Move, RICHEDIT50W1, % "h" (A_GuiHeight - 65) " w" (A_GuiWidth - 30)
}

cpGui_OnEscape() {
	Gui, %A_Gui%:Destroy
}

cpGui_OnClose() {
	Gui, %A_Gui%:Destroy
}

cpBclose() {
	Gui, %A_Gui%:Destroy
}

cpBmaxim() {
	WinGet, wMM, MinMax, A
	If wMM = 1	;already maximized
		WinRestore, A
	Else WinMaximize, A
	GuiControl, Focus, RICHEDIT50W1
}

cpBresto() {
	static x := A_ScreenWidth/2, h := A_ScreenHeight - 94, w := A_ScreenWidth - 6
	WinGet, wMM, MinMax, A
	If wMM = 0	;already restored
	{	WinGetPos, GuiX,,,, A
		If (GuiX + x >= A_ScreenWidth)
			Gui, Show, x-5 y51 h%h% w%w%
		Else Gui, Show, x%x% y51 h%h% w%w%
	}Else WinRestore, A
	GuiControl, Focus, RICHEDIT50W1
}

cpBminim() {
	WinMinimize, A
}

cpEventHdlr() {
	global lbduration
	IfWinActive, Context Peeking
	{	ControlGetFocus, foco, A
		If (foco not = "RICHEDIT50W1")
		{	MouseGetPos,,, mow, moc
			If not (mow = WinExist("Context Peeking") and InStr(moc, "Button"))
				GuiControl, Focus, RICHEDIT50W1
		}
	}
	v := this.ov
	If (this[v].CPseleT = this.CP.Selection.Text)
		Return
	If GetKeyState("RButton", "P")
		Return
	Sleep, 500	;this "sleep" exists with reason
	If GetKeyState("LButton", "P") or GetKeyState("Shift", "P")
		Return
	If not this[v].xFlag and WinActive("Context Peeking") and StrLen(this.CP.Selection.Text)
	{	this[v].xFlag := True, slcs := this.CP.Selection.Start
		If InStr("`r`n", SubStr(this.CP.Selection.Text, 0))
			this.CP.Range(slcs, slcs).Select, this.TakeThisLine("CP")
		Else
		{	MsgBox, 259, Request Response, "Yes" = To Copy The Selected Text`n`n"No" = To Take Entire Line
			IfMsgBox, Yes
			{	Clipboard := this[v].CPseleT := this.CP.Selection.Text
				Progress, zh0 w380 c10 fs18, `nSelection Copied`n,, Prompt, Segoe UI
				Sleep, 500
				Progress, Off
				If lbduration > 1000
				{	WinMinimize
					ControlSetText, Edit1, % Trim(Clipboard), % "ahk_id " this[v].ParWin
				}
			}IfMsgBox, No
				this.CP.Range(slcs, slcs).Select, this.TakeThisLine("CP")
			Sleep, 500	;this "sleep" exists with reason
		}
		this[v].xFlag := False, this[v].CPseleT := this.CP.Selection.Text
	}
}

tw4sh(t) {
	tog := "\/", va := "?\\'\w", ph := "[^" va "\n]", tar := "\" tog ph "*?\K[" va "]", ph := "[^\w\n]"
	If mpos:=RegExMatch(t, tar)	;contained toggle (on)
	{	pb := "[^\w\n]", sh := "((?<=^|" ph ")", st := "(?=(\W|$)))"
		skip_c := skip_w := yb := False
		r := StrReplace(SubStr(t, 1, mpos - 1), tog) sh, rr := xx := ""
		Loop
		{	c := SubStr(t, mpos, 1), cc := SubStr(t, mpos + 1, 1)
			If skip_c
				skip_c--
			Else If SubStr(t, mpos, StrLen(tog)) = tog	;toggle (off) encountered
			{	this.flush(r, xx, pb, yb, st), rr := xx := ""
				mpos += StrLen(tog), npos := mpos
				If mpos:=RegExMatch(t, tar,, npos)	;found next toggle (on)
					r .= StrReplace(SubStr(t, npos, mpos - npos), tog) sh, rr := xx := ""
				Else
				{	r .= SubStr(t, npos)
					Break
				}
				Continue
			}Else If RegExMatch(c, "\w") or (c = "?")	;valid character
			{	If rr
					If not skip_w and ((cc not = "/") or StrLen(xx))
						this.flush(r, xx, pb, yb)
					Else If (cc = "/") and not StrLen(xx)
					{	If SubStr(t, mpos + 2, 1) = "/"
							skip_w := skip_w ? skip_w : True, skip_c++
						skip_c++
					}Else{}
				Else If StrLen(rr)
					r .= xx sh, rr := xx := ""
				r .= (c = "?") ? (skip_w ? "\w" : ("\w+?", yb++)) : c (skip_w ? "" : ("\w*?", yb++)), skip_w -= skip_w ? 1 : 0, rr := True
			}Else If (c = A_Space) and rr
				this.flush(r, xx, pb, yb, st), xx := A_Space, rr := 0
			Else If (c = "'")
				xx .= "\W"
			Else If (c = "\") and skip_w not < 0
				If (cc == "Q")
					skip_c++, skip_w := -1, this.flush(r, xx, pb, yb)
				Else If (cc == "E")
					skip_c++, skip_w := False
				Else If (cc = c)
					xx .= c
				Else If RegExMatch(cc, "\w")
					skip_c++, xx .= cc
				Else skip_c++, xx .= c cc
			Else xx .= c
			mpos++
			If (mpos > StrLen(t))	;exceeded
			{	If rr
					this.flush(r, xx, pb, yb, st), rr := xx := ""
				Break
			}
		}
	}Else r := t
	Return r
}

flush(ByRef r, ByRef xx, pb, ByRef yb, st := "") {
	mb := "[^,;\w\n.?!]+?", ss := SubStr(xx, -1), sc := (ss == "\W") or (ss == "\s") or (ss == "\t") or (ss == "\r") or (ss == "\n"), r .= xx ? (RegExMatch(SubStr(xx, 1, 1), "\w") ? mb : pb "*?") xx (st ? ")" : (RegExMatch(ss, "\\?\w$") and not sc ? "" : pb "*?")) : (st ? st : (yb ? (mb, yb--) : "")), xx := ""
}

StrRepeat(string, times) {
	Loop, %times%
		output .= string
	Return output
}
escrx(h) {
	e := "\().[]*+?{}^$|"

	Loop, Parse, e
		If InStr(h, A_LoopField)
			h := StrReplace(h, A_LoopField, "\" A_LoopField)

	Return h
}
ReverseByLine(ByRef text, delimiter := "`n") {
	array := StrSplit(SubStr(text, 0) = delimiter ? SubStr(text, 1, StrLen(text) - 1) : text, delimiter), mi := array.MaxIndex()
	Loop, % mi
		If A_Index > 1
			text .= array[mi - A_Index + 1] delimiter
		Else text := array[mi] delimiter
}
ListGlobalVars() {	;written by Lexikos
	static hwndEdit, pSFW, pSW, bkpSFW, bkpSW

	If !hwndEdit
	{	dhw := A_DetectHiddenWindows
		DetectHiddenWindows, On
		Process, Exist
		ControlGet, hwndEdit, Hwnd,, Edit1, ahk_class AutoHotkey ahk_pid %ErrorLevel%
		DetectHiddenWindows, %dhw%

		astr := A_IsUnicode ? "astr":"str"
		ptr := A_PtrSize=8 ? "ptr":"uint"
		hmod := DllCall("GetModuleHandle", "str", "user32.dll")
		pSFW := DllCall("GetProcAddress", ptr, hmod, astr, "SetForegroundWindow")
		pSW := DllCall("GetProcAddress", ptr, hmod, astr, "ShowWindow")
		DllCall("VirtualProtect", ptr, pSFW, ptr, 8, "uint", 0x40, "uint*", 0)
		DllCall("VirtualProtect", ptr, pSW, ptr, 8, "uint", 0x40, "uint*", 0)
		bkpSFW := NumGet(pSFW+0, 0, "int64")
		bkpSW := NumGet(pSW+0, 0, "int64")
	}

	If (A_PtrSize=8)
	{	NumPut(0x0000C300000001B8, pSFW+0, 0, "int64")	;return TRUE
		NumPut(0x0000C300000001B8, pSW+0, 0, "int64")	;return TRUE
	}Else
	{	NumPut(0x0004C200000001B8, pSFW+0, 0, "int64")	;return TRUE
		NumPut(0x0008C200000001B8, pSW+0, 0, "int64")	;return TRUE
	}

	ListVars

	NumPut(bkpSFW, pSFW+0, 0, "int64")
	NumPut(bkpSW, pSW+0, 0, "int64")

	ControlGetText, text,, ahk_id %hwndEdit%

	RegExMatch(text, "sm)(?<=^Global Variables \(alphabetical\)`r`n-{50}`r`n).*", text)
	Return text
}
HelpPage() {
HelpPage=
(
{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Arial;}{\f1\fnil\fcharset0 Consolas;}}
{\colortbl ;\red255\green0\blue0;\red155\green0\blue211;\red0\green77\blue187;\red0\green176\blue80;\red0\green0\blue255;}
{\*\generator Riched20 10.0.19041}\viewkind4\uc1 
\pard\sa200\sl276\slmult1\b\fs36\lang9 H e l p _ P a g e\b0\par
\par
\cf1\b F1\cf0\b0  - to toggle this help page\par
\par
\b Basic syntax by example:\b0\par

\pard\li720\sa200\sl276\slmult1 coexisting words/strings/patterns -unwanted\par
for instance, \cf2\b\f1 d.*d -the and -oo \\ws\cf0\b0\f0\par
(the 5 segments (space separated) above can go all at once, and yet, they can also be entered one by one. that's the so-called multilevel approach, instead.)\par

\pard\sa200\sl276\slmult1\par
\b Feature keys:\b0\par

\pard\li720\sa200\sl276\slmult1\cf3\b Alt+a\cf0\b0  - to show assorted matches and toggle between chronological and alphabetical order.\par
\cf3\b Ctrl+t\cf0\b0  - to put assorted matches into a treeview gui which may ease the exploration when the list is long and involved multiple groups.\par
\cf3\b Ctrl+p\cf0\b0  - to bring up context peeking gui which provides an integrated way of reviewing the context of any lines in the shortlisted result.\par
\cf3\b WheelDown\cf0\b0  - to find the next match (downward) from the caret position (given that, the mouse pointer is currently outside both text/edit boxes.)\par
\cf3\b WheelUp\cf0\b0  - to find the next match (upward) from the caret position (given that, the mouse pointer is currently outside both text/edit boxes.)\par
\cf3\b Alt+v\cf0\b0  - to paste clipboard content into the big text/edit box.\par
\cf3\b Ctrl+o\cf0\b0  - to open a file.\par
\cf3\b Ctrl+r\cf0\b0  - to reload the file.\par
\cf3\b Rightclick\cf0\b0  "Back" button - to glance committed levels and select one to fall back to.\par
\cf3\b Esc\cf0\b0  - to quit/exit/leave. same as closing the window.\par
\cf3\b Tab\cf0\b0  - to change focus between the text/edit boxes (just try it.)\par
\par
these below only work when the \ul big\ulnone  text/edit box is in focus:\par

\pard\li1440\sa200\sl276\slmult1\cf3\b f\cf0\b0  - to find the next match (downward) from the caret position.\par
\cf3\b Shift+f\cf0\b0  - to find the next match (upward) from the caret position.\par
\i (note: "the line" refers to the current line, that's where the caret is on.)\i0\par
\cf3\b Doubleclick\cf0\b0  - to copy the line/selection.\par
\cf3\b Enter\cf0\b0  - to copy the line/selection.\par
\cf3\b Space\cf0\b0  - to page down\par
\cf3\b Shift+Space\cf0\b0  - to page up\par
\cf3\b s\cf0\b0  - to move the caret to the beginning/start of the line.\par
\cf3\b e\cf0\b0  - to move the caret to the end of the line.\par
\cf3\b t\cf0\b0  - to move the caret to the top of the text.\par
\cf3\b b\cf0\b0  - to move the caret to the bottom of the text.\par
\cf3\b + or =\cf0\b0  - to increase font size (same as \cf3\b Ctrl+WheelUp\cf0\b0 ).\par
\cf3\b minus "-"\cf0\b0  - to decrease font size (same as \cf3\b Ctrl+WheelDown\cf0\b0 ).\par
\i (side note: "caret" may be known as "cursor" to some people.)\i0\par

\pard\sa200\sl276\slmult1\par
\tab these below only work when the \ul small\ulnone  text/edit box is in focus:\par

\pard\li1440\sa200\sl276\slmult1\cf3\b Enter\cf0\b0  - to commit a level (which makes the current result becoming the base/source of the next level.) same as clicking the button Go.\par

\pard\sa200\sl276\slmult1\par

\pard\li720\sa200\sl276\slmult1\cf3\b Backtick (``)\cf0\b0  - since users mostly use this tool to locate the specific line of text and copy it for whatever subsequent actions to be taken, which typically involves Tab and then Enter (if the first line is the one wanted), backtick is an alternative which can supersede both keys by just hit backtick twice instead.\par

\pard\sa200\sl276\slmult1\par
The \b improvised shorthand\b0  feature:\par

\pard\li720\sa200\sl276\slmult1 this feature can be triggered through "\cf2\b\\/\cf0\b0 " (a \b backslash\b0  followed by a \b slash\b0 ), a "regex like" syntax style, which toggle it on or off. so, enter "\cf2\b\\/tr\cf0\b0 " will bring you those lines contained "\cf4\i the road\cf0\i0 ", "\cf4\i two roads\cf0\i0 ", as well as "\cf4\i them really\cf0\i0 " out of the poem, whereas enter "\cf2\b oo \\/a?a\cf0\b0 " or "\cf2\b\\/a?a\\/ oo\cf0\b0 " will return you these two lines "\cf4\i And looked down one as far as I could\cf0\i0 " and "\cf4\i Then took the other, as just as fair,\cf0\i0 " in which, the "\cf2\b ?\cf0\b0 " represents any valid character regex recognized it as "word" element. Besides, the space has been cared so that the toggle works across it. for instance, enter "\cf2\b\\/tr yw\cf0\b0 " or "\cf2\b\\/yw tr\cf0\b0 " will show this line "\cf4\i Two roads diverged in a yellow wood,\cf0\i0 " where the space is still a separator as always, even though the shorthand feature is toggled on.\par

\pard\sa200\sl276\slmult1\par
\tab three more elements of the shorthand syntax:\par
\par

\pard\fi-360\li1800\sa200\sl276\slmult1 1, \b extra qualifier\b0  (within a single word);\par
2, \b escape character\b0  (between words);\par
3, a single \b character\b0  representing any "\b non-word\b0 " one (between words).\par

\pard\sa200\sl276\slmult1\par

\pard\li720\sa200\sl276\slmult1 the most basic usage of improvised shorthand is to match the specific "phrase" by just entering the first letter of each word constituted it (for instance, "\cf2\b sameto\cf0\b0 " can match "\cf4\i some are more equal than others\cf0\i0 ") yet sometimes we may want to further narrow down the result. if "\cf2\b slh\cf0\b0 " brings you both "\cf4\i she likes him\cf0\i0 " and "\cf4\i she loves him\cf0\i0 ", an extra qualifier to pinpoint one may be useful. it could simply be a "v" for this example hence "\cf2\b slv/h\cf0\b0 " (in which, the "/" after the "v" tells the system that it's just an extra qualifier to the "l", not for a word starts with "v",) returns you "\cf4\i she loves him\cf0\i0 " only. likewise, you may sometimes want to tell the system exactly what the word should be ending with, for instance, if "\cf2\b ioy\cf0\b0 " brings you both "\cf4\i i owe you\cf0\i0 " and "\cf4\i i own you\cf0\i0 ", "\cf2\b ioe//y\cf0\b0 " (in which, the "//" after the "e" tells the system that it's a word ending character, that is, "oe//" represents a word starts with "o" and ends with "e") returns you "\cf4\i i owe you\cf0\i0 " only. and no matter how rare (and impractical) it may be, you may have multiple of these qualifiers for a word, such as, "\cf2\b cm/c/e//d//\cf0\b0 " can match the word "\cf4\i complicated\cf0\i0 " whereas "\cf2\b td/i/u//s//\cf0\b0 " can match the word "\cf4\i tedious\cf0\i0 ".\par
\par
a \b backslash\b0  "\cf2\b\\\cf0\b0 " may be used to escape a single character after it. its target should be a "word" character because you don't need to escape otherwise. for all "non-word" character, just enter them directly except "\\" itself which requires a \b double backslash\b0  "\cf2\b\\\\\cf0\b0 " for a single one. for regex syntax such as "\\s", it becomes "\\\\s" (not "\\\\\\s" you may presume.) in other words, all escaped character will only be matched barely itself. for \ul consecutive\ulnone  "word" characters that need to be escaped, enclose them in the \cf2\b\\Q\cf0\b0  \cf2\b\\E\cf0\b0  pair, similar idea as in regex. one thing to note though, escaped character may affect the word immediately after it, for instance, "\cf2\b z\\xy\cf0\b0 " may bring you "\cf4\i zebra xylophone\cf0\i0 " rather than "\cf4\i zombie x yesterday\cf0\i0 ".\par
\par
an \b apostrophe\b0  "\cf2\b\f1 '\cf0\b0\f0 " may be used to represent any "non-word" character. that is, same as "\\\\W" (the regex syntax "\\W" for a "non-word" character). it may be useful at the (beginning and/or ending) ends of the "phrase" if it can further narrow down the result or you simply want it to be a part of the match.\par

\pard\sa200\sl276\slmult1\par
The \b matches highlighting\b0  feature:\par

\pard\li720\sa200\sl276\slmult1 the \ul default behavior\ulnone  is to highlight no more than a thousand matches (which can improve the response time when too many matches are found.) it can nonetheless be overridden by a long press of your left mouse button on one of the available gui buttons (i.e. go or refresh or back), whereas long press means press it down and hold on for \ul one second or longer\ulnone . therefore, highlighting will cover the whole thing even if the total number of matches is over \ul one thousand\ulnone . this \ul long-press-to-override\ulnone  is not a toggle, it's just an \ul one-off\ulnone  thing, so do it every time you want more than the default.\par

\pard\sa200\sl276\slmult1\par
End of this help page.\par
}
)
	Return HelpPage
}
}	;end of class
SundayProgrammer
Posts: 143
Joined: 25 Dec 2020, 12:26

Re: Text Filter

25 Jul 2021, 04:47

egfung.PNG
egfung.PNG (246.42 KiB) Viewed 2663 times
egfung4.PNG
egfung4.PNG (135.6 KiB) Viewed 2663 times
egfunghei.PNG
egfunghei.PNG (108.16 KiB) Viewed 2663 times
SundayProgrammer
Posts: 143
Joined: 25 Dec 2020, 12:26

Re: Text Filter

25 Jul 2021, 04:49

egsi.PNG
egsi.PNG (258.45 KiB) Viewed 2663 times
egsi6.PNG
egsi6.PNG (264.8 KiB) Viewed 2663 times
egsi6a.PNG
egsi6a.PNG (273.34 KiB) Viewed 2663 times
SundayProgrammer
Posts: 143
Joined: 25 Dec 2020, 12:26

Re: Text Filter

25 Jul 2021, 04:51

egleun4gong.PNG
egleun4gong.PNG (93.73 KiB) Viewed 2663 times
egehdrf.PNG
egehdrf.PNG (12.08 KiB) Viewed 2663 times
User avatar
Kellyzkorner_NJ
Posts: 84
Joined: 20 Oct 2017, 18:33

Re: Text Filter

29 Sep 2021, 11:20

@SundayProgrammer I was wondering if your last iteration of this fantastic script is to translate, converting to letters? I'm sorry for being thick about this if I'm wrong. Thanks again for this, I use it often.
SundayProgrammer
Posts: 143
Joined: 25 Dec 2020, 12:26

Re: Text Filter

30 Sep 2021, 14:12

Kellyzkorner_NJ wrote:
29 Sep 2021, 11:20
@SundayProgrammer I was wondering if your last iteration of this fantastic script is to translate, converting to letters? I'm sorry for being thick about this if I'm wrong. Thanks again for this, I use it often.
@Kellyzkorner_NJ i'm glad you you like it, and thank you for letting me know. i myself use it everyday.

for the "last iteration", it's about being all the way stay in english, yet, can search text in other languages directly. (a) no need to change language, back and forth, at operating system level. (b) nor need to go through the "normal" inputting process which usually involved looking up the right one from a matched word list (a typical "'ime" way of doing thing), word by word, until the whole search term is completely entered in that language. and (c) don't even need to bother installing a language pack if that language pack hasn't yet been installed in the machine, one is using for the task.
User avatar
Kellyzkorner_NJ
Posts: 84
Joined: 20 Oct 2017, 18:33

Re: Text Filter

21 Oct 2021, 23:42

@SundayProgrammer Thanks very much for the explanation. :)

Kelly

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 47 guests