A helpful editing tool.

Post your working scripts, libraries and tools for AHK v1.1 and older
l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 02 Dec 2023, 00:30

I can get the information out... That's not the problem. First the Edit box only does `n's which means no matter what the text says the only value existing is a `n. Next the text has "CR+LF" feeds or "`n's" depending on user input, naturally. If I attempt to FileRead and there are "`n's" in the file I couldn't count on Fileread to know that's what they are... So instead I have to programically write that the user pressed +{enter} or just {enter} and have a way to actually keep up with it for reuse and consistency to the user's desire. See?

User avatar
boiler
Posts: 17184
Joined: 21 Dec 2014, 02:44

Re: A helpful editing tool.

Post by boiler » 02 Dec 2023, 00:36

OK, so use totally different characters to track what the user intended. I was just explaining how to use the parsing loop and StrSplit, not how you differentiate between what the user typed.

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 02 Dec 2023, 01:00

It's cool :lol: I am enjoying creating this project actually. I just wanted to do something a little more implicit instead of explicit... That way the user really wasn't aware of the differences.

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 02 Dec 2023, 21:10

On enter and shift enter are added. They both come with a hash code of \|/CR+LF\|/ and \|/Softreturn\|/. They have not been plugged into fileappend or anything except a message that tells you which lines to find their respective written locations. (meaning the differences will be lost if They aren't functioned to do something). of course plugging in a send code, a clear Cache\Temp.txt, and clear edit box is quite simple at those lines.

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)

FileRead, contents, % Temp
if (ErrorLevel == 1)
{
	FileAppend, This is a new user., % Temp, UTF-8
	contents:=% "This is a new user."
}

CoordMode, Caret, Screen
CoordMode, Mouse, Screen
Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, Add, Edit, r39 ym+25 x100 vWords w325 h500 hwndTracker,
Gui, Margin, 50, 30
Gui, Show, h600 w500, AI work
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, margin, 0, 0
Gui, Show, , Words
WinSet, Transparent, 0, Words
WinActivate, AI
GuiControl, AI:, Edit1, % contents
Sleep, 10000

historyarray:= []
ustring:= []

Loop,
{
	dif:= 0
	winwonder:=WinWonder()
	if (winwonder == "False")
	{
		Sleep, 500
		Continue
	}
	history:= GetHistory()
	userinput:= GetControl("Text")
	userarray:=ReturnLineArray(userinput, "Edit")
	histarray:= ReturnLineArray(history, "TXT")
	dif:= ReturnDif(userarray, histarray, "lines")
	if (dif == 0)
	{
		Sleep, 25
		Continue
	}
	s_harray:= Ret_Arr(histarray, dif)
	s_uarray:= Ret_Arr(userarray, dif)
	nstring:= ReturnDif(s_harray, s_uarray, "words")
	if (nstring == "NotFound")
		MsgBox, The text could not be found!
	usmiss:= s_uarray["wordPos" nstring]
	usfix:= s_harray["wordPos" nstring]
	usmiss:= RegExFix(usmiss, 1)
	usfix:= RegExFix(usfix, 1)
	wefixed:= RegExReplace(usmiss, usfix, "") ; Reg ex special characters that need replaced first are \.*?+[{|()^$
	Global wefixed:= RegExFix(wefixed, 2)
	ourlength:= StrLen(wefixed)
	if (ourlength < 2)
	{
		SpellChecker(0)
		Sleep, 500
		Continue
	}
	if (ourlength > 3)
	{
		ourwords:=WordCheck(wefixed, ourlength)
		if (ourwords == "")
			Continue
		SpellChecker(ourlength)
		GetControl(ourwords)
	}
	historyLength:=0
	userLength:= 0
}
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		str:= StrLen(wefixed)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		SpellChecker(0)
	}
	else
		Send, `t
}
else
	Send, `t
Return

~Space::
winwonder:=WinWonder()
if (winwonder != "False")
{
	sleep, 150
	userinput:= GetControl("Text")
	FileMove, % Cache "\Temp.txt", % Cache "\Tem.txt", 1
	FileAppend, % userinput, % Cache "\temp.txt", UTF-8
	SpellChecker(0)
}
return

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	line:= GetControl("Line")
	history:= GetHistory()
	StringReplace, history, history, \|/CR+LF\|/, (hardreturn)\|/CR+LF\|/, ALL
	StringReplace, history, history, \|/Softreturn\|/, (softreturn)\|/Softreturn\|/, ALL
	contents:= StrSplit(history, ["\|/CR+LF\|/", "\|/Softreturn\|/"])
	for Index, con in contents
	{
		if (Index == line)
			list:=% list con "\|/Softreturn\|/"
		else
		{
			StringReplace, con, con, (hardreturn), \|/CR+LF\|/, ALL
			StringReplace, con, con, (softreturn), \|/Softreturn\|/, ALL
			list:=% list con
		}
	}
	MsgBox, % "you will find this message box on line 145 in the ahk file... this is where a file append location for this can go`n" list
	list:= ; of couse list 
}	
return

~Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	line:= GetControl("Line")
	history:= GetHistory()
	StringReplace, history, history, \|/CR+LF\|/, (hardreturn)\|/CR+LF\|/, ALL
	StringReplace, history, history, \|/Softreturn\|/, (softreturn)\|/Softreturn\|/, ALL
	contents:= StrSplit(history, ["\|/CR+LF\|/", "\|/Softreturn\|/"])
	for Index, con in contents
	{
		if (Index == line)
			list:=% list con "\|/CR+LF\|/"
		else
		{
			StringReplace, con, con, (hardreturn), \|/CR+LF\|/, ALL
			StringReplace, con, con, (softreturn), \|/Softreturn\|/, ALL
			list:=% list con
		}
	}
	MsgBox, %  "you will find this message box on line 170 in the ahk file... this is where a file append location for this can go`n" list
	list:=
}	
return

;~Backspace::
;winwonder:=WinWonder()
;if (winwonder != "False")
;{
	; an unknow decision for this... maybe update edit differences of maybe just not needed.
;}
return

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	WinActivate, AI
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	WinGet, visible, Transparent, Words
	if (n == 0)
		WinSet, Transparent, 0, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	if ((visible == 0)&&(n != 0))
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	Return
}

RegExFix(string, n)
{
	if (n == 1)
	{
		StringReplace, string, string, \, \\, ALL
		StringReplace, string, string, ., \., ALL
		StringReplace, string, string, *, \*, ALL
		StringReplace, string, string, ?, \?, ALL
		StringReplace, string, string, +, \+, ALL
		StringReplace, string, string, [, \[, ALL ;]
		StringReplace, string, string, {, \{, ALL
		StringReplace, string, string, |, \|, ALL
		StringReplace, string, string, (, \(, ALL
		StringReplace, string, string, ), \), ALL
		StringReplace, string, string, ^, \^, ALL
		StringReplace, string, string, $, \$, ALL
		Return % string
	}
	if (n == 2)
	{
		StringReplace, string, string, \\, \, ALL
		StringReplace, string, string, \., ., ALL
		StringReplace, string, string, \*, *, ALL
		StringReplace, string, string, \?, ?, ALL
		StringReplace, string, string, \+, +, ALL
		StringReplace, string, string, \[, [, ALL ;]
		StringReplace, string, string, \{, {, ALL
		StringReplace, string, string, \|, |, ALL
		StringReplace, string, string, \(, (, ALL
		StringReplace, string, string, \), ), ALL
		StringReplace, string, string, \^, ^, ALL
		StringReplace, string, string, \$, $, ALL
		Return % string
	}
}

ReturnLineArray(lines, n)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/Softreturn\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

ReturnDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			uinput:= uarray["linePos" x]
			hinput:= harray["linePos" x]
			l_uinput:= StrLen(uinput)
			l_hinput:= StrLen(hinput)
			if (uinput != hinput)
				Return % x
			if (l_uinput != l_hinput)
				Return % x
			if (x == v) 
				Break
		}
		Return % "0"
	}
	if (dif == "words")
	{
		Loop
		{
			x++
			uinput:= uarray["wordPos" x]
			hinput:= harray["wordPos" x]
			if (uinput != hinput)
				Return % x
			else if (x == v)
				Break
		}
		Return % "0"
	}
	Return
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return "True"
	}
}

Ret_Arr(linearray, place)
{
	array:=[]
	sentence:= linearray["linePos" place]
	words:= StrSplit(sentence, A_Space)
	for Index, word in words
	{
		array["wordPos" Index]:= word
	}
	Return % array
}

GetLineCount(data, count)
{
	if (count == "Edit")
	{
		contents:= StrSplit(contents, ["\|/CR+LF\|/", "\|/Softreturn\|/"])
		for Index, cont in contents
		{
			x++
			if (Index == x)
				y:=% x
		}
	}
	if (count == "TXT")
	{
		contents:= StrSplit(text, "\|/Softreturn\|/")
		for Index, cont in contents
		{
			x++
			if (Index == x)
				y:=% x
		}
	}
	Return % y
}

GetHistory()
{
	FileRead, contents, % Temp
	StringReplace, contents, contents, `r`n,\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, \|/Softreturn\|/, ALL
	Return % contents
}

GetControl(FocTex)
{
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, % InFocus
	GuiControlGet, Word, Words:, Listbox1
	ControlGet, line, CurrentLine, , % InFocus
	StringReplace, text, text, `n, \|/Softreturn\|/, ALL
	if (FocTex == "Line")
		Return % line
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	x:=0
	GuiControl, Words:, Listbox1, | 
	Loop, Parse, % FocTex, |
		x++
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

Timer()
{
	Sleep, 500
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
}
	
RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitapp

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 02 Dec 2023, 21:16

I'll Also be adding the FileAppend (using the above stated hash codes) to overwrite the Cache\Temp.txt file.

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 04 Dec 2023, 01:03

This now will save updated information using the hash codes previously spokey about. I believe I have found a use for backspace... It is likely a user will delete a return feed. if a user does that it dynamically changes how the cache responds. A Save on backspace in the event of a line change for the return feed may need to be implemented to salvage the now lost return feed (basically the program won't save a deleted return feed and when you put in a return feel the line count will appear to be the same {at least untill space is used which may cause errors period throughout everything}).

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)

IniRead, Rest, % Cache "\Settings.ini", Timers, Key1
If (Rest == "ERROR")
{
	IniWrite, 10000, % Cache "\Settings.ini", Timers, Key1
	Rest:= 10000
}
IniRead, Notactive, % Cache "\Settings.ini", Timers, Key2
if (WinInactive == "ERROR")
{
	IniWrite, 500, % Cache "\Settings.ini", Timers, Key2
	Notactive:= 500
}
IniRead, NoDif, % Cache "\Settings.ini", Timers, Key3
if (NoDif == "ERROR")
{
	IniWrite, 25, % Cache "\Settings.ini", Timers, Key3
	NoDif:= 25
}

FileRead, contents, % Temp
if (ErrorLevel == 1)
{
	FileAppend, This is a new user., % Temp, UTF-8
	contents:=% "This is a new user."
}
contents:=HashContents(contents)

Menu, Settings, Add, Timers, Timers
Menu, Settings, Add, AlwaysOnTop`ton/off, Always
Menu, Settings, Add, Suspend`ton/off, SusOnOff
Menu, Settings, Add, Reload`tCtrl+r, Reload
Menu, AIsMenu, Add, Settings, :Settings

CoordMode, Caret, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Window
Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, Menu, AIsMenu
Gui, Add, Edit,  0x200  r39 ym+25 x100 vWords w325 h500 hwndTracker,
Gui, Add, Text, ym+555 x380 vInformation, Loading...
Gui, Margin, 50, 30
Gui, Show, h600 w500, AI work
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, margin, 0, 0
Gui, Show, , Words
ProcessStart(contents, Rest)

historyarray:= []
ustring:= []

Loop,
{
	dif:= 0
	winwonder:=WinWonder()
	if (winwonder == "False")
	{
		Sleep, % Notactive
		Continue
	}
	history:= GetHistory()
	userinput:= GetControl("Text")
	userarray:=ReturnLineArray(userinput, "Edit")
	histarray:= ReturnLineArray(history, "TXT")
	dif:= ReturnDif(userarray, histarray, "lines")
	if (dif == 0)
	{
		GuiControl, AI:, Information, Idle status
		Sleep, % NoDif
		Continue
	}
	s_harray:= Ret_Arr(histarray, dif)
	s_uarray:= Ret_Arr(userarray, dif)
	nstring:= ReturnDif(s_harray, s_uarray, "words")
	if (nstring == "NotFound")
		MsgBox, The text could not be found!
	usmiss:= s_uarray["wordPos" nstring]
	usfix:= s_harray["wordPos" nstring]
	usmiss:= RegExFix(usmiss, 1)
	usfix:= RegExFix(usfix, 1)
	wefixed:= RegExReplace(usmiss, usfix, "") ; Reg ex special characters that need replaced first are \.*?+[{|()^$
	Global wefixed:= RegExFix(wefixed, 2)
	ourlength:= StrLen(wefixed)
	if (ourlength < 2)
	{
		GuiControl, AI:, Information, Working...
		SpellChecker(0)
		Sleep, 500
		Continue
	}
	if (ourlength > 3)
	{
		GuiControl, AI:, Information, Working.
		ourwords:=WordCheck(wefixed, ourlength)
		if (ourwords == "")
			Continue
		SpellChecker(ourlength)
		GetControl(ourwords)
	}
	historyLength:=0
	userLength:= 0
}
Return

SusOnOff:
Suspend, Toggle
if (A_IsSuspended == 1)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOn
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOff
Return

Always:
WinSet, AlwaysOnTop, Toggle, AI
WinGet, ExStyle, ExStyle, AI
if (ExStyle == 0x00000180)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOff
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOn
Return

Timers:
Gui, Timers:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, y25, Rest Timer:`t`n(in seconds)
Gui, Add, Text, y75 xs, Window Not Active:`t`n(in milliseconds)
Gui, Add, Text, y125 xs, Process Loop timer:`t`n(in milliseconds)
Gui, Add, Edit, w250 r3 ys-15 -VScroll, This timer slows the script before it gets to the main loop function. It's used to help in processing the global function "Speller."
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the script when the it is not active.
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the main processing loop while typing. It's dependent on a difference created in the main edit control.
Gui, Add, Edit, ys xs+400 w50 y25
Gui, Add, UpDown, vRangeInSeconds Range1-50, 10
Gui, Add, Edit, ys xs+400 w50 y75
Gui, Add, UpDown, vRangeInMillisecondsOfActive Range1-1000, 500
Gui, Add, Edit, ys xs+400 w50 y125
Gui, Add, UpDown, vRangeInMillisecondsOfProcess Range1-100, 25
Gui, Add, Text, xm+10 ym+180, Select the above values to your personal preferences and click save to keep the changes.
Gui, Add, Text, xm+80 ym+215, (Note you have to restart the program to force the changes)
Gui, Add, Button, ym+210 xs+425 gSave, Save
Gui, Add, Button, ym+210 xs+370 gCancel, Cancel
Gui, Margin, 20, 50
Gui, Show, h250 w500, Timers
Control, Disable ,, Edit1, Timers
Control, Disable ,, Edit2, Timers
Control, Disable ,, Edit3, Timers
Return

Reload:
^r::
Reload
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		str:= StrLen(wefixed)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		SpellChecker(0)
	}
	else
		Send, `t
}
else
	Send, `t
Return

~Space::
winwonder:=WinWonder()
if (winwonder != "False")
{
	sleep, 175
	history:= GetHistory()
	StringReplace, history, history, \|/CR+LF\|/, (hardreturn)\|/CR+LF\|/, ALL
	StringReplace, history, history, \|/Softreturn\|/, (softreturn)\|/Softreturn\|/, ALL
	userinput:= GetControl("Text")
	userarray:=ReturnLineArray(userinput, "Edit")
	histarray:= ReturnLineArray(history, "TXT")
	dif:= ReturnClearDif(userarray, histarray, "lines")
	uinput:= userarray["linePos" dif]
	hinput:= histarray["linePos" dif]
	StringReplace, userinput, history, % hinput, % uinput, All
	StringReplace, userinput, userinput, (hardreturn)\|/CR+LF\|/, \|/CR+LF\|/, ALL
	StringReplace, userinput, userinput, (softreturn)\|/Softreturn\|/, \|/Softreturn\|/, ALL
	FileMove, % Cache "\Temp.txt", % Cache "\Tem.txt", 1
	FileAppend, % userinput, % Cache "\temp.txt", UTF-8
	SpellChecker(0)
}
return

ReturnClearDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			hinput:= harray["linePos" x]
			hsplit:= StrSplit(hinput, ["(hardreturn)", "(softreturn)"])
			for Index, h in hsplit
			{
				if (Index == 1)
					checkh:= % h
			}
			uinput:= uarray["linePos" x]
			StringReplace, uinput, uinput, (softreturn), , ALL
			StringReplace, uinput, uinput, (hardreturn), , ALL
			l_checkh:= StrLen(checkh)
			l_uinput:= StrLen(uinput)
			if (uinput != checkh)
				Return % x
			if (l_checkh != l_uinput)
				Return % x
			if (x == v)
				Break
			checkh:=
		}
		Return % "0"
	}
}

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	line:= GetControl("Line")
	history:= GetHistory()
	StringReplace, history, history, \|/CR+LF\|/, (hardreturn)\|/CR+LF\|/, ALL
	StringReplace, history, history, \|/Softreturn\|/, (softreturn)\|/Softreturn\|/, ALL
	contents:= StrSplit(history, ["\|/CR+LF\|/", "\|/Softreturn\|/"])
	for Index, con in contents
	{
		if (Index == line)
			list:=% list con "\|/Softreturn\|/"
		else
		{
			StringReplace, con, con, (hardreturn), \|/CR+LF\|/, ALL
			StringReplace, con, con, (softreturn), \|/Softreturn\|/, ALL
			list:=% list con
		}
	}
	FileMove, % Cache "\Temp.txt", % Cache "\Tem.txt", 1
	FileAppend, % list, % Cache "\temp.txt", UTF-8
	list:= ; of couse list 
}	
return

~Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	line:= GetControl("Line")
	history:= GetHistory()
	StringReplace, history, history, \|/CR+LF\|/, (hardreturn)\|/CR+LF\|/, ALL
	StringReplace, history, history, \|/Softreturn\|/, (softreturn)\|/Softreturn\|/, ALL
	contents:= StrSplit(history, ["\|/CR+LF\|/", "\|/Softreturn\|/"])
	for Index, con in contents
	{
		if (Index == line)
			list:=% list con "\|/CR+LF\|/"
		else
		{
			StringReplace, con, con, (hardreturn), \|/CR+LF\|/, ALL
			StringReplace, con, con, (softreturn), \|/Softreturn\|/, ALL
			list:=% list con
		}
	}
	FileMove, % Cache "\Temp.txt", % Cache "\Tem.txt", 1
	FileAppend, % list, % Cache "\temp.txt", UTF-8
	list:=
}	
return

Cancel:
Gui, Timers:Destroy
Return

Save:
Gui, Submit, NoHide
RangeInSeconds:=(RangeInSeconds*1000)
IniWrite, % RangeInSeconds, % Cache "\Settings.ini", Timers, Key1
IniWrite, % RangeInMillisecondsOfActive, % Cache "\Settings.ini", Timers, Key2
IniWrite, % RangeInMillisecondsOfProcess, % Cache "\Settings.ini", Timers, Key3
Gui, Timers:Destroy
Return

;~Backspace::
;winwonder:=WinWonder()
;if (winwonder != "False")
;{
	; an unknow decision for this... maybe update edit differences of maybe just not needed.
;}
;return

ProcessStart(contents, Rest)
{
	WinSet, Transparent, 0, Words
	Control, Disable ,, Edit1, AI
	WinActivate, AI
	GuiControl, AI:, Edit1, % contents
	Sleep, % Rest
	Control, Enable ,, Edit1, AI
	GuiControl, AI:, Information, Done
	Return
}

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	WinActivate, AI
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	WinGet, visible, Transparent, Words
	if (n == 0)
		WinSet, Transparent, 0, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	if ((visible == 0)&&(n != 0))
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	Return
}
return

RegExFix(string, n)
{
	if (n == 1)
	{
		StringReplace, string, string, \, \\, ALL
		StringReplace, string, string, ., \., ALL
		StringReplace, string, string, *, \*, ALL
		StringReplace, string, string, ?, \?, ALL
		StringReplace, string, string, +, \+, ALL
		StringReplace, string, string, [, \[, ALL ;]
		StringReplace, string, string, {, \{, ALL
		StringReplace, string, string, |, \|, ALL
		StringReplace, string, string, (, \(, ALL
		StringReplace, string, string, ), \), ALL
		StringReplace, string, string, ^, \^, ALL
		StringReplace, string, string, $, \$, ALL
		Return % string
	}
	if (n == 2)
	{
		StringReplace, string, string, \\, \, ALL
		StringReplace, string, string, \., ., ALL
		StringReplace, string, string, \*, *, ALL
		StringReplace, string, string, \?, ?, ALL
		StringReplace, string, string, \+, +, ALL
		StringReplace, string, string, \[, [, ALL ;]
		StringReplace, string, string, \{, {, ALL
		StringReplace, string, string, \|, |, ALL
		StringReplace, string, string, \(, (, ALL
		StringReplace, string, string, \), ), ALL
		StringReplace, string, string, \^, ^, ALL
		StringReplace, string, string, \$, $, ALL
		Return % string
	}
}

ReturnLineArray(lines, n)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/Softreturn\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

ReturnDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			uinput:= uarray["linePos" x]
			hinput:= harray["linePos" x]
			l_uinput:= StrLen(uinput)
			l_hinput:= StrLen(hinput)
			if (uinput != hinput)
				Return % x
			if (l_uinput != l_hinput)
				Return % x
			if (x == v) 
				Break
		}
		Return % "0"
	}
	if (dif == "words")
	{
		Loop
		{
			x++
			uinput:= uarray["wordPos" x]
			hinput:= harray["wordPos" x]
			if (uinput != hinput)
				Return % x
			else if (x == v)
				Break
		}
		Return % "0"
	}
	Return
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return "True"
	}
}

Ret_Arr(linearray, place)
{
	array:=[]
	sentence:= linearray["linePos" place]
	words:= StrSplit(sentence, A_Space)
	for Index, word in words
	{
		array["wordPos" Index]:= word
	}
	Return % array
}

GetLineCount(data, count)
{
	if (count == "Edit")
	{
		contents:= StrSplit(contents, ["\|/CR+LF\|/", "\|/Softreturn\|/"])
		for Index, cont in contents
		{
			x++
			if (Index == x)
				y:=% x
		}
	}
	if (count == "TXT")
	{
		contents:= StrSplit(text, "\|/Softreturn\|/")
		for Index, cont in contents
		{
			x++
			if (Index == x)
				y:=% x
		}
	}
	Return % y
}

GetHistory()
{
	FileRead, contents, % Temp
	StringReplace, contents, contents, `r`n,\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, \|/Softreturn\|/, ALL
	Return % contents
}

GetControl(FocTex)
{
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, % InFocus
	GuiControlGet, Word, Words:, Listbox1
	ControlGet, line, CurrentLine, , % InFocus
	StringReplace, text, text, `n, \|/Softreturn\|/, ALL
	if (FocTex == "Line")
		Return % line
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	x:=0
	GuiControl, Words:, Listbox1, | 
	Loop, Parse, % FocTex, |
		x++
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

Timer()
{
	Sleep, 500
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
}

HashContents(contents)
{
	StringReplace, contents, contents, \|/CR+LF\|/, `n, ALL
	StringReplace, contents, contents, \|/Softreturn\|/, `n, ALL
	return % contents
}

RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitapp

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 06 Dec 2023, 20:32

This update comes with logical array involvement and far less read/write... The difference between the two is speed vs. computer memory integrity. As a process writes and reads and writes and read... the physical location of that read and write is being degraded and overtime will fail (but almost all processes do that). It is usually best to try to keep the data in a logical state as much as possible. The biggest problem with keeping it in logical state is, as mentioned, speed. However, this version keeps the array in logical state and never saves unless you save it (you will definitely notice a speed difference). But it does work if given time.

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)
IniRead, Rest, % Cache "\Settings.ini", Timers, Key1
If (Rest == "ERROR")
{
	IniWrite, 10000, % Cache "\Settings.ini", Timers, Key1
	Rest:= 10000
}
IniRead, Notactive, % Cache "\Settings.ini", Timers, Key2
if (Notactive == "ERROR")
{
	IniWrite, 500, % Cache "\Settings.ini", Timers, Key2
	Notactive:= 500
}
IniRead, NoDif, % Cache "\Settings.ini", Timers, Key3
if (NoDif == "ERROR")
{
	IniWrite, 25, % Cache "\Settings.ini", Timers, Key3
	NoDif:= 25
}

contents:=HashContents(contents)

Menu, Settings, Add, Timers, Timers
Menu, Settings, Add, AlwaysOnTop`ton/off, Always
Menu, Settings, Add, Suspend`ton/off, SusOnOff
Menu, Settings, Add, Reload`tCtrl+r, Reload
Menu, AIsMenu, Add, Settings, :Settings

CoordMode, Caret, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Window
Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, Menu, AIsMenu
Gui, Add, Text, x0 y0 vButtonCountCheck w20, 0,Unknown
Gui, Add, Text, vWordKeeper w20, &not@a#rea1*sent3nc3
Gui, Add, Edit,  0x200  r39 ym+25 x100 vWords w325 h500 hwndTracker,
Gui, Add, Button, gAISave, Save
Gui, Add, Text, vAISave, Don't save
Gui, Add, Text, ym+555 x380 vInformation, Loading...
Gui, Margin, 50, 30
Gui, Show, h600 w500, AI work
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, margin, 0, 0
Gui, Show, , Words
ProcessStart(contents, Rest)

logicalhistory:= []
history:= GetHistory()
logicalhistory:= ReturnLineArray(history, user)
activeuserinput:= []

Loop,
{
	winwonder:=WinWonder()
	if (winwonder == "False")
	{
		Sleep, % Notactive
		Continue
	}
	getuserinput:= GetControl("Text")
	activeuserinput:=ReturnLineArray(getuserinput, "user")
	historylastline:= GetLineCount(logicalhistory)
	activeuserlastline:= GetLineCount(activeuserinput)
	if (activeuserlastline != historylastline)
	{
		logicallastlineaddition:=(activeuserlastline-historylastline)
		logicalhistory:= FixLogicalhistory_Array(logicalhistory, logicallastlineaddition) ; where last lines are being put in. and you will also want to function in lastline (Deleted_Line) to acompany the changes. if you are lagging ApplyLogicalChange().
		logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, logicallastlineaddition)
	}
	if (activeuserlastline == historylastline)
	{
		logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, 0)
	}
	savecheck:= GetControl("AISave")
	if (savecheck == "Save_File")
	{
		historycount:=GetLineCount(logicalhistory)
		Loop, % historycount
		{
			x++
			sentences:= logicalhistory["linePos" x]
			StringReplace, sentences, sentences, (softreturn), \|/softreturn\|/, ALL
			StringReplace, sentences, sentences, (hardreturn), \|/CR+LF\|/, ALL
			FileContents:=% FileContents sentences
		}
		FileMove, % Temp, % TempBack, 1
		FileAppend, % FileContents, % Temp, UTF-8
		GuiControl,AI:, AISave, Don't Save
	}
}
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		check:=GetControl("GetKeeper")
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 2)
				userword:=% chec
		}
		str:= StrLen(userword)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
	}
	else
	{
		Send, `t
	}
	Return
}
else
	Send, `t
Return

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",ShiftEnter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
return

~Enter::
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",Enter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
return

AISave:
GuiControl,AI:, AISave, Save_File
return
	
SusOnOff:
Suspend, Toggle
if (A_IsSuspended == 1)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOn
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOff
Return

Always:
WinSet, AlwaysOnTop, Toggle, AI
WinGet, ExStyle, ExStyle, AI
if (ExStyle == 0x00000180)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOff
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOn
Return
 
Timers:
Gui, Timers:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, y25, Rest Timer:`t`n(in seconds)
Gui, Add, Text, y75 xs, Window Not Active:`t`n(in milliseconds)
Gui, Add, Text, y125 xs, Process Loop timer:`t`n(in milliseconds)
Gui, Add, Edit, w250 r3 ys-15 -VScroll, This timer slows the script before it gets to the main loop function. It's used to help in processing the global function "Speller."
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the script when the it is not active.
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the main processing loop while typing. It's dependent on a difference created in the main edit control.
Gui, Add, Edit, ys xs+400 w50 y25
Gui, Add, UpDown, vRangeInSeconds Range1-50, 10
Gui, Add, Edit, ys xs+400 w50 y75
Gui, Add, UpDown, vRangeInMillisecondsOfActive Range1-1000, 500
Gui, Add, Edit, ys xs+400 w50 y125
Gui, Add, UpDown, vRangeInMillisecondsOfProcess Range1-100, 25
Gui, Add, Text, xm+10 ym+180, Select the above values to your personal preferences and click save to keep the changes.
Gui, Add, Text, xm+80 ym+215, (Note you have to restart the program to force the changes)
Gui, Add, Button, ym+210 xs+425 gSave, Save
Gui, Add, Button, ym+210 xs+370 gCancel, Cancel
Gui, Margin, 20, 50
Gui, Show, h250 w500, Timers
Control, Disable ,, Edit1, Timers
Control, Disable ,, Edit2, Timers
Control, Disable ,, Edit3, Timers
Return

Reload:
^r::
Reload
Return

Cancel:
Gui, Timers:Destroy
Return

Save:
Gui, Submit, NoHide
RangeInSeconds:=(RangeInSeconds*1000)
IniWrite, % RangeInSeconds, % Cache "\Settings.ini", Timers, Key1
IniWrite, % RangeInMillisecondsOfActive, % Cache "\Settings.ini", Timers, Key2
IniWrite, % RangeInMillisecondsOfProcess, % Cache "\Settings.ini", Timers, Key3
Gui, Timers:Destroy
Return

GetButton_Count()
{
	Loop,
	{
		ButtonCountCheck:= GetControl("ButtCount")
		if (ButtonCountCheck != OldButtonCountCheck)
		{
			OldCount:=% Count
			OldButton:=% Button
			Sleep, 500
			ButtonCount_Split:= StrSplit(ButtonCountCheck, ",")
			For Index, ButtCount in ButtonCount_Split
			{
				if (Index == 1)
					Count:=% ButtCount
				if (Index == 2)
					Button:=% ButtCount
			}
		}
		else if (ButtonCountCheck == OldButtonCountCheck)
			Break
		if ((Button != OldButton)&&(Count > 1))
			Break
		OldButtonCountCheck:=% ButtonCountCheck
	}
	if (Button == OldButton)
	{
		ButtonCountReturn:=% Count "," Button
		GuiControl,AI:, ButtonCountCheck, % "0," Button
	}
	if (Button != OldButton)
	{
		NewCount:=% Count-OldCount
		GuiControl,AI:, ButtonCountCheck, % NewCount "," Button
		ButtonCountReturn:=% OldCount "," OldButton
	}
	Return
}

ApplyLogicalChange(activeuserinput, logicalhistory, numberofdifferences)
{
	x:= 0
	newhistoryrecord:=[]
	activeuserinputlastline:= GetLineCount(activeuserinput)
	logicalhistorylastline:= GetLineCount(logicalhistory)
	LastLine:= logicalhistory["linePos" logicalhistorylastline]
	Loop, % activeuserinputlastline
	{
		record:=
		x++ ; a lagged y variable needed to stagger history.
		occurenceuser:= activeuserinput["linePos" x]
		if (y > 0)
		{
			y:=(x-z) ; this will be an opposite staggered y (x+z) for deleted lines.
			historyrecord:= logicalhistory["linePos" y]
		}
		else
			historyrecord:= logicalhistory["linePos" x] ; even though the line now isn't right doesn't mean next time it won't be.
		splithistoryrecord:= StrSplit(historyrecord, ["(hardreturn)", "(softreturn)"])
		for index, splithistory in splithistoryrecord
		{
			if (Index == 1)
				record:= % splithistory
		}
		if ((occurenceuser != record)&&(numberofdifferences != 0)) ; the number of occurences go negative when lines get deleted... I haven't updated the below else for that yet.
		{
			LastLine:= logicalhistory["linePos" logicalhistorylastline] ; if a user is lagging the array make sure you are putting in last lines right.
			if ((LastLine == "(softreturn)")||(LastLine == "(hardreturn)")) ; the last line shouldn't be any other value.
			{
				z++ ; a z variable making sure we don't lose y and holding the number of occurences.
				if (z == 1) ; there's not enough time to add different enters in different spots (meaning the user couldn't add enough enters in the time this will be done).
					y:=% x
				IfInString, LastLine, (softreturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(softreturn)"
				IfInString, LastLine, (hardreturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(hardreturn)"
				numberofdifferences--
				logicalhistorylastline--
			} ; the likely answer is a deleted line in occurenceuser. we need to add to the numberofdifferences. I'll also need to update this in the future for the array.
			else
				numberofdifferences++
		}
		else if ((occurenceuser != record)&&(numberofdifferences == 0)) ; meaning user has updated a line with a new record
		{
			newhistoryrecord["linePos" x]:= occurenceuser
			IfInString, record, (softreturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(softreturn)"
			IfInString, record, (hardreturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(hardreturn)"
			recordkeeper:=% record
			usersentence:=% occurenceuser
		} ; z from above holds all change counts. y from above holds the history record line back. technically y can equal x-z or just y++. I think for greater clarity it should be x-z because a user may choose to purposely lag the logicalhistoryarray Change function. Basically this function can be implimented at will as long as the keys are being kept up with and added to the historyarray in the main loop (of course that might also come with logical array issues).
		else if ((occurenceuser == record)&&(numberofdifferences == 0))
			newhistoryrecord["linePos" x]:= record
	}
	if (recordkeeper != "")
		Doppler(usersentence, recordkeeper)
	Return % newhistoryrecord ; There has been many different statements on using the % after return or in ":=" as an operorator (it technically doesn't need to be done and can cause issues if done improperly). I use it because honestly it's like my signature to my work.
}

Doppler(usersentence, historysentence)
{
	livewords:=[]
	pastwords:=[]
	check:=GetControl("GetKeeper")
	if (check == "&not@a#rea1*sent3nc3")
	{
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			livewords["wordPos" key]:= userwords
		}
		historysplit:=StrSplit(historysentence, A_Space)
		for key, historywords in historysplit
		{
			pastwords["wordPos" key]:= historywords
		}
		usercount:=GetLineCount(livewords)
		historycount:= GetLineCount(pastwords)
		Loop, % usercount
		{
			x++
			userword:=livewords["wordPos" x]
			historyword:=pastwords["wordPos" x]
			userwordlength:=StrLen(userword)
			historywordlength:= StrLen(historyword)
			if ((userword != historyword)||(historycount < x))
			{
				GuiControl, AI:, WordKeeper, % historyword "," userword "," x
			}
		}
		StringReplace, userword, userword, historyword, , ALL
	}
	else if (check != "&not@a#rea1*sent3nc3")
	{
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 1)
				historyword:=% chec
			if (index == 2)
				ouserword:=% chec
			if (index == 3)
				x:=% chec
		}
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			if (key == x)
				userword:=% userwords
		}
		GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		StringReplace, userword, userword, historyword, , ALL
	}
	userwordlength:=StrLen(userword)
	if (userwordlength < 2)
	{
		GuiControl, AI:, Information, Working...
		SpellChecker(0)
	}
	if (userwordlength > 3)
	{
		GuiControl, AI:, Information, Working.
		ourwords:=WordCheck(userword, userwordlength)
		if (ourwords == "")
			SpellChecker(0)
		SpellChecker(userwordlength)
		GetControl(ourwords)
	}
	Return
}

FixLogicalhistory_Array(historyarray, howmanylines)
{
	lastline:= GetLineCount(historyarray)
	whichbutton:= GetControl("ButtCount")
	Loop, % howmanylines
	{
		lastline++
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					historyarray["linePos" lastline]:= "(softreturn)"
				if (butt == "Enter")
					historyarray["linePos" lastline]:= "(hardreturn)"
			}
		}
	}
	Return % historyarray
}

ReturnLineArray(lines, user)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/Softreturn\|/", "\|/userreturns\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

GetButtonCount(pressed)
{
	pressing:= StrSplit(pressed, ",")
	For Index, press in pressing
		if (Index == 1)
			Return % press
}

FindingRealLineLOL(occurenceuser, rowbefore, thisrow)
{
	IfInString, occurenceuser, %rowbefore%
	{
		rowlength:= StrLen(rowbefore)
		occurencelength:= StrLen(occurenceuser)
		subtractedlength:=(occurencelength-rowlength)
		thisstring:= SubStr(occurenceuser, subtractedlength, occurencelength)
		if (thisstring == rowbefore)
		{
			IfInString, occurenceuser, %thisrow%
				Return % "Found"
			IfNotInstring, occurenceuser, %thisrow%
				Return % "NextRow"
		}
	}
	if (rowbefore == "NextRow")
		IfInString, occurenceuser, %thisrow%
			Return % "Found"
	Return % "NotFound"
}

ProcessStart(contents, Rest)
{
	WinSet, Transparent, 0, Words
	Control, Disable ,, Edit1, AI
	WinActivate, AI
	GuiControl, AI:, Edit1, % contents
	Sleep, % Rest
	Control, Enable ,, Edit1, AI
	GuiControl, AI:, Information, Done
	Return
}

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	WinActivate, AI
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	if (n > 3)
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	if (n == 0)
		WinSet, Transparent, 0, Words
	WinGet, visible, Transparent, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	Return
}
return

ReturnClearDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			hinput:= harray["linePos" x]
			hsplit:= StrSplit(hinput, ["(hardreturn)", "(softreturn)"])
			for Index, h in hsplit
			{
				if (Index == 1)
					checkh:= % h
			}
			uinput:= uarray["linePos" x]
			StringReplace, uinput, uinput, (softreturn), , ALL
			StringReplace, uinput, uinput, (hardreturn), , ALL
			l_checkh:= StrLen(checkh)
			l_uinput:= StrLen(uinput)
			if (uinput != checkh)
				Return % x
			if (l_checkh != l_uinput)
				Return % x
			if (x == v)
				Break
			checkh:=
		}
		Return % "0"
	}
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return % "True"
	}
}

GetLineCount(arraycount)
{
	LastLine:=0
	for Index, count in arraycount
		++LastLine
	Return % LastLine
}

GetControl(FocTex)
{
	WinActivate, AI
	Sleep, 1000
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, % InFocus
	ControlGet, row, CurrentLine, , % InFocus, AI
	GuiControlGet, Word, Words:, Listbox1
	StringReplace, text, text, `n, \|/userreturns\|/, ALL
	GuiControlGet, ButtonCountCheck, AI:, ButtonCountCheck
	GuiControlGet, Save_File, AI:, AISave
	GuiControlGet, DopplerGet, AI:, WordKeeper
	if (FocTex == "GetKeeper")
		Return % DopplerGet
	if (FocTex == "AISave")
		Return % Save_File
	if (FocTex == "ButtCount")
		Return % ButtonCountCheck
	if (FocTex == "Row")
		Return % row
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	x:=0
	GuiControl, Words:, Listbox1, | 
	Loop, Parse, % FocTex, |
		x++
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
}

HashContents(contents)
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, \|/CR+LF\|/, `n, ALL
	StringReplace, contents, contents, \|/Softreturn\|/, `n, ALL
	return % contents
}

GetHistory()
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, `r`n,(hardreturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, (softreturn)\|/Softreturn\|/, ALL
	Return % contents
}

RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitapp
My hope is to balance a more logical state array that isn't so labor intensive on a device (next step)!

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 08 Dec 2023, 22:33

I got to thinking... Here I am trying to make it run faster when in truth I'm doing it from the perspective of over 200k characters and over 2000 lines. The truth is, most people probably would never edit to that length. So basically I will opt to leave the last update as the default. That being said this update has something useful in it. A variable extractor.

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)
IniRead, Rest, % Cache "\Settings.ini", Timers, Key1
If (Rest == "ERROR")
{
	IniWrite, 10000, % Cache "\Settings.ini", Timers, Key1
	Rest:= 10000
}
IniRead, Notactive, % Cache "\Settings.ini", Timers, Key2
if (Notactive == "ERROR")
{
	IniWrite, 500, % Cache "\Settings.ini", Timers, Key2
	Notactive:= 500
}
IniRead, NoDif, % Cache "\Settings.ini", Timers, Key3
if (NoDif == "ERROR")
{
	IniWrite, 25, % Cache "\Settings.ini", Timers, Key3
	NoDif:= 25
}

contents:=HashContents(contents)

Menu, Settings, Add, Timers, Timers
Menu, Settings, Add, AlwaysOnTop`ton/off, Always
Menu, Settings, Add, Suspend`ton/off, SusOnOff
Menu, Settings, Add, Reload`tCtrl+r, Reload
Menu, AIsMenu, Add, Settings, :Settings

CoordMode, Caret, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Window
Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, Menu, AIsMenu
Gui, Add, Text, -E0x200 x0 y0 vButtonCountCheck w20, 0,Unknown
Gui, Add, Text, -E0x200 vWordKeeper w20, &not@a#rea1*sent3nc3
Gui, Add, Edit,  r39 ym+25 x100 vWords w325 h500 hwndTracker,
Gui, Add, Button, gAISave, Save
Gui, Add, Text, vAISave, Don't save
Gui, Add, Button, gFile w38 x150 ym+546, Files
Gui, Add, Text, vGlassCo, Go
Gui, Add, Text, ym+555 x380 vInformation, Loading...
Gui, Margin, 50, 30
Gui, Show, h600 w500, AI work
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, margin, 0, 0
Gui, Show, , Words
ProcessStart(contents, Rest)

logicalhistory:= []
history:= GetHistory()
logicalhistory:= ReturnLineArray(history, user)
activeuserinput:= []

Loop,
{
	winwonder:=WinWonder()
	if (winwonder == "False")
	{
		Sleep, % Notactive
		Continue
	}
	GuiControlGet, GlassCo, AI:, GlassCo
	if (GlassCo == "Stop")
		Sleep, % Notactive
	getuserinput:= GetControl("Text")
	activeuserinput:=ReturnLineArray(getuserinput, "user")
	historylastline:= GetLineCount(logicalhistory)
	activeuserlastline:= GetLineCount(activeuserinput)
	if (activeuserlastline != historylastline)
	{
		logicallastlineaddition:=(activeuserlastline-historylastline)
		logicalhistory:= FixLogicalhistory_Array(logicalhistory, logicallastlineaddition) ; where last lines are being put in. and you will also want to function in lastline (Deleted_Line) to acompany the changes. if you are lagging ApplyLogicalChange().
		logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, logicallastlineaddition)
	}
	if (activeuserlastline == historylastline)
	{
		logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, 0)
	}
	savecheck:= GetControl("AISave")
	if (savecheck == "Save_File")
	{
		historycount:=GetLineCount(logicalhistory)
		Loop, % historycount
		{
			x++
			sentences:= logicalhistory["linePos" x]
			StringReplace, sentences, sentences, (softreturn), \|/softreturn\|/, ALL
			StringReplace, sentences, sentences, (hardreturn), \|/CR+LF\|/, ALL
			FileContents:=% FileContents sentences
		}
		FileMove, % Temp, % TempBack, 1
		FileAppend, % FileContents, % Temp, UTF-8
		GuiControl,AI:, AISave, Don't Save
	}
}
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		check:=GetControl("GetKeeper")
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 2)
				userword:=% chec
		}
		str:= StrLen(userword)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
	}
	else
	{
		Send, `t
	}
	Return
}
else
	Send, `t
Return

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",ShiftEnter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
return

~Enter::
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",Enter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
return

AISave:
GuiControl,AI:, AISave, Save_File
return
	
SusOnOff:
Suspend, Toggle
if (A_IsSuspended == 1)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOn
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOff
Return

Always:
WinSet, AlwaysOnTop, Toggle, AI
WinGet, ExStyle, ExStyle, AI
if (ExStyle == 0x00000180)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOff
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOn
Return
 
Timers:
Gui, Timers:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, y25, Rest Timer:`t`n(in seconds)
Gui, Add, Text, y75 xs, Window Not Active:`t`n(in milliseconds)
Gui, Add, Text, y125 xs, Process Loop timer:`t`n(in milliseconds)
Gui, Add, Edit, w250 r3 ys-15 -VScroll, This timer slows the script before it gets to the main loop function. It's used to help in processing the global function "Speller."
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the script when the it is not active.
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the main processing loop while typing. It's dependent on a difference created in the main edit control.
Gui, Add, Edit, ys xs+400 w50 y25
Gui, Add, UpDown, vRangeInSeconds Range1-50, 10
Gui, Add, Edit, ys xs+400 w50 y75
Gui, Add, UpDown, vRangeInMillisecondsOfActive Range1-1000, 500
Gui, Add, Edit, ys xs+400 w50 y125
Gui, Add, UpDown, vRangeInMillisecondsOfProcess Range1-100, 25
Gui, Add, Text, xm+10 ym+180, Select the above values to your personal preferences and click save to keep the changes.
Gui, Add, Text, xm+80 ym+215, (Note you have to restart the program to force the changes)
Gui, Add, Button, ym+210 xs+425 gSave, Save
Gui, Add, Button, ym+210 xs+370 gCancel, Cancel
Gui, Margin, 20, 50
Gui, Show, h250 w500, Timers
Control, Disable ,, Edit1, Timers
Control, Disable ,, Edit2, Timers
Control, Disable ,, Edit3, Timers
Return

Reload:
^r::
Reload
Return

Cancel:
Gui, Timers:Destroy
Return

Save:
Gui, Submit, NoHide
RangeInSeconds:=(RangeInSeconds*1000)
IniWrite, % RangeInSeconds, % Cache "\Settings.ini", Timers, Key1
IniWrite, % RangeInMillisecondsOfActive, % Cache "\Settings.ini", Timers, Key2
IniWrite, % RangeInMillisecondsOfProcess, % Cache "\Settings.ini", Timers, Key3
Gui, Timers:Destroy
Return

File:
Gui, Submit, NoHide
GuiControlGet, GlassCo, AI:, GlassCo
if (GlassCo == "Stop")
{
	WinSet, AlwaysOnTop, On, AI
	GuiControl,AI:, GlassCo, Stop
	Return
}
MsgBox, Please select a .ahk file you want to extract the variables out of.`nNote*** DLL functions are not classified as variables. though, if they have output variables those may be seen.`nIt does get numeric values in if statements as these are still variables with "explicit" value.
Loop, Files, *.ahk, D F R
{
	IfInString, A_LoopFileName, @
	{
		Continue
	}
	wi=%wi%%A_LoopFileName%|
}
Gui, Files:New, +AlwaysOnTop +Resize +toolWindow
Gui, Add, ListBox, r10 gFileSelected vFileSelected, %wi%
Gui, Margin, 20, 20
Gui, Show, x247 y534, Files
wi=
return

FileSelected:
Gui, Submit, NoHide
GuiControl,AI:, GlassCo, Stop
FileRead, contents, % FileSelected
contents:= GetVariables(contents)
GuiControl, AI:, Words, % contents
WinClose, Files
WinSet, AlwaysOnTop, On, AI
Return

GetVariables(filecontents)
{
	linenumber:=0
	Loop, Parse, % filecontents, `r
	{
		linenumber++
		line:=% A_LoopField
		sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)
		for index, sentence in sentences
		{
			if (index == 1)
				codestring:=% sentence
			if (index == 2)
				commentstring:=% sentence
		}
		thiscodestring:=% codestring
		codestring:= RemoveCertainChars(codestring, "Start")
		IfInString, codestring, Box`,
			Continue
		IfInString, codestring, StringReplace
			Continue
		IfInString, codestring, RegEx
			Continue
		IfInString, codestring, Ini
			Continue
		IfInString, codestring, =
		{
			IfInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Percent", linenumber)
				IfNotInString, variablelist, % variablestring
						variablelist.= variablestring "`n"
			}
			else IfNotInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
			IfInString, codestring, [quotes]
				IfNotInString, variablelist, % codestring
				{
					variablestring:= GetVariableString(codestring, "Quotes", linenumber)
					IfNotInString, variablelist, % variablestring
						variablelist.= variablestring " `n"
				}
			else IfNotInString, codestring, [quotes]
				IfNotInString, variablelist, % codestring
					variablelist.= codestring " found in quotes`n"
				
		}
		else IfInString, codestring, [percent]
			variablestring:= GetVariableString(codestring, "Percent", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring "`n"
		else IfInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Quotes", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring "found in quotes`n"
			}
		IfInString, codestring, Gui
			IfInString, codestring, `,
				IfInString, codestring, %A_Space%v
				{
					variablestring:= GetVariableString(codestring, "Gui", linenumber)
					IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
				}
	}
	Loop, Parse, % variablelist, `n
	{
		thischeck:=
		information:=
		if (A_LoopField == "")
			Continue
		repeatcheck:= StrSplit(A_LoopField, "[thissplitter]")
		for index, repeat in repeatcheck
		{
			if (index == 1)
			{
				IfNotInString, completedlist, % repeat
					thischeck:=% repeat
				IfInString, completedlist, % repeat
					Continue
			}
			if (index == 2)
				information:=% repeat
		}
		if (thischeck != "")
		{
			checklist:=% Trim(thischeck) "`n" Trim(information) "`n"
			IfNotInString, completedlist, % checklist
				completedlist.= checklist
		}
	}
	completedlist:= RemoveCertainChars(completedlist, "End")
	Return % completedlist
}

GetVariableString(codestring, whichone, linenumber)
{
	if (whichone == "Gui")
	{
		variablestrings:= StrSplit(codestring, ",")
		for index, variablestring in variablestrings
		{
			if (index > 4)
				Continue
			IfInString, variablestring, %A_Space%v
				thisvariablestring:=% variablestring
		}
		variablestring:= StrSplit(thisvariablestring, A_Space)
		for index, variable in variablestring
		{
			thisvariableletter:= SubStr(variable, 1, 1)
			if (thisvariableletter == "v")
				return % variable "[thissplitter] Gui variable Line number is found at: " linenumber "`n"
		}
	}
	if (whichone == "Quotes")
	{
		variablestrings:= StrSplit(codestring, "[quotes]")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 0)
				IfNotInString, variablestring, %A_Space%
					IfNotInString, variables, % variablestring
						variables.= "[quotes]" variablestring "[quotes][thissplitter] explicit variable Line number is found at: " linenumber "`n"
		}
		Return % variables
	}
	if (whichone == "Percent")
	{
		IfInString, codestring, `,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					IfInString, variablestring, [percent]
						IfNotInString, variablestring, =
							IfInString, variablestring, A_Space
								variables.= variablestring "[thissplitter] implicit variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		IfNotInString, codestring, `,
		{
			IfInString, codestring, =
			{
				variablestrings:= StrSplit(codestring, "=")
				for index, variablestring in variablestrings
				{
					if (index == 1)
					{
						variables:= StrSplit(variablestring, A_Space)
						for index, variable in variables
							thisvariable:=% variable
					}
					if (index == 2)
						codestring:=% variablestring
				}
			}
			variablestrings:= StrSplit(codestring, "[percent]")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					variables.= "[percent]" variablestring "[percent][thissplitter] implicit variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		if (thisvariable != "")
			variables.= thisvariable "[thissplitter]implicit variable given explicit value Line number is found at: " linenumber "`n"
		Return % variables
	}
	if (whichone == "Equals")
	{
		variablestrings:= StrSplit(codestring, "=")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 1)
				IfNotInString, variablestring, [quotes]
				{
					thisvariablestring:= StrSplit(variablestring, A_Space)
					for index, thisvariable in thisvariablestring
					{
						variable:=% thisvariable "[thissplitter] implicit variable given explicit value Line number is found at: " linenumber "`n"
					}
				}
		}
		Return % variable
	}
	return % "Not Found"
}

RemoveCertainChars(string, special)
{
	if (special == "Start")
	{
		StringReplace, string, string, ", [quotes], ALL
		StringReplace, string, string, `%%A_Space%, [percent], ALL
		StringReplace, string, string, `%, [percent], ALL
		StringReplace, string, string, =%A_Space%, =, ALL
		StringReplace, string, string, %A_Space%=, =, ALL
		StringReplace, string, string, %A_Space%:, :, ALL
		StringReplace, string, string, :=, =, ALL
		StringReplace, string, string, %A_Space%!=, =, ALL
		StringReplace, string, string, ), , ALL
		StringReplace, string, string, (, , ALL
		StringReplace, string, string, `t, , ALL
	}
	if (special == "End")
	{
		StringReplace, string, string, [quotes], ", ALL
		StringReplace, string, string, [percent], `%, ALL
	}
	Return % string
}

GetButton_Count()
{
	Loop,
	{
		ButtonCountCheck:= GetControl("ButtCount")
		if (ButtonCountCheck != OldButtonCountCheck)
		{
			OldCount:=% Count
			OldButton:=% Button
			Sleep, 500
			ButtonCount_Split:= StrSplit(ButtonCountCheck, ",")
			For Index, ButtCount in ButtonCount_Split
			{
				if (Index == 1)
					Count:=% ButtCount
				if (Index == 2)
					Button:=% ButtCount
			}
		}
		else if (ButtonCountCheck == OldButtonCountCheck)
			Break
		if ((Button != OldButton)&&(Count > 1))
			Break
		OldButtonCountCheck:=% ButtonCountCheck
	}
	if (Button == OldButton)
	{
		ButtonCountReturn:=% Count "," Button
		GuiControl,AI:, ButtonCountCheck, % "0," Button
	}
	if (Button != OldButton)
	{
		NewCount:=% Count-OldCount
		GuiControl,AI:, ButtonCountCheck, % NewCount "," Button
		ButtonCountReturn:=% OldCount "," OldButton
	}
	Return
}

ApplyLogicalChange(activeuserinput, logicalhistory, numberofdifferences)
{
	x:= 0
	newhistoryrecord:=[]
	activeuserinputlastline:= GetLineCount(activeuserinput)
	logicalhistorylastline:= GetLineCount(logicalhistory)
	LastLine:= logicalhistory["linePos" logicalhistorylastline]
	Loop, % activeuserinputlastline
	{
		record:=
		x++ ; a lagged y variable needed to stagger history.
		occurenceuser:= activeuserinput["linePos" x]
		if (y > 0)
		{
			y:=(x-z) ; this will be an opposite staggered y (x+z) for deleted lines.
			historyrecord:= logicalhistory["linePos" y]
		}
		else
			historyrecord:= logicalhistory["linePos" x] ; even though the line now isn't right doesn't mean next time it won't be.
		splithistoryrecord:= StrSplit(historyrecord, ["(hardreturn)", "(softreturn)"])
		for index, splithistory in splithistoryrecord
		{
			if (Index == 1)
				record:= % splithistory
		}
		if ((occurenceuser != record)&&(numberofdifferences != 0)) ; the number of occurences go negative when lines get deleted... I haven't updated the below else for that yet.
		{
			LastLine:= logicalhistory["linePos" logicalhistorylastline] ; if a user is lagging the array make sure you are putting in last lines right.
			if ((LastLine == "(softreturn)")||(LastLine == "(hardreturn)")) ; the last line shouldn't be any other value.
			{
				z++ ; a z variable making sure we don't lose y and holding the number of occurences.
				if (z == 1) ; there's not enough time to add different enters in different spots (meaning the user couldn't add enough enters in the time this will be done).
					y:=% x
				IfInString, LastLine, (softreturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(softreturn)"
				IfInString, LastLine, (hardreturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(hardreturn)"
				numberofdifferences--
				logicalhistorylastline--
			} ; the likely answer is a deleted line in occurenceuser. we need to add to the numberofdifferences. I'll also need to update this in the future for the array.
			else
				numberofdifferences++
		}
		else if ((occurenceuser != record)&&(numberofdifferences == 0)) ; meaning user has updated a line with a new record
		{
			newhistoryrecord["linePos" x]:= occurenceuser
			IfInString, record, (softreturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(softreturn)"
			IfInString, record, (hardreturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(hardreturn)"
			recordkeeper:=% record
			usersentence:=% occurenceuser
		} ; z from above holds all change counts. y from above holds the history record line back. technically y can equal x-z or just y++. I think for greater clarity it should be x-z because a user may choose to purposely lag the logicalhistoryarray Change function. Basically this function can be implimented at will as long as the keys are being kept up with and added to the historyarray in the main loop (of course that might also come with logical array issues).
		else if ((occurenceuser == record)&&(numberofdifferences == 0))
			newhistoryrecord["linePos" x]:= record
	}
	if (recordkeeper != "")
		Doppler(usersentence, recordkeeper)
	Return % newhistoryrecord ; There has been many different statements on using the % after return or in ":=" as an operorator (it technically doesn't need to be done and can cause issues if done improperly). I use it because honestly it's like my signature to my work.
}

Doppler(usersentence, historysentence)
{
	livewords:=[]
	pastwords:=[]
	check:=GetControl("GetKeeper")
	if (check == "&not@a#rea1*sent3nc3")
	{
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			livewords["wordPos" key]:= userwords
		}
		historysplit:=StrSplit(historysentence, A_Space)
		for key, historywords in historysplit
		{
			pastwords["wordPos" key]:= historywords
		}
		usercount:=GetLineCount(livewords)
		historycount:= GetLineCount(pastwords)
		Loop, % usercount
		{
			x++
			userword:=livewords["wordPos" x]
			historyword:=pastwords["wordPos" x]
			userwordlength:=StrLen(userword)
			historywordlength:= StrLen(historyword)
			if ((userword != historyword)||(historycount < x))
			{
				GuiControl, AI:, WordKeeper, % historyword "," userword "," x
			}
		}
		StringReplace, userword, userword, historyword, , ALL
	}
	else if (check != "&not@a#rea1*sent3nc3")
	{
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 1)
				historyword:=% chec
			if (index == 2)
				ouserword:=% chec
			if (index == 3)
				x:=% chec
		}
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			if (key == x)
				userword:=% userwords
		}
		GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		StringReplace, userword, userword, historyword, , ALL
	}
	userwordlength:=StrLen(userword)
	if (userwordlength < 2)
	{
		GuiControl, AI:, Information, Working...
		SpellChecker(0)
	}
	if (userwordlength > 3)
	{
		GuiControl, AI:, Information, Working.
		ourwords:=WordCheck(userword, userwordlength)
		if (ourwords == "")
			SpellChecker(0)
		SpellChecker(userwordlength)
		GetControl(ourwords)
	}
	Return
}

FixLogicalhistory_Array(historyarray, howmanylines)
{
	lastline:= GetLineCount(historyarray)
	whichbutton:= GetControl("ButtCount")
	Loop, % howmanylines
	{
		lastline++
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					historyarray["linePos" lastline]:= "(softreturn)"
				if (butt == "Enter")
					historyarray["linePos" lastline]:= "(hardreturn)"
			}
		}
	}
	Return % historyarray
}

ReturnLineArray(lines, user)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/Softreturn\|/", "\|/userreturns\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

GetButtonCount(pressed)
{
	pressing:= StrSplit(pressed, ",")
	For Index, press in pressing
		if (Index == 1)
			Return % press
}

FindingRealLineLOL(occurenceuser, rowbefore, thisrow)
{
	IfInString, occurenceuser, %rowbefore%
	{
		rowlength:= StrLen(rowbefore)
		occurencelength:= StrLen(occurenceuser)
		subtractedlength:=(occurencelength-rowlength)
		thisstring:= SubStr(occurenceuser, subtractedlength, occurencelength)
		if (thisstring == rowbefore)
		{
			IfInString, occurenceuser, %thisrow%
				Return % "Found"
			IfNotInstring, occurenceuser, %thisrow%
				Return % "NextRow"
		}
	}
	if (rowbefore == "NextRow")
		IfInString, occurenceuser, %thisrow%
			Return % "Found"
	Return % "NotFound"
}

ProcessStart(contents, Rest)
{
	WinSet, Transparent, 0, Words
	Control, Disable ,, Edit1, AI
	WinActivate, AI
	GuiControl, AI:, Edit1, % contents
	Sleep, % Rest
	Control, Enable ,, Edit1, AI
	GuiControl, AI:, Information, Done
	Return
}

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	WinActivate, AI
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	if (n > 3)
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	if (n == 0)
		WinSet, Transparent, 0, Words
	WinGet, visible, Transparent, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	Return
}
return

ReturnClearDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			hinput:= harray["linePos" x]
			hsplit:= StrSplit(hinput, ["(hardreturn)", "(softreturn)"])
			for Index, h in hsplit
			{
				if (Index == 1)
					checkh:= % h
			}
			uinput:= uarray["linePos" x]
			StringReplace, uinput, uinput, (softreturn), , ALL
			StringReplace, uinput, uinput, (hardreturn), , ALL
			l_checkh:= StrLen(checkh)
			l_uinput:= StrLen(uinput)
			if (uinput != checkh)
				Return % x
			if (l_checkh != l_uinput)
				Return % x
			if (x == v)
				Break
			checkh:=
		}
		Return % "0"
	}
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return % "True"
	}
}

GetLineCount(arraycount)
{
	LastLine:=0
	for Index, count in arraycount
		++LastLine
	Return % LastLine
}

GetControl(FocTex)
{
	WinActivate, AI
	Sleep, 1000
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, % InFocus
	ControlGet, row, CurrentLine, , % InFocus, AI
	GuiControlGet, Word, Words:, Listbox1
	StringReplace, text, text, `n, \|/userreturns\|/, ALL
	GuiControlGet, ButtonCountCheck, AI:, ButtonCountCheck
	GuiControlGet, Save_File, AI:, AISave
	GuiControlGet, DopplerGet, AI:, WordKeeper
	if (FocTex == "GetKeeper")
		Return % DopplerGet
	if (FocTex == "AISave")
		Return % Save_File
	if (FocTex == "ButtCount")
		Return % ButtonCountCheck
	if (FocTex == "Row")
		Return % row
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	x:=0
	GuiControl, Words:, Listbox1, | 
	Loop, Parse, % FocTex, |
		x++
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
}

HashContents(contents)
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, \|/CR+LF\|/, `n, ALL
	StringReplace, contents, contents, \|/Softreturn\|/, `n, ALL
	return % contents
}

GetHistory()
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, `r`n,(hardreturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, (softreturn)\|/Softreturn\|/, ALL
	Return % contents
}

RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitapp

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 09 Dec 2023, 09:09

I did notice that the updated variable extractor obtained a large number of different variables so now I have added a "filter" feature. If you are having issues first make sure the file is in the <path> (folder) of the ahk file you want to extract from. Second the "Start" Remove special characters are limited at this moment (mostly :=, .=, !=, <, > basically the ones you use you would want to add {e.g *=, ~= so on}. I do plan to add those but first I wanted to make sure the variables worked well and could be filtered right). Another issue is if the .ahk script you are working on has [thisspliter] it will be completely ignored as a variable paramater because of the StrSplit(variable, "[thissplitter]") function. Once you have ensured these small differences and added it to the right folder simply click files and click okay.

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)
IniRead, Rest, % Cache "\Settings.ini", Timers, Key1
If (Rest == "ERROR")
{
	IniWrite, 10000, % Cache "\Settings.ini", Timers, Key1
	Rest:= 10000
}
IniRead, Notactive, % Cache "\Settings.ini", Timers, Key2
if (Notactive == "ERROR")
{
	IniWrite, 500, % Cache "\Settings.ini", Timers, Key2
	Notactive:= 500
}
IniRead, NoDif, % Cache "\Settings.ini", Timers, Key3
if (NoDif == "ERROR")
{
	IniWrite, 25, % Cache "\Settings.ini", Timers, Key3
	NoDif:= 25
}

contents:=HashContents(contents)

Menu, Settings, Add, Timers, Timers
Menu, Settings, Add, AlwaysOnTop`ton/off, Always
Menu, Settings, Add, Suspend`ton/off, SusOnOff
Menu, Settings, Add, Reload`tCtrl+r, Reload
Menu, AIsMenu, Add, Settings, :Settings

CoordMode, Caret, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Window
Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, Menu, AIsMenu
Gui, Add, Text, -E0x200 x0 y0 vButtonCountCheck w20, 0,Unknown
Gui, Add, Text, -E0x200 vWordKeeper w20, &not@a#rea1*sent3nc3
Gui, Add, Edit,  r39 ym+25 x100 vWords w325 h500 hwndTracker,
Gui, Add, Button, gAISave, Save
Gui, Add, Text, vAISave, Don't save
Gui, Add, Button, gFile w38 x150 ym+546, Files
Gui, Add, Text, vGlassCo, Go
Gui, Add, Text, ym+555 x380 vInformation, Loading...
Gui, Margin, 50, 30
Gui, Show, h600 w500, AI work
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, margin, 0, 0
Gui, Show, , Words
ProcessStart(contents, Rest)

logicalhistory:= []
history:= GetHistory()
logicalhistory:= ReturnLineArray(history, user)
activeuserinput:= []

Loop,
{
	winwonder:=WinWonder()
	if (winwonder == "False")
	{
		Sleep, % Notactive
		Continue
	}
	GuiControlGet, GlassCo, AI:, GlassCo
	if (GlassCo == "Stop")
		Sleep, % Notactive
	getuserinput:= GetControl("Text")
	activeuserinput:=ReturnLineArray(getuserinput, "user")
	historylastline:= GetLineCount(logicalhistory)
	activeuserlastline:= GetLineCount(activeuserinput)
	if (activeuserlastline != historylastline)
	{
		logicallastlineaddition:=(activeuserlastline-historylastline)
		logicalhistory:= FixLogicalhistory_Array(logicalhistory, logicallastlineaddition) ; where last lines are being put in. and you will also want to function in lastline (Deleted_Line) to acompany the changes. if you are lagging ApplyLogicalChange().
		logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, logicallastlineaddition)
	}
	if (activeuserlastline == historylastline)
	{
		logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, 0)
	}
	savecheck:= GetControl("AISave")
	if (savecheck == "Save_File")
	{
		historycount:=GetLineCount(logicalhistory)
		Loop, % historycount
		{
			x++
			sentences:= logicalhistory["linePos" x]
			StringReplace, sentences, sentences, (softreturn), \|/softreturn\|/, ALL
			StringReplace, sentences, sentences, (hardreturn), \|/CR+LF\|/, ALL
			FileContents:=% FileContents sentences
		}
		FileMove, % Temp, % TempBack, 1
		FileAppend, % FileContents, % Temp, UTF-8
		GuiControl,AI:, AISave, Don't Save
	}
}
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		check:=GetControl("GetKeeper")
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 2)
				userword:=% chec
		}
		str:= StrLen(userword)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
	}
	else
	{
		Send, `t
	}
	Return
}
else
	Send, `t
Return

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",ShiftEnter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
return

~Enter::
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",Enter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
return

AISave:
GuiControl,AI:, AISave, Save_File
return
	
SusOnOff:
Suspend, Toggle
if (A_IsSuspended == 1)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOn
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOff
Return

Always:
WinSet, AlwaysOnTop, Toggle, AI
WinGet, ExStyle, ExStyle, AI
if (ExStyle == 0x00000180)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOff
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOn
Return
 
Timers:
Gui, Timers:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, y25, Rest Timer:`t`n(in seconds)
Gui, Add, Text, y75 xs, Window Not Active:`t`n(in milliseconds)
Gui, Add, Text, y125 xs, Process Loop timer:`t`n(in milliseconds)
Gui, Add, Edit, w250 r3 ys-15 -VScroll, This timer slows the script before it gets to the main loop function. It's used to help in processing the global function "Speller."
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the script when the it is not active.
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the main processing loop while typing. It's dependent on a difference created in the main edit control.
Gui, Add, Edit, ys xs+400 w50 y25
Gui, Add, UpDown, vRangeInSeconds Range1-50, 10
Gui, Add, Edit, ys xs+400 w50 y75
Gui, Add, UpDown, vRangeInMillisecondsOfActive Range1-1000, 500
Gui, Add, Edit, ys xs+400 w50 y125
Gui, Add, UpDown, vRangeInMillisecondsOfProcess Range1-100, 25
Gui, Add, Text, xm+10 ym+180, Select the above values to your personal preferences and click save to keep the changes.
Gui, Add, Text, xm+80 ym+215, (Note you have to restart the program to force the changes)
Gui, Add, Button, ym+210 xs+425 gSave, Save
Gui, Add, Button, ym+210 xs+370 gCancel, Cancel
Gui, Margin, 20, 50
Gui, Show, h250 w500, Timers
Control, Disable ,, Edit1, Timers
Control, Disable ,, Edit2, Timers
Control, Disable ,, Edit3, Timers
Return

Reload:
^r::
Reload
Return

Cancel:
Gui, Timers:Destroy
Return

Save:
Gui, Submit, NoHide
RangeInSeconds:=(RangeInSeconds*1000)
IniWrite, % RangeInSeconds, % Cache "\Settings.ini", Timers, Key1
IniWrite, % RangeInMillisecondsOfActive, % Cache "\Settings.ini", Timers, Key2
IniWrite, % RangeInMillisecondsOfProcess, % Cache "\Settings.ini", Timers, Key3
Gui, Timers:Destroy
Return

File:
Gui, Submit, NoHide
GuiControlGet, GlassCo, AI:, GlassCo
if (GlassCo == "Stop")
{
	WinSet, AlwaysOnTop, On, AI
	GuiControl,AI:, GlassCo, Stop
	Return
}
MsgBox, Please select a .ahk file you want to extract the variables out of.`nNote*** DLL functions are not classified as variables. though, if they have output variables those may be seen.`nIt does get numeric values in if statements as these are still variables with "explicit" value.
Loop, Files, *.ahk, D F R
{
	IfInString, A_LoopFileName, @
	{
		Continue
	}
	wi=%wi%%A_LoopFileName%|
}
Gui, Files:New, +AlwaysOnTop +Resize +toolWindow
Gui, Add, ListBox, r10 gFileSelected vFileSelected, %wi%
Gui, Add, Checkbox, vGui, Gui Variables
Gui, Add, Checkbox, vExplicit, Explicit Variables
Gui, Add, Checkbox, vImplicitExplicit, Implicit-Explicit
Gui, Margin, 20, 20
Gui, Show, x247 y534, Files
wi=
return

FileSelected:
Gui, Submit, NoHide
FileRead, contents, % FileSelected
if (Gui == 1)
	filters.= "[Filter='Gui'],"
if (Explicit == 1)
	filters.= "[Filter='explicit'],"
if (ImplicitExplicit == 1)
	filters.= "[Filter='implicit-explicit'],"
contents:= GetVariables(contents, filters)
GuiControl, AI:, Words, % contents
WinClose, Files
Return

GetVariables(filecontents, filters)
{
	linenumber:=0
	Loop, Parse, % filecontents, `r
	{
		linenumber++
		line:=% A_LoopField
		sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)
		for index, sentence in sentences
		{
			if (index == 1)
				codestring:=% sentence
			if (index == 2)
				commentstring:=% sentence
		}
		codestring:= RemoveCertainChars(codestring, "Start")
		IfInString, codestring, Box`,
			Continue
		IfInString, codestring, StringReplace
			Continue
		IfInString, codestring, RegEx
			Continue
		IfInString, codestring, Ini
			Continue
		IfInString, codestring, =
		{
			IfInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Percent", linenumber)
				IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
			}
			else IfNotInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
			IfInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Quotes", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring 
			}
			else IfNotInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
		}
		else IfInString, codestring, [percent]
		{
			variablestring:= GetVariableString(codestring, "Percent", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring
		}
		else IfInString, codestring, [quotes]
		{
			variablestring:= GetVariableString(codestring, "Quotes", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring "found in quotes 2`n"
		}
		IfInString, codestring, Gui
			IfInString, codestring, `,
				IfInString, codestring, %A_Space%v
				{
					variablestring:= GetVariableString(codestring, "Gui", linenumber)
					IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
				}
	}
	thesefilters:=StrSplit(filters, ",")
	for index, filter in thesefilters
	{
		if (index == 1)
			if (filter == "")
				Continue
			firstfilter:=% filter
		if (index == 2)
			if (filter == "")
				Continue
			secondfilter:=% filter
		if (index == 3)
			if (filter == "")
				Continue
			thirdfilter:=% filter
	}
	Loop, Parse, % variablelist, `n
	{
		checking:=
		thischeck:=
		information:=
		if (A_LoopField == "")
			Continue
		repeatcheck:= StrSplit(A_LoopField, "[thissplitter]")
		for index, repeat in repeatcheck
		{
			if (index == 1)
			{
				IfNotInString, completedlist, % repeat
					thischeck:=% repeat
				IfInString, completedlist, % repeat
				{
					checking:= MakeSure(completedlist, repeat)
					if (checking == "True")
						Continue
					else if (checking == "False")
						thischeck:=% repeat
				}
			}
			if (index == 2)
			{
				if (firstfilter != "")
					IfInString, repeat, % firstfilter
					{
						applyfilters:= StrSplit(repeat, firstfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
				if (secondfilter != "")
					IfInString, repeat, % secondfilter
					{
						applyfilters:= StrSplit(repeat, secondfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
				if (thirdfilter != "")
					IfInString, repeat, % thirdfilter
					{
						applyfilters:= StrSplit(repeat, thirdfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
			}
		}
		if (information == "")
			Continue
		if (thischeck != "")
		{
			checklist:=% Trim(thischeck) "`n" Trim(information) "`n"
			IfNotInString, completedlist, % checklist
				completedlist.= checklist
		}
	}
	completedlist:= RemoveCertainChars(completedlist, "End")
	Return % completedlist
}

MakeSure(listinprogress, checkword)
{
	Loop, Parse, % listinprogress, `n
	{
		if (checkword == A_LoopField)
			Return % "True"
	}
	Return % "False"
}

GetVariableString(codestring, whichone, linenumber)
{
	if (whichone == "Gui")
	{
		variablestrings:= StrSplit(codestring, ",")
		for index, variablestring in variablestrings
		{
			if (index > 4)
				Continue
			IfInString, variablestring, %A_Space%v
				thisvariablestring:=% variablestring
		}
		variablestring:= StrSplit(thisvariablestring, A_Space)
		for index, variable in variablestring
		{
			thisvariableletter:= SubStr(variable, 1, 1)
			if (thisvariableletter == "v")
				return % variable "[thissplitter] Gui variable[Filter='Gui'] Line number is found at: " linenumber "`n"
		}
		Return % variable "[thissplitter] Gui variable Line number is found at: " linenumber "`n"
	}
	if (whichone == "Quotes")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [quotes]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		variablestrings:= StrSplit(codestring, "[quotes]")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 0)
				IfNotInString, variablestring, %A_Space%
					IfNotInString, variables, % variablestring
						variables.= "[quotes]" variablestring "[quotes][thissplitter] explicit[Filter='explicit'] variable Line number is found at: " linenumber "`n"
		}
		Return % variables
	}
	if (whichone == "Percent")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [percent]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		IfInString, codestring, `,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					IfInString, variablestring, [percent]
						IfNotInString, variablestring, =
							IfInString, variablestring, A_Space
								variables.= variablestring "[thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		IfNotInString, codestring, `,
		{
			IfInString, codestring, =
			{
				variablestrings:= StrSplit(codestring, "=")
				for index, variablestring in variablestrings
				{
					if (index == 1)
					{
						variables:= StrSplit(variablestring, A_Space)
						for index, variable in variables
							thisvariable:=% variable
					}
					if (index == 2)
						codestring:=% variablestring
				}
			}
			variablestrings:= StrSplit(codestring, "[percent]")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					variables.= "[percent]" variablestring "[percent][thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		if (thisvariable != "")
			variables.= thisvariable "[thissplitter]implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
		Return % variables
	}
	if (whichone == "Equals")
	{
		variablestrings:= StrSplit(codestring, "=")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 1)
				IfNotInString, variablestring, [quotes]
				{
					thisvariablestring:= StrSplit(variablestring, A_Space)
					for index, thisvariable in thisvariablestring
					{
						variable:=% thisvariable "[thissplitter] implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
					}
				}
		}
		Return % variable
	}
	return % "Not Found"
}

RemoveCertainChars(string, special)
{
	if (special == "Start")
	{
		StringReplace, string, string, ", [quotes], ALL
		StringReplace, string, string, `%%A_Space%, [percent], ALL
		StringReplace, string, string, `%, [percent], ALL
		StringReplace, string, string, %A_Space%:, :, ALL
		StringReplace, string, string, :=, =, ALL
		StringReplace, string, string, ==, =, ALL
		StringReplace, string, string, >, =, ALL
		StringReplace, string, string, <, =, ALL
		StringReplace, string, string, %A_Space%!=, =, ALL
		StringReplace, string, string, =%A_Space%, =, ALL
		StringReplace, string, string, %A_Space%=, =, ALL
		StringReplace, string, string, ), , ALL
		StringReplace, string, string, (, , ALL
		StringReplace, string, string, `t, , ALL
	}
	if (special == "End")
	{
		StringReplace, string, string, [quotes], ", ALL
		StringReplace, string, string, [percent], `%, ALL
		StringReplace, string, string, `,, , ALL
	}
	Return % string
}

GetButton_Count()
{
	Loop,
	{
		ButtonCountCheck:= GetControl("ButtCount")
		if (ButtonCountCheck != OldButtonCountCheck)
		{
			OldCount:=% Count
			OldButton:=% Button
			Sleep, 500
			ButtonCount_Split:= StrSplit(ButtonCountCheck, ",")
			For Index, ButtCount in ButtonCount_Split
			{
				if (Index == 1)
					Count:=% ButtCount
				if (Index == 2)
					Button:=% ButtCount
			}
		}
		else if (ButtonCountCheck == OldButtonCountCheck)
			Break
		if ((Button != OldButton)&&(Count > 1))
			Break
		OldButtonCountCheck:=% ButtonCountCheck
	}
	if (Button == OldButton)
	{
		ButtonCountReturn:=% Count "," Button
		GuiControl,AI:, ButtonCountCheck, % "0," Button
	}
	if (Button != OldButton)
	{
		NewCount:=% Count-OldCount
		GuiControl,AI:, ButtonCountCheck, % NewCount "," Button
		ButtonCountReturn:=% OldCount "," OldButton
	}
	Return
}

ApplyLogicalChange(activeuserinput, logicalhistory, numberofdifferences)
{
	x:= 0
	newhistoryrecord:=[]
	activeuserinputlastline:= GetLineCount(activeuserinput)
	logicalhistorylastline:= GetLineCount(logicalhistory)
	LastLine:= logicalhistory["linePos" logicalhistorylastline]
	Loop, % activeuserinputlastline
	{
		record:=
		x++ ; a lagged y variable needed to stagger history.
		occurenceuser:= activeuserinput["linePos" x]
		if (y > 0)
		{
			y:=(x-z) ; this will be an opposite staggered y (x+z) for deleted lines.
			historyrecord:= logicalhistory["linePos" y]
		}
		else
			historyrecord:= logicalhistory["linePos" x] ; even though the line now isn't right doesn't mean next time it won't be.
		splithistoryrecord:= StrSplit(historyrecord, ["(hardreturn)", "(softreturn)"])
		for index, splithistory in splithistoryrecord
		{
			if (Index == 1)
				record:= % splithistory
		}
		if ((occurenceuser != record)&&(numberofdifferences != 0)) ; the number of occurences go negative when lines get deleted... I haven't updated the below else for that yet.
		{
			LastLine:= logicalhistory["linePos" logicalhistorylastline] ; if a user is lagging the array make sure you are putting in last lines right.
			if ((LastLine == "(softreturn)")||(LastLine == "(hardreturn)")) ; the last line shouldn't be any other value.
			{
				z++ ; a z variable making sure we don't lose y and holding the number of occurences.
				if (z == 1) ; there's not enough time to add different enters in different spots (meaning the user couldn't add enough enters in the time this will be done).
					y:=% x
				IfInString, LastLine, (softreturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(softreturn)"
				IfInString, LastLine, (hardreturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(hardreturn)"
				numberofdifferences--
				logicalhistorylastline--
			} ; the likely answer is a deleted line in occurenceuser. we need to add to the numberofdifferences. I'll also need to update this in the future for the array.
			else
				numberofdifferences++
		}
		else if ((occurenceuser != record)&&(numberofdifferences == 0)) ; meaning user has updated a line with a new record
		{
			newhistoryrecord["linePos" x]:= occurenceuser
			IfInString, record, (softreturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(softreturn)"
			IfInString, record, (hardreturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(hardreturn)"
			recordkeeper:=% record
			usersentence:=% occurenceuser
		} ; z from above holds all change counts. y from above holds the history record line back. technically y can equal x-z or just y++. I think for greater clarity it should be x-z because a user may choose to purposely lag the logicalhistoryarray Change function. Basically this function can be implimented at will as long as the keys are being kept up with and added to the historyarray in the main loop (of course that might also come with logical array issues).
		else if ((occurenceuser == record)&&(numberofdifferences == 0))
			newhistoryrecord["linePos" x]:= record
	}
	if (recordkeeper != "")
		Doppler(usersentence, recordkeeper)
	Return % newhistoryrecord ; There has been many different statements on using the % after return or in ":=" as an operorator (it technically doesn't need to be done and can cause issues if done improperly). I use it because honestly it's like my signature to my work.
}

Doppler(usersentence, historysentence)
{
	livewords:=[]
	pastwords:=[]
	check:=GetControl("GetKeeper")
	if (check == "&not@a#rea1*sent3nc3")
	{
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			livewords["wordPos" key]:= userwords
		}
		historysplit:=StrSplit(historysentence, A_Space)
		for key, historywords in historysplit
		{
			pastwords["wordPos" key]:= historywords
		}
		usercount:=GetLineCount(livewords)
		historycount:= GetLineCount(pastwords)
		Loop, % usercount
		{
			x++
			userword:=livewords["wordPos" x]
			historyword:=pastwords["wordPos" x]
			userwordlength:=StrLen(userword)
			historywordlength:= StrLen(historyword)
			if ((userword != historyword)||(historycount < x))
			{
				GuiControl, AI:, WordKeeper, % historyword "," userword "," x
			}
		}
		StringReplace, userword, userword, historyword, , ALL
	}
	else if (check != "&not@a#rea1*sent3nc3")
	{
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 1)
				historyword:=% chec
			if (index == 2)
				ouserword:=% chec
			if (index == 3)
				x:=% chec
		}
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			if (key == x)
				userword:=% userwords
		}
		GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		StringReplace, userword, userword, historyword, , ALL
	}
	userwordlength:=StrLen(userword)
	if (userwordlength < 2)
	{
		GuiControl, AI:, Information, Working...
		SpellChecker(0)
	}
	if (userwordlength > 3)
	{
		GuiControl, AI:, Information, Working.
		ourwords:=WordCheck(userword, userwordlength)
		if (ourwords == "")
			SpellChecker(0)
		SpellChecker(userwordlength)
		GetControl(ourwords)
	}
	Return
}

FixLogicalhistory_Array(historyarray, howmanylines)
{
	lastline:= GetLineCount(historyarray)
	whichbutton:= GetControl("ButtCount")
	Loop, % howmanylines
	{
		lastline++
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					historyarray["linePos" lastline]:= "(softreturn)"
				if (butt == "Enter")
					historyarray["linePos" lastline]:= "(hardreturn)"
			}
		}
	}
	Return % historyarray
}

ReturnLineArray(lines, user)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/Softreturn\|/", "\|/userreturns\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

GetButtonCount(pressed)
{
	pressing:= StrSplit(pressed, ",")
	For Index, press in pressing
		if (Index == 1)
			Return % press
}

FindingRealLineLOL(occurenceuser, rowbefore, thisrow)
{
	IfInString, occurenceuser, %rowbefore%
	{
		rowlength:= StrLen(rowbefore)
		occurencelength:= StrLen(occurenceuser)
		subtractedlength:=(occurencelength-rowlength)
		thisstring:= SubStr(occurenceuser, subtractedlength, occurencelength)
		if (thisstring == rowbefore)
		{
			IfInString, occurenceuser, %thisrow%
				Return % "Found"
			IfNotInstring, occurenceuser, %thisrow%
				Return % "NextRow"
		}
	}
	if (rowbefore == "NextRow")
		IfInString, occurenceuser, %thisrow%
			Return % "Found"
	Return % "NotFound"
}

ProcessStart(contents, Rest)
{
	WinSet, Transparent, 0, Words
	Control, Disable ,, Edit1, AI
	WinActivate, AI
	GuiControl, AI:, Edit1, % contents
	Sleep, % Rest
	Control, Enable ,, Edit1, AI
	GuiControl, AI:, Information, Done
	Return
}

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	WinActivate, AI
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	if (n > 3)
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	if (n == 0)
		WinSet, Transparent, 0, Words
	WinGet, visible, Transparent, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	Return
}
return

ReturnClearDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			hinput:= harray["linePos" x]
			hsplit:= StrSplit(hinput, ["(hardreturn)", "(softreturn)"])
			for Index, h in hsplit
			{
				if (Index == 1)
					checkh:= % h
			}
			uinput:= uarray["linePos" x]
			StringReplace, uinput, uinput, (softreturn), , ALL
			StringReplace, uinput, uinput, (hardreturn), , ALL
			l_checkh:= StrLen(checkh)
			l_uinput:= StrLen(uinput)
			if (uinput != checkh)
				Return % x
			if (l_checkh != l_uinput)
				Return % x
			if (x == v)
				Break
			checkh:=
		}
		Return % "0"
	}
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return % "True"
	}
}

GetLineCount(arraycount)
{
	LastLine:=0
	for Index, count in arraycount
		++LastLine
	Return % LastLine
}

GetControl(FocTex)
{
	WinActivate, AI
	Sleep, 1000
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, % InFocus
	ControlGet, row, CurrentLine, , % InFocus, AI
	GuiControlGet, Word, Words:, Listbox1
	StringReplace, text, text, `n, \|/userreturns\|/, ALL
	GuiControlGet, ButtonCountCheck, AI:, ButtonCountCheck
	GuiControlGet, Save_File, AI:, AISave
	GuiControlGet, DopplerGet, AI:, WordKeeper
	if (FocTex == "GetKeeper")
		Return % DopplerGet
	if (FocTex == "AISave")
		Return % Save_File
	if (FocTex == "ButtCount")
		Return % ButtonCountCheck
	if (FocTex == "Row")
		Return % row
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	x:=0
	GuiControl, Words:, Listbox1, | 
	Loop, Parse, % FocTex, |
		x++
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
}

HashContents(contents)
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, \|/CR+LF\|/, `n, ALL
	StringReplace, contents, contents, \|/Softreturn\|/, `n, ALL
	return % contents
}

GetHistory()
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, `r`n,(hardreturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, (softreturn)\|/Softreturn\|/, ALL
	Return % contents
}

RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitapp

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 09 Dec 2023, 20:24

I next plan to add 3 clipboards... I have personally been stuck in the situation of needing to paste 2 maybe three things over and over and over again... And honestly that just well bites (for lack of better words). I now decided to embed the variable/filter on the main Gui for easier usage. I also fixed the missing curly braces in the filter selection process...

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)
IniRead, Rest, % Cache "\Settings.ini", Timers, Key1
If (Rest == "ERROR")
{
	IniWrite, 10000, % Cache "\Settings.ini", Timers, Key1
	Rest:= 10000
}
IniRead, Notactive, % Cache "\Settings.ini", Timers, Key2
if (Notactive == "ERROR")
{
	IniWrite, 500, % Cache "\Settings.ini", Timers, Key2
	Notactive:= 500
}
IniRead, NoDif, % Cache "\Settings.ini", Timers, Key3
if (NoDif == "ERROR")
{
	IniWrite, 25, % Cache "\Settings.ini", Timers, Key3
	NoDif:= 25
}

Loop, Files, *.ahk, D F R
{
	IfInString, A_LoopFileName, @
	{
		Continue
	}
	wi=%wi%%A_LoopFileName%|
}

Menu, Settings, Add, Timers, Timers
Menu, Settings, Add, AlwaysOnTop`ton/off, Always
Menu, Settings, Add, Suspend`ton/off, SusOnOff
Menu, Settings, Add, Reload`tCtrl+r, Reload
Menu, AIsMenu, Add, Settings, :Settings

CoordMode, Caret, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Window
Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, Menu, AIsMenu
Gui, Add, GroupBox, x25 y80 h250 w150 wrap, Get variables`n(Filter results by Checkbox)
Gui, Add, ListBox, r10 yp+35  xp+15 w120 gFileSelected vFileSelected, %wi%
Gui, Add, Checkbox, vGui, Gui Variables
Gui, Add, Checkbox, vExplicit, Explicit Variables
Gui, Add, Checkbox, vImplicitExplicit, Implicit-Explicit
Gui, Add, Text, -E0x200 x0 y0 vButtonCountCheck w20, 0,Unknown
Gui, Add, Text, -E0x200 vWordKeeper w20, &not@a#rea1*sent3nc3
Gui, Add, Edit,  r20 ym+25 x200 vWords w325 h500 hwndTracker,
Gui, Add, Button, gAISave, Save
Gui, Add, Text, vAISave, Don't save
Gui, Add, Text, ym+298 x470 vInformation, Loading...
Gui, Margin, 50, 30
Gui, Show, h400, AI work
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, margin, 0, 0
Gui, Show, , Words

contents:=HashContents(contents)
logicalhistory:= []
logicalhistory:= ProcessStart(contents, Rest)
activeuserinput:= []

Loop,
{
	winwonder:=WinWonder()
	if (winwonder == "False")
	{
		Sleep, % Notactive
		Continue
	}
	getuserinput:= GetControl("Text")
	activeuserinput:=ReturnLineArray(getuserinput, "user")
	historylastline:= GetLineCount(logicalhistory)
	activeuserlastline:= GetLineCount(activeuserinput)
	check:=GetControl("GetKeeper")
	if (check == "7h151s@a#res37")
	{
		If (getuserinput == "")
		{
			Sleep, % Notactive
			Continue
		}
		GuiControl, AI:, WordKeeper, &not@a#rea1*sent3nc3
		contents:=HashContents(contents)
		logicalhistory:= ProcessStart(contents, Rest)
		Continue
	}
	else
	{
		Sleep, % Notactive
		Continue
	}
	if (activeuserlastline != historylastline)
	{
		logicallastlineaddition:=(activeuserlastline-historylastline)
		logicalhistory:= FixLogicalhistory_Array(logicalhistory, logicallastlineaddition) ; where last lines are being put in. and you will also want to function in lastline (Deleted_Line) to acompany the changes. if you are lagging ApplyLogicalChange().
		logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, logicallastlineaddition)
	}
	if (activeuserlastline == historylastline)
	{
		logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, 0)
	}
	savecheck:= GetControl("AISave")
	if (savecheck == "Save_File")
	{
		historycount:=GetLineCount(logicalhistory)
		Loop, % historycount
		{
			x++
			sentences:= logicalhistory["linePos" x]
			StringReplace, sentences, sentences, (softreturn), \|/softreturn\|/, ALL
			StringReplace, sentences, sentences, (hardreturn), \|/CR+LF\|/, ALL
			FileContents:=% FileContents sentences
		}
		FileMove, % Temp, % TempBack, 1
		FileAppend, % FileContents, % Temp, UTF-8
		GuiControl,AI:, AISave, Don't Save
	}
}
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		check:=GetControl("GetKeeper")
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 2)
				userword:=% chec
		}
		str:= StrLen(userword)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
	}
	else
	{
		Send, `t
	}
	Return
}
else
	Send, `t
Return

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",ShiftEnter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
return

~Enter::
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",Enter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
return

AISave:
GuiControl,AI:, AISave, Save_File
return
	
SusOnOff:
Suspend, Toggle
if (A_IsSuspended == 1)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOn
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOff
Return

Always:
WinSet, AlwaysOnTop, Toggle, AI
WinGet, ExStyle, ExStyle, AI
if (ExStyle == 0x00000180)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOff
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOn
Return
 
Timers:
Gui, Timers:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, y25, Rest Timer:`t`n(in seconds)
Gui, Add, Text, y75 xs, Window Not Active:`t`n(in milliseconds)
Gui, Add, Text, y125 xs, Process Loop timer:`t`n(in milliseconds)
Gui, Add, Edit, w250 r3 ys-15 -VScroll, This timer slows the script before it gets to the main loop function. It's used to help in processing the global function "Speller."
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the script when the it is not active.
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the main processing loop while typing. It's dependent on a difference created in the main edit control.
Gui, Add, Edit, ys xs+400 w50 y25
Gui, Add, UpDown, vRangeInSeconds Range1-50, 10
Gui, Add, Edit, ys xs+400 w50 y75
Gui, Add, UpDown, vRangeInMillisecondsOfActive Range1-1000, 500
Gui, Add, Edit, ys xs+400 w50 y125
Gui, Add, UpDown, vRangeInMillisecondsOfProcess Range1-100, 25
Gui, Add, Text, xm+10 ym+180, Select the above values to your personal preferences and click save to keep the changes.
Gui, Add, Text, xm+80 ym+215, (Note you have to restart the program to force the changes)
Gui, Add, Button, ym+210 xs+425 gSave, Save
Gui, Add, Button, ym+210 xs+370 gCancel, Cancel
Gui, Margin, 20, 50
Gui, Show, h250 w500, Timers
Control, Disable ,, Edit1, Timers
Control, Disable ,, Edit2, Timers
Control, Disable ,, Edit3, Timers
Return

Reload:
^r::
Reload
Return

Cancel:
Gui, Timers:Destroy
Return

Save:
Gui, Submit, NoHide
RangeInSeconds:=(RangeInSeconds*1000)
IniWrite, % RangeInSeconds, % Cache "\Settings.ini", Timers, Key1
IniWrite, % RangeInMillisecondsOfActive, % Cache "\Settings.ini", Timers, Key2
IniWrite, % RangeInMillisecondsOfProcess, % Cache "\Settings.ini", Timers, Key3
Gui, Timers:Destroy
Return

FileSelected:
Gui, Submit, NoHide
Control, Disable ,, ListBox1, AI
Control, Disable ,, Edit1, AI
FileRead, contents, % FileSelected
GuiControl, AI:, WordKeeper, 7h151s@a#res37
if (Gui == 1)
	filters.= "[Filter='Gui'],"
if (Explicit == 1)
	filters.= "[Filter='explicit'],"
if (ImplicitExplicit == 1)
	filters.= "[Filter='implicit-explicit'],"
wi:=
Loop, Files, *.ahk, D F R
{
	IfInString, A_LoopFileName, @
	{
		Continue
	}
	wi=%wi%%A_LoopFileName%|
}
GuiControl, AI:, Button2, 0
GuiControl, AI:, Button3, 0
GuiControl, AI:, Button4, 0
GuiControl, AI:, ListBox1, % "|" wi
GuiControl, AI:, Words,
GuiControl, AI:, Words, % contents
whichbutton:=GetControl("ButtCount")
button:= StrSplit(whichbutton, ",")
for key, butt in button
{
	if (key == 2)
	{
		if (butt == "ShiftEnter")
			thisbutton:= "\|/Softreturn\|/"
		if (butt == "Enter")
			thisbutton:= "\|/hardreturn\|/"
		if (butt == "Unknown")
			thisbutton:= " \|/Softreturn\|/"
	}
}
StringReplace, contents, contents, \|/userreturns\|/, %thisbutton%, ALL
FileMove, % Temp, % TempBack, 1
FileAppend, % contents, % Temp, UTF-8
Sleep, 1000
Return

GetVariables(filecontents, filters)
{
	linenumber:=0
	sentences:=
	line:=
	Loop, Parse, % filecontents, `r
	{
		linenumber++
		line:=% A_LoopField
		sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
		for index, sentence in sentences
		{
			if (index == 1)
				codestring:=% sentence
			if (index == 2)
				commentstring:=% sentence
		}
		codestring:= RemoveCertainChars(codestring, "Start")
		IfInString, codestring, Box`,
			Continue
		IfInString, codestring, StringReplace
			Continue
		IfInString, codestring, RegEx
			Continue
		IfInString, codestring, Ini
			Continue
		IfInString, codestring, =
		{
			IfInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Percent", linenumber)
				IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
			}
			else IfNotInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
			IfInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Quotes", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring 
			}
			else IfNotInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
		}
		else IfInString, codestring, [percent]
		{
			variablestring:= GetVariableString(codestring, "Percent", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring
		}
		else IfInString, codestring, [quotes]
		{
			variablestring:= GetVariableString(codestring, "Quotes", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring "found in quotes 2`n"
		}
		IfInString, codestring, Gui
			IfInString, codestring, `,
				IfInString, codestring, %A_Space%v
				{
					variablestring:= GetVariableString(codestring, "Gui", linenumber)
					IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
				}
	}
	thesefilters:=StrSplit(filters, ",")
	for index, filter in thesefilters
	{
		if (index == 1)
		{
			if (filter == "")
				Continue
			firstfilter:=% filter
		}
		if (index == 2)
		{
			if (filter == "")
				Continue
			secondfilter:=% filter
		}
		if (index == 3)
		{
			if (filter == "")
				Continue
			thirdfilter:=% filter
		}
	}
	Loop, Parse, % variablelist, `n
	{
		checking:=
		thischeck:=
		information:=
		if (A_LoopField == "")
			Continue
		repeatcheck:= StrSplit(A_LoopField, "[thissplitter]")
		for index, repeat in repeatcheck
		{
			if (index == 1)
			{
				IfNotInString, completedlist, % repeat
					thischeck:=% repeat
				IfInString, completedlist, % repeat
				{
					checking:= MakeSure(completedlist, repeat)
					if (checking == "True")
						Continue
					else if (checking == "False")
						thischeck:=% repeat
				}
			}
			if (index == 2)
			{
				if (firstfilter != "")
					IfInString, repeat, % firstfilter
					{
						applyfilters:= StrSplit(repeat, firstfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
				if (secondfilter != "")
					IfInString, repeat, % secondfilter
					{
						applyfilters:= StrSplit(repeat, secondfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
				if (thirdfilter != "")
					IfInString, repeat, % thirdfilter
					{
						applyfilters:= StrSplit(repeat, thirdfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
			}
		}
		if (information == "")
			Continue
		if (thischeck != "")
		{
			checklist:=% Trim(thischeck) "`n" Trim(information) "`n"
			IfNotInString, completedlist, % checklist
				completedlist.= checklist
		}
	}
	completedlist:= RemoveCertainChars(completedlist, "End")
	Return % completedlist
}

MakeSure(listinprogress, checkword)
{
	Loop, Parse, % listinprogress, `n
	{
		if (checkword == A_LoopField)
			Return % "True"
	}
	Return % "False"
}

GetVariableString(codestring, whichone, linenumber)
{
	if (whichone == "Gui")
	{
		variablestrings:= StrSplit(codestring, ",")
		for index, variablestring in variablestrings
		{
			if (index > 4)
				Continue
			IfInString, variablestring, %A_Space%v
				thisvariablestring:=% variablestring
		}
		variablestring:= StrSplit(thisvariablestring, A_Space)
		for index, variable in variablestring
		{
			thisvariableletter:= SubStr(variable, 1, 1)
			if (thisvariableletter == "v")
				return % variable "[thissplitter] Gui variable[Filter='Gui'] Line number is found at: " linenumber "`n"
		}
		Return % variable "[thissplitter] Gui variable Line number is found at: " linenumber "`n"
	}
	if (whichone == "Quotes")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [quotes]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		variablestrings:= StrSplit(codestring, "[quotes]")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 0)
				IfNotInString, variablestring, %A_Space%
					IfNotInString, variables, % variablestring
						variables.= "[quotes]" variablestring "[quotes][thissplitter] explicit[Filter='explicit'] variable Line number is found at: " linenumber "`n"
		}
		Return % variables
	}
	if (whichone == "Percent")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [percent]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		IfInString, codestring, `,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					IfInString, variablestring, [percent]
						IfNotInString, variablestring, =
							IfInString, variablestring, A_Space
								variables.= variablestring "[thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		IfNotInString, codestring, `,
		{
			IfInString, codestring, =
			{
				variablestrings:= StrSplit(codestring, "=")
				for index, variablestring in variablestrings
				{
					if (index == 1)
					{
						variables:= StrSplit(variablestring, A_Space)
						for index, variable in variables
							thisvariable:=% variable
					}
					if (index == 2)
						codestring:=% variablestring
				}
			}
			variablestrings:= StrSplit(codestring, "[percent]")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					variables.= "[percent]" variablestring "[percent][thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		if (thisvariable != "")
			variables.= thisvariable "[thissplitter]implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
		Return % variables
	}
	if (whichone == "Equals")
	{
		variablestrings:= StrSplit(codestring, "=")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 1)
				IfNotInString, variablestring, [quotes]
				{
					thisvariablestring:= StrSplit(variablestring, A_Space)
					for index, thisvariable in thisvariablestring
					{
						variable:=% thisvariable "[thissplitter] implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
					}
				}
		}
		Return % variable
	}
	return % "Not Found"
}

RemoveCertainChars(string, special)
{
	if (special == "Start")
	{
		StringReplace, string, string, ", [quotes], ALL ; "
		StringReplace, string, string, `%%A_Space%, [percent], ALL
		StringReplace, string, string, `%, [percent], ALL
		StringReplace, string, string, %A_Space%:, :, ALL
		StringReplace, string, string, :=, =, ALL
		StringReplace, string, string, ==, =, ALL
		StringReplace, string, string, >, =, ALL
		StringReplace, string, string, <, =, ALL
		StringReplace, string, string, %A_Space%!=, =, ALL
		StringReplace, string, string, =%A_Space%, =, ALL
		StringReplace, string, string, %A_Space%=, =, ALL
		StringReplace, string, string, ), , ALL
		StringReplace, string, string, (, , ALL
		StringReplace, string, string, `t, , ALL
	}
	if (special == "End")
	{
		StringReplace, string, string, [quotes], ", ALL ; "
		StringReplace, string, string, [percent], `%, ALL
		StringReplace, string, string, `,, , ALL
	}
	Return % string
}

GetButton_Count()
{
	Loop,
	{
		ButtonCountCheck:= GetControl("ButtCount")
		if (ButtonCountCheck != OldButtonCountCheck)
		{
			OldCount:=% Count
			OldButton:=% Button
			Sleep, 500
			ButtonCount_Split:= StrSplit(ButtonCountCheck, ",")
			For Index, ButtCount in ButtonCount_Split
			{
				if (Index == 1)
					Count:=% ButtCount
				if (Index == 2)
					Button:=% ButtCount
			}
		}
		else if (ButtonCountCheck == OldButtonCountCheck)
			Break
		if ((Button != OldButton)&&(Count > 1))
			Break
		OldButtonCountCheck:=% ButtonCountCheck
	}
	if (Button == OldButton)
	{
		ButtonCountReturn:=% Count "," Button
		GuiControl,AI:, ButtonCountCheck, % "0," Button
	}
	if (Button != OldButton)
	{
		NewCount:=% Count-OldCount
		GuiControl,AI:, ButtonCountCheck, % NewCount "," Button
		ButtonCountReturn:=% OldCount "," OldButton
	}
	Return
}

ApplyLogicalChange(activeuserinput, logicalhistory, numberofdifferences)
{
	x:= 0
	newhistoryrecord:=[]
	activeuserinputlastline:= GetLineCount(activeuserinput)
	logicalhistorylastline:= GetLineCount(logicalhistory)
	LastLine:= logicalhistory["linePos" logicalhistorylastline]
	Loop, % activeuserinputlastline
	{
		record:=
		x++ ; a lagged y variable needed to stagger history.
		occurenceuser:= activeuserinput["linePos" x]
		if (y > 0)
		{
			y:=(x-z) ; this will be an opposite staggered y (x+z) for deleted lines.
			historyrecord:= logicalhistory["linePos" y]
		}
		else
			historyrecord:= logicalhistory["linePos" x] ; even though the line now isn't right doesn't mean next time it won't be.
		splithistoryrecord:= StrSplit(historyrecord, ["(hardreturn)", "(softreturn)"])
		for index, splithistory in splithistoryrecord
		{
			if (Index == 1)
				record:= % splithistory
		}
		if ((occurenceuser != record)&&(numberofdifferences != 0)) ; the number of occurences go negative when lines get deleted... I haven't updated the below else for that yet.
		{
			LastLine:= logicalhistory["linePos" logicalhistorylastline] ; if a user is lagging the array make sure you are putting in last lines right.
			if ((LastLine == "(softreturn)")||(LastLine == "(hardreturn)")) ; the last line shouldn't be any other value.
			{
				z++ ; a z variable making sure we don't lose y and holding the number of occurences.
				if (z == 1) ; there's not enough time to add different enters in different spots (meaning the user couldn't add enough enters in the time this will be done).
					y:=% x
				IfInString, LastLine, (softreturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(softreturn)"
				IfInString, LastLine, (hardreturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(hardreturn)"
				numberofdifferences--
				logicalhistorylastline--
			} ; the likely answer is a deleted line in occurenceuser. we need to add to the numberofdifferences. I'll also need to update this in the future for the array.
			else
				numberofdifferences++
		}
		else if ((occurenceuser != record)&&(numberofdifferences == 0)) ; meaning user has updated a line with a new record
		{
			newhistoryrecord["linePos" x]:= occurenceuser
			IfInString, record, (softreturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(softreturn)"
			IfInString, record, (hardreturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(hardreturn)"
			recordkeeper:=% record
			usersentence:=% occurenceuser
		} ; z from above holds all change counts. y from above holds the history record line back. technically y can equal x-z or just y++. I think for greater clarity it should be x-z because a user may choose to purposely lag the logicalhistoryarray Change function. Basically this function can be implimented at will as long as the keys are being kept up with and added to the historyarray in the main loop (of course that might also come with logical array issues).
		else if ((occurenceuser == record)&&(numberofdifferences == 0))
			newhistoryrecord["linePos" x]:= record
	}
	check:=GetControl("GetKeeper")
	if (check == "7h151s@a#res37")
		Return
	if (recordkeeper != "")
		Doppler(usersentence, recordkeeper)
	Return % newhistoryrecord ; There has been many different statements on using the % after return or in ":=" as an operorator (it technically doesn't need to be done and can cause issues if done improperly). I use it because honestly it's like my signature to my work.
}

Doppler(usersentence, historysentence)
{
	livewords:=[]
	pastwords:=[]
	check:=GetControl("GetKeeper")
	if (check == "&not@a#rea1*sent3nc3")
	{
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			livewords["wordPos" key]:= userwords
		}
		historysplit:=StrSplit(historysentence, A_Space)
		for key, historywords in historysplit
		{
			pastwords["wordPos" key]:= historywords
		}
		usercount:=GetLineCount(livewords)
		historycount:= GetLineCount(pastwords)
		Loop, % usercount
		{
			x++
			userword:=livewords["wordPos" x]
			historyword:=pastwords["wordPos" x]
			userwordlength:=StrLen(userword)
			historywordlength:= StrLen(historyword)
			if ((userword != historyword)||(historycount < x))
			{
				GuiControl, AI:, WordKeeper, % historyword "," userword "," x
			}
		}
		StringReplace, userword, userword, historyword, , ALL
	}
	else if (check != "&not@a#rea1*sent3nc3")
	{
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 1)
				historyword:=% chec
			if (index == 2)
				ouserword:=% chec
			if (index == 3)
				x:=% chec
		}
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			if (key == x)
				userword:=% userwords
		}
		GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		StringReplace, userword, userword, historyword, , ALL
	}
	userwordlength:=StrLen(userword)
	if (userwordlength < 2)
	{
		GuiControl, AI:, Information, Working...
		SpellChecker(0)
	}
	if (userwordlength > 3)
	{
		GuiControl, AI:, Information, Working.
		ourwords:=WordCheck(userword, userwordlength)
		if (ourwords == "")
			SpellChecker(0)
		SpellChecker(userwordlength)
		GetControl(ourwords)
	}
	Return
}

FixLogicalhistory_Array(historyarray, howmanylines)
{
	lastline:= GetLineCount(historyarray)
	whichbutton:= GetControl("ButtCount")
	Loop, % howmanylines
	{
		lastline++
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					historyarray["linePos" lastline]:= "(softreturn)"
				if (butt == "Enter")
					historyarray["linePos" lastline]:= "(hardreturn)"
			}
		}
	}
	Return % historyarray
}

ReturnLineArray(lines, user)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/Softreturn\|/", "\|/userreturns\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

GetButtonCount(pressed)
{
	pressing:= StrSplit(pressed, ",")
	For Index, press in pressing
		if (Index == 1)
			Return % press
}

FindingRealLineLOL(occurenceuser, rowbefore, thisrow)
{
	IfInString, occurenceuser, %rowbefore%
	{
		rowlength:= StrLen(rowbefore)
		occurencelength:= StrLen(occurenceuser)
		subtractedlength:=(occurencelength-rowlength)
		thisstring:= SubStr(occurenceuser, subtractedlength, occurencelength)
		if (thisstring == rowbefore)
		{
			IfInString, occurenceuser, %thisrow%
				Return % "Found"
			IfNotInstring, occurenceuser, %thisrow%
				Return % "NextRow"
		}
	}
	if (rowbefore == "NextRow")
		IfInString, occurenceuser, %thisrow%
			Return % "Found"
	Return % "NotFound"
}

ProcessStart(contents, Rest)
{
	logicalhistory:= []
	WinSet, Transparent, 0, Words
	history:= GetHistory()
	logicalhistory:= ReturnLineArray(history, user)
	Control, Disable ,, Edit1, AI
	WinActivate, AI
	GuiControl, AI:, Edit1, % contents
	Sleep, % Rest
	Control, Enable ,, Edit1, AI
	GuiControl, AI:, Information, Done
	Control, Enable ,, ListBox1, AI
	Return % logicalhistory
}

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	WinActivate, AI
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	if (n > 3)
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	if (n == 0)
		WinSet, Transparent, 0, Words
	WinGet, visible, Transparent, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	Return
}
return

ReturnClearDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			hinput:= harray["linePos" x]
			hsplit:= StrSplit(hinput, ["(hardreturn)", "(softreturn)"])
			for Index, h in hsplit
			{
				if (Index == 1)
					checkh:= % h
			}
			uinput:= uarray["linePos" x]
			StringReplace, uinput, uinput, (softreturn), , ALL
			StringReplace, uinput, uinput, (hardreturn), , ALL
			l_checkh:= StrLen(checkh)
			l_uinput:= StrLen(uinput)
			if (uinput != checkh)
				Return % x
			if (l_checkh != l_uinput)
				Return % x
			if (x == v)
				Break
			checkh:=
		}
		Return % "0"
	}
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return % "True"
	}
}

GetLineCount(arraycount)
{
	LastLine:=0
	for Index, count in arraycount
		++LastLine
	Return % LastLine
}

GetControl(FocTex)
{
	WinActivate, AI
	Sleep, 1000
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, Edit1
	ControlGet, row, CurrentLine, , Edit1, AI
	GuiControlGet, Word, Words:, Listbox1
	StringReplace, text, text, `n, \|/userreturns\|/, ALL
	GuiControlGet, ButtonCountCheck, AI:, ButtonCountCheck
	GuiControlGet, Save_File, AI:, AISave
	GuiControlGet, DopplerGet, AI:, WordKeeper
	if (FocTex == "GetKeeper")
		Return % DopplerGet
	if (FocTex == "AISave")
		Return % Save_File
	if (FocTex == "ButtCount")
		Return % ButtonCountCheck
	if (FocTex == "Row")
		Return % row
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	x:=0
	GuiControl, Words:, Listbox1, | 
	Loop, Parse, % FocTex, |
		x++
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
	Return
}

HashContents(contents)
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, \|/CR+LF\|/, `n, ALL
	StringReplace, contents, contents, \|/Softreturn\|/, `n, ALL
	return % contents
}

GetHistory()
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, `r`n,(hardreturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, (softreturn)\|/Softreturn\|/, ALL
	Return % contents
}

RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitapp

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 10 Dec 2023, 10:27

there is a hotkey on the {LCtrl} button... a Input() is inside it. What it does is captures the keys pressed after the {LCtrl} button is pressed on a 0.75 timer (that feels a little natural for me however you may need to adjust to your own personal liking). Everything else (like Ctrl-c, v, s and so on...) works just fine. To access the second or third clipboard (MaxMem of 64 MB) it's {Ctrl}vv or {Ctrl}vvv. I also fixed some lagging areas I accidently left in. Now to clean up the functions and simplify where I can.

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)
IniRead, Rest, % Cache "\Settings.ini", Timers, Key1
If (Rest == "ERROR")
{
	IniWrite, 10000, % Cache "\Settings.ini", Timers, Key1
	Rest:= 10000
}
IniRead, Notactive, % Cache "\Settings.ini", Timers, Key2
if (Notactive == "ERROR")
{
	IniWrite, 500, % Cache "\Settings.ini", Timers, Key2
	Notactive:= 500
}
IniRead, NoDif, % Cache "\Settings.ini", Timers, Key3
if (NoDif == "ERROR")
{
	IniWrite, 25, % Cache "\Settings.ini", Timers, Key3
	NoDif:= 25
}

Loop, Files, *.ahk, D F R
{
	IfInString, A_LoopFileName, @
	{
		Continue
	}
	wi=%wi%%A_LoopFileName%|
}

Menu, Settings, Add, Timers, Timers
Menu, Settings, Add, AlwaysOnTop`ton/off, Always
Menu, Settings, Add, Suspend`ton/off, SusOnOff
Menu, Settings, Add, Reload`tCtrl+r, Reload
Menu, AIsMenu, Add, Settings, :Settings

CoordMode, Caret, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Window
Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, Menu, AIsMenu
Gui, Add, GroupBox, x25 y80 h250 w150 wrap, Get variables`n(Filter results by Checkbox)
Gui, Add, ListBox, r10 yp+35  xp+15 w120 gFileSelected vFileSelected, %wi%
Gui, Add, Checkbox, vGui, Gui Variables
Gui, Add, Checkbox, vExplicit, Explicit Variables
Gui, Add, Checkbox, vImplicitExplicit, Implicit-Explicit
Gui, Add, Text, -E0x200 x0 y0 vButtonCountCheck w20, 0,Unknown
Gui, Add, Text, -E0x200 vWordKeeper w20, &not@a#rea1*sent3nc3
Gui, Add, Edit,  r20 ym+25 x200 vWords w325 h500 hwndTracker,
Gui, Add, Button, gAISave, Save
Gui, Add, Text, vAISave, Don't save
Gui, Add, Text, ym+298 x470 vInformation, Loading...
Gui, Margin, 50, 30
Gui, Show, h400, AI work
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, margin, 0, 0
Gui, Show, , Words

contents:=HashContents(contents)
logicalhistory:= []
logicalhistory:= ProcessStart(contents, Rest)
activeuserinput:= []

Loop,
{
	if ((ClipBoard != "")&&(ClipBoard != ClipBoard1))
	{
		if (ClipBoard1 == "")
			ClipBoard1:=% ClipBoard
		else if (ClipBoard1 != "")
		{
			if (ClipBoard2 == "" )
				ClipBoard2:=% ClipBoard1
			else if (ClipBoard2 != "")
			{
				ClipBoard3:=% ClipBoard2
				ClipBoard2:=% ClipBoard1
				ClipBoard1:=% ClipBoard
			}
		}
	}
	winwonder:=WinWonder()
	if (winwonder == "False")
	{
		Sleep, % Notactive
		Continue
	}
	check:=GetControl("GetKeeper")
	usersentence:=GetControl("RowText")
	if (recordkeeper == "")
		recordkeeper:=% usersentence
	if (recordkeeper != usersentence)
	{
		Doppler(usersentence, recordkeeper)
		recordkeeper:=% usersentence
	}
	getuserinput:= GetControl("Text")
	activeuserinput:=ReturnLineArray(getuserinput, "user")
	historylastline:= GetLineCount(logicalhistory)
	activeuserlastline:= GetLineCount(activeuserinput)
	if (check == "7h151s@a#res37")
	{
		If (getuserinput == "")
		{
			Sleep, % Notactive
			Continue
		}
		GuiControl, AI:, WordKeeper, &not@a#rea1*sent3nc3
		contents:=HashContents(contents)
		logicalhistory:= ProcessStart(contents, Rest)
		Continue
	}
	if (usersentence != "")
	{
		if (activeuserlastline != historylastline)
		{
			logicallastlineaddition:=(activeuserlastline-historylastline)
			logicalhistory:= FixLogicalhistory_Array(logicalhistory, logicallastlineaddition) ; where last lines are being put in. and you will also want to function in lastline (Deleted_Line) to acompany the changes. if you are lagging ApplyLogicalChange().
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, logicallastlineaddition)
		}
		if (activeuserlastline == historylastline)
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, 0)
	}
	savecheck:= GetControl("AISave")
	if (savecheck == "Save_File")
	{
		historycount:=GetLineCount(logicalhistory)
		Loop, % historycount
		{
			x++
			sentences:= logicalhistory["linePos" x]
			StringReplace, sentences, sentences, (softReturn), \|/softReturn\|/, ALL
			StringReplace, sentences, sentences, (hardReturn), \|/CR+LF\|/, ALL
			FileContents:=% FileContents sentences
		}
		FileMove, % Temp, % TempBack, 1
		FileAppend, % FileContents, % Temp, UTF-8
		GuiControl,AI:, AISave, Don't Save
	}
}
Return

LCtrl::
Input, userinput, L3 T0.75 M ; this has a 0.75 second timer... That feels a little natural. however on the person to person scale this might need adjusted.
KeyWait, Control, U
if (userinput == "vv")
	Send, % ClipBoard2
else if (userinput == "vvv")
	Send, % ClipBoard3
else
	Send, ^%userinput%
Return

$Backspace::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Backspace}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Backspace}
	}
	Return
}
else
	Send, {Backspace}
Return
	
$Space::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Space}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Space}
	}
	Return
}
else
	Send, {Space}
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		check:=GetControl("GetKeeper")
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 2)
				userword:=% chec
		}
		str:= StrLen(userword)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
	}
	else
	{
		Send, `t
	}
	Return
}
else
	Send, `t
Return

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",ShiftEnter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
Return

~Enter::
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",Enter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
Return

AISave:
GuiControl,AI:, AISave, Save_File
Return
	
SusOnOff:
Suspend, Toggle
if (A_IsSuspended == 1)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOn
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOff
Return

Always:
WinSet, AlwaysOnTop, Toggle, AI
WinGet, ExStyle, ExStyle, AI
if (ExStyle == 0x00000180)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOff
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOn
Return
 
Timers:
Gui, Timers:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, y25, Rest Timer:`t`n(in seconds)
Gui, Add, Text, y75 xs, Window Not Active:`t`n(in milliseconds)
Gui, Add, Text, y125 xs, Process Loop timer:`t`n(in milliseconds)
Gui, Add, Edit, w250 r3 ys-15 -VScroll, This timer slows the script before it gets to the main loop function. It's used to help in processing the global function "Speller."
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the script when the it is not active.
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the main processing loop while typing. It's dependent on a difference created in the main edit control.
Gui, Add, Edit, ys xs+400 w50 y25
Gui, Add, UpDown, vRangeInSeconds Range1-50, 10
Gui, Add, Edit, ys xs+400 w50 y75
Gui, Add, UpDown, vRangeInMillisecondsOfActive Range1-1000, 500
Gui, Add, Edit, ys xs+400 w50 y125
Gui, Add, UpDown, vRangeInMillisecondsOfProcess Range1-100, 25
Gui, Add, Text, xm+10 ym+180, Select the above values to your personal preferences and click save to keep the changes.
Gui, Add, Text, xm+80 ym+215, (Note you have to restart the program to force the changes)
Gui, Add, Button, ym+210 xs+425 gSave, Save
Gui, Add, Button, ym+210 xs+370 gCancel, Cancel
Gui, Margin, 20, 50
Gui, Show, h250 w500, Timers
Control, Disable ,, Edit1, Timers
Control, Disable ,, Edit2, Timers
Control, Disable ,, Edit3, Timers
Return

Reload:
^r::
Reload
Return

Cancel:
Gui, Timers:Destroy
Return

Save:
Gui, Submit, NoHide
RangeInSeconds:=(RangeInSeconds*1000)
IniWrite, % RangeInSeconds, % Cache "\Settings.ini", Timers, Key1
IniWrite, % RangeInMillisecondsOfActive, % Cache "\Settings.ini", Timers, Key2
IniWrite, % RangeInMillisecondsOfProcess, % Cache "\Settings.ini", Timers, Key3
Gui, Timers:Destroy
Return

FileSelected:
Gui, Submit, NoHide
FileRead, contents, % FileSelected
GuiControl, AI:, WordKeeper, 7h151s@a#res37
if (Gui == 1)
	filters.= "[Filter='Gui'],"
if (Explicit == 1)
	filters.= "[Filter='explicit'],"
if (ImplicitExplicit == 1)
	filters.= "[Filter='implicit-explicit'],"
wi:=
if (filters != "")
{
	Control, Disable ,, ListBox1, AI
	Control, Disable ,, Edit1, AI
	contents:= GetVariables(contents, filters)
	Loop, Files, *.ahk, D F R
	{
		IfInString, A_LoopFileName, @
		{
			Continue
		}
		wi=%wi%%A_LoopFileName%|
	}
	GuiControl, AI:, Button2, 0
	GuiControl, AI:, Button3, 0
	GuiControl, AI:, Button4, 0
	GuiControl, AI:, ListBox1, % "|" wi
	GuiControl, AI:, Words,
	GuiControl, AI:, Words, % contents
	whichbutton:=GetControl("ButtCount")
	button:= StrSplit(whichbutton, ",")
	for key, butt in button
	{
		if (key == 2)
		{
			if (butt == "ShiftEnter")
				thisbutton:= "\|/SoftReturn\|/"
			if (butt == "Enter")
				thisbutton:= "\|/hardReturn\|/"
			if (butt == "Unknown")
				thisbutton:= " \|/SoftReturn\|/"
		}
	}
	MsgBox, % contents
	StringReplace, contents, contents, `n, %thisbutton%, ALL
	MsgBox, % contents
	FileMove, % Temp, % TempBack, 1
	FileAppend, % contents, % Temp, UTF-8
}
Return

GetVariables(filecontents, filters)
{
	linenumber:=0
	sentences:=
	line:=
	Loop, Parse, % filecontents, `r
	{
		linenumber++
		line:=% A_LoopField
		sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
		for index, sentence in sentences
		{
			if (index == 1)
				codestring:=% sentence
			if (index == 2)
				commentstring:=% sentence
		}
		codestring:= RemoveCertainChars(codestring, "Start")
		IfInString, codestring, Box`,
			Continue
		IfInString, codestring, StringReplace
			Continue
		IfInString, codestring, RegEx
			Continue
		IfInString, codestring, Ini
			Continue
		IfInString, codestring, =
		{
			IfInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Percent", linenumber)
				IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
			}
			else IfNotInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
			IfInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Quotes", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring 
			}
			else IfNotInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
		}
		else IfInString, codestring, [percent]
		{
			variablestring:= GetVariableString(codestring, "Percent", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring
		}
		else IfInString, codestring, [quotes]
		{
			variablestring:= GetVariableString(codestring, "Quotes", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring "found in quotes 2`n"
		}
		IfInString, codestring, Gui
			IfInString, codestring, `,
				IfInString, codestring, %A_Space%v
				{
					variablestring:= GetVariableString(codestring, "Gui", linenumber)
					IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
				}
	}
	thesefilters:=StrSplit(filters, ",")
	for index, filter in thesefilters
	{
		if (index == 1)
		{
			if (filter == "")
				Continue
			firstfilter:=% filter
		}
		if (index == 2)
		{
			if (filter == "")
				Continue
			secondfilter:=% filter
		}
		if (index == 3)
		{
			if (filter == "")
				Continue
			thirdfilter:=% filter
		}
	}
	Loop, Parse, % variablelist, `n
	{
		checking:=
		thischeck:=
		information:=
		if (A_LoopField == "")
			Continue
		repeatcheck:= StrSplit(A_LoopField, "[thissplitter]")
		for index, repeat in repeatcheck
		{
			if (index == 1)
			{
				IfNotInString, completedlist, % repeat
					thischeck:=% repeat
				IfInString, completedlist, % repeat
				{
					checking:= MakeSure(completedlist, repeat)
					if (checking == "True")
						Continue
					else if (checking == "False")
						thischeck:=% repeat
				}
			}
			if (index == 2)
			{
				if (firstfilter != "")
					IfInString, repeat, % firstfilter
					{
						applyfilters:= StrSplit(repeat, firstfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
				if (secondfilter != "")
					IfInString, repeat, % secondfilter
					{
						applyfilters:= StrSplit(repeat, secondfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
				if (thirdfilter != "")
					IfInString, repeat, % thirdfilter
					{
						applyfilters:= StrSplit(repeat, thirdfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
			}
		}
		if (information == "")
			Continue
		if (thischeck != "")
		{
			checklist:=% Trim(thischeck) "`n" Trim(information) "`n"
			IfNotInString, completedlist, % checklist
				completedlist.= checklist
		}
	}
	completedlist:= RemoveCertainChars(completedlist, "End")
	Return % completedlist
}

MakeSure(listinprogress, checkword)
{
	Loop, Parse, % listinprogress, `n
	{
		if (checkword == A_LoopField)
			Return % "True"
	}
	Return % "False"
}

GetVariableString(codestring, whichone, linenumber)
{
	if (whichone == "Gui")
	{
		variablestrings:= StrSplit(codestring, ",")
		for index, variablestring in variablestrings
		{
			if (index > 4)
				Continue
			IfInString, variablestring, %A_Space%v
				thisvariablestring:=% variablestring
		}
		variablestring:= StrSplit(thisvariablestring, A_Space)
		for index, variable in variablestring
		{
			thisvariableletter:= SubStr(variable, 1, 1)
			if (thisvariableletter == "v")
				Return % variable "[thissplitter] Gui variable[Filter='Gui'] Line number is found at: " linenumber "`n"
		}
		Return % variable "[thissplitter] Gui variable Line number is found at: " linenumber "`n"
	}
	if (whichone == "Quotes")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [quotes]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		variablestrings:= StrSplit(codestring, "[quotes]")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 0)
				IfNotInString, variablestring, %A_Space%
					IfNotInString, variables, % variablestring
						variables.= "[quotes]" variablestring "[quotes][thissplitter] explicit[Filter='explicit'] variable Line number is found at: " linenumber "`n"
		}
		Return % variables
	}
	if (whichone == "Percent")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [percent]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		IfInString, codestring, `,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					IfInString, variablestring, [percent]
						IfNotInString, variablestring, =
							IfInString, variablestring, A_Space
								variables.= variablestring "[thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		IfNotInString, codestring, `,
		{
			IfInString, codestring, =
			{
				variablestrings:= StrSplit(codestring, "=")
				for index, variablestring in variablestrings
				{
					if (index == 1)
					{
						variables:= StrSplit(variablestring, A_Space)
						for index, variable in variables
							thisvariable:=% variable
					}
					if (index == 2)
						codestring:=% variablestring
				}
			}
			variablestrings:= StrSplit(codestring, "[percent]")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					variables.= "[percent]" variablestring "[percent][thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		if (thisvariable != "")
			variables.= thisvariable "[thissplitter]implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
		Return % variables
	}
	if (whichone == "Equals")
	{
		variablestrings:= StrSplit(codestring, "=")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 1)
				IfNotInString, variablestring, [quotes]
				{
					thisvariablestring:= StrSplit(variablestring, A_Space)
					for index, thisvariable in thisvariablestring
					{
						variable:=% thisvariable "[thissplitter] implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
					}
				}
		}
		Return % variable
	}
	Return % "Not Found"
}

RemoveCertainChars(string, special)
{
	if (special == "Start")
	{
		StringReplace, string, string, ", [quotes], ALL ; "
		StringReplace, string, string, `%%A_Space%, [percent], ALL
		StringReplace, string, string, `%, [percent], ALL
		StringReplace, string, string, %A_Space%:, :, ALL
		StringReplace, string, string, :=, =, ALL
		StringReplace, string, string, ==, =, ALL
		StringReplace, string, string, >, =, ALL
		StringReplace, string, string, <, =, ALL
		StringReplace, string, string, %A_Space%!=, =, ALL
		StringReplace, string, string, =%A_Space%, =, ALL
		StringReplace, string, string, %A_Space%=, =, ALL
		StringReplace, string, string, ), , ALL
		StringReplace, string, string, (, , ALL
		StringReplace, string, string, `t, , ALL
	}
	if (special == "End")
	{
		StringReplace, string, string, [quotes], ", ALL ; "
		StringReplace, string, string, [percent], `%, ALL
		StringReplace, string, string, `,, , ALL
	}
	Return % string
}

GetButton_Count()
{
	Loop,
	{
		ButtonCountCheck:= GetControl("ButtCount")
		if (ButtonCountCheck != OldButtonCountCheck)
		{
			OldCount:=% Count
			OldButton:=% Button
			Sleep, 500
			ButtonCount_Split:= StrSplit(ButtonCountCheck, ",")
			For Index, ButtCount in ButtonCount_Split
			{
				if (Index == 1)
					Count:=% ButtCount
				if (Index == 2)
					Button:=% ButtCount
			}
		}
		else if (ButtonCountCheck == OldButtonCountCheck)
			Break
		if ((Button != OldButton)&&(Count > 1))
			Break
		OldButtonCountCheck:=% ButtonCountCheck
	}
	if (Button == OldButton)
	{
		ButtonCountReturn:=% Count "," Button
		GuiControl,AI:, ButtonCountCheck, % "0," Button
	}
	if (Button != OldButton)
	{
		NewCount:=% Count-OldCount
		GuiControl,AI:, ButtonCountCheck, % NewCount "," Button
		ButtonCountReturn:=% OldCount "," OldButton
	}
	Return
}

ApplyLogicalChange(activeuserinput, logicalhistory, numberofdifferences)
{
	x:= 0
	newhistoryrecord:=[]
	activeuserinputlastline:= GetLineCount(activeuserinput)
	logicalhistorylastline:= GetLineCount(logicalhistory)
	LastLine:= logicalhistory["linePos" logicalhistorylastline]
	Loop, % activeuserinputlastline
	{
		record:=
		x++ ; a lagged y variable needed to stagger history.
		occurenceuser:= activeuserinput["linePos" x]
		if (y > 0)
		{
			y:=(x-z) ; this will be an opposite staggered y (x+z) for deleted lines.
			historyrecord:= logicalhistory["linePos" y]
		}
		else
			historyrecord:= logicalhistory["linePos" x] ; even though the line now isn't right doesn't mean next time it won't be.
		splithistoryrecord:= StrSplit(historyrecord, ["(hardReturn)", "(softReturn)"])
		for index, splithistory in splithistoryrecord
		{
			if (Index == 1)
				record:= % splithistory
		}
		if ((occurenceuser != record)&&(numberofdifferences != 0)) ; the number of occurences go negative when lines get deleted... I haven't updated the below else for that yet.
		{
			LastLine:= logicalhistory["linePos" logicalhistorylastline] ; if a user is lagging the array make sure you are putting in last lines right.
			if ((LastLine == "(softReturn)")||(LastLine == "(hardReturn)")) ; the last line shouldn't be any other value.
			{
				z++ ; a z variable making sure we don't lose y and holding the number of occurences.
				if (z == 1) ; there's not enough time to add different enters in different spots (meaning the user couldn't add enough enters in the time this will be done).
					y:=% x
				IfInString, LastLine, (softReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
				IfInString, LastLine, (hardReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
				numberofdifferences--
				logicalhistorylastline--
			} ; the likely answer is a deleted line in occurenceuser. we need to add to the numberofdifferences. I'll also need to update this in the future for the array.
			else
				numberofdifferences++
		}
		else if ((occurenceuser != record)&&(numberofdifferences == 0)) ; meaning user has updated a line with a new record
		{
			newhistoryrecord["linePos" x]:= occurenceuser
			IfInString, record, (softReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
			IfInString, record, (hardReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
		} ; z from above holds all change counts. y from above holds the history record line back. technically y can equal x-z or just y++. I think for greater clarity it should be x-z because a user may choose to purposely lag the logicalhistoryarray Change function. Basically this function can be implimented at will as long as the keys are being kept up with and added to the historyarray in the main loop (of course that might also come with logical array issues).
		else if ((occurenceuser == record)&&(numberofdifferences == 0))
			newhistoryrecord["linePos" x]:= record
	}
	check:=GetControl("GetKeeper")
	if (check == "7h151s@a#res37")
		Return
	Return % newhistoryrecord ; There has been many different statements on using the % after Return or in ":=" as an operorator (it technically doesn't need to be done and can cause issues if done improperly). I use it because honestly it's like my signature to my work.
}

Doppler(usersentence, historysentence)
{
	livewords:=[]
	pastwords:=[]
	check:=GetControl("GetKeeper")
	if (check == "&not@a#rea1*sent3nc3")
	{
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			livewords["wordPos" key]:= userwords
		}
		historysplit:=StrSplit(historysentence, A_Space)
		for key, historywords in historysplit
		{
			pastwords["wordPos" key]:= historywords
		}
		usercount:=GetLineCount(livewords)
		historycount:= GetLineCount(pastwords)
		Loop, % usercount
		{
			x++
			userword:=livewords["wordPos" x]
			historyword:=pastwords["wordPos" x]
			userwordlength:=StrLen(userword)
			historywordlength:= StrLen(historyword)
			if ((userword != historyword)||(historycount < x))
				GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		}
		StringReplace, userword, userword, historyword, , ALL
	}
	else if (check != "&not@a#rea1*sent3nc3")
	{
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 1)
				historyword:=% chec
			if (index == 2)
				ouserword:=% chec
			if (index == 3)
				x:=% chec
		}
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			if (key == x)
				userword:=% userwords
		}
		GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		StringReplace, userword, userword, historyword, , ALL
	}
	userwordlength:=StrLen(userword)
	if (userwordlength < 2)
	{
		GuiControl, AI:, Information, Working...
		SpellChecker(0)
	}
	if (userwordlength > 3)
	{
		GuiControl, AI:, Information, Working.
		ourwords:=WordCheck(userword, userwordlength)
		if (ourwords == "")
			SpellChecker(0)
		else if (ourwords != "")
		{
			SpellChecker(userwordlength)
			GetControl(ourwords)
		}
	}
	Return
}

FixLogicalhistory_Array(historyarray, howmanylines)
{
	lastline:= GetLineCount(historyarray)
	whichbutton:= GetControl("ButtCount")
	Loop, % howmanylines
	{
		lastline++
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					historyarray["linePos" lastline]:= "(softReturn)"
				if (butt == "Enter")
					historyarray["linePos" lastline]:= "(hardReturn)"
			}
		}
	}
	Return % historyarray
}

ReturnLineArray(lines, user)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/SoftReturn\|/", "\|/userReturns\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

GetButtonCount(pressed)
{
	pressing:= StrSplit(pressed, ",")
	For Index, press in pressing
		if (Index == 1)
			Return % press
}

FindingRealLineLOL(occurenceuser, rowbefore, thisrow)
{
	IfInString, occurenceuser, %rowbefore%
	{
		rowlength:= StrLen(rowbefore)
		occurencelength:= StrLen(occurenceuser)
		subtractedlength:=(occurencelength-rowlength)
		thisstring:= SubStr(occurenceuser, subtractedlength, occurencelength)
		if (thisstring == rowbefore)
		{
			IfInString, occurenceuser, %thisrow%
				Return % "Found"
			IfNotInstring, occurenceuser, %thisrow%
				Return % "NextRow"
		}
	}
	if (rowbefore == "NextRow")
		IfInString, occurenceuser, %thisrow%
			Return % "Found"
	Return % "NotFound"
}

ProcessStart(contents, Rest)
{
	logicalhistory:= []
	WinSet, Transparent, 0, Words
	history:= GetHistory()
	logicalhistory:= ReturnLineArray(history, user)
	Control, Disable ,, Edit1, AI
	WinActivate, AI
	GuiControl, AI:, Edit1, % contents
	Sleep, % Rest
	Control, Enable ,, Edit1, AI
	GuiControl, AI:, Information, Done
	Control, Enable ,, ListBox1, AI
	Return % logicalhistory
}

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	WinActivate, AI
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	if (n > 3)
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	if (n == 0)
		WinSet, Transparent, 0, Words
	WinGet, visible, Transparent, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	Return
}
Return

ReturnClearDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			hinput:= harray["linePos" x]
			hsplit:= StrSplit(hinput, ["(hardReturn)", "(softReturn)"])
			for Index, h in hsplit
			{
				if (Index == 1)
					checkh:= % h
			}
			uinput:= uarray["linePos" x]
			StringReplace, uinput, uinput, (softReturn), , ALL
			StringReplace, uinput, uinput, (hardReturn), , ALL
			l_checkh:= StrLen(checkh)
			l_uinput:= StrLen(uinput)
			if (uinput != checkh)
				Return % x
			if (l_checkh != l_uinput)
				Return % x
			if (x == v)
				Break
			checkh:=
		}
		Return % "0"
	}
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return % "True"
	}
}

GetLineCount(arraycount)
{
	LastLine:=0
	for Index, count in arraycount
		++LastLine
	Return % LastLine
}

GetControl(FocTex)
{
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, Edit1
	ControlGet, row, CurrentLine, , Edit1, AI
	ControlGet, rowtext, Line, % row, Edit1, AI
	GuiControlGet, Word, Words:, Listbox1
	StringReplace, text, text, `n, \|/userReturns\|/, ALL
	GuiControlGet, ButtonCountCheck, AI:, ButtonCountCheck
	GuiControlGet, Save_File, AI:, AISave
	GuiControlGet, DopplerGet, AI:, WordKeeper
	if (FocTex == "RowText")
		Return % rowtext
	if (FocTex == "GetKeeper")
		Return % DopplerGet
	if (FocTex == "AISave")
		Return % Save_File
	if (FocTex == "ButtCount")
		Return % ButtonCountCheck
	if (FocTex == "Row")
		Return % row
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	x:=0
	GuiControl, Words:, Listbox1, | 
	Loop, Parse, % FocTex, |
		x++
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
	Return
}

HashContents(contents)
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, \|/CR+LF\|/, `n, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, `n, ALL
	Return % contents
}

GetHistory()
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, `r`n,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, (softReturn)\|/SoftReturn\|/, ALL
	Return % contents
}

RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitapp

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 16 Dec 2023, 01:50

So, after days of running through various different ways to simplify I did figure a much smaller way to do it... However, this also came with a serious slowdown of the process :headwall: . Basically I placed line breakers to split at each location of the editbox. This made the array much easier to write even find difference but to impliment each linebreak to each key was just a slow process in of itself. So after a few days of trying to figure out how to make the process quicker I have given up on simplification. Today's update comes with the ability to get function out of script by name and even a recursive feature to get function inside that relies on other (outside) functions in the script. This should help in debugging or rewriting functions. My future plan is to create a way to make a "Test.ahk" that takes a script to bare bones of just headers, gui command, sublabels, and exit (no hotkeys or innerfunctions of sublabels). I believe that with the ability to create a naked test.ahk and the quick ability to get functions can make the building of a program (and upkeep) easier.

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)
IniRead, Rest, % Cache "\Settings.ini", Timers, Key1
If (Rest == "ERROR")
{
	IniWrite, 10000, % Cache "\Settings.ini", Timers, Key1
	Rest:= 10000
}
IniRead, Notactive, % Cache "\Settings.ini", Timers, Key2
if (Notactive == "ERROR")
{
	IniWrite, 500, % Cache "\Settings.ini", Timers, Key2
	Notactive:= 500
}
IniRead, NoDif, % Cache "\Settings.ini", Timers, Key3
if (NoDif == "ERROR")
{
	IniWrite, 25, % Cache "\Settings.ini", Timers, Key3
	NoDif:= 25
}

Loop, Files, *.ahk, D F R
{
	IfInString, A_LoopFileName, @
	{
		Continue
	}
	wi=%wi%|%A_LoopFileName%
}

Menu, Settings, Add, Timers, Timers
Menu, Settings, Add, AlwaysOnTop`ton/off, Always
Menu, Settings, Add, Suspend`ton/off, SusOnOff
Menu, Settings, Add, Reload`tCtrl+r, Reload
Menu, AIsMenu, Add, Settings, :Settings

CoordMode, Caret, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Window
Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, Menu, AIsMenu
Gui, Add, DropDownList, x25 y50 w150 vChangeType gChangeType, Get Variables||Get Function|Create Test File
Gui, Add, GroupBox, x25 y80 h250 w150 wrap vResults, Get variables`n(Filter results by Checkbox)
Gui, Add, ListBox, r10 yp+35  xp+15 w120 gFileSelected vFileSelected, %wi%
Gui, Add, Edit, r4 yp+140 xp -VScroll vTestInfo w120,  Select a file to create a Test.ahk file with no function or sublabeled function.
Gui, Add, Text, yp xp vFunctionLabel, input the function lablel
Gui, Add, Edit, r1 w120 vFunctionName,
Gui, Add, Checkbox, vAssociateV, Associated functions
Gui, Add, Checkbox, yp-40 xp vGui, Gui Variables
Gui, Add, Checkbox, vExplicit, Explicit Variables
Gui, Add, Checkbox, vImplicitExplicit, Implicit-Explicit
Gui, Add, Text, -E0x200 x0 y0 vButtonCountCheck w0, 0,Unknown
Gui, Add, Text, -E0x200 vWordKeeper w0, &not@a#rea1*sent3nc3s
Gui, Add, Edit,  r20 ym+25 x200 vWords w325 h500 hwndTracker,
Gui, Add, Button, gAISave, Save
Gui, Add, Text, vAISave w0s, Don't save
Gui, Add, Text, ym+298 x470 vInformation, Loading...
Gui, Margin, 50, 30
Gui, Show, h400, AI work
GuiControl, AI:Hide, FunctionName
GuiControl, AI:Hide, FunctionLabel
GuiControl, AI:Hide, Button2
GuiControl, AI:Hide, Edit1
Control, Disable , , Edit1, AI
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, margin, 0, 0
Gui, Show, , Words

contents:=HashContents(contents)
logicalhistory:= []
logicalhistory:= ProcessStart(contents, Rest)
activeuserinput:= []

Loop,
{
	if ((ClipBoard != "")&&(ClipBoard != ClipBoard1))
	{
		if (ClipBoard1 == "")
			ClipBoard1:=% ClipBoard
		else if (ClipBoard1 != "")
		{
			if (ClipBoard2 == "" )
				ClipBoard2:=% ClipBoard1
			else if (ClipBoard2 != "")
			{
				ClipBoard3:=% ClipBoard2
				ClipBoard2:=% ClipBoard1
				ClipBoard1:=% ClipBoard
			}
		}
	}
	winwonder:=WinWonder()
	if (winwonder == "False")
	{
		SpellChecker(0)
		Sleep, % Notactive
		Continue
	}
	check:=GetControl("GetKeeper")
	usersentence:=GetControl("RowText")
	if (recordkeeper == "")
		recordkeeper:=% usersentence
	if (recordkeeper != usersentence)
	{
		Doppler(usersentence, recordkeeper)
		recordkeeper:=% usersentence
	}
	getuserinput:= GetControl("Text")
	activeuserinput:=ReturnLineArray(getuserinput, "user")
	historylastline:= GetLineCount(logicalhistory)
	activeuserlastline:= GetLineCount(activeuserinput)
	if (check == "7h151s@a#res37")
	{
		If (getuserinput == "")
		{
			Sleep, % Notactive
			Continue
		}
		GuiControl, AI:, WordKeeper, &not@a#rea1*sent3nc3
		contents:=HashContents(contents)
		logicalhistory:= ProcessStart(contents, Rest)
		Continue
	}
	if (usersentence != "")
	{
		if (activeuserlastline != historylastline)
		{
			logicallastlineaddition:=(activeuserlastline-historylastline)
			logicalhistory:= FixLogicalhistory_Array(logicalhistory, logicallastlineaddition) ; where last lines are being put in. and you will also want to function in lastline (Deleted_Line) to acompany the changes. if you are lagging ApplyLogicalChange().
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, logicallastlineaddition)
		}
		if (activeuserlastline == historylastline)
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, 0)
	}
	savecheck:= GetControl("AISave")
	if (savecheck == "Save_File")
	{
		historycount:=GetLineCount(logicalhistory)
		Loop, % historycount
		{
			x++
			sentences:= logicalhistory["linePos" x]
			StringReplace, sentences, sentences, (softReturn), \|/softReturn\|/, ALL
			StringReplace, sentences, sentences, (hardReturn), \|/CR+LF\|/, ALL
			FileContents:=% FileContents sentences
		}
		FileMove, % Temp, % TempBack, 1
		FileAppend, % FileContents, % Temp, UTF-8
		GuiControl,AI:, AISave, Don't Save
	}
}
Return

LCtrl::
Button= GetControl("ButtCount")
if (Button == "Ctrl") ; in case it jumps in a loop
{
	GuiControl,AI:, ButtonCountCheck,
	Return
}
GuiControl,AI:, ButtonCountCheck, Ctrl
Input, userinput, L3 T0.75 M ; this has a 0.75 second timer... That feels a little natural. however on the person to person scale this might need adjusted.
KeyWait, Control, U
if (userinput == "vv")
	Send, % ClipBoard2
else if (userinput == "vvv")
	Send, % ClipBoard3
else
	Send, ^%userinput%
Return

$Backspace::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Backspace}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Backspace}
	}
	Return
}
else
	Send, {Backspace}
Return

$Space::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Space}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Space}
	}
	Return
}
else
	Send, {Space}
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		check:=GetControl("GetKeeper")
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 2)
				userword:=% chec
		}
		str:= StrLen(userword)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
	}
	else
	{
		Send, `t
	}
	Return
}
else
	Send, `t
Return

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",ShiftEnter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
Return

~Enter::
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",Enter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
Return

AISave:
GuiControl,AI:, AISave, Save_File
Return
	
SusOnOff:
Suspend, Toggle
if (A_IsSuspended == 1)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOn
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOff
Return

Always:
WinSet, AlwaysOnTop, Toggle, AI
WinGet, ExStyle, ExStyle, AI
if (ExStyle == 0x00000180)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOff
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOn
Return
 
Timers:
Gui, Timers:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, y25, Rest Timer:`t`n(in seconds)
Gui, Add, Text, y75 xs, Window Not Active:`t`n(in milliseconds)
Gui, Add, Text, y125 xs, Process Loop timer:`t`n(in milliseconds)
Gui, Add, Edit, w250 r3 ys-15 -VScroll, This timer slows the script before it gets to the main loop function. It's used to help in processing the global function "Speller."
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the script when the it is not active.
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the main processing loop while typing. It's dependent on a difference created in the main edit control.
Gui, Add, Edit, ys xs+400 w50 y25
Gui, Add, UpDown, vRangeInSeconds Range1-50, 10
Gui, Add, Edit, ys xs+400 w50 y75
Gui, Add, UpDown, vRangeInMillisecondsOfActive Range1-1000, 500
Gui, Add, Edit, ys xs+400 w50 y125
Gui, Add, UpDown, vRangeInMillisecondsOfProcess Range1-100, 25
Gui, Add, Text, xm+10 ym+180, Select the above values to your personal preferences and click save to keep the changes.
Gui, Add, Text, xm+80 ym+215, (Note you have to restart the program to force the changes)
Gui, Add, Button, ym+210 xs+425 gSave, Save
Gui, Add, Button, ym+210 xs+370 gCancel, Cancel
Gui, Margin, 20, 50
Gui, Show, h250 w500, Timers
Control, Disable ,, Edit1, Timers
Control, Disable ,, Edit2, Timers
Control, Disable ,, Edit3, Timers
Return

Reload:
^r::
Reload
Return

Cancel:
Gui, Timers:Destroy
Return

Save:
Gui, Submit, NoHide
RangeInSeconds:=(RangeInSeconds*1000)
IniWrite, % RangeInSeconds, % Cache "\Settings.ini", Timers, Key1
IniWrite, % RangeInMillisecondsOfActive, % Cache "\Settings.ini", Timers, Key2
IniWrite, % RangeInMillisecondsOfProcess, % Cache "\Settings.ini", Timers, Key3
Gui, Timers:Destroy
Return

FileSelected: 
Gui, Submit, NoHide
FileRead, contents, % FileSelected
if (ChangeType == "Get Variables")
{
	if (Gui == 1)
		filters.= "[Filter='Gui'],"
	if (Explicit == 1)
		filters.= "[Filter='explicit'],"
	if (ImplicitExplicit == 1)
		filters.= "[Filter='implicit-explicit'],"
	wi:=
	if (filters != "")
	{
		Control, Disable ,, ListBox1, AI
		Control, Disable ,, Edit3, AI
		contents:= GetVariables(contents, filters)
		GuiControl, AI:, Words,
		GuiControl, AI:, Words, % contents
		whichbutton:=GetControl("ButtCount")
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					thisbutton:= "\|/SoftReturn\|/"
				if (butt == "Enter")
					thisbutton:= "\|/hardReturn\|/"
				if (butt == "Unknown")
					thisbutton:= " \|/SoftReturn\|/"
			}
		}
		StringReplace, contents, contents, `n, %thisbutton%, ALL
		FileMove, % Temp, % TempBack, 1
		FileAppend, % contents, % Temp, UTF-8
	}
}
else if (ChangeType == "Get Function") ;ChangeType gChangeType, Get Variables||Get Function|Create Test File
{
	ControlGet, row, CurrentLine, , Edit2, AI
	ControlGet, rowtext, Line, % row, Edit2, AI
	if (rowtext == "")
	{
		MsgBox, Please insert the function label name
		Return
	}
	if (AssociateV == 1)
		thisignore:=% "Do_Not"
	function:=GetThisFunction(rowtext, thisignore, contents)
	GuiControl, AI:, Words, % function
	FileMove, % Temp, % TempBack, 1
	FileAppend, % function, % Temp, UTF-8
}
else if (ChangeType == "Create Test File")
{
	thesecontents:= GetTestFile(contents)
}
GuiControl, AI:, FileSelected, |
Loop, Files, *.ahk, D F R
{
	IfInString, A_LoopFileName, @
	{
		Continue
	}
	wi=%wi%|%A_LoopFileName%
}
GuiControl, AI:, Button2, 0
GuiControl, AI:, Button3, 0
GuiControl, AI:, Button4, 0
GuiControl, AI:, Button5, 0
GuiControl, AI:, FileSelected, % wi
GuiControl, AI:, Edit2,
GuiControl, AI:, WordKeeper, 7h151s@a#res37
Return

GetTestFile(data)
{
	MsgBox, This portion of the code is still in massive upgrading. However, I'm sure you can see where it's going. And if you can't don't worry I plan to update this part soon!
	Return
	IniRead, loopcount, % Cache "\Settings.ini", Looper, Key1
	if (loopcount != "ERROR")
	{
		Loop, % loopcount
		{
			Break
		}
	}
	else if (loopcount == "ERROR")
	{
		MsgBox, 70, Be sure before you continue., In the following message boxes you will be shown the beginning of your code. This will omit the comments and anything past the first comma as demiliters for your test.ahk creation. each type will be added to the Ini file settings and read for your future creations. You can always change this setting by selecting default in the default menu.
		IfMsgBox Continue
		{
			data:= StrReplace(data, "`r", "")
			Loop, Parse, % data, `n
			{
				x++
				line:=% A_LoopField
				sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
				for index, sentence in sentences
				{
					if (index == 1)
						codestring:=% sentence
					if (index == 2)
						commentstring:=% sentence
				}
				if (codestring == "")
					Continue
				IfInString, codestring, =
					Continue
				IfInString, codestring, (
					Continue
				IfInString, codestring, {
					Continue
				IfInString, codestring, }
					Continue
				IfInString, codestring, `%
					Continue
				IfinString, codestring, `t
					Continue
				IfinString, codestring, Loop
					Continue
				IfinString, codestring, else
					Continue
				IfinString, codestring, if%A_Space%
				if (thischecker != 1)
				{
					IfinString, codestring, :
						IfNotInString, codestring, Gui
							IfNotInString, codestring, ::
								IfNotInString, codestring, Menu
									if (x != 1)
									{
										thischecker:= 1
										x:=1
										MsgBox, 32, g-Sublabels, sublabels are automatically added
										Continue
									}
				}
				if (thischeck == 1)
				{
					IfInString, codestring, `t
					{
						Continue
					}
					IfNotInString, codestring, Return
					{
						thischecker:= 0
						Continue
					}
				}
				IfinString, codestring, ::
					Continue
				MsgBox, 36, Do you want to add this line?, % codestring "`n`npress yes if you want to add the first (word or :)of this line to your demimiter fields."
				IfMsgBox Yes
					Continue
				IfMsgBox No
					Return
			}
		}
	}
	Return
}

GetThisFunction(function, get, data)
{
	functionlength:=StrLen(function)
	data:= StrReplace(data, "`r", "")
	function:= GetFunction(data, functionlength, function)
	thisfoundfunction.= function "`n"
	function:=""
	if (get == "Do_Not")
	{
		Loop,
		{
			Loop, Parse, % thisfoundfunction, `n
			{
				IfInString, A_LoopField, =
					IfInString, A_LoopField, (
					{
						foundpossible:= FunctionLabelGet(A_LoopField)
						Trim(foundpossible)
						IfNotInString, foundpossible, % A_Space
							IfNotInString, thesefound, % foundpossible
							{
								functionlength:=StrLen(foundpossible)
								function:= GetFunction(data, functionlength, foundpossible)
							}
						if (function != "")
							thisfoundfunction.= function "`n"
					}
				if (function != "")
					function:=
				thesefound.= foundpossible ", "
			}
			IfNotInString, thesefoundpast, % thesefound
				thesefoundpast.= thesefound
			IfinString, thesefoundpast, % thesefound
				Break
		}
	}
	Return % thisfoundfunction
}

GetFunction(data, functionlength, function)
{
	Loop, Parse, % data, `n
	{
		if (thisfunction == "")
		{
			linesubstring:= SubStr(A_LoopField, 1, functionlength)
			if (function == linesubstring)
				thisfunction:= % A_LoopField "`n"
			z:=1
		}
		else if (thisfunction != "")
		{
			thisfunction.= A_LoopField "`n"
			if (A_LoopField == "{")
				x++
			if (A_LoopField == "}")
				x--
			if (z == 1)&&(A_LoopField != "{")
				thisfunction:= ""
			z:=0
		}
		if ((x == 0)&&(thisfunction != ""))
		{
			thisfoundfunction:= % thisfunction
			thisfunction:= ""
		}
	}
	Return % thisfoundfunction
}

FunctionLabelGet(line)
{
	thissplitfunction:= StrSplit(line, "= ")
	for index, thissplit in thissplitfunction
		if (index == 2)
			thispart:=% thissplit
	thispartsplit:= StrSplit(thispart, "(") ;"
	for index, function in thispartsplit
		if (index == 1)
			Return % function
	Return
}

ChangeType:
Gui, Submit, NoHide
if (ChangeType == "Get Variables")
{
	GuiControl, AI:Text, Results, Get variables`n(Filter results by Checkbox)
	GuiControl, AI:Hide, FunctionName
	GuiControl, AI:Hide, FunctionLabel
	GuiControl, AI:Hide, Button2
	GuiControl, AI:Show, Button5
	GuiControl, AI:Show, Button3
	GuiControl, AI:Show, Button4
	GuiControl, AI:Hide, Edit1
}
if (ChangeType == "Get Function")
{
	GuiControl, AI:Text, Results, Get Function`n(Select a file to get a function)
	GuiControl, AI:Hide, Button5
	GuiControl, AI:Hide, Button3
	GuiControl, AI:hide, Button4
	GuiControl, AI:Show, FunctionName
	GuiControl, AI:Show, FunctionLabel
	GuiControl, AI:Show, Button2
	GuiControl, AI:Hide, Edit1
}
if (ChangeType == "Create Test File")
{
	GuiControl, AI:Text, results, Create a Test File`n(Create a functionless test ahk)
	GuiControl, AI:Hide, Button5
	GuiControl, AI:Hide, Button3
	GuiControl, AI:hide, Button4
	GuiControl, AI:hide, FunctionName
	GuiControl, AI:hide, FunctionLabel
	GuiControl, AI:hide, Button2
	GuiControl, AI:Show, Edit1
}
Return

GetVariables(filecontents, filters)
{
	Loop, Parse, % filecontents, `r
	{
		linenumber++
		line:=% A_LoopField
		sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
		for index, sentence in sentences
		{
			if (index == 1)
				codestring:=% sentence
			if (index == 2)
				commentstring:=% sentence
		}
		codestring:= RemoveCertainChars(codestring, "Start")
		IfInString, codestring, Dll
			Continue
		IfInString, codestring, Box`,
			Continue
		IfInString, codestring, StringReplace
			Continue
		IfInString, codestring, RegEx
			Continue
		IfInString, codestring, Ini
			Continue
		IfInString, codestring, =
		{
			IfInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Percent", linenumber)
				IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
			}
			else IfNotInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
			IfInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Quotes", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring 
			}
			else IfNotInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
		}
		else IfInString, codestring, [percent]
		{
			variablestring:= GetVariableString(codestring, "Percent", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring
		}
		else IfInString, codestring, [quotes]
		{
			variablestring:= GetVariableString(codestring, "Quotes", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring "found in quotes 2`n"
		}
		IfInString, codestring, Gui
			IfInString, codestring, `,
				IfInString, codestring, %A_Space%v
				{
					variablestring:= GetVariableString(codestring, "Gui", linenumber)
					IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
				}
	}
	thesefilters:=StrSplit(filters, ",")
	for index, filter in thesefilters
	{
		if (index == 1)
		{
			if (filter == "")
				Continue
			firstfilter:=% filter
		}
		if (index == 2)
		{
			if (filter == "")
				Continue
			secondfilter:=% filter
		}
		if (index == 3)
		{
			if (filter == "")
				Continue
			thirdfilter:=% filter
		}
	}
	Loop, Parse, % variablelist, `n
	{
		checking:=
		thischeck:=
		information:=
		if (A_LoopField == "")
			Continue
		repeatcheck:= StrSplit(A_LoopField, "[thissplitter]")
		for index, repeat in repeatcheck
		{
			if (index == 1)
			{
				IfNotInString, completedlist, % repeat
					thischeck:=% repeat
				IfInString, completedlist, % repeat
				{
					checking:= MakeSure(completedlist, repeat)
					if (checking == "True")
						Continue
					else if (checking == "False")
						thischeck:=% repeat
				}
			}
			if (index == 2)
			{
				if (firstfilter != "")
					IfInString, repeat, % firstfilter
					{
						applyfilters:= StrSplit(repeat, firstfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
				if (secondfilter != "")
					IfInString, repeat, % secondfilter
					{
						applyfilters:= StrSplit(repeat, secondfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
				if (thirdfilter != "")
					IfInString, repeat, % thirdfilter
					{
						applyfilters:= StrSplit(repeat, thirdfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
			}
		}
		if (information == "")
			Continue
		if (thischeck != "")
		{
			checklist:=% Trim(thischeck) "`n" Trim(information) "`n"
			IfNotInString, completedlist, % checklist
				completedlist.= checklist
		}
	}
	completedlist:= RemoveCertainChars(completedlist, "End")
	Return % completedlist
}

MakeSure(listinprogress, checkword)
{
	Loop, Parse, % listinprogress, `n
	{
		if (checkword == A_LoopField)
			Return % "True"
	}
	Return % "False"
}

GetVariableString(codestring, whichone, linenumber)
{
	if (whichone == "Gui")
	{
		variablestrings:= StrSplit(codestring, ",")
		for index, variablestring in variablestrings
		{
			if (index > 4)
				Continue
			IfInString, variablestring, %A_Space%v
				thisvariablestring:=% variablestring
		}
		variablestring:= StrSplit(thisvariablestring, A_Space)
		for index, variable in variablestring
		{
			thisvariableletter:= SubStr(variable, 1, 1)
			if (thisvariableletter == "v")
				Return % variable "[thissplitter] Gui variable[Filter='Gui'] Line number is found at: " linenumber "`n"
		}
		Return % variable "[thissplitter] Gui variable Line number is found at: " linenumber "`n"
	}
	if (whichone == "Quotes")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [quotes]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		variablestrings:= StrSplit(codestring, "[quotes]")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 0)
				IfNotInString, variablestring, %A_Space%
					IfNotInString, variables, % variablestring
						variables.= "[quotes]" variablestring "[quotes][thissplitter] explicit[Filter='explicit'] variable Line number is found at: " linenumber "`n"
		}
		Return % variables
	}
	if (whichone == "Percent")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [percent]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		IfInString, codestring, `,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					IfInString, variablestring, [percent]
						IfNotInString, variablestring, =
							IfInString, variablestring, A_Space
								variables.= variablestring "[thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		IfNotInString, codestring, `,
		{
			IfInString, codestring, =
			{
				variablestrings:= StrSplit(codestring, "=")
				for index, variablestring in variablestrings
				{
					if (index == 1)
					{
						variables:= StrSplit(variablestring, A_Space)
						for index, variable in variables
							thisvariable:=% variable
					}
					if (index == 2)
						codestring:=% variablestring
				}
			}
			variablestrings:= StrSplit(codestring, "[percent]")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					variables.= "[percent]" variablestring "[percent][thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		if (thisvariable != "")
			variables.= thisvariable "[thissplitter]implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
		Return % variables
	}
	if (whichone == "Equals")
	{
		variablestrings:= StrSplit(codestring, "=")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 1)
				IfNotInString, variablestring, [quotes]
				{
					thisvariablestring:= StrSplit(variablestring, A_Space)
					for index, thisvariable in thisvariablestring
					{
						variable:=% thisvariable "[thissplitter] implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
					}
				}
		}
		Return % variable
	}
	Return % "Not Found"
}

RemoveCertainChars(string, special)
{
	if (special == "Start")
	{
		StringReplace, string, string, ", [quotes], ALL ; "
		StringReplace, string, string, `%%A_Space%, [percent], ALL
		StringReplace, string, string, `%, [percent], ALL
		StringReplace, string, string, %A_Space%:, :, ALL
		StringReplace, string, string, :=, =, ALL
		StringReplace, string, string, ==, =, ALL
		StringReplace, string, string, >, =, ALL
		StringReplace, string, string, <, =, ALL
		StringReplace, string, string, %A_Space%!=, =, ALL
		StringReplace, string, string, =%A_Space%, =, ALL
		StringReplace, string, string, %A_Space%=, =, ALL
		StringReplace, string, string, ), , ALL
		StringReplace, string, string, (, , ALL ;)
		StringReplace, string, string, `t, , ALL
	}
	if (special == "End")
	{
		StringReplace, string, string, [quotes], ", ALL ; "
		StringReplace, string, string, [percent], `%, ALL
		StringReplace, string, string, `,, , ALL
	}
	Return % string
}

GetButton_Count()
{
	Loop,
	{
		ButtonCountCheck:= GetControl("ButtCount")
		if (ButtonCountCheck != OldButtonCountCheck)
		{
			OldCount:=% Count
			OldButton:=% Button
			Sleep, 500
			ButtonCount_Split:= StrSplit(ButtonCountCheck, ",")
			For Index, ButtCount in ButtonCount_Split
			{
				if (Index == 1)
					Count:=% ButtCount
				if (Index == 2)
					Button:=% ButtCount
			}
		}
		else if (ButtonCountCheck == OldButtonCountCheck)
			Break
		if ((Button != OldButton)&&(Count > 1))
			Break
		OldButtonCountCheck:=% ButtonCountCheck
	}
	if (Button == OldButton)
	{
		ButtonCountReturn:=% Count "," Button
		GuiControl,AI:, ButtonCountCheck, % "0," Button
	}
	if (Button != OldButton)
	{
		NewCount:=% Count-OldCount
		GuiControl,AI:, ButtonCountCheck, % NewCount "," Button
		ButtonCountReturn:=% OldCount "," OldButton
	}
	Return
}

ApplyLogicalChange(activeuserinput, logicalhistory, numberofdifferences)
{
	x:= 0
	newhistoryrecord:=[]
	activeuserinputlastline:= GetLineCount(activeuserinput)
	logicalhistorylastline:= GetLineCount(logicalhistory)
	LastLine:= logicalhistory["linePos" logicalhistorylastline]
	Loop, % activeuserinputlastline
	{
		record:=
		x++ ; a lagged y variable needed to stagger history.
		occurenceuser:= activeuserinput["linePos" x]
		if (y > 0)
		{
			y:=(x-z) ; this will be an opposite staggered y (x+z) for deleted lines.
			historyrecord:= logicalhistory["linePos" y]
		}
		else
			historyrecord:= logicalhistory["linePos" x] ; even though the line now isn't right doesn't mean next time it won't be.
		splithistoryrecord:= StrSplit(historyrecord, ["(hardReturn)", "(softReturn)"])
		for index, splithistory in splithistoryrecord
		{
			if (Index == 1)
				record:= % splithistory
		}
		if ((occurenceuser != record)&&(numberofdifferences != 0)) ; the number of occurences go negative when lines get deleted... I haven't updated the below else for that yet.
		{
			LastLine:= logicalhistory["linePos" logicalhistorylastline] ; if a user is lagging the array make sure you are putting in last lines right.
			if ((LastLine == "(softReturn)")||(LastLine == "(hardReturn)")) ; the last line shouldn't be any other value.
			{
				z++ ; a z variable making sure we don't lose y and holding the number of occurences.
				if (z == 1) ; there's not enough time to add different enters in different spots (meaning the user couldn't add enough enters in the time this will be done).
					y:=% x
				IfInString, LastLine, (softReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
				IfInString, LastLine, (hardReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
				numberofdifferences--
				logicalhistorylastline--
			} ; the likely answer is a deleted line in occurenceuser. we need to add to the numberofdifferences. I'll also need to update this in the future for the array.
			else
				numberofdifferences++
		}
		else if ((occurenceuser != record)&&(numberofdifferences == 0)) ; meaning user has updated a line with a new record
		{
			newhistoryrecord["linePos" x]:= occurenceuser
			IfInString, record, (softReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
			IfInString, record, (hardReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
		} ; z from above holds all change counts. y from above holds the history record line back. technically y can equal x-z or just y++. I think for greater clarity it should be x-z because a user may choose to purposely lag the logicalhistoryarray Change function. Basically this function can be implimented at will as long as the keys are being kept up with and added to the historyarray in the main loop (of course that might also come with logical array issues).
		else if ((occurenceuser == record)&&(numberofdifferences == 0))
			newhistoryrecord["linePos" x]:= record
	}
	check:=GetControl("GetKeeper")
	if (check == "7h151s@a#res37")
		Return
	Return % newhistoryrecord ; There has been many different statements on using the % after Return or in ":=" as an operorator (it technically doesn't need to be done and can cause issues if done improperly). I use it because honestly it's like my signature to my work.
}

Doppler(usersentence, historysentence)
{
	livewords:=[]
	pastwords:=[]
	check:=GetControl("GetKeeper")
	if (check == "&not@a#rea1*sent3nc3")
	{
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			livewords["wordPos" key]:= userwords
		}
		historysplit:=StrSplit(historysentence, A_Space)
		for key, historywords in historysplit
		{
			pastwords["wordPos" key]:= historywords
		}
		usercount:=GetLineCount(livewords)
		historycount:= GetLineCount(pastwords)
		Loop, % usercount
		{
			x++
			userword:=livewords["wordPos" x]
			historyword:=pastwords["wordPos" x]
			userwordlength:=StrLen(userword)
			historywordlength:= StrLen(historyword)
			if ((userword != historyword)||(historycount < x))
				GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		}
		StringReplace, userword, userword, historyword, , ALL
	}
	else if (check != "&not@a#rea1*sent3nc3")
	{
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 1)
				historyword:=% chec
			if (index == 2)
				ouserword:=% chec
			if (index == 3)
				x:=% chec
		}
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			if (key == x)
				userword:=% userwords
		}
		GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		StringReplace, userword, userword, historyword, , ALL
	}
	userwordlength:=StrLen(userword)
	if (userwordlength < 2)
	{
		GuiControl, AI:, Information, Working...
		SpellChecker(0)
	}
	if (userwordlength > 3)
	{
		GuiControl, AI:, Information, Working.
		ourwords:=WordCheck(userword, userwordlength)
		if (ourwords == "")
			SpellChecker(0)
		else if (ourwords != "")
		{
			SpellChecker(userwordlength)
			GetControl(ourwords)
		}
	}
	Return
}

FixLogicalhistory_Array(historyarray, howmanylines)
{
	lastline:= GetLineCount(historyarray)
	whichbutton:= GetControl("ButtCount")
	Loop, % howmanylines
	{
		lastline++
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					historyarray["linePos" lastline]:= "(softReturn)"
				if (butt == "Enter")
					historyarray["linePos" lastline]:= "(hardReturn)"
			}
		}
	}
	Return % historyarray
}

ReturnLineArray(lines, user)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/SoftReturn\|/", "\|/userReturns\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

GetButtonCount(pressed)
{
	pressing:= StrSplit(pressed, ",")
	For Index, press in pressing
		if (Index == 1)
			Return % press
}

FindingRealLineLOL(occurenceuser, rowbefore, thisrow)
{
	IfInString, occurenceuser, %rowbefore%
	{
		rowlength:= StrLen(rowbefore)
		occurencelength:= StrLen(occurenceuser)
		subtractedlength:=(occurencelength-rowlength)
		thisstring:= SubStr(occurenceuser, subtractedlength, occurencelength)
		if (thisstring == rowbefore)
		{
			IfInString, occurenceuser, %thisrow%
				Return % "Found"
			IfNotInstring, occurenceuser, %thisrow%
				Return % "NextRow"
		}
	}
	if (rowbefore == "NextRow")
		IfInString, occurenceuser, %thisrow%
			Return % "Found"
	Return % "NotFound"
}

ProcessStart(contents, Rest)
{
	logicalhistory:= []
	WinSet, Transparent, 0, Words
	history:= GetHistory()
	logicalhistory:= ReturnLineArray(history, user)
	Control, Disable ,, Edit3, AI
	WinActivate, AI
	GuiControl, AI:, Edit3, % contents
	Sleep, % Rest
	Control, Enable ,, Edit3, AI
	GuiControl, AI:, Information, Done
	Control, Enable ,, ListBox1, AI
	Return % logicalhistory
}

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	if (n > 3)
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	if (n == 0)
		WinSet, Transparent, 0, Words
	WinGet, visible, Transparent, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	Return
}
Return

ReturnClearDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			hinput:= harray["linePos" x]
			hsplit:= StrSplit(hinput, ["(hardReturn)", "(softReturn)"])
			for Index, h in hsplit
			{
				if (Index == 1)
					checkh:= % h
			}
			uinput:= uarray["linePos" x]
			StringReplace, uinput, uinput, (softReturn), , ALL
			StringReplace, uinput, uinput, (hardReturn), , ALL
			l_checkh:= StrLen(checkh)
			l_uinput:= StrLen(uinput)
			if (uinput != checkh)
				Return % x
			if (l_checkh != l_uinput)
				Return % x
			if (x == v)
				Break
			checkh:=
		}
		Return % "0"
	}
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return % "True"
	}
}

GetLineCount(arraycount)
{
	LastLine:=0
	for Index, count in arraycount
		++LastLine
	Return % LastLine
}

GetControl(FocTex)
{
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, Edit3
	ControlGet, row, CurrentLine, , Edit3, AI
	ControlGet, rowtext, Line, % row, Edit3, AI
	GuiControlGet, Word, Words:, Listbox1
	StringReplace, text, text, `n, \|/userReturns\|/, ALL
	GuiControlGet, ButtonCountCheck, AI:, ButtonCountCheck
	GuiControlGet, Save_File, AI:, AISave
	GuiControlGet, DopplerGet, AI:, WordKeeper
	if (FocTex == "RowText")
		Return % rowtext
	if (FocTex == "GetKeeper")
		Return % DopplerGet
	if (FocTex == "AISave")
		Return % Save_File
	if (FocTex == "ButtCount")
		Return % ButtonCountCheck
	if (FocTex == "Row")
		Return % row
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	x:=0
	GuiControl, Words:, Listbox1, | 
	Loop, Parse, % FocTex, |
		x++
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
	Return
}

HashContents(contents)
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, \|/CR+LF\|/, `n, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, `n, ALL
	Return % contents
}

GetHistory()
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, `r`n,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, (softReturn)\|/SoftReturn\|/, ALL
	Return % contents
}

RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitapp

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 16 Dec 2023, 18:16

So far I have been able to make the {LCtrl} hotkey function almost completely normal (we no longer have to lift our finger off control for autosend, it also doesn't loop, And keeps clipboards in {Ctrl} loop). The test file actually works out pretty nice on the first run. However future runs come with "Return" duplicates. I wanted to try to eliminate that but if I just ignore returns then knowing when a g-sublabel ends is almost impossible (because of course everything should be ignored till the end of the label). I also want to add two other features a "Directory changer" and "Control to specific window." I believe while editing a script if the "window" we're working on is active and "connected" to the program and the "script" being written a great deal of information can be obtained (pixel locations, width hieght ect {yes I know window spy does that but...}).

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
#InstallkeybdHook
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)
IniRead, Rest, % Cache "\Settings.ini", Timers, Key1
If (Rest == "ERROR")
{
	IniWrite, 10000, % Cache "\Settings.ini", Timers, Key1
	Rest:= 10000
}
IniRead, Notactive, % Cache "\Settings.ini", Timers, Key2
if (Notactive == "ERROR")
{
	IniWrite, 500, % Cache "\Settings.ini", Timers, Key2
	Notactive:= 500
}
IniRead, NoDif, % Cache "\Settings.ini", Timers, Key3
if (NoDif == "ERROR")
{
	IniWrite, 25, % Cache "\Settings.ini", Timers, Key3
	NoDif:= 25
}

Loop, Files, *.ahk, D F R
{
	IfInString, A_LoopFileName, @
	{
		Continue
	}
	wi=%wi%%A_LoopFileName%|
}

Menu, Settings, Add, Timers, Timers
Menu, Settings, Add, AlwaysOnTop`ton/off, Always
Menu, Settings, Add, Suspend`ton/off, SusOnOff
Menu, Settings, Add, Reload`tCtrl+r, Reload
Menu, AIsMenu, Add, Settings, :Settings

CoordMode, Caret, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Window
Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, Menu, AIsMenu
Gui, Add, DropDownList, x25 y50 w150 vChangeType gChangeType, Get Variables||Get Function|Create Test File
Gui, Add, GroupBox, x25 y80 h250 w150 wrap vResults, Get variables`n(Filter results by Checkbox)
Gui, Add, ListBox, r10 yp+35  xp+15 w120 gFileSelected vFileSelected, %wi%
Gui, Add, Edit, r4 yp+140 xp -VScroll vTestInfo w120,  Select a file to create a Test.ahk file with no function or sublabeled function.
Gui, Add, Text, yp xp vFunctionLabel, input the function lablel
Gui, Add, Edit, r1 w120 vFunctionName,
Gui, Add, Checkbox, vAssociateV, Associated functions
Gui, Add, Checkbox, yp-40 xp vGui, Gui Variables
Gui, Add, Checkbox, vExplicit, Explicit Variables
Gui, Add, Checkbox, vImplicitExplicit, Implicit-Explicit
Gui, Add, Text, -E0x200 x0 y0 vButtonCountCheck w0, 0,Unknown
Gui, Add, Text, -E0x200 vWordKeeper w0, &not@a#rea1*sent3nc3s
Gui, Add, Edit,  r20 ym+25 x200 vWords w325 h500 hwndTracker,
Gui, Add, Button, gAISave, Save
Gui, Add, Text, vAISave w0s, Don't save
Gui, Add, Text, ym+298 x470 vInformation, Loading...
Gui, Margin, 50, 30
Gui, Show, h400, AI work
GuiControl, AI:Hide, FunctionName
GuiControl, AI:Hide, FunctionLabel
GuiControl, AI:Hide, Button2
GuiControl, AI:Hide, Edit1
Control, Disable , , Edit1, AI
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, margin, 0, 0
Gui, Show, , Words

contents:=HashContents(contents)
logicalhistory:= []
logicalhistory:= ProcessStart(contents, Rest)
activeuserinput:= []

Loop,
{
	ClipBoardFunction()
	winwonder:=WinWonder()
	if (winwonder == "False")
	{
		SpellChecker(0)
		Sleep, % Notactive
		Continue
	}
	check:=GetControl("GetKeeper")
	usersentence:=GetControl("RowText")
	if (recordkeeper == "")
		recordkeeper:=% usersentence
	if (recordkeeper != usersentence)
	{
		Doppler(usersentence, recordkeeper)
		recordkeeper:=% usersentence
	}
	getuserinput:= GetControl("Text")
	activeuserinput:=ReturnLineArray(getuserinput, "user")
	historylastline:= GetLineCount(logicalhistory)
	activeuserlastline:= GetLineCount(activeuserinput)
	if (check == "7h151s@a#res37")
	{
		If (getuserinput == "")
		{
			Sleep, % Notactive
			Continue
		}
		GuiControl, AI:, WordKeeper, &not@a#rea1*sent3nc3
		contents:=HashContents(contents)
		logicalhistory:= ProcessStart(contents, Rest)
		Continue
	}
	if (usersentence != "")
	{
		if (activeuserlastline != historylastline)
		{
			logicallastlineaddition:=(activeuserlastline-historylastline)
			logicalhistory:= FixLogicalhistory_Array(logicalhistory, logicallastlineaddition) ; where last lines are being put in. and you will also want to function in lastline (Deleted_Line) to acompany the changes. if you are lagging ApplyLogicalChange().
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, logicallastlineaddition)
		}
		if (activeuserlastline == historylastline)
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, 0)
	}
	savecheck:= GetControl("AISave")
	if (savecheck == "Save_File")
	{
		historycount:=GetLineCount(logicalhistory)
		Loop, % historycount
		{
			x++
			sentences:= logicalhistory["linePos" x]
			StringReplace, sentences, sentences, (softReturn), \|/softReturn\|/, ALL
			StringReplace, sentences, sentences, (hardReturn), \|/CR+LF\|/, ALL
			FileContents:=% FileContents sentences
		}
		FileMove, % Temp, % TempBack, 1
		FileAppend, % FileContents, % Temp, UTF-8
		GuiControl,AI:, AISave, Don't Save
	}
}
Return

~LCtrl::
thiskeystate:= GetKeyState("LCtrl", P)
if (thiskeystate != 0)
{
	Loop,
	{
		CtrlC := Chr(3)
		Input, userinput, L3 T0.75 M ; this has a 0.75 second timer... That feels a little natural. however on the person to person scale this might need adjusted.
		if (userinput == "vv")
			Send, % ClipBoard2
		else if (userinput == "vvv")
			Send, % ClipBoard3
		else if (userinput == CtrlC)
			Send, ^c
		else
			Send, ^%userinput%
		ClipBoardFunction()
		thiskeystate:= GetKeyState("LCtrl", P)
		if (thiskeystate == 0)
			Break
	}
}
Return

ClipBoardFunction()
{
	if ((ClipBoard != "")&&(ClipBoard != ClipBoard1))
	{
		if (ClipBoard1 == "")
			ClipBoard1:=% ClipBoard
		else if (ClipBoard1 != "")
		{
			if (ClipBoard2 == "" )
				ClipBoard2:=% ClipBoard1
			else if (ClipBoard2 != "")
			{
				ClipBoard3:=% ClipBoard2
				ClipBoard2:=% ClipBoard1
				ClipBoard1:=% ClipBoard
			}
		}
	}
	Return
}

$Backspace::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Backspace}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Backspace}
	}
	Return
}
else
	Send, {Backspace}
Return

$Space::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Space}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Space}
	}
	Return
}
else
	Send, {Space}
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		check:=GetControl("GetKeeper")
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 2)
				userword:=% chec
		}
		str:= StrLen(userword)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
	}
	else
	{
		Send, `t
	}
	Return
}
else
	Send, `t
Return

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",ShiftEnter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
Return

~Enter::
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",Enter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
Return

AISave:
GuiControl,AI:, AISave, Save_File
Return
	
SusOnOff:
Suspend, Toggle
if (A_IsSuspended == 1)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOn
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOff
Return

Always:
WinSet, AlwaysOnTop, Toggle, AI
WinGet, ExStyle, ExStyle, AI
if (ExStyle == 0x00000180)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOff
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOn
Return
 
Timers:
Gui, Timers:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, y25, Rest Timer:`t`n(in seconds)
Gui, Add, Text, y75 xs, Window Not Active:`t`n(in milliseconds)
Gui, Add, Text, y125 xs, Process Loop timer:`t`n(in milliseconds)
Gui, Add, Edit, w250 r3 ys-15 -VScroll, This timer slows the script before it gets to the main loop function. It's used to help in processing the global function "Speller."
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the script when the it is not active.
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the main processing loop while typing. It's dependent on a difference created in the main edit control.
Gui, Add, Edit, ys xs+400 w50 y25
Gui, Add, UpDown, vRangeInSeconds Range1-50, 10
Gui, Add, Edit, ys xs+400 w50 y75
Gui, Add, UpDown, vRangeInMillisecondsOfActive Range1-1000, 500
Gui, Add, Edit, ys xs+400 w50 y125
Gui, Add, UpDown, vRangeInMillisecondsOfProcess Range1-100, 25
Gui, Add, Text, xm+10 ym+180, Select the above values to your personal preferences and click save to keep the changes.
Gui, Add, Text, xm+80 ym+215, (Note you have to restart the program to force the changes)
Gui, Add, Button, ym+210 xs+425 gSave, Save
Gui, Add, Button, ym+210 xs+370 gCancel, Cancel
Gui, Margin, 20, 50
Gui, Show, h250 w500, Timers
Control, Disable ,, Edit1, Timers
Control, Disable ,, Edit2, Timers
Control, Disable ,, Edit3, Timers
Return

Reload:
^r::
Reload
Return

Cancel:
Gui, Timers:Destroy
Return

Save:
Gui, Submit, NoHide
RangeInSeconds:=(RangeInSeconds*1000)
IniWrite, % RangeInSeconds, % Cache "\Settings.ini", Timers, Key1
IniWrite, % RangeInMillisecondsOfActive, % Cache "\Settings.ini", Timers, Key2
IniWrite, % RangeInMillisecondsOfProcess, % Cache "\Settings.ini", Timers, Key3
Gui, Timers:Destroy
Return

FileSelected: 
Gui, Submit, NoHide
FileRead, contents, % FileSelected
if (ChangeType == "Get Variables")
{
	if (Gui == 1)
		filters.= "[Filter='Gui'],"
	if (Explicit == 1)
		filters.= "[Filter='explicit'],"
	if (ImplicitExplicit == 1)
		filters.= "[Filter='implicit-explicit'],"
	wi:=
	if (filters != "")
	{
		Control, Disable ,, ListBox1, AI
		Control, Disable ,, Edit3, AI
		contents:= GetVariables(contents, filters)
		GuiControl, AI:, Words,
		GuiControl, AI:, Words, % contents
		whichbutton:=GetControl("ButtCount")
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					thisbutton:= "\|/SoftReturn\|/"
				if (butt == "Enter")
					thisbutton:= "\|/hardReturn\|/"
				if (butt == "Unknown")
					thisbutton:= " \|/SoftReturn\|/"
			}
		}
		StringReplace, contents, contents, `n, %thisbutton%, ALL
		FileMove, % Temp, % TempBack, 1
		FileAppend, % contents, % Temp, UTF-8
	}
}
else if (ChangeType == "Get Function") ;ChangeType gChangeType, Get Variables||Get Function|Create Test File
{
	ControlGet, row, CurrentLine, , Edit2, AI
	ControlGet, rowtext, Line, % row, Edit2, AI
	if (rowtext == "")
	{
		MsgBox, Please insert the function label name
		Return
	}
	if (AssociateV == 1)
		thisignore:=% "Do_Not"
	function:=GetThisFunction(rowtext, thisignore, contents)
	GuiControl, AI:, Words, % function
	FileMove, % Temp, % TempBack, 1
	FileAppend, % function, % Temp, UTF-8
}
else if (ChangeType == "Create Test File")
{
	thesecontents:= GetTestFile(contents)
	thesecontents:= StrReplace(thesecontents, "`n`n", "`n")
	thesecontents:= StrReplace(thesecontents, "`n`n", "`n")
	Loop, Parse, % thesecontents, `n
	{
		thisline:=% A_LoopField
		if ((thisline == "")&&(oldline == "Return"))
			thisfile.= "`n"
		else if ((thisline == "")&&(oldline != "Return"))
			Continue
		if (oldline != thisline)
		{
			if (thisline == "Return")
				thisfile.= A_LoopField "`n`n"
			else
				thisfile.= A_LoopField "`n"
		}
		oldline:=% thisline
	}
	FileMove, Test.ahk, % TempBack, 1
	FileAppend, % thisfile, *Test.ahk, UTF-8
}
GuiControl, AI:, Button2, 0
GuiControl, AI:, Button3, 0
GuiControl, AI:, Button4, 0
GuiControl, AI:, Button5, 0
GuiControl, AI:, Edit2,
GuiControl, AI:, WordKeeper, 7h151s@a#res37
Return

GetTestFile(data)
{
	IniRead, loopcount, % Cache "\Settings.ini", Looper, Key1
	if (loopcount != "ERROR")
	{
		Loop, % loopcount
		{
			IniRead, codex, % Cache "\Settings.ini", KeyCodes, Key%loopcount%
			codexlist.= codex ","
			loopcount--
		}
		IniRead, loopcount, % Cache "\Settings.ini", DroppedCodeCount, Key1
		if (loopcount != "ERROR")
		{
			Loop, % loopcount
			{
				IniRead, codedrop, % Cache "\Settings.ini", DroppedCode, Key%loopcount%
				codeylist.= codedrop ","
				loopcount--
			}
		}
		data:= StrReplace(data, "`r", "")
		Loop, Parse, % data, `n
		{
			y++
			codestring:=
			line:=% A_LoopField
			sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
			for index, sentence in sentences
			{
				if (index == 1)
					codestring:=% sentence
				if (index == 2)
					commentstring:=% sentence
			}
			IfInString, codestring, GuiControl
				Continue
			IfInString, codestring, =
				Continue
			IfInString, codestring, ( ;)
				Continue
			IfInString, codestring, {
				Continue
			IfInString, codestring, } ;
				Continue
			IfInString, codestring, `%
				Continue
			IfinString, codestring, `t
				Continue
			IfinString, codestring, Loop
				Continue
			IfinString, codestring, else
				Continue
			IfinString, codestring, if%A_Space%
				Continue
			IfinString, codestring, ::
				Continue
			keycodex:= StrReplace(codestring, ",",  " ")
			keycodex:= StrReplace(keycodex, "  ", " ")
			keycodex:= StrReplace(keycodex, "  ", " ")
			keycodex:=% Trim(keycodex)
			thesewords:= StrSplit(keycodex, A_Space)
			for index, keycode in thesewords
				if (index == 1)
					keycodex:=% keycode
			codeylistsplit:= StrSplit(codeylist, ",")
			for index, codey in codeylistsplit
			{
				if (codey == keycodex)
					codestring:=
			}
			codexlistsplit:= StrSplit(codexlist, ",")
			for index, codex in codexlistsplit
			{
				IfInString, codestring, % codex
				{
					filecontents.= codestring "`n"
					Continue
				}
			}
			IfInString, codestring, GuiControl
				Continue
			IfInString, codestring, Gui
			{
				IfinString, codestring, Show
					filecontents.= codestring "`nReturn`n`n"
				IfNotinString, codestring, Show
					filecontents.= codestring "`n"
				Continue
			}
			IfInString, codestring, Menu
			{
				filecontents.= codestring "`n"
				Continue
			}
			IfinString, codestring, :
			{
				IfInString, codestring, Gui
					Continue
				if (thischecker != 1)
				{
					if (x != 1)
					{
						thischecker:= 1
						x:=1
						Continue
					}
				}
				filecontents.= codestring "`nReturn`n`n"
				Continue
			}
			if (thischeck == 1)
				if (codestring == "Return")
				{
					thischecker:= 0
					Continue
				}
		}
	}
	else if (loopcount == "ERROR")
	{
		MsgBox, 70, Be sure before you continue., In the following message boxes you will be shown the beginning of your code. This will omit the comments and anything past the first comma as demiliters for your test.ahk creation. each type will be added to the Ini file settings and read for your future creations. You can always change this setting by selecting default in the default menu.
		IfMsgBox Continue
		{
			data:= StrReplace(data, "`r", "")
			Loop, Parse, % data, `n
			{
				y++
				line:=% A_LoopField
				sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
				for index, sentence in sentences
				{
					if (index == 1)
						codestring:=% sentence
					if (index == 2)
						commentstring:=% sentence
				}
				if (codestring == "")
					Continue
				IfInString, codestring, GuiControl
					Continue
				IfInString, codestring, =
					Continue
				IfInString, codestring, ( ;)
					Continue
				IfInString, codestring, {
					Continue
				IfInString, codestring, }
					Continue
				IfInString, codestring, `%
					Continue
				IfinString, codestring, `t
					Continue
				IfinString, codestring, Loop
					Continue
				IfinString, codestring, else
					Continue
				IfinString, codestring, if%A_Space%
					Continue
				IfinString, codestring, ::
					Continue
				IfInString, codestring, Gui
				{
					IfinString, codestring, Show
						filecontents.= codestring "`nReturn`n`n"
					else
						filecontents.= codestring "`n"
					Continue
				}
				IfInString, codestring, Menu
				{
					filecontents.= codestring "`n"
					Continue
				}
				IfinString, codestring, Return
					Continue
				IfinString, codestring, :
				{
					IfInString, codestring, Gui
						Continue
					if (thischecker != 1)
					{
						if (x != 1)
						{
							thischecker:= 1
							x:=1
							MsgBox, 32, g-Sublabels, sublabels are automatically added
							Continue
						}
					}
					filecontents.= codestring "`nReturn`n`n"
					Continue
				}
				if (thischeck == 1)
					if (codestring == "Return")
					{
						IfInString, codestring, % "`t"
							Continue
						filecontents.= codestring "`n`n"
						thischecker:= 0
						Continue
					}
				keycodex:= StrReplace(codestring, ",",  " ")
				keycodex:= StrReplace(keycodex, "  ", " ")
				keycodex:= StrReplace(keycodex, "  ", " ")
				keycodex:=% Trim(keycodex)
				thesewords:= StrSplit(keycodex, A_Space)
				for index, keycode in thesewords
					if (index == 1)
						keycodex:=% keycode
				IfinString, thisignoredlist, % keycodex
					Continue
				IfinString, thisgottenlist, % keycodex
				{
					filecontents.= codestring "`n"
					Continue
				}
				IfinString, filecontents, % codestring
					Continue
				MsgBox, 36, Do you want to add this line?, % keycodex "`n`nFound on line: " y "`n`npress yes if you want to add the first (word or :)of this line to your demimiter fields."
				IfMsgBox Yes
				{
					z++
					IniWrite, % z, % Cache "\Settings.ini", Looper, Key1
					IniWrite, % keycodex, % Cache "\Settings.ini", KeyCodes, Key%z%
					thisgottenlist.= keycodex
					filecontents.= codestring "`n"
				}
				IfMsgBox No
				{
					w++
					IniWrite, % w, % Cache "\Settings.ini", DroppedCodeCount, Key1
					IniWrite, % keycodex, % Cache "\Settings.ini", DroppedCode, Key%w%
					thisignoredlist.= codestring " "
					Continue
				}
			}
		}
	}
	Return % filecontents
}

GetThisFunction(function, get, data)
{
	functionlength:=StrLen(function)
	data:= StrReplace(data, "`r", "")
	function:= GetFunction(data, functionlength, function)
	thisfoundfunction.= function "`n"
	function:=""
	if (get == "Do_Not")
	{
		Loop,
		{
			Loop, Parse, % thisfoundfunction, `n
			{
				IfInString, A_LoopField, =
					IfInString, A_LoopField, (
					{
						foundpossible:= FunctionLabelGet(A_LoopField)
						Trim(foundpossible)
						IfNotInString, foundpossible, % A_Space
							IfNotInString, thesefound, % foundpossible
							{
								functionlength:=StrLen(foundpossible)
								function:= GetFunction(data, functionlength, foundpossible)
							}
						if (function != "")
							thisfoundfunction.= function "`n"
					}
				if (function != "")
					function:=
				thesefound.= foundpossible ", "
			}
			IfNotInString, thesefoundpast, % thesefound
				thesefoundpast.= thesefound
			IfinString, thesefoundpast, % thesefound
				Break
		}
	}
	Return % thisfoundfunction
}

GetFunction(data, functionlength, function)
{
	Loop, Parse, % data, `n
	{
		if (thisfunction == "")
		{
			linesubstring:= SubStr(A_LoopField, 1, functionlength)
			if (function == linesubstring)
				thisfunction:= % A_LoopField "`n"
			z:=1
		}
		else if (thisfunction != "")
		{
			thisfunction.= A_LoopField "`n"
			if (A_LoopField == "{")
				x++
			if (A_LoopField == "}")
				x--
			if (z == 1)&&(A_LoopField != "{")
				thisfunction:= ""
			z:=0
		}
		if ((x == 0)&&(thisfunction != ""))
		{
			thisfoundfunction:= % thisfunction
			thisfunction:= ""
		}
	}
	Return % thisfoundfunction
}

FunctionLabelGet(line)
{
	thissplitfunction:= StrSplit(line, "= ")
	for index, thissplit in thissplitfunction
		if (index == 2)
			thispart:=% thissplit
	thispartsplit:= StrSplit(thispart, "(") ;"
	for index, function in thispartsplit
		if (index == 1)
			Return % function
	Return
}

ChangeType:
Gui, Submit, NoHide
if (ChangeType == "Get Variables")
{
	GuiControl, AI:Text, Results, Get variables`n(Filter results by Checkbox)
	GuiControl, AI:Hide, FunctionName
	GuiControl, AI:Hide, FunctionLabel
	GuiControl, AI:Hide, Button2
	GuiControl, AI:Show, Button5
	GuiControl, AI:Show, Button3
	GuiControl, AI:Show, Button4
	GuiControl, AI:Hide, Edit1
}
if (ChangeType == "Get Function")
{
	GuiControl, AI:Text, Results, Get Function`n(Select a file to get a function)
	GuiControl, AI:Hide, Button5
	GuiControl, AI:Hide, Button3
	GuiControl, AI:hide, Button4
	GuiControl, AI:Show, FunctionName
	GuiControl, AI:Show, FunctionLabel
	GuiControl, AI:Show, Button2
	GuiControl, AI:Hide, Edit1
}
if (ChangeType == "Create Test File")
{
	GuiControl, AI:Text, results, Create a Test File`n(Create a functionless test ahk)
	GuiControl, AI:Hide, Button5
	GuiControl, AI:Hide, Button3
	GuiControl, AI:hide, Button4
	GuiControl, AI:hide, FunctionName
	GuiControl, AI:hide, FunctionLabel
	GuiControl, AI:hide, Button2
	GuiControl, AI:Show, Edit1
}
Return

GetVariables(filecontents, filters)
{
	Loop, Parse, % filecontents, `r
	{
		linenumber++
		line:=% A_LoopField
		sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
		for index, sentence in sentences
		{
			if (index == 1)
				codestring:=% sentence
			if (index == 2)
				commentstring:=% sentence
		}
		codestring:= RemoveCertainChars(codestring, "Start")
		IfInString, codestring, Dll
			Continue
		IfInString, codestring, Box`,
			Continue
		IfInString, codestring, StringReplace
			Continue
		IfInString, codestring, RegEx
			Continue
		IfInString, codestring, Ini
			Continue
		IfInString, codestring, =
		{
			IfInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Percent", linenumber)
				IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
			}
			else IfNotInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
			IfInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Quotes", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring 
			}
			else IfNotInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
		}
		else IfInString, codestring, [percent]
		{
			variablestring:= GetVariableString(codestring, "Percent", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring
		}
		else IfInString, codestring, [quotes]
		{
			variablestring:= GetVariableString(codestring, "Quotes", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring "found in quotes 2`n"
		}
		IfInString, codestring, Gui
			IfInString, codestring, `,
				IfInString, codestring, %A_Space%v
				{
					variablestring:= GetVariableString(codestring, "Gui", linenumber)
					IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
				}
	}
	thesefilters:=StrSplit(filters, ",")
	for index, filter in thesefilters
	{
		if (index == 1)
		{
			if (filter == "")
				Continue
			firstfilter:=% filter
		}
		if (index == 2)
		{
			if (filter == "")
				Continue
			secondfilter:=% filter
		}
		if (index == 3)
		{
			if (filter == "")
				Continue
			thirdfilter:=% filter
		}
	}
	Loop, Parse, % variablelist, `n
	{
		checking:=
		thischeck:=
		information:=
		if (A_LoopField == "")
			Continue
		repeatcheck:= StrSplit(A_LoopField, "[thissplitter]")
		for index, repeat in repeatcheck
		{
			if (index == 1)
			{
				IfNotInString, completedlist, % repeat
					thischeck:=% repeat
				IfInString, completedlist, % repeat
				{
					checking:= MakeSure(completedlist, repeat)
					if (checking == "True")
						Continue
					else if (checking == "False")
						thischeck:=% repeat
				}
			}
			if (index == 2)
			{
				if (firstfilter != "")
					IfInString, repeat, % firstfilter
					{
						applyfilters:= StrSplit(repeat, firstfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
				if (secondfilter != "")
					IfInString, repeat, % secondfilter
					{
						applyfilters:= StrSplit(repeat, secondfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
				if (thirdfilter != "")
					IfInString, repeat, % thirdfilter
					{
						applyfilters:= StrSplit(repeat, thirdfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
			}
		}
		if (information == "")
			Continue
		if (thischeck != "")
		{
			checklist:=% Trim(thischeck) "`n" Trim(information) "`n"
			IfNotInString, completedlist, % checklist
				completedlist.= checklist
		}
	}
	completedlist:= RemoveCertainChars(completedlist, "End")
	Return % completedlist
}

MakeSure(listinprogress, checkword)
{
	Loop, Parse, % listinprogress, `n
	{
		if (checkword == A_LoopField)
			Return % "True"
	}
	Return % "False"
}

GetVariableString(codestring, whichone, linenumber)
{
	if (whichone == "Gui")
	{
		variablestrings:= StrSplit(codestring, ",")
		for index, variablestring in variablestrings
		{
			if (index > 4)
				Continue
			IfInString, variablestring, %A_Space%v
				thisvariablestring:=% variablestring
		}
		variablestring:= StrSplit(thisvariablestring, A_Space)
		for index, variable in variablestring
		{
			thisvariableletter:= SubStr(variable, 1, 1)
			if (thisvariableletter == "v")
				Return % variable "[thissplitter] Gui variable[Filter='Gui'] Line number is found at: " linenumber "`n"
		}
		Return % variable "[thissplitter] Gui variable Line number is found at: " linenumber "`n"
	}
	if (whichone == "Quotes")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [quotes]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		variablestrings:= StrSplit(codestring, "[quotes]")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 0)
				IfNotInString, variablestring, %A_Space%
					IfNotInString, variables, % variablestring
						variables.= "[quotes]" variablestring "[quotes][thissplitter] explicit[Filter='explicit'] variable Line number is found at: " linenumber "`n"
		}
		Return % variables
	}
	if (whichone == "Percent")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [percent]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		IfInString, codestring, `,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					IfInString, variablestring, [percent]
						IfNotInString, variablestring, =
							IfInString, variablestring, A_Space
								variables.= variablestring "[thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		IfNotInString, codestring, `,
		{
			IfInString, codestring, =
			{
				variablestrings:= StrSplit(codestring, "=")
				for index, variablestring in variablestrings
				{
					if (index == 1)
					{
						variables:= StrSplit(variablestring, A_Space)
						for index, variable in variables
							thisvariable:=% variable
					}
					if (index == 2)
						codestring:=% variablestring
				}
			}
			variablestrings:= StrSplit(codestring, "[percent]")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					variables.= "[percent]" variablestring "[percent][thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		if (thisvariable != "")
			variables.= thisvariable "[thissplitter]implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
		Return % variables
	}
	if (whichone == "Equals")
	{
		variablestrings:= StrSplit(codestring, "=")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 1)
				IfNotInString, variablestring, [quotes]
				{
					thisvariablestring:= StrSplit(variablestring, A_Space)
					for index, thisvariable in thisvariablestring
					{
						variable:=% thisvariable "[thissplitter] implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
					}
				}
		}
		Return % variable
	}
	Return % "Not Found"
}

RemoveCertainChars(string, special)
{
	if (special == "Start")
	{
		StringReplace, string, string, ", [quotes], ALL ; "
		StringReplace, string, string, `%%A_Space%, [percent], ALL
		StringReplace, string, string, `%, [percent], ALL
		StringReplace, string, string, %A_Space%:, :, ALL
		StringReplace, string, string, :=, =, ALL
		StringReplace, string, string, ==, =, ALL
		StringReplace, string, string, >, =, ALL
		StringReplace, string, string, <, =, ALL
		StringReplace, string, string, %A_Space%!=, =, ALL
		StringReplace, string, string, =%A_Space%, =, ALL
		StringReplace, string, string, %A_Space%=, =, ALL
		StringReplace, string, string, ), , ALL
		StringReplace, string, string, (, , ALL ;)
		StringReplace, string, string, `t, , ALL
	}
	if (special == "End")
	{
		StringReplace, string, string, [quotes], ", ALL ; "
		StringReplace, string, string, [percent], `%, ALL
		StringReplace, string, string, `,, , ALL
	}
	Return % string
}

GetButton_Count()
{
	Loop,
	{
		ButtonCountCheck:= GetControl("ButtCount")
		if (ButtonCountCheck != OldButtonCountCheck)
		{
			OldCount:=% Count
			OldButton:=% Button
			Sleep, 500
			ButtonCount_Split:= StrSplit(ButtonCountCheck, ",")
			For Index, ButtCount in ButtonCount_Split
			{
				if (Index == 1)
					Count:=% ButtCount
				if (Index == 2)
					Button:=% ButtCount
			}
		}
		else if (ButtonCountCheck == OldButtonCountCheck)
			Break
		if ((Button != OldButton)&&(Count > 1))
			Break
		OldButtonCountCheck:=% ButtonCountCheck
	}
	if (Button == OldButton)
	{
		ButtonCountReturn:=% Count "," Button
		GuiControl,AI:, ButtonCountCheck, % "0," Button
	}
	if (Button != OldButton)
	{
		NewCount:=% Count-OldCount
		GuiControl,AI:, ButtonCountCheck, % NewCount "," Button
		ButtonCountReturn:=% OldCount "," OldButton
	}
	Return
}

ApplyLogicalChange(activeuserinput, logicalhistory, numberofdifferences)
{
	x:= 0
	newhistoryrecord:=[]
	activeuserinputlastline:= GetLineCount(activeuserinput)
	logicalhistorylastline:= GetLineCount(logicalhistory)
	LastLine:= logicalhistory["linePos" logicalhistorylastline]
	Loop, % activeuserinputlastline
	{
		record:=
		x++ ; a lagged y variable needed to stagger history.
		occurenceuser:= activeuserinput["linePos" x]
		if (y > 0)
		{
			y:=(x-z) ; this will be an opposite staggered y (x+z) for deleted lines.
			historyrecord:= logicalhistory["linePos" y]
		}
		else
			historyrecord:= logicalhistory["linePos" x] ; even though the line now isn't right doesn't mean next time it won't be.
		splithistoryrecord:= StrSplit(historyrecord, ["(hardReturn)", "(softReturn)"])
		for index, splithistory in splithistoryrecord
		{
			if (Index == 1)
				record:= % splithistory
		}
		if ((occurenceuser != record)&&(numberofdifferences != 0)) ; the number of occurences go negative when lines get deleted... I haven't updated the below else for that yet.
		{
			LastLine:= logicalhistory["linePos" logicalhistorylastline] ; if a user is lagging the array make sure you are putting in last lines right.
			if ((LastLine == "(softReturn)")||(LastLine == "(hardReturn)")) ; the last line shouldn't be any other value.
			{
				z++ ; a z variable making sure we don't lose y and holding the number of occurences.
				if (z == 1) ; there's not enough time to add different enters in different spots (meaning the user couldn't add enough enters in the time this will be done).
					y:=% x
				IfInString, LastLine, (softReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
				IfInString, LastLine, (hardReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
				numberofdifferences--
				logicalhistorylastline--
			} ; the likely answer is a deleted line in occurenceuser. we need to add to the numberofdifferences. I'll also need to update this in the future for the array.
			else
				numberofdifferences++
		}
		else if ((occurenceuser != record)&&(numberofdifferences == 0)) ; meaning user has updated a line with a new record
		{
			newhistoryrecord["linePos" x]:= occurenceuser
			IfInString, record, (softReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
			IfInString, record, (hardReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
		} ; z from above holds all change counts. y from above holds the history record line back. technically y can equal x-z or just y++. I think for greater clarity it should be x-z because a user may choose to purposely lag the logicalhistoryarray Change function. Basically this function can be implimented at will as long as the keys are being kept up with and added to the historyarray in the main loop (of course that might also come with logical array issues).
		else if ((occurenceuser == record)&&(numberofdifferences == 0))
			newhistoryrecord["linePos" x]:= record
	}
	check:=GetControl("GetKeeper")
	if (check == "7h151s@a#res37")
		Return
	Return % newhistoryrecord ; There has been many different statements on using the % after Return or in ":=" as an operorator (it technically doesn't need to be done and can cause issues if done improperly). I use it because honestly it's like my signature to my work.
}

Doppler(usersentence, historysentence)
{
	livewords:=[]
	pastwords:=[]
	check:=GetControl("GetKeeper")
	if (check == "&not@a#rea1*sent3nc3")
	{
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			livewords["wordPos" key]:= userwords
		}
		historysplit:=StrSplit(historysentence, A_Space)
		for key, historywords in historysplit
		{
			pastwords["wordPos" key]:= historywords
		}
		usercount:=GetLineCount(livewords)
		historycount:= GetLineCount(pastwords)
		Loop, % usercount
		{
			x++
			userword:=livewords["wordPos" x]
			historyword:=pastwords["wordPos" x]
			userwordlength:=StrLen(userword)
			historywordlength:= StrLen(historyword)
			if ((userword != historyword)||(historycount < x))
				GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		}
		StringReplace, userword, userword, historyword, , ALL
	}
	else if (check != "&not@a#rea1*sent3nc3")
	{
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 1)
				historyword:=% chec
			if (index == 2)
				ouserword:=% chec
			if (index == 3)
				x:=% chec
		}
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			if (key == x)
				userword:=% userwords
		}
		GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		StringReplace, userword, userword, historyword, , ALL
	}
	userwordlength:=StrLen(userword)
	if (userwordlength < 2)
	{
		GuiControl, AI:, Information, Working...
		SpellChecker(0)
	}
	if (userwordlength > 3)
	{
		GuiControl, AI:, Information, Working.
		ourwords:=WordCheck(userword, userwordlength)
		if (ourwords == "")
			SpellChecker(0)
		else if (ourwords != "")
		{
			SpellChecker(userwordlength)
			GetControl(ourwords)
		}
	}
	Return
}

FixLogicalhistory_Array(historyarray, howmanylines)
{
	lastline:= GetLineCount(historyarray)
	whichbutton:= GetControl("ButtCount")
	Loop, % howmanylines
	{
		lastline++
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					historyarray["linePos" lastline]:= "(softReturn)"
				if (butt == "Enter")
					historyarray["linePos" lastline]:= "(hardReturn)"
			}
		}
	}
	Return % historyarray
}

ReturnLineArray(lines, user)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/SoftReturn\|/", "\|/userReturns\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

GetButtonCount(pressed)
{
	pressing:= StrSplit(pressed, ",")
	For Index, press in pressing
		if (Index == 1)
			Return % press
}

FindingRealLineLOL(occurenceuser, rowbefore, thisrow)
{
	IfInString, occurenceuser, %rowbefore%
	{
		rowlength:= StrLen(rowbefore)
		occurencelength:= StrLen(occurenceuser)
		subtractedlength:=(occurencelength-rowlength)
		thisstring:= SubStr(occurenceuser, subtractedlength, occurencelength)
		if (thisstring == rowbefore)
		{
			IfInString, occurenceuser, %thisrow%
				Return % "Found"
			IfNotInstring, occurenceuser, %thisrow%
				Return % "NextRow"
		}
	}
	if (rowbefore == "NextRow")
		IfInString, occurenceuser, %thisrow%
			Return % "Found"
	Return % "NotFound"
}

ProcessStart(contents, Rest)
{
	logicalhistory:= []
	WinSet, Transparent, 0, Words
	history:= GetHistory()
	logicalhistory:= ReturnLineArray(history, user)
	Control, Disable ,, Edit3, AI
	GuiControl, AI:, Edit3, % contents
	Sleep, % Rest
	Control, Enable ,, Edit3, AI
	GuiControl, AI:, Information, Done
	Control, Enable ,, ListBox1, AI
	Return % logicalhistory
}

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	if (n > 3)
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	if (n == 0)
		WinSet, Transparent, 0, Words
	WinGet, visible, Transparent, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	Return
}
Return

ReturnClearDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			hinput:= harray["linePos" x]
			hsplit:= StrSplit(hinput, ["(hardReturn)", "(softReturn)"])
			for Index, h in hsplit
			{
				if (Index == 1)
					checkh:= % h
			}
			uinput:= uarray["linePos" x]
			StringReplace, uinput, uinput, (softReturn), , ALL
			StringReplace, uinput, uinput, (hardReturn), , ALL
			l_checkh:= StrLen(checkh)
			l_uinput:= StrLen(uinput)
			if (uinput != checkh)
				Return % x
			if (l_checkh != l_uinput)
				Return % x
			if (x == v)
				Break
			checkh:=
		}
		Return % "0"
	}
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return % "True"
	}
}

GetLineCount(arraycount)
{
	LastLine:=0
	for Index, count in arraycount
		++LastLine
	Return % LastLine
}

GetControl(FocTex)
{
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, Edit3
	ControlGet, row, CurrentLine, , Edit3, AI
	ControlGet, rowtext, Line, % row, Edit3, AI
	GuiControlGet, Word, Words:, Listbox1
	StringReplace, text, text, `n, \|/userReturns\|/, ALL
	GuiControlGet, ButtonCountCheck, AI:, ButtonCountCheck
	GuiControlGet, Save_File, AI:, AISave
	GuiControlGet, DopplerGet, AI:, WordKeeper
	if (FocTex == "RowText")
		Return % rowtext
	if (FocTex == "GetKeeper")
		Return % DopplerGet
	if (FocTex == "AISave")
		Return % Save_File
	if (FocTex == "ButtCount")
		Return % ButtonCountCheck
	if (FocTex == "Row")
		Return % row
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	GuiControl, Words:, Listbox1, | 
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
	Return
}

HashContents(contents)
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, \|/CR+LF\|/, `n, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, `n, ALL
	Return % contents
}

GetHistory()
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, `r`n,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, (softReturn)\|/SoftReturn\|/, ALL
	Return % contents
}

RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitapp

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 17 Dec 2023, 19:51

Control functions have been completely fixed now. The Ahk test creation works nicely however, depending on how code is written (rewritten comment splits, not using tabs, continuation sentences, Particular ways a project might be written...) are not accounted for. The control key now has {Ctrl}vv and {Ctrl}vvv functions added (while holding the {ctrl} button down). Of course this is implying that the keyboard you use has LControl. Plus lock to a window has been added.

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability. ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
#InstallkeybdHook
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
Global Settings:= % Cache "\Settings.ini"
IniRead, Directory, % Settings, Directory, Key1
if (Directory != "ERROR")
	SetWorkingDir %Directory%
else
	SetWorkingDir %A_ScriptDir% 
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)
IniRead, Rest, % Settings, Timers, Key1
If (Rest == "ERROR")
{
	IniWrite, 10000, % Settings, Timers, Key1
	Rest:= 10000
}
IniRead, Notactive, % Settings, Timers, Key2
if (Notactive == "ERROR")
{
	IniWrite, 500, % Settings, Timers, Key2
	Notactive:= 500
}
IniRead, NoDif, % Settings, Timers, Key3
if (NoDif == "ERROR")
{
	IniWrite, 25, % Settings, Timers, Key3
	NoDif:= 25
}
IniRead, Always, % Settings, AlwaysOnTop, Key1
if (Always != "ERROR")
	GuestOn:=% Always

Loop, Files, *.ahk, F R
{
	IfInString, A_LoopFileName, @
		Continue
	IfNotInString, wi, % A_LoopFileName
		wi=%wi%%A_LoopFileName%|
}

Menu, Settings, Add, Timers, Timers
Menu, Settings, Add, AlwaysOnTop`ton/off, Always
Menu, Settings, Add, Suspend`ton/off, SusOnOff
Menu, Settings, Add, Reload`tCtrl+r, Reload
Menu, AIsMenu, Add, Settings, :Settings
Menu, Default, Add, Default Settings, Default
Menu, AIsMenu, Add, Default, :Default

CoordMode, Caret, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Window
if (GuestOn == 1)
	Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
else if (GuestOn == 0)
	Gui, AI:New, -AlwaysOnTop +Resize +toolWindow
else
	Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, Menu, AIsMenu
Gui, Add, Edit, r1 x25 y20 w150 ReadOnly, % A_WorkingDir
Gui, Add, DropDownList, x25 y50 w150 vChangeType gChangeType, Get Variables||Get Function|Create Test File
Gui, Add, GroupBox, x25 y80 h250 w150 wrap vResults, Get variables`n(Filter results by Checkbox)
Gui, Add, ListBox, r10 yp+35  xp+15 w120 gFileSelected vFileSelected, %wi%
Gui, Add, Edit, r4 yp+140 xp -VScroll vTestInfo w120,  Select a file to create a Test.ahk file with no function or sublabeled function.
Gui, Add, Text, yp xp vFunctionLabel, input the function lablel
Gui, Add, Edit, r1 w120 vFunctionName,
Gui, Add, Checkbox, vAssociateV, Associated functions
Gui, Add, Checkbox, yp-40 xp vGui, Gui Variables
Gui, Add, Checkbox, vExplicit, Explicit Variables
Gui, Add, Checkbox, vImplicitExplicit, Implicit-Explicit
Gui, Add, Text, -E0x200 x0 y0 vButtonCountCheck w0, 0,Unknown
Gui, Add, Text, -E0x200 vWordKeeper w0, &not@a#rea1*sent3nc3s
Gui, Add, Edit,  r18 ym+45 x200 vWords w325 hwndTracker,
Gui, Add, Button, gAISave, Save
Gui, Add, Text, vAISave w0, Don't save
Gui, Add, Edit,  r1 ym+15 x200 vWindowControl w325,
Gui, Add, Text, ym+298 x470 vInformation, Loading...
Gui, Add, Text, ym+15 x550 vWindowLabel gLock +Border Center h18, %A_Space%%A_Space%+`tAdd Window%A_Space%%A_Space%
Gui, Add, GroupBox, ym+40 x550 h250 w150 wrap vGroupControls, Window Controls
Gui, Add, Checkbox, yp+40 xp+10 vGetWindow gLocktoWindow, Lock Window Control
Gui, Margin, 50, 30
Gui, Show, h400, AI work
GuiControl, AI:Hide, GroupControls
GuiControl, AI:Hide, Button8
GuiControl, AI:Hide, GroupBox2
GuiControl, AI:Hide, FunctionName
GuiControl, AI:Hide, FunctionLabel
GuiControl, AI:Hide, Button2
GuiControl, AI:Hide, Edit2
Control, Disable , , Edit2, AI
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, Add, Text, vClipBoard2 w0 h0 x5 y5,
Gui, Add, Text, vClipBoard3 w0 h0 x5 y5,
Gui, margin, 0, 0
Gui, Show, , Words
GuiControl, Words:Hide, ClipBoard2
GuiControl, Words:Hide, ClipBoard3

contents:=HashContents(contents)
logicalhistory:= []
logicalhistory:= ProcessStart(contents, Rest)
activeuserinput:= []

Loop,
{
	ClipBoardFunction()
	winwonder:=WinWonder()
	if (winwonder == "False")
	{
		SpellChecker(0)
		Sleep, % Notactive
		Continue
	}
	check:=GetControl("GetKeeper")
	usersentence:=GetControl("RowText")
	if (recordkeeper == "")
		recordkeeper:=% usersentence
	if (recordkeeper != usersentence)
	{
		Doppler(usersentence, recordkeeper)
		recordkeeper:=% usersentence
	}
	getuserinput:= GetControl("Text")
	activeuserinput:=ReturnLineArray(getuserinput, "user")
	historylastline:= GetLineCount(logicalhistory)
	activeuserlastline:= GetLineCount(activeuserinput)
	if (check == "7h151s@a#res37")
	{
		If (getuserinput == "")
		{
			Sleep, % Notactive
			Continue
		}
		GuiControl, AI:, WordKeeper, &not@a#rea1*sent3nc3
		contents:=HashContents(contents)
		logicalhistory:= ProcessStart(contents, Rest)
		Continue
	}
	if (usersentence != "")
	{
		if (activeuserlastline != historylastline)
		{
			logicallastlineaddition:=(activeuserlastline-historylastline)
			logicalhistory:= FixLogicalhistory_Array(logicalhistory, logicallastlineaddition) ; where last lines are being put in. and you will also want to function in lastline (Deleted_Line) to acompany the changes. if you are lagging ApplyLogicalChange().
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, logicallastlineaddition)
		}
		if (activeuserlastline == historylastline)
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, 0)
	}
	savecheck:= GetControl("AISave")
	if (savecheck == "Save_File")
	{
		historycount:=GetLineCount(logicalhistory)
		Loop, % historycount
		{
			x++
			sentences:= logicalhistory["linePos" x]
			StringReplace, sentences, sentences, (softReturn), \|/softReturn\|/, ALL
			StringReplace, sentences, sentences, (hardReturn), \|/CR+LF\|/, ALL
			FileContents:=% FileContents sentences
		}
		FileMove, % Temp, % TempBack, 1
		FileAppend, % FileContents, % Temp, UTF-8
		GuiControl,AI:, AISave, Don't Save
	}
}
Return

~LCtrl::
thiskeystate:= GetKeyState("LCtrl", P)
if (thiskeystate != 0)
{
	Loop,
	{
		CtrlC := Chr(3)
		CtrlVV:= (Chr(22) . Chr(22))
		CtrlVVV:= (Chr(22) . Chr(22) . Chr(22))
		GuiControlGet, ClipBoard2, Word:, ClipBoard2
		GuiControlGet, ClipBoard3, Word:, ClipBoard3
		Input, userinput, L3 T0.75 M ; this has a 0.75 second timer... That feels a little natural. however on the person to person scale this might need adjusted.
		if (userinput == CtrlVV)
			Send, % ClipBoard2
		else if (userinput == CtrlVVV)
			Send, % ClipBoard3
		else if (userinput == CtrlC)
			Send, ^c
		else
			Send, ^%userinput%
		ClipBoardFunction()
		thiskeystate:= GetKeyState("LCtrl", P)
		if (thiskeystate == 0)
			Break
	}
}
Return

ClipBoardFunction()
{
	if ((ClipBoard != "")&&(ClipBoard != ClipBoard2))
	{
		if (ClipBoard2 == "" )
			ClipBoard2:=% ClipBoard1
		else if (ClipBoard2 != "")
		{
			ClipBoard3:=% ClipBoard2
			ClipBoard2:=% ClipBoard
		}
	}
	if (ClipBoard2 != "" )
		GuiControl,Word:, ClipBoard2, % ClipBoard2
	if (ClipBoard3 != "" )
		GuiControl,Word:, ClipBoard3, % ClipBoard3
	Return
}

$Backspace::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Backspace}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Backspace}
	}
	Return
}
else
	Send, {Backspace}
Return

$Space::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Space}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Space}
	}
	Return
}
else
	Send, {Space}
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		check:=GetControl("GetKeeper")
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 2)
				userword:=% chec
		}
		str:= StrLen(userword)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
	}
	else
	{
		Send, `t
	}
	Return
}
else
	Send, `t
Return

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",ShiftEnter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
Return

~Enter::
if (winwonder != "False")
{
	ButtonCountCheck:= GetControl("ButtCount")
	PressCount:=GetButtonCount(ButtonCountCheck)
	PressCount++
	WhichButtonCount:=% PressCount ",Enter"
	GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
	KeyWait, Backspace, U
	GetButton_Count()
}
Return

LocktoWindow:
Gui, Submit, NoHide
if (GetWindow == 1)
{
	WinGetActiveTitle, checkthistitle
	GuiControl, AI:, Edit5, Select a window to lock to.
	Loop,
	{
		WinGetActiveTitle, newtitletocheck
		if (checkthistitle != newtitletocheck)
			Break
	}
	GuiControl, AI:, Edit5, % newtitletocheck
	GuiControl, Disable, Edit5
}
if (GetWindow == 0)
{
	GuiControl, AI:, Edit5, No window locked
	GuiControl, Enable, Edit5
}
Return

Lock:
x++
LockMod:= Mod(x, 2)
if (LockMod == 1)
{
	GuiControl, AI:, WindowLabel, %A_Space%%A_Space%-`tAdd Window%A_Space%%A_Space%
	GuiControl, AI:Show, GroupControls
	GuiControl, AI:Show, Button8
}
if (LockMod == 0)
{
	GuiControl,AI:, WindowLabel, %A_Space%%A_Space%+`tAdd Window%A_Space%%A_Space%
	GuiControl, AI:Hide, GroupControls
	GuiControl, AI:Hide, Button8
}
Return

Default:
IniRead, Always, % Settings, AlwaysOnTop, Key1
if (Always != "ERROR")
	GuestOn:=% Always
IniRead, Directory, % Settings, Directory, Key1
if (Directory != "ERROR")
	MainDirectory:=% Directory
IniRead, loopxcount, % Settings, Looper, Key1
if (loopxcount != "ERROR")
{
	Loop, % loopxcount
	{
		IniRead, codex, % Settings, KeyCodes, Key%loopxcount%
		codexlist.=  codex "|"
		loopxcount--
	}
}
IniRead, loopycount, % Settings, DroppedCodeCount, Key1
if (loopycount != "ERROR")
{
	Loop, % loopycount
	{
		IniRead, codedrop, % Settings, DroppedCode, Key%loopycount%
		codeylist.= codedrop  "|"
		loopycount--
	}
}
Gui, Defaults:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Edit, y20 x85, Below are the default settings for the program.
Gui, Add, Text, x20, Default working directory:`t`n(place the full folder location.)`t
Gui, Add, Text, , Create test file parameters:`t`n(To add type one that doesn't exist.`t`n To remove select one from the list.)`t`nTo add more delimit by "|"
Gui, Add, Text, , Delimited words from create test file:`t`n(To add type one that doesn't exist.`t`n To remove select one from the list.)`t`nTo add more delimit by "|"
Gui, Add, Checkbox, x140 ym+210 vYesOrNo, Default AlwaysOnTop On
Gui, Add, Button, x310 ym+235 gDCancel, Cancel
Gui, Add, Button, wp hp yp x375 gDSave, Save
Gui, Add, Text, x120 ym+230 cRed, (Must click save to save changes!)`n  Must reload for directory change
if (MainDirectory != "")
	Gui, Add, Edit, xm+200 ym+45 w200 vDirectory, % MainDirectory
else
	Gui, Add, Edit, xm+200 ym+45 w200 vDirectory, % A_ScriptDir
Gui, Add, ComboBox, xm+200 ym+100 w200 vKodexList gListxChange, % codexlist
Gui, Add, ComboBox, xm+200 ym+165 w200 vKodeyList gListyChange, % codeylist
Gui, Margin, 20, 20
Gui, Show, , Defaults
Control, Disable ,, Edit2, Defaults
if (GuestOn == 1)
	GuiControl, Defaults:, Button1, 1
else if (GuestOn == 0)
	GuiControl, Defaults:, Button1, 0
else
	GuiControl, Defaults:, Button1, 1
Return

ListxChange:
Gui, Submit, NoHide
KodexList:= StrReplace(codexlist, KodexList, "")
GuiControl, Defaults:, KodexList, % KodexList
Return

ListyChange:
Gui, Submit, NoHide
KodeyList:= StrReplace(codeylist, KodeyList, "")
GuiControl, Defaults:, KodeyList, % KodeyList
Return

DCancel:
Gui, Defaults:Destroy
Return

DSave:
Gui, Submit, NoHide
IniDelete, % Settings, KeyCodes
IniDelete, % Settings, DroppedCode
IniDelete, % Settings, Directory
IniDelete, % Settings, AlwaysOnTop
IniDelete, % Settings, Looper
IniDelete, % Settings, DroppedCodeCount
IniWrite, % YesOrNo, % Settings, AlwaysOnTop, Key1
IniWrite, % Directory, % Settings, Directory, Key1
ControlGet, Kodex_List, List, , ComboBox1, Defaults
GuiControlGet, Personalizedx, , Edit3, Defaults
personalx:= StrReplace(Personalizedx, "|", "`n")
Kodex_List:=% (personalx "`n" . Kodex_List)
Kodex_List:= StrReplace(Kodex_List, "`n`n", "`n")
Loop, Parse, % Kodex_List, `n
{
	z++
	IniWrite, % z, % Settings, Looper, Key1
	IniWrite, % A_LoopField, % Settings, KeyCodes, Key%z%
}
ControlGet, Kodey_List, List, , ComboBox2, Defaults
GuiControlGet, Personalizedy, , Edit3, Defaults
personaly:= StrReplace(Personalizedy, "|", "`n")
Kodey_List:=% (personaly "`n" . Kodey_List)
Kodey_List:= StrReplace(Kodey_List, "`n`n", "`n")
Loop, Parse, % Kodey_List, `n
{
	w++
	IniWrite, % w, % Settings, DroppedCodeCount, Key1
	IniWrite, % A_LoopField, % Settings, DroppedCode, Key%w%
}
Return

AISave:
GuiControl,AI:, AISave, Save_File
Return
	
SusOnOff:
Suspend, Toggle
if (A_IsSuspended == 1)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOn
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOff
Return

Always:
WinSet, AlwaysOnTop, Toggle, AI
WinGet, ExStyle, ExStyle, AI
if (ExStyle == 0x00000180)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOff
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOn
Return
 
Timers:
Gui, Timers:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, y25, Rest Timer:`t`n(in seconds)
Gui, Add, Text, y75 xs, Window Not Active:`t`n(in milliseconds)
Gui, Add, Text, y125 xs, Process Loop timer:`t`n(in milliseconds)
Gui, Add, Edit, w250 r3 ys-15 -VScroll, This timer slows the script before it gets to the main loop function. It's used to help in processing the global function "Speller."
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the script when the it is not active.
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the main processing loop while typing. It's dependent on a difference created in the main edit control.
Gui, Add, Edit, ys xs+400 w50 y25
Gui, Add, UpDown, vRangeInSeconds Range1-50, 10
Gui, Add, Edit, ys xs+400 w50 y75
Gui, Add, UpDown, vRangeInMillisecondsOfActive Range1-1000, 500
Gui, Add, Edit, ys xs+400 w50 y125
Gui, Add, UpDown, vRangeInMillisecondsOfProcess Range1-100, 25
Gui, Add, Text, xm+10 ym+180, Select the above values to your personal preferences and click save to keep the changes.
Gui, Add, Text, xm+80 ym+215, (Note you have to restart the program to force the changes)
Gui, Add, Button, ym+210 xs+425 gSave, Save
Gui, Add, Button, ym+210 xs+370 gCancel, Cancel
Gui, Margin, 20, 50
Gui, Show, h250 w500, Timers
Control, Disable ,, Edit1, Timers
Control, Disable ,, Edit2, Timers
Control, Disable ,, Edit3, Timers
Return

Reload:
^r::
Reload
Return

Cancel:
Gui, Timers:Destroy
Return

Save:
Gui, Submit, NoHide
RangeInSeconds:=(RangeInSeconds*1000)
IniWrite, % RangeInSeconds, % Settings, Timers, Key1
IniWrite, % RangeInMillisecondsOfActive, % Settings, Timers, Key2
IniWrite, % RangeInMillisecondsOfProcess, % Settings, Timers, Key3
Gui, Timers:Destroy
Return

FileSelected: 
Gui, Submit, NoHide
FileRead, contents, % FileSelected
if (ChangeType == "Get Variables")
{
	if (Gui == 1)
		filters.= "[Filter='Gui'],"
	if (Explicit == 1)
		filters.= "[Filter='explicit'],"
	if (ImplicitExplicit == 1)
		filters.= "[Filter='implicit-explicit'],"
	wi:=
	if (filters != "")
	{
		Control, Disable ,, ListBox1, AI
		Control, Disable ,, Edit3, AI
		contents:= GetVariables(contents, filters)
		GuiControl, AI:, Words,
		GuiControl, AI:, Words, % contents
		whichbutton:=GetControl("ButtCount")
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					thisbutton:= "\|/SoftReturn\|/"
				if (butt == "Enter")
					thisbutton:= "\|/hardReturn\|/"
				if (butt == "Unknown")
					thisbutton:= " \|/SoftReturn\|/"
			}
		}
		StringReplace, contents, contents, `n, %thisbutton%, ALL
		FileMove, % Temp, % TempBack, 1
		FileAppend, % contents, % Temp, UTF-8
	}
}
else if (ChangeType == "Get Function") ;ChangeType gChangeType, Get Variables||Get Function|Create Test File
{
	ControlGet, row, CurrentLine, , Edit2, AI
	ControlGet, rowtext, Line, % row, Edit2, AI
	if (rowtext == "")
	{
		MsgBox, Please insert the function label name
		Return
	}
	if (AssociateV == 1)
		thisignore:=% "Do_Not"
	function:=GetThisFunction(rowtext, thisignore, contents)
	GuiControl, AI:, Words, % function
	FileMove, % Temp, % TempBack, 1
	FileAppend, % function, % Temp, UTF-8
}
else if (ChangeType == "Create Test File")
{
	thesecontents:= GetTestFile(contents)
	Loop, Parse, % thesecontents, `n
	{
		if (A_LoopField == "")
			Continue
		if (A_LoopField == "Return")
			thisfile:=% thisfile A_LoopField "`n`n"
		else if (A_LoopField != "Return")
			thisfile:=% thisfile A_LoopField "`n"
	}
	FileMove, Test.ahk, % TempBack, 1
	FileAppend, % thisfile, *Test.ahk, UTF-8
}
GuiControl, AI:, Button2, 0
GuiControl, AI:, Button3, 0
GuiControl, AI:, Button4, 0
GuiControl, AI:, Button5, 0
GuiControl, AI:, Edit2,
GuiControl, AI:, WordKeeper, 7h151s@a#res37
Return

GetTestFile(data)
{
	IniRead, loopcount, % Settings, Looper, Key1
	if (loopcount != "ERROR")
	{
		Loop, % loopcount
		{
			IniRead, codex, % Settings, KeyCodes, Key%loopcount%
			codexlist.= codex "`n"
			loopcount--
		}
		IniRead, loopcount, % Settings, DroppedCodeCount, Key1
		if (loopcount != "ERROR")
		{
			Loop, % loopcount
			{
				IniRead, codedrop, % Settings, DroppedCode, Key%loopcount%
				codeylist.= codedrop "`n"
				loopcount--
			}
		}
		data:= StrReplace(data, "`r", "")
		Loop, Parse, % data, `n
		{
			y++
			codestring:=
			line:=% A_LoopField
			sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
			for index, sentence in sentences
			{
				if (index == 1)
					codestring:=% sentence
				if (index == 2)
					commentstring:=% sentence
			}
			codestring:= CodeStringCheck(codestring)
			if (codestring != "")
			{
				IfinString, codestring, Return
				{
					if (thischecker == 1)
						IfNotInString, codestring, % "`t"
							thischecker:= 0
					codestring:=% ""
				}
				IfInString, codestring, Global
				{
					filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfInString, codestring, Gui
				{
					IfinString, codestring, Show
						filecontents:=% filecontents codestring "`nReturn`n`n"
					else
						filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfInString, codestring, Menu
				{
					filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfinString, codestring, :
				{
					IfInString, codestring, Gui
						codestring:=% ""
					if (thischecker != 1)
					{
						thischecker:= 1
						if (x != 1)
							x:=1
					}
					filecontents:=% filecontents codestring "`nReturn`n`n"
					codestring:=% ""
				}
				keycodex:= StrReplace(codestring, ",",  " ")
				keycodex:= StrReplace(keycodex, "  ", " ")
				keycodex:= StrReplace(keycodex, "  ", " ")
				keycodex:=% Trim(keycodex)
				thesewords:= StrSplit(keycodex, A_Space)
				for index, keycode in thesewords
					if (index == 1)
						keycodex:=% keycode
				IfinString, codeylist, % keycodex
					codestring:=% ""
				IfinString, codexlist, % keycodex
				{
					filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfInString, filecontents, % codestring
					codestring:=% ""
			}
		}
	}
	else if (loopcount == "ERROR")
	{
		MsgBox, 70, Be sure before you continue., In the following message boxes you will be shown the beginning of your code. This will omit the comments and anything past the first comma as demiliters for your test.ahk creation. each type will be added to the Ini file settings and read for your future creations. You can always change this setting by selecting default in the default menu.`n`n**Also note This does skip continuation sections.
		IfMsgBox Continue
		{
			data:= StrReplace(data, "`r", "")
			Loop, Parse, % data, `n
			{
				y++
				line:=% A_LoopField
				sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
				for index, sentence in sentences
				{
					if (index == 1)
						codestring:=% sentence
					if (index == 2)
						commentstring:=% sentence
				}
				codestring:= CodeStringCheck(codestring)
				if (codestring != "")
				{
					IfinString, codestring, Return
					{
						if (thischecker == 1)
							IfNotInString, codestring, % "`t"
								thischecker:= 0
						codestring:=% ""
					}
					IfInString, codestring, Global
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, codestring, Gui
					{
						IfinString, codestring, Show
							filecontents:=% filecontents codestring "`nReturn`n`n"
						else
							filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, codestring, Menu
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfinString, codestring, :
					{
						IfInString, codestring, Gui
							codestring:=% ""
						if (thischecker != 1)
						{
							thischecker:= 1
							if (x != 1)
							{
								x:=1
								MsgBox, 32, g-Sublabels, sublabels are automatically added
							}
						}
						filecontents:=% filecontents codestring "`nReturn`n`n"
						codestring:=% ""
					}
					keycodex:= StrReplace(codestring, ",",  " ")
					keycodex:= StrReplace(keycodex, "  ", " ")
					keycodex:= StrReplace(keycodex, "  ", " ")
					keycodex:=% Trim(keycodex)
					thesewords:= StrSplit(keycodex, A_Space)
					for index, keycode in thesewords
						if (index == 1)
							keycodex:=% keycode
					IfinString, thisignoredlist, % keycodex
						codestring:=% ""
					IfinString, thisgottenlist, % keycodex
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, filecontents, % codestring
						codestring:=% ""
					if (codestring != "")
					{
						MsgBox, 36, Do you want to add this line?, % keycodex "`n`nFound on line: " y "`n`npress yes if you want to add the first (word) of this line to your delimiter fields."
						IfMsgBox Yes
						{
							z++
							IniWrite, % z, % Settings, Looper, Key1
							IniWrite, % keycodex, % Settings, KeyCodes, Key%z%
							thisgottenlist.= keycodex
							filecontents:=% filecontents codestring "`n"
						}
						else IfMsgBox No
						{
							w++
							IniWrite, % w, % Settings, DroppedCodeCount, Key1
							IniWrite, % keycodex, % Settings, DroppedCode, Key%w%
							thisignoredlist.= codestring " "
							Continue
						}
					}
				}
			}
		}
	}
	Return % filecontents
}

CodeStringCheck(codestring)
{
	IfInString, codestring, GuiControl
		codestring:=% ""
	IfinString, codestring, `t
		codestring:=% ""
	IfInString, codestring, Global
		Return % codestring
	IfInString, codestring, Gui ; It's likely a user may place any of the below special characters in a gui 4th parameter.
		Return % codestring
	IfInString, codestring, =
		codestring:=% ""
	IfInString, codestring, ( ;)
		codestring:=% ""
	IfInString, codestring, {
		codestring:=% ""
	IfInString, codestring, }
		codestring:=% ""
	IfInString, codestring, `%
		IfNotInString, codestring, SetWorkingDir
			codestring:=% ""
	IfinString, codestring, Loop
		codestring:=% ""
	IfinString, codestring, else
		codestring:=% ""
	IfinString, codestring, if%A_Space%
		codestring:=% ""
	IfinString, codestring, ::
		codestring:=% ""
	Return % codestring
}

GetThisFunction(function, get, data)
{
	functionlength:=StrLen(function)
	data:= StrReplace(data, "`r", "")
	function:= GetFunction(data, functionlength, function)
	thisfoundfunction.= function "`n"
	function:=""
	if (get == "Do_Not")
	{
		Loop,
		{
			Loop, Parse, % thisfoundfunction, `n
			{
				IfInString, A_LoopField, =
					IfInString, A_LoopField, (
					{
						foundpossible:= FunctionLabelGet(A_LoopField)
						Trim(foundpossible)
						IfNotInString, foundpossible, % A_Space
							IfNotInString, thesefound, % foundpossible
							{
								functionlength:=StrLen(foundpossible)
								function:= GetFunction(data, functionlength, foundpossible)
							}
						if (function != "")
							thisfoundfunction.= function "`n"
					}
				if (function != "")
					function:=
				thesefound.= foundpossible ", "
			}
			IfNotInString, thesefoundpast, % thesefound
				thesefoundpast.= thesefound
			IfinString, thesefoundpast, % thesefound
				Break
		}
	}
	Return % thisfoundfunction
}

GetFunction(data, functionlength, function)
{
	Loop, Parse, % data, `n
	{
		if (thisfunction == "")
		{
			linesubstring:= SubStr(A_LoopField, 1, functionlength)
			if (function == linesubstring)
				thisfunction:= % A_LoopField "`n"
			z:=1
		}
		else if (thisfunction != "")
		{
			thisfunction.= A_LoopField "`n"
			if (A_LoopField == "{")
				x++
			if (A_LoopField == "}")
				x--
			if (z == 1)&&(A_LoopField != "{")
				thisfunction:= ""
			z:=0
		}
		if ((x == 0)&&(thisfunction != ""))
		{
			thisfoundfunction:= % thisfunction
			thisfunction:= ""
		}
	}
	Return % thisfoundfunction
}

FunctionLabelGet(line)
{
	thissplitfunction:= StrSplit(line, "= ")
	for index, thissplit in thissplitfunction
		if (index == 2)
			thispart:=% thissplit
	thispartsplit:= StrSplit(thispart, "(") ;"
	for index, function in thispartsplit
		if (index == 1)
			Return % function
	Return
}

ChangeType:
Gui, Submit, NoHide
if (ChangeType == "Get Variables")
{
	GuiControl, AI:Text, Results, Get variables`n(Filter results by Checkbox)
	GuiControl, AI:Hide, FunctionName
	GuiControl, AI:Hide, FunctionLabel
	GuiControl, AI:Hide, Button2
	GuiControl, AI:Hide, Edit2
	GuiControl, AI:Show, Button5
	GuiControl, AI:Show, Button3
	GuiControl, AI:Show, Button4
}
if (ChangeType == "Get Function")
{
	GuiControl, AI:Text, Results, Get Function`n(Select a file to get a function)
	GuiControl, AI:Hide, Button5
	GuiControl, AI:Hide, Button3
	GuiControl, AI:hide, Button4
	GuiControl, AI:Show, FunctionName
	GuiControl, AI:Show, FunctionLabel
	GuiControl, AI:Show, Button2
	GuiControl, AI:Hide, Edit2
}
if (ChangeType == "Create Test File")
{
	GuiControl, AI:Text, results, Create a Test File`n(Create a functionless test ahk)
	GuiControl, AI:Hide, Button5
	GuiControl, AI:Hide, Button3
	GuiControl, AI:hide, Button4
	GuiControl, AI:hide, FunctionName
	GuiControl, AI:hide, FunctionLabel
	GuiControl, AI:hide, Button2
	GuiControl, AI:Show, Edit2
}
Return

GetVariables(filecontents, filters)
{
	Loop, Parse, % filecontents, `r
	{
		linenumber++
		line:=% A_LoopField
		sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
		for index, sentence in sentences
		{
			if (index == 1)
				codestring:=% sentence
			if (index == 2)
				commentstring:=% sentence
		}
		codestring:= RemoveCertainChars(codestring, "Start")
		IfInString, codestring, Dll
			Continue
		IfInString, codestring, Box`,
			Continue
		IfInString, codestring, StringReplace
			Continue
		IfInString, codestring, RegEx
			Continue
		IfInString, codestring, Ini
			Continue
		IfInString, codestring, =
		{
			IfInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Percent", linenumber)
				IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
			}
			else IfNotInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
			IfInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Quotes", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring 
			}
			else IfNotInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
		}
		else IfInString, codestring, [percent]
		{
			variablestring:= GetVariableString(codestring, "Percent", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring
		}
		else IfInString, codestring, [quotes]
		{
			variablestring:= GetVariableString(codestring, "Quotes", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring "found in quotes 2`n"
		}
		IfInString, codestring, Gui
			IfInString, codestring, `,
				IfInString, codestring, %A_Space%v
				{
					variablestring:= GetVariableString(codestring, "Gui", linenumber)
					IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
				}
	}
	thesefilters:=StrSplit(filters, ",")
	for index, filter in thesefilters
	{
		if (index == 1)
		{
			if (filter == "")
				Continue
			firstfilter:=% filter
		}
		if (index == 2)
		{
			if (filter == "")
				Continue
			secondfilter:=% filter
		}
		if (index == 3)
		{
			if (filter == "")
				Continue
			thirdfilter:=% filter
		}
	}
	Loop, Parse, % variablelist, `n
	{
		checking:=
		thischeck:=
		information:=
		if (A_LoopField == "")
			Continue
		repeatcheck:= StrSplit(A_LoopField, "[thissplitter]")
		for index, repeat in repeatcheck
		{
			if (index == 1)
			{
				IfNotInString, completedlist, % repeat
					thischeck:=% repeat
				IfInString, completedlist, % repeat
				{
					checking:= MakeSure(completedlist, repeat)
					if (checking == "True")
						Continue
					else if (checking == "False")
						thischeck:=% repeat
				}
			}
			if (index == 2)
			{
				if (firstfilter != "")
					IfInString, repeat, % firstfilter
					{
						applyfilters:= StrSplit(repeat, firstfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
				if (secondfilter != "")
					IfInString, repeat, % secondfilter
					{
						applyfilters:= StrSplit(repeat, secondfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
				if (thirdfilter != "")
					IfInString, repeat, % thirdfilter
					{
						applyfilters:= StrSplit(repeat, thirdfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
			}
		}
		if (information == "")
			Continue
		if (thischeck != "")
		{
			checklist:=% Trim(thischeck) "`n" Trim(information) "`n"
			IfNotInString, completedlist, % checklist
				completedlist.= checklist
		}
	}
	completedlist:= RemoveCertainChars(completedlist, "End")
	Return % completedlist
}

MakeSure(listinprogress, checkword)
{
	Loop, Parse, % listinprogress, `n
	{
		if (checkword == A_LoopField)
			Return % "True"
	}
	Return % "False"
}

GetVariableString(codestring, whichone, linenumber)
{
	if (whichone == "Gui")
	{
		variablestrings:= StrSplit(codestring, ",")
		for index, variablestring in variablestrings
		{
			if (index > 4)
				Continue
			IfInString, variablestring, %A_Space%v
				thisvariablestring:=% variablestring
		}
		variablestring:= StrSplit(thisvariablestring, A_Space)
		for index, variable in variablestring
		{
			thisvariableletter:= SubStr(variable, 1, 1)
			if (thisvariableletter == "v")
				Return % variable "[thissplitter] Gui variable[Filter='Gui'] Line number is found at: " linenumber "`n"
		}
		Return % variable "[thissplitter] Gui variable Line number is found at: " linenumber "`n"
	}
	if (whichone == "Quotes")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [quotes]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		variablestrings:= StrSplit(codestring, "[quotes]")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 0)
				IfNotInString, variablestring, %A_Space%
					IfNotInString, variables, % variablestring
						variables.= "[quotes]" variablestring "[quotes][thissplitter] explicit[Filter='explicit'] variable Line number is found at: " linenumber "`n"
		}
		Return % variables
	}
	if (whichone == "Percent")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [percent]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		IfInString, codestring, `,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					IfInString, variablestring, [percent]
						IfNotInString, variablestring, =
							IfInString, variablestring, A_Space
								variables.= variablestring "[thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		IfNotInString, codestring, `,
		{
			IfInString, codestring, =
			{
				variablestrings:= StrSplit(codestring, "=")
				for index, variablestring in variablestrings
				{
					if (index == 1)
					{
						variables:= StrSplit(variablestring, A_Space)
						for index, variable in variables
							thisvariable:=% variable
					}
					if (index == 2)
						codestring:=% variablestring
				}
			}
			variablestrings:= StrSplit(codestring, "[percent]")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					variables.= "[percent]" variablestring "[percent][thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		if (thisvariable != "")
			variables.= thisvariable "[thissplitter]implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
		Return % variables
	}
	if (whichone == "Equals")
	{
		variablestrings:= StrSplit(codestring, "=")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 1)
				IfNotInString, variablestring, [quotes]
				{
					thisvariablestring:= StrSplit(variablestring, A_Space)
					for index, thisvariable in thisvariablestring
					{
						variable:=% thisvariable "[thissplitter] implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
					}
				}
		}
		Return % variable
	}
	Return % "Not Found"
}

RemoveCertainChars(string, special)
{
	if (special == "Start")
	{
		StringReplace, string, string, ", [quotes], ALL ; "
		StringReplace, string, string, `%%A_Space%, [percent], ALL
		StringReplace, string, string, `%, [percent], ALL
		StringReplace, string, string, %A_Space%:, :, ALL
		StringReplace, string, string, :=, =, ALL
		StringReplace, string, string, ==, =, ALL
		StringReplace, string, string, >, =, ALL
		StringReplace, string, string, <, =, ALL
		StringReplace, string, string, %A_Space%!=, =, ALL
		StringReplace, string, string, =%A_Space%, =, ALL
		StringReplace, string, string, %A_Space%=, =, ALL
		StringReplace, string, string, ), , ALL
		StringReplace, string, string, (, , ALL ;)
		StringReplace, string, string, `t, , ALL
	}
	if (special == "End")
	{
		StringReplace, string, string, [quotes], ", ALL ; "
		StringReplace, string, string, [percent], `%, ALL
		StringReplace, string, string, `,, , ALL
	}
	Return % string
}

GetButton_Count()
{
	Loop,
	{
		ButtonCountCheck:= GetControl("ButtCount")
		if (ButtonCountCheck != OldButtonCountCheck)
		{
			OldCount:=% Count
			OldButton:=% Button
			Sleep, 500
			ButtonCount_Split:= StrSplit(ButtonCountCheck, ",")
			For Index, ButtCount in ButtonCount_Split
			{
				if (Index == 1)
					Count:=% ButtCount
				if (Index == 2)
					Button:=% ButtCount
			}
		}
		else if (ButtonCountCheck == OldButtonCountCheck)
			Break
		if ((Button != OldButton)&&(Count > 1))
			Break
		OldButtonCountCheck:=% ButtonCountCheck
	}
	if (Button == OldButton)
	{
		ButtonCountReturn:=% Count "," Button
		GuiControl,AI:, ButtonCountCheck, % "0," Button
	}
	if (Button != OldButton)
	{
		NewCount:=% Count-OldCount
		GuiControl,AI:, ButtonCountCheck, % NewCount "," Button
		ButtonCountReturn:=% OldCount "," OldButton
	}
	Return
}

ApplyLogicalChange(activeuserinput, logicalhistory, numberofdifferences)
{
	x:= 0
	newhistoryrecord:=[]
	activeuserinputlastline:= GetLineCount(activeuserinput)
	logicalhistorylastline:= GetLineCount(logicalhistory)
	LastLine:= logicalhistory["linePos" logicalhistorylastline]
	Loop, % activeuserinputlastline
	{
		record:=
		x++ ; a lagged y variable needed to stagger history.
		occurenceuser:= activeuserinput["linePos" x]
		if (y > 0)
		{
			y:=(x-z) ; this will be an opposite staggered y (x+z) for deleted lines.
			historyrecord:= logicalhistory["linePos" y]
		}
		else
			historyrecord:= logicalhistory["linePos" x] ; even though the line now isn't right doesn't mean next time it won't be.
		splithistoryrecord:= StrSplit(historyrecord, ["(hardReturn)", "(softReturn)"])
		for index, splithistory in splithistoryrecord
		{
			if (Index == 1)
				record:= % splithistory
		}
		if ((occurenceuser != record)&&(numberofdifferences != 0)) ; the number of occurences go negative when lines get deleted... I haven't updated the below else for that yet.
		{
			LastLine:= logicalhistory["linePos" logicalhistorylastline] ; if a user is lagging the array make sure you are putting in last lines right.
			if ((LastLine == "(softReturn)")||(LastLine == "(hardReturn)")) ; the last line shouldn't be any other value.
			{
				z++ ; a z variable making sure we don't lose y and holding the number of occurences.
				if (z == 1) ; there's not enough time to add different enters in different spots (meaning the user couldn't add enough enters in the time this will be done).
					y:=% x
				IfInString, LastLine, (softReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
				IfInString, LastLine, (hardReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
				numberofdifferences--
				logicalhistorylastline--
			} ; the likely answer is a deleted line in occurenceuser. we need to add to the numberofdifferences. I'll also need to update this in the future for the array.
			else
				numberofdifferences++
		}
		else if ((occurenceuser != record)&&(numberofdifferences == 0)) ; meaning user has updated a line with a new record
		{
			newhistoryrecord["linePos" x]:= occurenceuser
			IfInString, record, (softReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
			IfInString, record, (hardReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
		} ; z from above holds all change counts. y from above holds the history record line back. technically y can equal x-z or just y++. I think for greater clarity it should be x-z because a user may choose to purposely lag the logicalhistoryarray Change function. Basically this function can be implimented at will as long as the keys are being kept up with and added to the historyarray in the main loop (of course that might also come with logical array issues).
		else if ((occurenceuser == record)&&(numberofdifferences == 0))
			newhistoryrecord["linePos" x]:= record
	}
	check:=GetControl("GetKeeper")
	if (check == "7h151s@a#res37")
		Return
	Return % newhistoryrecord ; There has been many different statements on using the % after Return or in ":=" as an operorator (it technically doesn't need to be done and can cause issues if done improperly). I use it because honestly it's like my signature to my work.
}

Doppler(usersentence, historysentence)
{
	livewords:=[]
	pastwords:=[]
	check:=GetControl("GetKeeper")
	if (check == "&not@a#rea1*sent3nc3")
	{
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			livewords["wordPos" key]:= userwords
		}
		historysplit:=StrSplit(historysentence, A_Space)
		for key, historywords in historysplit
		{
			pastwords["wordPos" key]:= historywords
		}
		usercount:=GetLineCount(livewords)
		historycount:= GetLineCount(pastwords)
		Loop, % usercount
		{
			x++
			userword:=livewords["wordPos" x]
			historyword:=pastwords["wordPos" x]
			userwordlength:=StrLen(userword)
			historywordlength:= StrLen(historyword)
			if ((userword != historyword)||(historycount < x))
				GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		}
		StringReplace, userword, userword, historyword, , ALL
	}
	else if (check != "&not@a#rea1*sent3nc3")
	{
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 1)
				historyword:=% chec
			if (index == 2)
				ouserword:=% chec
			if (index == 3)
				x:=% chec
		}
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			if (key == x)
				userword:=% userwords
		}
		GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		StringReplace, userword, userword, historyword, , ALL
	}
	userwordlength:=StrLen(userword)
	if (userwordlength < 2)
	{
		GuiControl, AI:, Information, Working...
		SpellChecker(0)
	}
	if (userwordlength > 3)
	{
		GuiControl, AI:, Information, Working.
		ourwords:=WordCheck(userword, userwordlength)
		if (ourwords == "")
			SpellChecker(0)
		else if (ourwords != "")
		{
			SpellChecker(userwordlength)
			GetControl(ourwords)
		}
	}
	Return
}

FixLogicalhistory_Array(historyarray, howmanylines)
{
	lastline:= GetLineCount(historyarray)
	whichbutton:= GetControl("ButtCount")
	Loop, % howmanylines
	{
		lastline++
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					historyarray["linePos" lastline]:= "(softReturn)"
				if (butt == "Enter")
					historyarray["linePos" lastline]:= "(hardReturn)"
			}
		}
	}
	Return % historyarray
}

ReturnLineArray(lines, user)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/SoftReturn\|/", "\|/userReturns\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

GetButtonCount(pressed)
{
	pressing:= StrSplit(pressed, ",")
	For Index, press in pressing
		if (Index == 1)
			Return % press
}

FindingRealLineLOL(occurenceuser, rowbefore, thisrow)
{
	IfInString, occurenceuser, %rowbefore%
	{
		rowlength:= StrLen(rowbefore)
		occurencelength:= StrLen(occurenceuser)
		subtractedlength:=(occurencelength-rowlength)
		thisstring:= SubStr(occurenceuser, subtractedlength, occurencelength)
		if (thisstring == rowbefore)
		{
			IfInString, occurenceuser, %thisrow%
				Return % "Found"
			IfNotInstring, occurenceuser, %thisrow%
				Return % "NextRow"
		}
	}
	if (rowbefore == "NextRow")
		IfInString, occurenceuser, %thisrow%
			Return % "Found"
	Return % "NotFound"
}

ProcessStart(contents, Rest)
{
	logicalhistory:= []
	WinSet, Transparent, 0, Words
	history:= GetHistory()
	logicalhistory:= ReturnLineArray(history, user)
	Control, Disable ,, Edit3, AI
	GuiControl, AI:, Edit3, % contents
	Sleep, % Rest
	Control, Enable ,, Edit3, AI
	GuiControl, AI:, Information, Done
	Control, Enable ,, ListBox1, AI
	Return % logicalhistory
}

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	if (n > 3)
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	if (n == 0)
		WinSet, Transparent, 0, Words
	WinGet, visible, Transparent, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	Return
}
Return

ReturnClearDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			hinput:= harray["linePos" x]
			hsplit:= StrSplit(hinput, ["(hardReturn)", "(softReturn)"])
			for Index, h in hsplit
			{
				if (Index == 1)
					checkh:= % h
			}
			uinput:= uarray["linePos" x]
			StringReplace, uinput, uinput, (softReturn), , ALL
			StringReplace, uinput, uinput, (hardReturn), , ALL
			l_checkh:= StrLen(checkh)
			l_uinput:= StrLen(uinput)
			if (uinput != checkh)
				Return % x
			if (l_checkh != l_uinput)
				Return % x
			if (x == v)
				Break
			checkh:=
		}
		Return % "0"
	}
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return % "True"
	}
}

GetLineCount(arraycount)
{
	LastLine:=0
	for Index, count in arraycount
		++LastLine
	Return % LastLine
}

GetControl(FocTex)
{
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, Edit3
	ControlGet, row, CurrentLine, , Edit3, AI
	ControlGet, rowtext, Line, % row, Edit3, AI
	GuiControlGet, Word, Words:, Listbox1
	StringReplace, text, text, `n, \|/userReturns\|/, ALL
	GuiControlGet, ButtonCountCheck, AI:, ButtonCountCheck
	GuiControlGet, Save_File, AI:, AISave
	GuiControlGet, DopplerGet, AI:, WordKeeper
	if (FocTex == "RowText")
		Return % rowtext
	if (FocTex == "GetKeeper")
		Return % DopplerGet
	if (FocTex == "AISave")
		Return % Save_File
	if (FocTex == "ButtCount")
		Return % ButtonCountCheck
	if (FocTex == "Row")
		Return % row
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	GuiControl, Words:, Listbox1, | 
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
	Return
}

HashContents(contents)
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, \|/CR+LF\|/, `n, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, `n, ALL
	Return % contents
}

GetHistory()
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, `r`n,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, (softReturn)\|/SoftReturn\|/, ALL
	Return % contents
}

RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitapp

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 18 Dec 2023, 17:25

Well a few more functions have been added. A few extra bugs have been found and some minor forgotten edits... Those have been since fixed. I have also noticed the lock to window sometimes "chooses :think: " to just go with a blank window as not like the active window... (IDK really but I have added the if (newtitletocheck == "") continue... So far it works good (maybe a sleep timer :think: ).

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability. ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
#InstallkeybdHook
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
Global Settings:= % Cache "\Settings.ini"
IniRead, Directory, % Settings, Directory, Key1
if (Directory != "ERROR")
	SetWorkingDir %Directory%
else
	SetWorkingDir %A_ScriptDir% 
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)
IniRead, Rest, % Settings, Timers, Key1
If (Rest == "ERROR")
{
	IniWrite, 10000, % Settings, Timers, Key1
	Rest:= 10000
}
IniRead, Notactive, % Settings, Timers, Key2
if (Notactive == "ERROR")
{
	IniWrite, 500, % Settings, Timers, Key2
	Notactive:= 500
}
IniRead, NoDif, % Settings, Timers, Key3
if (NoDif == "ERROR")
{
	IniWrite, 25, % Settings, Timers, Key3
	NoDif:= 25
}
IniRead, Always, % Settings, AlwaysOnTop, Key1
if (Always != "ERROR")
	GuestOn:=% Always

Loop, Files, *.ahk, F R
{
	IfInString, A_LoopFileName, @
		Continue
	IfNotInString, wi, % A_LoopFileName
		wi=%wi%%A_LoopFileName%|
}

Menu, Settings, Add, Timers, Timers
Menu, Settings, Add, AlwaysOnTop`ton/off, Always
Menu, Settings, Add, Suspend`ton/off, SusOnOff
Menu, Settings, Add, Reload`tCtrl+r, Reload
Menu, AIsMenu, Add, Settings, :Settings
Menu, Default, Add, Default Settings, Default
Menu, AIsMenu, Add, Default, :Default

CoordMode, Caret, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Window
if (GuestOn == 1)
	Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
else if (GuestOn == 0)
	Gui, AI:New, -AlwaysOnTop +Resize +toolWindow
else
	Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, Menu, AIsMenu
Gui, Add, Edit, r1 x25 y20 w150 ReadOnly, % A_WorkingDir
Gui, Add, DropDownList, x25 y50 w150 vChangeType gChangeType, Get Variables||Get Function|Create Test File
Gui, Add, GroupBox, x25 y80 h250 w150 wrap vResults, Get variables`n(Filter results by Checkbox)
Gui, Add, ListBox, r10 yp+35  xp+15 w120 gFileSelected vFileSelected, %wi%
Gui, Add, Edit, r4 yp+140 xp -VScroll vTestInfo w120,  Select a file to create a Test.ahk file with no function or sublabeled function.
Gui, Add, Text, yp xp vFunctionLabel, input the function lablel
Gui, Add, Edit, r1 w120 vFunctionName,
Gui, Add, Checkbox, vAssociateV, Associated functions
Gui, Add, Checkbox, yp-40 xp vGui, Gui Variables
Gui, Add, Checkbox, vExplicit, Explicit Variables
Gui, Add, Checkbox, vImplicitExplicit, Implicit-Explicit
Gui, Add, Text, -E0x200 x0 y0 vButtonCountCheck w0, 0,Unknown
Gui, Add, Text, -E0x200 vWordKeeper w0, &not@a#rea1*sent3nc3s
Gui, Add, Edit,  r18 ym+45 x200 vWords w325 hwndTracker,
Gui, Add, Button, gAISave, Save
Gui, Add, Text, vAISave w0, Don't save
Gui, Add, Edit,  r1 ym+15 x200 vWindowControl w325,
Gui, Add, Text, ym+298 x470 vInformation, Loading...
Gui, Add, Text, ym+15 x550 vWindowLabel gLock +Border Center h18, %A_Space%%A_Space%+`tAdd Window%A_Space%%A_Space%
Gui, Add, GroupBox, ym+40 x550 h250 w150 wrap vGroupControls, Window Controls
Gui, Add, Checkbox, yp+40 xp+10 vGetWindow gLocktoWindow, Lock Window Control
Gui, Add, Checkbox, yp+20 xp vSnapWindow gSnapToWindow, Snap to Window
Gui, Add, Checkbox, yp+20 xp vSnapToEditor gSnapToEditor, Snap to Editor
Gui, Add, Checkbox, yp+20 xp vAutoEdit gAutoEdit, Enable Auto Edit
Gui, Add, Checkbox, yp+20 xp vEnableCC gEnableCC, Enable copy anywhere
Gui, Add, Checkbox, yp+20 xp vEnableVV gEnableVV, Enable paste 2nd Clip
Gui, Add, Edit, yp+20 xp r5 w130 -VScroll vControlInformation, Information about the above controls
Gui, Margin, 50, 30
Gui, Show, h400, AI work
GuiControl, AI:Hide, GroupControls
GuiControl, AI:Hide, Button8
GuiControl, AI:Hide, Button9
GuiControl, AI:Hide, Button10
GuiControl, AI:Hide, Button11
GuiControl, AI:Hide, Button12
GuiControl, AI:Hide, Button13
GuiControl, AI:Hide, GroupBox2
GuiControl, AI:Hide, FunctionName
GuiControl, AI:Hide, FunctionLabel
GuiControl, AI:Hide, Button2
GuiControl, AI:Hide, Edit2
Control, Disable , , Edit2, AI
Control, Disable , , Edit6, AI
GuiControl, Focus, Edit4
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, Add, Text, vClipBoard2 w0 h0 x5 y5,
Gui, Add, Text, vClipBoard3 w0 h0 x5 y5,
Gui, margin, 0, 0
Gui, Show, , Words
GuiControl, Words:Hide, ClipBoard2
GuiControl, Words:Hide, ClipBoard3

contents:=HashContents(contents)
logicalhistory:= []
logicalhistory:= ProcessStart(contents, Rest)
activeuserinput:= []

Loop,
{
	ClipBoardFunction()
	winwonder:=WinWonder()
	if (A_TimeIdle > 3000)
	{
		thisz++
		if (thisz == 1)
			GuiControl, AI:, Information, Done
		Sleep, % Notactive
		Continue
	}
	if (winwonder == "False")
	{
		SpellChecker(0)
		Sleep, % Notactive
		Continue
	}
	check:=GetControl("GetKeeper")
	usersentence:=GetControl("RowText")
	if (recordkeeper == "")
		recordkeeper:=% usersentence
	if (recordkeeper != usersentence)
	{
		Doppler(usersentence, recordkeeper)
		recordkeeper:=% usersentence
	}
	getuserinput:= GetControl("Text")
	activeuserinput:=ReturnLineArray(getuserinput, "user")
	historylastline:= GetLineCount(logicalhistory)
	activeuserlastline:= GetLineCount(activeuserinput)
	if (check == "7h151s@a#res37")
	{
		If (getuserinput == "")
		{
			Sleep, % Notactive
			Continue
		}
		GuiControl, AI:, WordKeeper, &not@a#rea1*sent3nc3
		contents:=HashContents(contents)
		logicalhistory:= ProcessStart(contents, Rest)
		Continue
	}
	if (usersentence != "")
	{
		if (activeuserlastline != historylastline)
		{
			logicallastlineaddition:=(activeuserlastline-historylastline)
			logicalhistory:= FixLogicalhistory_Array(logicalhistory, logicallastlineaddition) ; where last lines are being put in. and you will also want to function in lastline (Deleted_Line) to acompany the changes. if you are lagging ApplyLogicalChange().
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, logicallastlineaddition)
		}
		if (activeuserlastline == historylastline)
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, 0)
	}
	savecheck:= GetControl("AISave")
	if (savecheck == "Save_File")
	{
		historycount:=GetLineCount(logicalhistory)
		Loop, % historycount
		{
			x++
			sentences:= logicalhistory["linePos" x]
			StringReplace, sentences, sentences, (softReturn), \|/softReturn\|/, ALL
			StringReplace, sentences, sentences, (hardReturn), \|/CR+LF\|/, ALL
			FileContents:=% FileContents sentences
		}
		FileMove, % Temp, % TempBack, 1
		FileAppend, % FileContents, % Temp, UTF-8
		GuiControl,AI:, AISave, Don't Save
	}
}
Return

~LCtrl::
thiskeystate:= GetKeyState("LCtrl", P)
if (thiskeystate != 0)
{
	Loop,
	{
		GuiControlGet, EnableCC, AI:, EnableCC
		GuiControlGet, EnableVV, AI:, EnableVV
		CtrlC := Chr(3)
		if (EnableVV == 1)
		{
			CtrlVV:= (Chr(22) . Chr(22))
			CtrlVVV:= (Chr(22) . Chr(22) . Chr(22))
			ClipBoardFunction()
			GuiControlGet, ClipBoard2, Word:, ClipBoard2
			GuiControlGet, ClipBoard3, Word:, ClipBoard3
		}
		Input, userinput, L3 T0.75 M ; this has a 0.75 second timer... That feels a little natural. however on the person to person scale this might need adjusted.
		if (EnableVV == 1)
		{
			if (userinput == CtrlVV)
			{
				saveClip:=% ClipBoard
				ClipBoard:=% Clipboard2
				Send, ^v
				ClipBoard:=% saveClip
				saveClip:=
			}
			else if (userinput == CtrlVVV)
			{
				saveClip:=% ClipBoard
				ClipBoard:=% Clipboard3
				Send, ^v
				ClipBoard:=% saveClip
				saveClip:=
			}
		}
		else if ((userinput == CtrlC CtrlC)&&(EnableCC == 1))
		{
			logicalhistorylastline:= GetLineCount(logicalhistory)
			Loop, % logicalhistorylastline
			{
				thisx++
				saveline:= logicalhistory["linePos" thisx]
				saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
				saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
				thesecontents.= saveline
			}
			thesecontents:= SpecialReplace(thesecontents)
			MsgBox, % "The edit fields are ready to be sent. It autosends after this message. After you learn how this works you can delete this messge on line 237. Make sure the place you want your text sent is +lastfound"
			Send, % thesecontents
			thisx:=
			thesecontents:=
		}
		else if (userinput == CtrlC)
			Send, ^c
		else
			Send, ^%userinput%
		thiskeystate:= GetKeyState("LCtrl", P)
		if (thiskeystate == 0)
			Break
	}
}
Return
	
ClipBoardFunction()
{
	if ((ClipBoard != "")&&(ClipBoard != ClipBoard2))
	{
		if (ClipBoard2 == "" )
			ClipBoard2:=% ClipBoard1
		else if (ClipBoard2 != "")
		{
			ClipBoard3:=% ClipBoard2
			ClipBoard2:=% ClipBoard
		}
	}
	if (ClipBoard2 != "" )
		GuiControl,Word:, ClipBoard2, % ClipBoard2
	if (ClipBoard3 != "" )
		GuiControl,Word:, ClipBoard3, % ClipBoard3
	Return
}

$Backspace::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Backspace}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Backspace}
	}
	Return
}
else
	Send, {Backspace}
Return

$Space::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Space}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Space}
	}
	Return
}
else
	Send, {Space}
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		check:=GetControl("GetKeeper")
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 2)
				userword:=% chec
		}
		str:= StrLen(userword)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
	}
	else
	{
		Send, `t
	}
	Return
}
else
	Send, `t
Return

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	GuiControlGet, AutoEdit, AI:, AutoEdit
	If (AutoEdit == 1)
	{
		logicalhistorylastline:= GetLineCount(logicalhistory)
		Loop, % logicalhistorylastline
		{
			thisx++
			saveline:= logicalhistory["linePos" thisx]
			saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
			saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
			thesecontents.= saveline
		}
		thesecontents:= SpecialReplace(thesecontents)
		GuiControlGet, wintitle, AI:, WindowControl, Edit5
		if (wintitle == "")
		{
			MsgBox, Please lock to a window first
			Return
		}
		WinActivate, % wintitle
		WinWait, % wintitle
		Send, % thesecontents
		FileMove, % Temp, % TempBack, 1
		FileAppend, "", % Temp, UTF-8
		GuiControl, AI:, Edit4,
		logicalhistory:=[]
		thisx:=
		thesecontents:=
	}
	else if (AutoEdit == 0)
	{
		ButtonCountCheck:= GetControl("ButtCount")
		PressCount:=GetButtonCount(ButtonCountCheck)
		PressCount++
		WhichButtonCount:=% PressCount ",ShiftEnter"
		GuiControl, AI:, ButtonCountCheck, % WhichButtonCount
		KeyWait, Backspace, U
		GetButton_Count()
	}
}
Return

~Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	GuiControlGet, AutoEdit, AI:, AutoEdit
	If (AutoEdit == 1)
	{
		logicalhistorylastline:= GetLineCount(logicalhistory)
		Loop, % logicalhistorylastline
		{
			thisx++
			saveline:= logicalhistory["linePos" thisx]
			saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
			saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
			thesecontents.= saveline
		}
		thesecontents:= SpecialReplace(thesecontents)
		GuiControlGet, wintitle, AI:, WindowControl, Edit5
		if (wintitle == "")
		{
			MsgBox, Please lock to a window first
			Return
		}
		WinActivate, % wintitle
		WinWait, % wintitle
		Send, % thesecontents "+{Enter}"
		FileMove, % Temp, % TempBack, 1
		FileAppend, "", % Temp, UTF-8
		GuiControl, AI:, Edit4,
		logicalhistory:=[]
		thisx:=
		thesecontents:=
	}
	else if (AutoEdit == 0)
	{
		ButtonCountCheck:= GetControl("ButtCount")
		PressCount:=GetButtonCount(ButtonCountCheck)
		PressCount++
		WhichButtonCount:=% PressCount ",Enter"
		GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
		KeyWait, Backspace, U
		GetButton_Count()
	}
}
Return

SpecialReplace(thesecontents)
{
	fixedcharacters:= StrReplace(thesecontents, "!", "{!}")
	fixedcharacters:= StrReplace(fixedcharacters, "#", "{#}")
	fixedcharacters:= StrReplace(fixedcharacters, "+", "{+}")
	fixedcharacters:= StrReplace(fixedcharacters, "^", "{^}")
	fixedcharacters:= StrReplace(fixedcharacters, "{", "{{}") ; if this is done then output will be {{}
	fixedcharacters:= StrReplace(fixedcharacters, "}", "{}}") ; from the above if this is done output will be {{{}}
	fixedcharacters:= StrReplace(fixedcharacters, "{{{}}", "{{}")
	Sleep, 50
	Tabcontrol:= StrSplit(fixedcharacters, ["(hardReturn)", "(softReturn)"])
	for index, Tabs in Tabcontrol
	{
		IfinString, Tabs, % "`t" ; <----- it is assumed the editor you're using controls tab.
		{
			thiscount:= StrReplace(Tabs, "`t", "", thismany)
			thisstring:=% thiscount
			if (thismany != thatmany)
			{
				if (thismany > thatmany)
				{
					n:=(thismany-thatmany)
					thisbutton:=% "{Tab " n "}"
				}
				if (thismany < thatmany)
				{
					n:=(thatmany-thismany)
					thisbutton:=% "{Backspace " n "}"
				}
			}
		}
		IfNotInString, Tabs, % "`t"
		{
			if (thismany > 1)
				thisbutton:=% "{Backspace " n "}"
			else if (thismany == 1)
			{
				thismany:=0
				thisbutton:=% "{Backspace}"
			}
			else if (thismany == 0)
				thisbutton:=% ""
			thisstring:=% Tabs
		}
		thatmany:=% thismany
		edittext.= thisbutton thisstring
		thisbutton:= ""
	}
	edittext:= StrReplace(edittext, "[Enter]", "{Backspace}{Enter}")
	edittext:= StrReplace(edittext, "[ShiftEnter]", "{Backspace}+{Enter}")
	Return % edittext
}

EnableVV:
GuiControl, AI:, ControlInformation, This enables paste from second and third ClipBoard. {LCtrl}+vv and {LCtrl}+vvv. if clipboard2 or 3 sends acsii code
Return

SnapToWindow:
GuiControl, AI:, ControlInformation, This will place the Main Gui in one of 9 locations on the locked window.
Return

SnapToEditor:
GuiControl, AI:, ControlInformation, This will place the Main Gui in one of 9 locations on the editor. Notepad is Default.
Return

AutoEdit:
GuiControl, AI:, ControlInformation, On Enter ({Enter} or +{Enter} this button sends to your default editor if it's active and Clears the window.
Return

EnableCC:
GuiControl, AI:, ControlInformation, This activates {LCtrl}+cc when you press that (anywhere) ClipBoard is filled (main edit contents) and autosent to insert location.
Return

LocktoWindow:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This button locks the Gui to a running window. Just activate the window you want.
if (GetWindow == 1)
{
	WinGetActiveTitle, checkthistitle
	GuiControl, AI:, Edit5, Select a window to lock to.
	Loop,
	{
		WinGetActiveTitle, newtitletocheck
		if (newtitletocheck == "")
			Continue
		if (checkthistitle != newtitletocheck)
			Break
	}
	GuiControl, AI:, Edit5, % newtitletocheck
	GuiControl, Disable, Edit5
}
if (GetWindow == 0)
{
	GuiControl, AI:, Edit5,
	GuiControl, Enable, Edit5
}
Return

Lock:
GuiControl, AI:, ControlInformation, Information about the above controls
x++
LockMod:= Mod(x, 2)
if (LockMod == 1)
{
	GuiControl, AI:, WindowLabel, %A_Space%%A_Space%-`tAdd Window%A_Space%%A_Space%
	GuiControl, AI:Show, GroupControls
	GuiControl, AI:Show, Button8
	GuiControl, AI:Show, Button9
	GuiControl, AI:Show, Button10
	GuiControl, AI:Show, Button11
	GuiControl, AI:Show, Button12
	GuiControl, AI:Show, Button13
}
if (LockMod == 0)
{
	GuiControl,AI:, WindowLabel, %A_Space%%A_Space%+`tAdd Window%A_Space%%A_Space%
	GuiControl, AI:Hide, GroupControls
	GuiControl, AI:Hide, Button8
	GuiControl, AI:Hide, Button9
	GuiControl, AI:Hide, Button10
	GuiControl, AI:Hide, Button11
	GuiControl, AI:Hide, Button12
	GuiControl, AI:Hide, Button13 
}
Return

Default:
IniRead, Always, % Settings, AlwaysOnTop, Key1
if (Always != "ERROR")
	GuestOn:=% Always
IniRead, Directory, % Settings, Directory, Key1
if (Directory != "ERROR")
	MainDirectory:=% Directory
IniRead, loopxcount, % Settings, Looper, Key1
if (loopxcount != "ERROR")
{
	Loop, % loopxcount
	{
		IniRead, codex, % Settings, KeyCodes, Key%loopxcount%
		codexlist.=  codex "|"
		loopxcount--
	}
}
IniRead, loopycount, % Settings, DroppedCodeCount, Key1
if (loopycount != "ERROR")
{
	Loop, % loopycount
	{
		IniRead, codedrop, % Settings, DroppedCode, Key%loopycount%
		codeylist.= codedrop  "|"
		loopycount--
	}
}
Gui, Defaults:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Edit, y20 x85, Below are the default settings for the program.
Gui, Add, Text, x20, Default working directory:`t`n(place the full folder location.)`t
Gui, Add, Text, , Create test file parameters:`t`n(To add type one that doesn't exist.`t`n To remove select one from the list.)`t`nTo add more delimit by "|"
Gui, Add, Text, , Delimited words from create test file:`t`n(To add type one that doesn't exist.`t`n To remove select one from the list.)`t`nTo add more delimit by "|"
Gui, Add, Checkbox, x140 ym+210 vYesOrNo, Default AlwaysOnTop On
Gui, Add, Button, x310 ym+235 gDCancel, Cancel
Gui, Add, Button, wp hp yp x375 gDSave, Save
Gui, Add, Text, x120 ym+230 cRed, (Must click save to save changes!)`n  Must reload for directory change
if (MainDirectory != "")
	Gui, Add, Edit, xm+200 ym+45 w200 vDirectory, % MainDirectory
else
	Gui, Add, Edit, xm+200 ym+45 w200 vDirectory, % A_ScriptDir
Gui, Add, ComboBox, xm+200 ym+100 w200 vKodexList gListxChange, % codexlist
Gui, Add, ComboBox, xm+200 ym+165 w200 vKodeyList gListyChange, % codeylist
Gui, Margin, 20, 20
Gui, Show, , Defaults
Control, Disable ,, Edit1, Defaults
if (GuestOn == 1)
	GuiControl, Defaults:, Button1, 1
else if (GuestOn == 0)
	GuiControl, Defaults:, Button1, 0
else
	GuiControl, Defaults:, Button1, 1
Return

ListxChange:
Gui, Submit, NoHide
KodexList:= StrReplace(codexlist, KodexList, "")
GuiControl, Defaults:, KodexList, % KodexList
Return

ListyChange:
Gui, Submit, NoHide
KodeyList:= StrReplace(codeylist, KodeyList, "")
GuiControl, Defaults:, KodeyList, % KodeyList
Return

DCancel:
Gui, Defaults:Destroy
Return

DSave:
Gui, Submit, NoHide
IniDelete, % Settings, KeyCodes
IniDelete, % Settings, DroppedCode
IniDelete, % Settings, Directory
IniDelete, % Settings, AlwaysOnTop
IniDelete, % Settings, Looper
IniDelete, % Settings, DroppedCodeCount
IniWrite, % YesOrNo, % Settings, AlwaysOnTop, Key1
IniWrite, % Directory, % Settings, Directory, Key1
ControlGet, Kodex_List, List, , ComboBox1, Defaults
GuiControlGet, Personalizedx, , Edit3, Defaults
personalx:= StrReplace(Personalizedx, "|", "`n")
Kodex_List:=% (personalx "`n" . Kodex_List)
Kodex_List:= StrReplace(Kodex_List, "`n`n", "`n")
Loop, Parse, % Kodex_List, `n
{
	z++
	IniWrite, % z, % Settings, Looper, Key1
	IniWrite, % A_LoopField, % Settings, KeyCodes, Key%z%
}
ControlGet, Kodey_List, List, , ComboBox2, Defaults
GuiControlGet, Personalizedy, , Edit3, Defaults
personaly:= StrReplace(Personalizedy, "|", "`n")
Kodey_List:=% (personaly "`n" . Kodey_List)
Kodey_List:= StrReplace(Kodey_List, "`n`n", "`n")
Loop, Parse, % Kodey_List, `n
{
	w++
	IniWrite, % w, % Settings, DroppedCodeCount, Key1
	IniWrite, % A_LoopField, % Settings, DroppedCode, Key%w%
}
Return

AISave:
GuiControl,AI:, AISave, Save_File
Return
	
SusOnOff:
Suspend, Toggle
if (A_IsSuspended == 1)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOn
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOff
Return

Always:
WinSet, AlwaysOnTop, Toggle, AI
WinGet, ExStyle, ExStyle, AI
if (ExStyle == 0x00000180)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOff
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOn
Return
 
Timers:
Gui, Timers:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, y25, Rest Timer:`t`n(in seconds)
Gui, Add, Text, y75 xs, Window Not Active:`t`n(in milliseconds)
Gui, Add, Text, y125 xs, Process Loop timer:`t`n(in milliseconds)
Gui, Add, Edit, w250 r3 ys-15 -VScroll, This timer slows the script before it gets to the main loop function. It's used to help in processing the global function "Speller."
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the script when the it is not active.
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the main processing loop while typing. It's dependent on a difference created in the main edit control.
Gui, Add, Edit, ys xs+400 w50 y25
Gui, Add, UpDown, vRangeInSeconds Range1-50, 10
Gui, Add, Edit, ys xs+400 w50 y75
Gui, Add, UpDown, vRangeInMillisecondsOfActive Range1-1000, 500
Gui, Add, Edit, ys xs+400 w50 y125
Gui, Add, UpDown, vRangeInMillisecondsOfProcess Range1-100, 25
Gui, Add, Text, xm+10 ym+180, Select the above values to your personal preferences and click save to keep the changes.
Gui, Add, Text, xm+80 ym+215, (Note you have to restart the program to force the changes)
Gui, Add, Button, ym+210 xs+425 gSave, Save
Gui, Add, Button, ym+210 xs+370 gCancel, Cancel
Gui, Margin, 20, 50
Gui, Show, h250 w500, Timers
Control, Disable ,, Edit1, Timers
Control, Disable ,, Edit2, Timers
Control, Disable ,, Edit3, Timers
Return

Reload:
^r::
Reload
Return

Cancel:
Gui, Timers:Destroy
Return

Save:
Gui, Submit, NoHide
RangeInSeconds:=(RangeInSeconds*1000)
IniWrite, % RangeInSeconds, % Settings, Timers, Key1
IniWrite, % RangeInMillisecondsOfActive, % Settings, Timers, Key2
IniWrite, % RangeInMillisecondsOfProcess, % Settings, Timers, Key3
Gui, Timers:Destroy
Return

FileSelected: 
Gui, Submit, NoHide
GuiControl, AI:, Information, Working..
FileRead, contents, % FileSelected
if (ChangeType == "Get Variables")
{
	if (Gui == 1)
		filters.= "[Filter='Gui'],"
	if (Explicit == 1)
		filters.= "[Filter='explicit'],"
	if (ImplicitExplicit == 1)
		filters.= "[Filter='implicit-explicit'],"
	wi:=
	if (filters != "")
	{
		Control, Disable ,, ListBox1, AI
		Control, Disable ,, Edit3, AI
		contents:= GetVariables(contents, filters)
		GuiControl, AI:, Words,
		GuiControl, AI:, Words, % contents
		whichbutton:=GetControl("ButtCount")
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					thisbutton:= "\|/SoftReturn\|/"
				if (butt == "Enter")
					thisbutton:= "\|/hardReturn\|/"
				if (butt == "Unknown")
					thisbutton:= " \|/SoftReturn\|/"
			}
		}
		StringReplace, contents, contents, `n, %thisbutton%, ALL
		FileMove, % Temp, % TempBack, 1
		FileAppend, % contents, % Temp, UTF-8
	}
}
else if (ChangeType == "Get Function") ;ChangeType gChangeType, Get Variables||Get Function|Create Test File
{
	ControlGet, row, CurrentLine, , Edit3, AI
	ControlGet, rowtext, Line, % row, Edit3, AI
	if (rowtext == "")
	{
		MsgBox, Please insert the function label name
		Return
	}
	if (AssociateV == 1)
		thisignore:=% "Do_Not"
	function:=GetThisFunction(rowtext, thisignore, contents)
	GuiControl, AI:, Words, % function
	FileMove, % Temp, % TempBack, 1
	FileAppend, % function, % Temp, UTF-8
}
else if (ChangeType == "Create Test File")
{
	thesecontents:= GetTestFile(contents)
	Loop, Parse, % thesecontents, `n
	{
		if (A_LoopField == "")
			Continue
		if (A_LoopField == "Return")
			thisfile:=% thisfile A_LoopField "`n`n"
		else if (A_LoopField != "Return")
			thisfile:=% thisfile A_LoopField "`n"
	}
	FileMove, Test.ahk, % TempBack, 1
	FileAppend, % thisfile, *Test.ahk, UTF-8
}
GuiControl, AI:, Button2, 0
GuiControl, AI:, Button3, 0
GuiControl, AI:, Button4, 0
GuiControl, AI:, Button5, 0
GuiControl, AI:, Edit3,
GuiControl, AI:, WordKeeper, 7h151s@a#res37
GuiControl, AI:, Information, Done
Return

GetTestFile(data)
{
	IniRead, loopcount, % Settings, Looper, Key1
	if (loopcount != "ERROR")
	{
		Loop, % loopcount
		{
			IniRead, codex, % Settings, KeyCodes, Key%loopcount%
			codexlist.= codex "`n"
			loopcount--
		}
		IniRead, loopcount, % Settings, DroppedCodeCount, Key1
		if (loopcount != "ERROR")
		{
			Loop, % loopcount
			{
				IniRead, codedrop, % Settings, DroppedCode, Key%loopcount%
				codeylist.= codedrop "`n"
				loopcount--
			}
		}
		data:= StrReplace(data, "`r", "")
		Loop, Parse, % data, `n
		{
			y++
			codestring:=
			line:=% A_LoopField
			sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
			for index, sentence in sentences
			{
				if (index == 1)
					codestring:=% sentence
				if (index == 2)
					commentstring:=% sentence
			}
			keycodex:= StrReplace(codestring, ",",  " ")
			keycodex:= StrReplace(keycodex, "  ", " ")
			keycodex:= StrReplace(keycodex, "  ", " ")
			keycodex:=% Trim(keycodex)
			thesewords:= StrSplit(keycodex, A_Space)
			for index, keycode in thesewords
				if (index == 1)
					keycodex:=% keycode
			IfinString, codeylist, % keycodex
				codestring:=% ""
			IfinString, codexlist, % keycodex
			{
				filecontents:=% filecontents codestring "`n"
				codestring:=% ""
			}
			codestring:= CodeStringCheck(codestring)
			if (codestring != "")
			{
				IfinString, codestring, Return
				{
					if (thischecker == 1)
						IfNotInString, codestring, % "`t"
							thischecker:= 0
					codestring:=% ""
				}
				IfInString, codestring, Global
				{
					filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfInString, codestring, Gui
				{
					IfinString, codestring, Show
						filecontents:=% filecontents codestring "`nReturn`n`n"
					else
						filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfInString, codestring, Menu
				{
					filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfinString, codestring, :
				{
					IfInString, codestring, Gui
						codestring:=% ""
					if (thischecker != 1)
					{
						thischecker:= 1
						if (x != 1)
							x:=1
					}
					filecontents:=% filecontents codestring "`nReturn`n`n"
					codestring:=% ""
				}
				IfInString, filecontents, % codestring
					codestring:=% ""
			}
		}
	}
	else if (loopcount == "ERROR")
	{
		MsgBox, 70, Be sure before you continue., In the following message boxes you will be shown the beginning of your code. This will omit the comments and anything past the first comma as demiliters for your test.ahk creation. each type will be added to the Ini file settings and read for your future creations. You can always change this setting by selecting default in the default menu.`n`n**Also note This does skip continuation sections.
		IfMsgBox Continue
		{
			data:= StrReplace(data, "`r", "")
			Loop, Parse, % data, `n
			{
				y++
				line:=% A_LoopField
				sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
				for index, sentence in sentences
				{
					if (index == 1)
						codestring:=% sentence
					if (index == 2)
						commentstring:=% sentence
				}
				codestring:= CodeStringCheck(codestring)
				if (codestring != "")
				{
					IfinString, codestring, Return
					{
						if (thischecker == 1)
							IfNotInString, codestring, % "`t"
								thischecker:= 0
						codestring:=% ""
					}
					IfInString, codestring, Global
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, codestring, Gui
					{
						IfinString, codestring, Show
							filecontents:=% filecontents codestring "`nReturn`n`n"
						else
							filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, codestring, Menu
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfinString, codestring, :
					{
						IfInString, codestring, Gui
							codestring:=% ""
						if (thischecker != 1)
						{
							thischecker:= 1
							if (x != 1)
							{
								x:=1
								MsgBox, 32, g-Sublabels, sublabels are automatically added
							}
						}
						filecontents:=% filecontents codestring "`nReturn`n`n"
						codestring:=% ""
					}
					keycodex:= StrReplace(codestring, ",",  " ")
					keycodex:= StrReplace(keycodex, "  ", " ")
					keycodex:= StrReplace(keycodex, "  ", " ")
					keycodex:=% Trim(keycodex)
					thesewords:= StrSplit(keycodex, A_Space)
					for index, keycode in thesewords
						if (index == 1)
							keycodex:=% keycode
					IfinString, thisignoredlist, % keycodex
						codestring:=% ""
					IfinString, thisgottenlist, % keycodex
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, filecontents, % codestring
						codestring:=% ""
					if (codestring != "")
					{
						MsgBox, 36, Do you want to add this line?, % keycodex "`n`nFound on line: " y "`n`npress yes if you want to add the first (word) of this line to your delimiter fields."
						IfMsgBox Yes
						{
							z++
							IniWrite, % z, % Settings, Looper, Key1
							IniWrite, % keycodex, % Settings, KeyCodes, Key%z%
							thisgottenlist.= keycodex
							filecontents:=% filecontents codestring "`n"
						}
						else IfMsgBox No
						{
							w++
							IniWrite, % w, % Settings, DroppedCodeCount, Key1
							IniWrite, % keycodex, % Settings, DroppedCode, Key%w%
							thisignoredlist.= codestring " "
							Continue
						}
					}
				}
			}
		}
	}
	Return % filecontents
}

CodeStringCheck(codestring)
{
	IfInString, codestring, GuiControl
		codestring:=% ""
	IfinString, codestring, `t
		codestring:=% ""
	IfInString, codestring, Global
		Return % codestring
	IfInString, codestring, Gui ; It's likely a user may place any of the below special characters in a gui 4th parameter.
		Return % codestring
	IfInString, codestring, =
		codestring:=% ""
	IfInString, codestring, ( ;)
		codestring:=% ""
	IfInString, codestring, {
		codestring:=% ""
	IfInString, codestring, }
		codestring:=% ""
	IfInString, codestring, `%
		IfNotInString, codestring, SetWorkingDir
			codestring:=% ""
	IfinString, codestring, Loop
		codestring:=% ""
	IfinString, codestring, else
		codestring:=% ""
	IfinString, codestring, if%A_Space%
		codestring:=% ""
	IfinString, codestring, ::
		codestring:=% ""
	Return % codestring
}

GetThisFunction(function, get, data)
{
	function:= StrReplace(function, "`r`n", "")
	function:= StrReplace(function, "`n", "")
	functionlength:=StrLen(function)
	data:= StrReplace(data, "`r", "")
	function:= GetFunction(data, functionlength, function)
	thisfoundfunction.= function "`n"
	function:=""
	if (get == "Do_Not")
	{
		Loop,
		{
			Loop, Parse, % thisfoundfunction, `n
			{
				IfInString, A_LoopField, =
					IfInString, A_LoopField, (
					{
						foundpossible:= FunctionLabelGet(A_LoopField)
						Trim(foundpossible)
						IfNotInString, foundpossible, % A_Space
							IfNotInString, thesefound, % foundpossible
							{
								functionlength:=StrLen(foundpossible)
								function:= GetFunction(data, functionlength, foundpossible)
							}
						if (function != "")
							thisfoundfunction.= function "`n"
					}
				if (function != "")
					function:=
				thesefound.= foundpossible ", "
			}
			IfNotInString, thesefoundpast, % thesefound
				thesefoundpast.= thesefound
			IfinString, thesefoundpast, % thesefound
				Break
		}
	}
	Return % thisfoundfunction
}

GetFunction(data, functionlength, function)
{
	Loop, Parse, % data, `n
	{
		if (thisfunction == "")
		{
			linesubstring:= SubStr(A_LoopField, 1, functionlength)
			if (function == linesubstring)
			{
				thisfunction:= % A_LoopField "`n"
				z:=1
			}
		}
		else if (thisfunction != "")
		{
			thisfunction.= A_LoopField "`n"
			if (A_LoopField == "{")
				x++
			if (A_LoopField == "}")
				x--
			if (z == 1)&&(A_LoopField != "{")
				thisfunction:= ""
			z:=0
		}
		if ((x == 0)&&(thisfunction != ""))
		{
			thisfoundfunction:= % thisfunction
			thisfunction:= ""
		}
	}
	Return % thisfoundfunction
}

FunctionLabelGet(line)
{
	thissplitfunction:= StrSplit(line, "= ")
	for index, thissplit in thissplitfunction
		if (index == 2)
			thispart:=% thissplit
	thispartsplit:= StrSplit(thispart, "(") ;"
	for index, function in thispartsplit
		if (index == 1)
			Return % function
	Return
}

ChangeType:
Gui, Submit, NoHide
if (ChangeType == "Get Variables")
{
	GuiControl, AI:Text, Results, Get variables`n(Filter results by Checkbox)
	GuiControl, AI:Hide, FunctionName
	GuiControl, AI:Hide, FunctionLabel
	GuiControl, AI:Hide, Button2
	GuiControl, AI:Hide, Edit2
	GuiControl, AI:Show, Button5
	GuiControl, AI:Show, Button3
	GuiControl, AI:Show, Button4
}
if (ChangeType == "Get Function")
{
	GuiControl, AI:Text, Results, Get Function`n(Select a file to get a function)
	GuiControl, AI:Hide, Button5
	GuiControl, AI:Hide, Button3
	GuiControl, AI:hide, Button4
	GuiControl, AI:Show, FunctionName
	GuiControl, AI:Show, FunctionLabel
	GuiControl, AI:Show, Button2
	GuiControl, AI:Hide, Edit2
	GuiControl, Focus, Edit3
}
if (ChangeType == "Create Test File")
{
	GuiControl, AI:Text, results, Create a Test File`n(Create a functionless test ahk)
	GuiControl, AI:Hide, Button5
	GuiControl, AI:Hide, Button3
	GuiControl, AI:hide, Button4
	GuiControl, AI:hide, FunctionName
	GuiControl, AI:hide, FunctionLabel
	GuiControl, AI:hide, Button2
	GuiControl, AI:Show, Edit2
}
Return

GetVariables(filecontents, filters)
{
	Loop, Parse, % filecontents, `r
	{
		linenumber++
		line:=% A_LoopField
		sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
		for index, sentence in sentences
		{
			if (index == 1)
				codestring:=% sentence
			if (index == 2)
				commentstring:=% sentence
		}
		codestring:= RemoveCertainChars(codestring, "Start")
		IfInString, codestring, Dll
			Continue
		IfInString, codestring, Box`,
			Continue
		IfInString, codestring, StringReplace
			Continue
		IfInString, codestring, RegEx
			Continue
		IfInString, codestring, Ini
			Continue
		IfInString, codestring, =
		{
			IfInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Percent", linenumber)
				IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
			}
			else IfNotInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
			IfInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Quotes", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring 
			}
			else IfNotInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
		}
		else IfInString, codestring, [percent]
		{
			variablestring:= GetVariableString(codestring, "Percent", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring
		}
		else IfInString, codestring, [quotes]
		{
			variablestring:= GetVariableString(codestring, "Quotes", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring "found in quotes 2`n"
		}
		IfInString, codestring, Gui
			IfInString, codestring, `,
				IfInString, codestring, %A_Space%v
				{
					variablestring:= GetVariableString(codestring, "Gui", linenumber)
					IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
				}
	}
	thesefilters:=StrSplit(filters, ",")
	for index, filter in thesefilters
	{
		if (index == 1)
		{
			if (filter == "")
				Continue
			firstfilter:=% filter
		}
		if (index == 2)
		{
			if (filter == "")
				Continue
			secondfilter:=% filter
		}
		if (index == 3)
		{
			if (filter == "")
				Continue
			thirdfilter:=% filter
		}
	}
	Loop, Parse, % variablelist, `n
	{
		if (A_LoopField == "")
			Continue
		repeatcheck:= StrSplit(A_LoopField, "[thissplitter]")
		for index, repeat in repeatcheck
		{
			if (index == 1)
			{
				IfNotInString, completedlist, % repeat
					thischeck:=% repeat
				IfInString, completedlist, % repeat
				{
					checking:= MakeSure(completedlist, repeat)
					if (checking == "True")
						Continue
					else if (checking == "False")
						thischeck:=% repeat
				}
			}
			if (index == 2)
			{
				if (firstfilter != "")
					IfInString, repeat, % firstfilter
					{
						applyfilters:= StrSplit(repeat, firstfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
				if (secondfilter != "")
					IfInString, repeat, % secondfilter
					{
						applyfilters:= StrSplit(repeat, secondfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
				if (thirdfilter != "")
					IfInString, repeat, % thirdfilter
					{
						applyfilters:= StrSplit(repeat, thirdfilter)
						for index, apply in applyfilters
						{
							information.= apply
						}
					}
			}
		}
		if (information == "")
			Continue
		if (thischeck != "")
		{
			checklist:=% Trim(thischeck) "`n" Trim(information) "`n"
			IfNotInString, completedlist, % checklist
				completedlist.= checklist
		}
	}
	completedlist:= RemoveCertainChars(completedlist, "End")
	Return % completedlist
}

MakeSure(listinprogress, checkword)
{
	Loop, Parse, % listinprogress, `n
	{
		if (checkword == A_LoopField)
			Return % "True"
	}
	Return % "False"
}

GetVariableString(codestring, whichone, linenumber)
{
	if (whichone == "Gui")
	{
		variablestrings:= StrSplit(codestring, ",")
		for index, variablestring in variablestrings
		{
			if (index > 4)
				Continue
			IfInString, variablestring, %A_Space%v
				thisvariablestring:=% variablestring
		}
		variablestring:= StrSplit(thisvariablestring, A_Space)
		for index, variable in variablestring
		{
			thisvariableletter:= SubStr(variable, 1, 1)
			if (thisvariableletter == "v")
				Return % variable "[thissplitter] Gui variable[Filter='Gui'] Line number is found at: " linenumber "`n"
		}
		Return % variable "[thissplitter] Gui variable Line number is found at: " linenumber "`n"
	}
	if (whichone == "Quotes")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [quotes]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		variablestrings:= StrSplit(codestring, "[quotes]")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 0)
				IfNotInString, variablestring, %A_Space%
					IfNotInString, variables, % variablestring
						variables.= "[quotes]" variablestring "[quotes][thissplitter] explicit[Filter='explicit'] variable Line number is found at: " linenumber "`n"
		}
		Return % variables
	}
	if (whichone == "Percent")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [percent]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		IfInString, codestring, `,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					IfInString, variablestring, [percent]
						IfNotInString, variablestring, =
							IfInString, variablestring, A_Space
								variables.= variablestring "[thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		IfNotInString, codestring, `,
		{
			IfInString, codestring, =
			{
				variablestrings:= StrSplit(codestring, "=")
				for index, variablestring in variablestrings
				{
					if (index == 1)
					{
						variables:= StrSplit(variablestring, A_Space)
						for index, variable in variables
							thisvariable:=% variable
					}
					if (index == 2)
						codestring:=% variablestring
				}
			}
			variablestrings:= StrSplit(codestring, "[percent]")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					variables.= "[percent]" variablestring "[percent][thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		if (thisvariable != "")
			variables.= thisvariable "[thissplitter]implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
		Return % variables
	}
	if (whichone == "Equals")
	{
		variablestrings:= StrSplit(codestring, "=")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 1)
				IfNotInString, variablestring, [quotes]
				{
					thisvariablestring:= StrSplit(variablestring, A_Space)
					for index, thisvariable in thisvariablestring
					{
						variable:=% thisvariable "[thissplitter] implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
					}
				}
		}
		Return % variable
	}
	Return % "Not Found"
}

RemoveCertainChars(string, special)
{
	if (special == "Start")
	{
		StringReplace, string, string, ", [quotes], ALL ; "
		StringReplace, string, string, `%%A_Space%, [percent], ALL
		StringReplace, string, string, `%, [percent], ALL
		StringReplace, string, string, %A_Space%:, :, ALL
		StringReplace, string, string, :=, =, ALL
		StringReplace, string, string, ==, =, ALL
		StringReplace, string, string, >, =, ALL
		StringReplace, string, string, <, =, ALL
		StringReplace, string, string, %A_Space%!=, =, ALL
		StringReplace, string, string, =%A_Space%, =, ALL
		StringReplace, string, string, %A_Space%=, =, ALL
		StringReplace, string, string, ), , ALL
		StringReplace, string, string, (, , ALL ;)
		StringReplace, string, string, `t, , ALL
	}
	if (special == "End")
	{
		StringReplace, string, string, [quotes], ", ALL ; "
		StringReplace, string, string, [percent], `%, ALL
		StringReplace, string, string, `,, , ALL
	}
	Return % string
}

GetButton_Count()
{
	Loop,
	{
		ButtonCountCheck:= GetControl("ButtCount")
		if (ButtonCountCheck != OldButtonCountCheck)
		{
			OldCount:=% Count
			OldButton:=% Button
			Sleep, 500
			ButtonCount_Split:= StrSplit(ButtonCountCheck, ",")
			For Index, ButtCount in ButtonCount_Split
			{
				if (Index == 1)
					Count:=% ButtCount
				if (Index == 2)
					Button:=% ButtCount
			}
		}
		else if (ButtonCountCheck == OldButtonCountCheck)
			Break
		if ((Button != OldButton)&&(Count > 1))
			Break
		OldButtonCountCheck:=% ButtonCountCheck
	}
	if (Button == OldButton)
	{
		ButtonCountReturn:=% Count "," Button
		GuiControl,AI:, ButtonCountCheck, % "0," Button
	}
	if (Button != OldButton)
	{
		NewCount:=% Count-OldCount
		GuiControl,AI:, ButtonCountCheck, % NewCount "," Button
		ButtonCountReturn:=% OldCount "," OldButton
	}
	Return
}

ApplyLogicalChange(activeuserinput, logicalhistory, numberofdifferences)
{
	x:= 0
	newhistoryrecord:=[]
	activeuserinputlastline:= GetLineCount(activeuserinput)
	logicalhistorylastline:= GetLineCount(logicalhistory)
	LastLine:= logicalhistory["linePos" logicalhistorylastline]
	Loop, % activeuserinputlastline
	{
		record:=
		x++ ; a lagged y variable needed to stagger history.
		occurenceuser:= activeuserinput["linePos" x]
		if (y > 0)
		{
			y:=(x-z) ; this will be an opposite staggered y (x+z) for deleted lines.
			historyrecord:= logicalhistory["linePos" y]
		}
		else
			historyrecord:= logicalhistory["linePos" x] ; even though the line now isn't right doesn't mean next time it won't be.
		splithistoryrecord:= StrSplit(historyrecord, ["(hardReturn)", "(softReturn)"])
		for index, splithistory in splithistoryrecord
		{
			if (Index == 1)
				record:= % splithistory
		}
		if ((occurenceuser != record)&&(numberofdifferences != 0)) ; the number of occurences go negative when lines get deleted... I haven't updated the below else for that yet.
		{
			LastLine:= logicalhistory["linePos" logicalhistorylastline] ; if a user is lagging the array make sure you are putting in last lines right.
			if ((LastLine == "(softReturn)")||(LastLine == "(hardReturn)")) ; the last line shouldn't be any other value.
			{
				z++ ; a z variable making sure we don't lose y and holding the number of occurences.
				if (z == 1) ; there's not enough time to add different enters in different spots (meaning the user couldn't add enough enters in the time this will be done).
					y:=% x
				IfInString, LastLine, (softReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
				IfInString, LastLine, (hardReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
				numberofdifferences--
				logicalhistorylastline--
			} ; the likely answer is a deleted line in occurenceuser. we need to add to the numberofdifferences. I'll also need to update this in the future for the array.
			else
				numberofdifferences++
		}
		else if ((occurenceuser != record)&&(numberofdifferences == 0)) ; meaning user has updated a line with a new record
		{
			newhistoryrecord["linePos" x]:= occurenceuser
			IfInString, record, (softReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
			IfInString, record, (hardReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
		} ; z from above holds all change counts. y from above holds the history record line back. technically y can equal x-z or just y++. I think for greater clarity it should be x-z because a user may choose to purposely lag the logicalhistoryarray Change function. Basically this function can be implimented at will as long as the keys are being kept up with and added to the historyarray in the main loop (of course that might also come with logical array issues).
		else if ((occurenceuser == record)&&(numberofdifferences == 0))
			newhistoryrecord["linePos" x]:= record
	}
	check:=GetControl("GetKeeper")
	if (check == "7h151s@a#res37")
		Return
	Return % newhistoryrecord ; There has been many different statements on using the % after Return or in ":=" as an operorator (it technically doesn't need to be done and can cause issues if done improperly). I use it because honestly it's like my signature to my work.
}

Doppler(usersentence, historysentence)
{
	livewords:=[]
	pastwords:=[]
	check:=GetControl("GetKeeper")
	if (check == "&not@a#rea1*sent3nc3")
	{
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			livewords["wordPos" key]:= userwords
		}
		historysplit:=StrSplit(historysentence, A_Space)
		for key, historywords in historysplit
		{
			pastwords["wordPos" key]:= historywords
		}
		usercount:=GetLineCount(livewords)
		historycount:= GetLineCount(pastwords)
		Loop, % usercount
		{
			x++
			userword:=livewords["wordPos" x]
			historyword:=pastwords["wordPos" x]
			userwordlength:=StrLen(userword)
			historywordlength:= StrLen(historyword)
			if ((userword != historyword)||(historycount < x))
				GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		}
		StringReplace, userword, userword, historyword, , ALL
	}
	else if (check != "&not@a#rea1*sent3nc3")
	{
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 1)
				historyword:=% chec
			if (index == 2)
				ouserword:=% chec
			if (index == 3)
				x:=% chec
		}
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			if (key == x)
				userword:=% userwords
		}
		GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		StringReplace, userword, userword, historyword, , ALL
	}
	userwordlength:=StrLen(userword)
	if (userwordlength < 2)
	{
		GuiControl, AI:, Information, Working...
		SpellChecker(0)
	}
	if (userwordlength > 3)
	{
		GuiControl, AI:, Information, Working.
		ourwords:=WordCheck(userword, userwordlength)
		if (ourwords == "")
			SpellChecker(0)
		else if (ourwords != "")
		{
			SpellChecker(userwordlength)
			GetControl(ourwords)
		}
	}
	Return
}

FixLogicalhistory_Array(historyarray, howmanylines)
{
	lastline:= GetLineCount(historyarray)
	whichbutton:= GetControl("ButtCount")
	Loop, % howmanylines
	{
		lastline++
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					historyarray["linePos" lastline]:= "(softReturn)"
				if (butt == "Enter")
					historyarray["linePos" lastline]:= "(hardReturn)"
			}
		}
	}
	Return % historyarray
}

ReturnLineArray(lines, user)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/SoftReturn\|/", "\|/userReturns\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

GetButtonCount(pressed)
{
	pressing:= StrSplit(pressed, ",")
	For Index, press in pressing
		if (Index == 1)
			Return % press
}

FindingRealLineLOL(occurenceuser, rowbefore, thisrow)
{
	IfInString, occurenceuser, %rowbefore%
	{
		rowlength:= StrLen(rowbefore)
		occurencelength:= StrLen(occurenceuser)
		subtractedlength:=(occurencelength-rowlength)
		thisstring:= SubStr(occurenceuser, subtractedlength, occurencelength)
		if (thisstring == rowbefore)
		{
			IfInString, occurenceuser, %thisrow%
				Return % "Found"
			IfNotInstring, occurenceuser, %thisrow%
				Return % "NextRow"
		}
	}
	if (rowbefore == "NextRow")
		IfInString, occurenceuser, %thisrow%
			Return % "Found"
	Return % "NotFound"
}

ProcessStart(contents, Rest)
{
	logicalhistory:= []
	WinSet, Transparent, 0, Words
	history:= GetHistory()
	logicalhistory:= ReturnLineArray(history, user)
	Control, Disable ,, Edit4, AI
	GuiControl, AI:, Edit4, % contents
	Sleep, % Rest
	Control, Enable ,, Edit4, AI
	GuiControl, AI:, Information, Done
	Control, Enable ,, ListBox1, AI
	Return % logicalhistory
}

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	if (n > 3)
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	if (n == 0)
		WinSet, Transparent, 0, Words
	WinGet, visible, Transparent, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	Return
}
Return

ReturnClearDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			hinput:= harray["linePos" x]
			hsplit:= StrSplit(hinput, ["(hardReturn)", "(softReturn)"])
			for Index, h in hsplit
			{
				if (Index == 1)
					checkh:= % h
			}
			uinput:= uarray["linePos" x]
			StringReplace, uinput, uinput, (softReturn), , ALL
			StringReplace, uinput, uinput, (hardReturn), , ALL
			l_checkh:= StrLen(checkh)
			l_uinput:= StrLen(uinput)
			if (uinput != checkh)
				Return % x
			if (l_checkh != l_uinput)
				Return % x
			if (x == v)
				Break
			checkh:=
		}
		Return % "0"
	}
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return % "True"
	}
}

GetLineCount(arraycount)
{
	LastLine:=0
	for Index, count in arraycount
		++LastLine
	Return % LastLine
}

GetControl(FocTex)
{
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, Edit3
	ControlGet, row, CurrentLine, , Edit3, AI
	ControlGet, rowtext, Line, % row, Edit3, AI
	GuiControlGet, Word, Words:, Listbox1
	StringReplace, text, text, `n, \|/userReturns\|/, ALL
	GuiControlGet, ButtonCountCheck, AI:, ButtonCountCheck
	GuiControlGet, Save_File, AI:, AISave
	GuiControlGet, DopplerGet, AI:, WordKeeper
	if (FocTex == "RowText")
		Return % rowtext
	if (FocTex == "GetKeeper")
		Return % DopplerGet
	if (FocTex == "AISave")
		Return % Save_File
	if (FocTex == "ButtCount")
		Return % ButtonCountCheck
	if (FocTex == "Row")
		Return % row
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	GuiControl, Words:, Listbox1, | 
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
	Return
}

HashContents(contents)
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, \|/CR+LF\|/, `n, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, `n, ALL
	Return % contents
}

GetHistory()
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, `r`n,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, (softReturn)\|/SoftReturn\|/, ALL
	StringReplace, contents, contents, \|/CR+LF\|/,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, (softReturn)\|/SoftReturn\|/, ALL
	Return % contents
}

RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitapp

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 20 Dec 2023, 03:21

A bit more easier said than done... After ironing out a few more issues I found and getting the window to behave as I mentioned... My eyes hurt because of the color tones of the window. I had to change that. It seem a little less painful on the eyes now.

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability. ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
#InstallkeybdHook
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
Global Settings:= % Cache "\Settings.ini"
IniRead, Directory, % Settings, Directory, Key1
if (Directory != "ERROR")
	SetWorkingDir %Directory%
else
	SetWorkingDir %A_ScriptDir% 
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)
IniRead, Editor, % Settings, Editor, Key1
if (Editor == "ERROR")
	Editor:=% "Notepad.exe"
IniRead, Rest, % Settings, Timers, Key1
If (Rest == "ERROR")
{
	IniWrite, 10000, % Settings, Timers, Key1
	Rest:= 10000
}
IniRead, Notactive, % Settings, Timers, Key2
if (Notactive == "ERROR")
{
	IniWrite, 500, % Settings, Timers, Key2
	Notactive:= 500
}
IniRead, NoDif, % Settings, Timers, Key3
if (NoDif == "ERROR")
{
	IniWrite, 25, % Settings, Timers, Key3
	NoDif:= 25
}
IniRead, Always, % Settings, AlwaysOnTop, Key1
if (Always != "ERROR")
	GuestOn:=% Always

Loop, Files, *.ahk, F R
{
	IfInString, A_LoopFileName, @
		Continue
	IfNotInString, wi, % A_LoopFileName
		wi=%wi%%A_LoopFileName%|
}

Menu, AIsMenu, Add, Minimize,
Menu, Settings, Add, Timers, Timers
Menu, Settings, Add, AlwaysOnTop`ton/off, Always
Menu, Settings, Add, Suspend`ton/off, SusOnOff
Menu, Settings, Add, Reload`tCtrl+r, Reload
Menu, AIsMenu, Add, Settings, :Settings
Menu, Default, Add, Default Editor, Editor
Menu, Default, Add, Default Settings, Default
Menu, AIsMenu, Add, Default, :Default

SetTitleMatchMode, 2
CoordMode, Caret, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Window
if (GuestOn == 1)
	Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
else if (GuestOn == 0)
	Gui, AI:New, -AlwaysOnTop +Resize +toolWindow
else
	Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, AI:Font, 0f0d03, Arial
Gui, Menu, AIsMenu
Gui, Add, Edit, r1 x25 y21 w150 ReadOnly, % A_WorkingDir
Gui, Add, DropDownList, x25 y55 w150 vChangeType gChangeType, Get Variables||Get Function|Create Test File
Gui, Add, GroupBox, x25 y90 h250 w150 wrap vResults, Get variables`n(Filter results by Checkbox)
Gui, Add, ListBox, r10 yp+35  xp+15 w120 gFileSelected vFileSelected, %wi%
Gui, Add, Edit, r4 yp+150 xp -VScroll vTestInfo w120,  Select a file to create a Test.ahk file with no function or sublabeled function.
Gui, Add, Text, yp xp vFunctionLabel, input the function lablel
Gui, Add, Edit, r1 w120 vFunctionName,
Gui, Add, Checkbox, vAssociateV, Associated functions
Gui, Add, Checkbox, yp-40 xp vGui, Gui Variables
Gui, Add, Checkbox, vExplicit, Explicit Variables
Gui, Add, Checkbox, vImplicitExplicit, Implicit-Explicit
Gui, Add, Text, -E0x200 x0 y0 vButtonCountCheck w0, 0,Unknown
Gui, Add, Text, -E0x200 vWordKeeper w0, &not@a#rea1*sent3nc3s
Gui, Add, Edit,  r18 ym+45 x200 vWords w325 hwndTracker,
Gui, Add, Button, gAISave, Save
Gui, Add, Text, vAISave w0, Don't save
Gui, Add, Button, x250 y317 gAIClear, Clear
Gui, Add, Edit,  r1 ym+15 x200 vWindowControl w325,
Gui, Add, Text, ym+315 x470 vInformation, Loading...
Gui, Add, Text, ym+17 x550 vWindowLabel gLock +Border Center h18, %A_Space%%A_Space%+`tAdd Window%A_Space%%A_Space%
Gui, Add, Edit, ym+45 x550 w150 vWelcome -VScroll ReadOnly, Welcome to my program. Above you will see a Label named Add Window. This is a control bar Click it to see other controls. Left and right navigation buttons are beside it to add further Controls. To the left of the screen you will notice your "Working directory" is added in case you need to know it. below is the default editor. In the center is collected information from "Get Variables", "Functions"... It can also be a scratch pad.`n I hope you enjoy using my program. Have a Good day!
Gui, Add, Text, ym+17 x661 w20 vLeftNave gLeftNav +Border Center h18, <
Gui, Add, Text, ym+17 x679 w20 vRightnav gRightNav +Border Center h18, >
Gui, Add, GroupBox, ym+50 x550 h250 w150 wrap vGroupControls, Window Controls
Gui, Add, Checkbox, yp+40 xp+10 vGetWindow gLocktoWindow, Lock Window Control
Gui, Add, Checkbox, yp+20 xp vSnapWindow gSnapToWindow, Snap to Window
Gui, Add, Checkbox, yp+20 xp vSnapToEditor gSnapToEditor, Snap to Editor
Gui, Add, Checkbox, yp+20 xp vAutoEdit gAutoEdit, Enable Auto Edit
Gui, Add, Checkbox, yp+20 xp vEnableCC gEnableCC, Enable copy anywhere
Gui, Add, Checkbox, yp+20 xp vEnableVV gEnableVV, Enable paste 2nd Clip
Gui, Add, Edit, yp+20 xp r5 w130 -VScroll ReadOnly vControlInformation, Information about the above controls
Gui, Add, Edit, yp+110 xp-10 r1 w150 -VScroll ReadOnly vDefaultEdit, % Editor
Gui, Margin, 50, 30
Gui, Color, d6d5d0, f5f4f0
Gui, Show, h400, AI work
GuiControl, AI:Hide, GroupControls
GuiControl, AI:Hide, Button8
GuiControl, AI:Hide, Button9
GuiControl, AI:Hide, Button10
GuiControl, AI:Hide, Button11
GuiControl, AI:Hide, Button12
GuiControl, AI:Hide, Button13
GuiControl, AI:Hide, GroupBox2
GuiControl, AI:Hide, FunctionName
GuiControl, AI:Hide, FunctionLabel
GuiControl, AI:Hide, Button2
GuiControl, AI:Hide, Edit2
GuiControl, AI:Hide, Edit7
Control, Disable , , Edit2, AI
Control, Disable , , Edit6, AI
Control, Disable , , Edit7, AI
GuiControl, Focus, Edit4
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, Add, Text, vClipBoard2 w0 h0 x5 y5,
Gui, Add, Text, vClipBoard3 w0 h0 x5 y5,
Gui, margin, 0, 0
Gui, Show, , Words
GuiControl, Words:Hide, ClipBoard2
GuiControl, Words:Hide, ClipBoard3

contents:=HashContents(contents)
logicalhistory:= []
logicalhistory:= ProcessStart(contents, Rest)
activeuserinput:= []

Loop,
{
	ClipBoardFunction()
	winwonder:=WinWonder()
	if (A_TimeIdle > 3000)
	{
		thisz++
		if (thisz == 1)
			GuiControl, AI:, Information, Done
		Sleep, % Notactive
		Continue
	}
	if (winwonder == "False")
	{
		SpellChecker(0)
		Sleep, % Notactive
		Continue
	}
	check:=GetControl("GetKeeper")
	usersentence:=GetControl("RowText")
	if (recordkeeper == "")
		recordkeeper:=% usersentence
	if (recordkeeper != usersentence)
	{
		Doppler(usersentence, recordkeeper)
		recordkeeper:=% usersentence
	}
	getuserinput:= GetControl("Text")
	activeuserinput:=ReturnLineArray(getuserinput, "user")
	historylastline:= GetLineCount(logicalhistory)
	activeuserlastline:= GetLineCount(activeuserinput)
	if (check == "7h151s@a#res37")
	{
		If (getuserinput == "")
		{
			Sleep, % Notactive
			Continue
		}
		GuiControl, AI:, WordKeeper, &not@a#rea1*sent3nc3
		contents:=HashContents(contents)
		logicalhistory:= ProcessStart(contents, Rest)
		Continue
	}
	if (usersentence != "")
	{
		if (activeuserlastline != historylastline)
		{
			logicallastlineaddition:=(activeuserlastline-historylastline)
			logicalhistory:= FixLogicalhistory_Array(logicalhistory, logicallastlineaddition) ; where last lines are being put in. and you will also want to function in lastline (Deleted_Line) to acompany the changes. if you are lagging ApplyLogicalChange().
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, logicallastlineaddition)
		}
		if (activeuserlastline == historylastline)
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, 0)
	}
	savecheck:= GetControl("AISave")
	if (savecheck == "Save_File")
	{
		historycount:=GetLineCount(logicalhistory)
		Loop, % historycount
		{
			x++
			sentences:= logicalhistory["linePos" x]
			StringReplace, sentences, sentences, (softReturn), \|/softReturn\|/, ALL
			StringReplace, sentences, sentences, (hardReturn), \|/CR+LF\|/, ALL
			FileContents:=% FileContents sentences
		}
		FileMove, % Temp, % TempBack, 1
		FileAppend, % FileContents, % Temp, UTF-8
		GuiControl,AI:, AISave, Don't Save
	}
}
Return

~LCtrl::
thiskeystate:= GetKeyState("LCtrl", P)
if (thiskeystate != 0)
{
	Loop,
	{
		GuiControlGet, EnableCC, AI:, EnableCC
		GuiControlGet, EnableVV, AI:, EnableVV
		CtrlC := Chr(3)
		if (EnableVV == 1)
		{
			CtrlVV:= (Chr(22) . Chr(22))
			CtrlVVV:= (Chr(22) . Chr(22) . Chr(22))
			ClipBoardFunction()
			GuiControlGet, ClipBoard2, Word:, ClipBoard2
			GuiControlGet, ClipBoard3, Word:, ClipBoard3
		}
		Input, userinput, L3 T0.75 M ; this has a 0.75 second timer... That feels a little natural. however on the person to person scale this might need adjusted.
		if (EnableVV == 1)
		{
			if (userinput == CtrlVV)
			{
				saveClip:=% ClipBoard
				ClipBoard:=% Clipboard2
				Send, ^v
				ClipBoard:=% saveClip
				saveClip:=
			}
			else if (userinput == CtrlVVV)
			{
				saveClip:=% ClipBoard
				ClipBoard:=% Clipboard3
				Send, ^v
				ClipBoard:=% saveClip
				saveClip:=
			}
		}
		else if ((userinput == CtrlC CtrlC)&&(EnableCC == 1))
		{
			logicalhistorylastline:= GetLineCount(logicalhistory)
			Loop, % logicalhistorylastline
			{
				thisx++
				saveline:= logicalhistory["linePos" thisx]
				saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
				saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
				thesecontents.= saveline
			}
			thesecontents:= SpecialReplace(thesecontents)
			MsgBox, % "The edit fields are ready to be sent. It autosends after this message. After you learn how this works you can delete this messge on line 237. Make sure the place you want your text sent is +lastfound"
			Send, % thesecontents
			thisx:=
			thesecontents:=
		}
		else if (userinput == CtrlC)
			Send, ^c
		else
			Send, ^%userinput%
		thiskeystate:= GetKeyState("LCtrl", P)
		if (thiskeystate == 0)
			Break
	}
}
Return
	
ClipBoardFunction()
{
	if ((ClipBoard != "")&&(ClipBoard != ClipBoard2))
	{
		if (ClipBoard2 == "" )
			ClipBoard2:=% ClipBoard1
		else if (ClipBoard2 != "")
		{
			ClipBoard3:=% ClipBoard2
			ClipBoard2:=% ClipBoard
		}
	}
	if (ClipBoard2 != "" )
		GuiControl,Word:, ClipBoard2, % ClipBoard2
	if (ClipBoard3 != "" )
		GuiControl,Word:, ClipBoard3, % ClipBoard3
	Return
}

$Backspace::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Backspace}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Backspace}
	}
	Return
}
else
	Send, {Backspace}
Return

$Space::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Space}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Space}
	}
	Return
}
else
	Send, {Space}
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		check:=GetControl("GetKeeper")
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 2)
				userword:=% chec
		}
		str:= StrLen(userword)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
	}
	else
	{
		Send, `t
	}
	Return
}
else
	Send, `t
Return

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	GuiControlGet, AutoEdit, AI:, AutoEdit
	If (AutoEdit == 1)
	{
		logicalhistorylastline:= GetLineCount(logicalhistory)
		Loop, % logicalhistorylastline
		{
			thisx++
			saveline:= logicalhistory["linePos" thisx]
			saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
			saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
			thesecontents.= saveline
		}
		thesecontents:= SpecialReplace(thesecontents)
		GuiControlGet, wintitle, AI:, WindowControl, Edit5
		if (wintitle == "")
		{
			MsgBox, Please lock to a window first
			Return
		}
		WinActivate, % wintitle
		WinWait, % wintitle
		Send, % thesecontents
		FileMove, % Temp, % TempBack, 1
		FileAppend, , % Temp, UTF-8
		GuiControl, AI:, Edit4,
		logicalhistory:=[]
		thisx:=
		thesecontents:=
	}
	else if (AutoEdit == 0)
	{
		ButtonCountCheck:= GetControl("ButtCount")
		PressCount:=GetButtonCount(ButtonCountCheck)
		PressCount++
		WhichButtonCount:=% PressCount ",ShiftEnter"
		GuiControl, AI:, ButtonCountCheck, % WhichButtonCount
		KeyWait, Backspace, U
		GetButton_Count()
	}
}
Return

~Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	GuiControlGet, AutoEdit, AI:, AutoEdit
	If (AutoEdit == 1)
	{
		logicalhistorylastline:= GetLineCount(logicalhistory)
		Loop, % logicalhistorylastline
		{
			thisx++
			saveline:= logicalhistory["linePos" thisx]
			saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
			saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
			thesecontents.= saveline
		}
		thesecontents:= SpecialReplace(thesecontents)
		GuiControlGet, wintitle, AI:, WindowControl, Edit5
		if (wintitle == "")
		{
			MsgBox, Please lock to a window first
			Return
		}
		WinActivate, % wintitle
		WinWait, % wintitle
		Send, % thesecontents "+{Enter}"
		FileMove, % Temp, % TempBack, 1
		FileAppend, , % Temp, UTF-8
		GuiControl, AI:, Edit4,
		logicalhistory:=[]
		thisx:=
		thesecontents:=
	}
	else if (AutoEdit == 0) ;
	{
		ButtonCountCheck:= GetControl("ButtCount")
		PressCount:=GetButtonCount(ButtonCountCheck)
		PressCount++
		WhichButtonCount:=% PressCount ",Enter"
		GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
		KeyWait, Backspace, U
		GetButton_Count()
	}
}
Return

SpecialReplace(thesecontents)
{
	fixedcharacters:= StrReplace(thesecontents, "!", "{!}")
	fixedcharacters:= StrReplace(fixedcharacters, "#", "{#}")
	fixedcharacters:= StrReplace(fixedcharacters, "+", "{+}")
	fixedcharacters:= StrReplace(fixedcharacters, "^", "{^}")
	fixedcharacters:= StrReplace(fixedcharacters, "{", "{{}") ; if this is done then output will be {{}
	fixedcharacters:= StrReplace(fixedcharacters, "}", "{}}") ; from the above if this is done output will be {{{}}
	fixedcharacters:= StrReplace(fixedcharacters, "{{{}}", "{{}")
	Sleep, 50
	Tabcontrol:= StrSplit(fixedcharacters, ["(hardReturn)", "(softReturn)"])
	for index, Tabs in Tabcontrol
	{
		IfinString, Tabs, % "`t" ; <----- it is assumed the editor you're using controls tab.
		{
			thiscount:= StrReplace(Tabs, "`t", "", thismany)
			thisstring:=% thiscount
			if (thismany != thatmany)
			{
				if (thismany > thatmany)
				{
					n:=(thismany-thatmany)
					thisbutton:=% "{Tab " n "}"
				}
				if (thismany < thatmany)
				{
					n:=(thatmany-thismany)
					thisbutton:=% "{Backspace " n "}"
				}
			}
		}
		IfNotInString, Tabs, % "`t"
		{
			if (thismany > 1)
				thisbutton:=% "{Backspace " n "}"
			else if (thismany == 1)
			{
				thismany:=0
				thisbutton:=% "{Backspace}"
			}
			else if (thismany == 0)
				thisbutton:=% ""
			thisstring:=% Tabs
		}
		thatmany:=% thismany
		edittext.= thisbutton thisstring
		thisbutton:= ""
	}
	edittext:= StrReplace(edittext, "[Enter]", "{Backspace}{Enter}")
	edittext:= StrReplace(edittext, "[ShiftEnter]", "{Backspace}+{Enter}")
	Return % edittext
}

EnableVV:
GuiControl, AI:, ControlInformation, This enables paste from second and third ClipBoard. {LCtrl}+vv and {LCtrl}+vvv. if clipboard2 or 3 sends acsii code
Return

SnapToWindow:
GuiControl, AI:, ControlInformation, This will place the Main Gui in one of 9 locations on the locked window.
IniRead, DefaultLoc, % Settings, WinManger, Key1
GuiControlGet, fullwindow, AI:, Edit5
if (fullwindow == "")
{
	MsgBox, 262144, Please lock to a window., Please first lock to a window.
	GuiControl, AI:, Button10, 0
	Return
}
GetMoveWindow(DefaultLoc, 0, fullwindow)
Return

SnapToEditor:
GuiControl, AI:, ControlInformation, This will place the Main Gui in one of 9 locations on the editor. Notepad is Default.
GuiControlGet, DefaultEdit, AI:, DefaultEdit
IfInString, DefaultEdit, .
{
	windows:= StrSplit(DefaultEdit, ".")
	for index, window in windows
		if (index == 1)
			thiswindow:=% window
}
WinGetTitle, fullwindow, % "ahk_class" thiswindow
if (fullwindow == "")
{
	MsgBox, 4, Window Not Found!, % "The current Editor is not open:`nahk_class " thiswindow "`nWould you like to open it?"
	IfMsgBox Yes
		run, % DefaultEdit
	IfMsgBox No
		Return
	Loop,
	{
		Sleep, 150 ; prevent needless process
		WinGetTitle, fullwindow, % "ahk_class" thiswindow
		if (fullwindow != "")
			Break
		x++
		if (x > 15)
		{
			MsgBox, There is an error opening the window or a naming error. ;"
			Return
		}
	}
}
IfWinExist, % fullwindow
{
	WinActivate, % fullwindow
	WinWait, % fullwindow
	IniRead, DefaultLoc, % Settings, WinManger, Key1
	GetMoveWindow(DefaultLoc, 0, fullwindow)
}
Return

AutoEdit:
GuiControl, AI:, ControlInformation, On Enter ({Enter} or +{Enter} this button sends to your default editor if it's active and Clears the window.
Return

EnableCC:
GuiControl, AI:, ControlInformation, This activates {LCtrl}+cc when you press that (anywhere) main edit contents are autosent to insert location.
Return

LocktoWindow:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This button locks the Gui to a running window. Just activate the window you want.
if (GetWindow == 1)
{
	WinGetActiveTitle, checkthistitle
	GuiControl, AI:, Edit5, Select a window to lock to.
	Loop,
	{
		WinGetActiveTitle, newtitletocheck
		if (newtitletocheck == "")
			Continue
		if (checkthistitle != newtitletocheck)
			Break
	}
	GuiControl, AI:, Edit5, % newtitletocheck
	GuiControl, Disable, Edit5
}
if (GetWindow == 0)
{
	GuiControl, AI:, Edit5,
	GuiControl, Enable, Edit5
}
Return

LeftNav:
Return

RightNav:
Return

Lock:
GuiControl, AI:, ControlInformation, Information about the above controls
x++
LockMod:= Mod(x, 2)
if (LockMod == 1)
{
	GuiControl, AI:, WindowLabel, %A_Space%%A_Space%-`tAdd Window%A_Space%%A_Space%
	GuiControl, AI:Show, GroupControls
	GuiControl, AI:Show, Button8
	GuiControl, AI:Show, Button9
	GuiControl, AI:Show, Button10
	GuiControl, AI:Show, Button11
	GuiControl, AI:Show, Button12
	GuiControl, AI:Show, Button13
	GuiControl, AI:Show, Button14
	GuiControl, AI:Show, Edit7
	GuiControl, AI:Hide, Edit6
}
if (LockMod == 0)
{
	GuiControl,AI:, WindowLabel, %A_Space%%A_Space%+`tAdd Window%A_Space%%A_Space%
	GuiControl, AI:Hide, GroupControls
	GuiControl, AI:Hide, Button8
	GuiControl, AI:Hide, Button9
	GuiControl, AI:Hide, Button10
	GuiControl, AI:Hide, Button11
	GuiControl, AI:Hide, Button12
	GuiControl, AI:Hide, Button13 
	GuiControl, AI:Hide, Button14
	GuiControl, AI:Hide, Edit7
	GuiControl, AI:Show, Edit6
}
Return

Editor:
IniRead, Editor, % Settings, Editor, Key1
if (Editor == "ERROR")
	Editor:=% "Notepad.exe"
Gui, Editor:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, x20 y23, Your default Editor is:
Gui, Add, Edit, x145 y20 w100, % Editor
Gui, Add, Button, x205 w40 gEditSave, Save
Gui, Add, Button, ys+24 x155 gEditCancel, Cancel
Gui, Margin, 20, 20
Gui, Show, x130, Editor
Return

EditSave:
GuiControlGet, Editor, , Edit1, Editor
IniWrite, % Editor, % Settings, Editor, Key1
GuiControl, AI:, Edit7, % Editor
Gui, Editor:Destroy
Return

EditCancel:
Gui, Editor:Destroy
Return

Default:
IniRead, Always, % Settings, AlwaysOnTop, Key1
if (Always != "ERROR")
	GuestOn:=% Always
IniRead, Directory, % Settings, Directory, Key1
if (Directory != "ERROR")
	MainDirectory:=% Directory
IniRead, loopxcount, % Settings, Looper, Key1
if (loopxcount != "ERROR")
{
	Loop, % loopxcount
	{
		IniRead, codex, % Settings, KeyCodes, Key%loopxcount%
		codexlist.=  codex "|"
		loopxcount--
	}
}
IniRead, loopycount, % Settings, DroppedCodeCount, Key1
if (loopycount != "ERROR")
{
	Loop, % loopycount
	{
		IniRead, codedrop, % Settings, DroppedCode, Key%loopycount%
		codeylist.= codedrop  "|"
		loopycount--
	}
}
Gui, Defaults:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Edit, y20 x85, Below are the default settings for the program.
Gui, Add, Text, x20, Default working directory:`t`n(place the full folder location.)`t
Gui, Add, Text, , Create test file parameters:`t`n(To add type one that doesn't exist.`t`n To remove select one from the list.)`t`nTo add more delimit by "|"
Gui, Add, Text, , Delimited words from create test file:`t`n(To add type one that doesn't exist.`t`n To remove select one from the list.)`t`nTo add more delimit by "|"
Gui, Add, Checkbox, x140 ym+210 vYesOrNo, Default AlwaysOnTop On
Gui, Add, Button, x310 ym+235 gDCancel, Cancel
Gui, Add, Button, wp hp yp x375 gDSave, Save
Gui, Add, Text, x120 ym+230 cRed, (Must click save to save changes!)`n  Must reload for directory change
if (MainDirectory != "")
	Gui, Add, Edit, xm+200 ym+45 w200 vDirectory, % MainDirectory
else
	Gui, Add, Edit, xm+200 ym+45 w200 vDirectory, % A_ScriptDir
Gui, Add, ComboBox, xm+200 ym+100 w200 vKodexList gListxChange, % codexlist
Gui, Add, ComboBox, xm+200 ym+165 w200 vKodeyList gListyChange, % codeylist
Gui, Margin, 20, 20
Gui, Show, , Defaults
Control, Disable ,, Edit1, Defaults
if (GuestOn == 1)
	GuiControl, Defaults:, Button1, 1
else if (GuestOn == 0)
	GuiControl, Defaults:, Button1, 0
else
	GuiControl, Defaults:, Button1, 1
Return

ListxChange:
Gui, Submit, NoHide
KodexList:= StrReplace(codexlist, KodexList, "")
GuiControl, Defaults:, KodexList, % KodexList
Return

ListyChange:
Gui, Submit, NoHide
KodeyList:= StrReplace(codeylist, KodeyList, "")
GuiControl, Defaults:, KodeyList, % KodeyList
Return

DCancel:
Gui, Defaults:Destroy
Return

DSave:
Gui, Submit, NoHide
IniDelete, % Settings, KeyCodes
IniDelete, % Settings, DroppedCode
IniDelete, % Settings, Directory
IniDelete, % Settings, AlwaysOnTop
IniDelete, % Settings, Looper
IniDelete, % Settings, DroppedCodeCount
IniWrite, % YesOrNo, % Settings, AlwaysOnTop, Key1
IniWrite, % Directory, % Settings, Directory, Key1
ControlGet, Kodex_List, List, , ComboBox1, Defaults
GuiControlGet, Personalizedx, , Edit3, Defaults
personalx:= StrReplace(Personalizedx, "|", "`n")
Kodex_List:=% (personalx "`n" . Kodex_List)
Kodex_List:= StrReplace(Kodex_List, "`n`n", "`n")
Loop, Parse, % Kodex_List, `n
{
	z++
	IniWrite, % z, % Settings, Looper, Key1
	IniWrite, % A_LoopField, % Settings, KeyCodes, Key%z%
}
ControlGet, Kodey_List, List, , ComboBox2, Defaults
GuiControlGet, Personalizedy, , Edit3, Defaults
personaly:= StrReplace(Personalizedy, "|", "`n")
Kodey_List:=% (personaly "`n" . Kodey_List)
Kodey_List:= StrReplace(Kodey_List, "`n`n", "`n")
Loop, Parse, % Kodey_List, `n
{
	w++
	IniWrite, % w, % Settings, DroppedCodeCount, Key1
	IniWrite, % A_LoopField, % Settings, DroppedCode, Key%w%
}
Gui, Defaults:Destroy
Return

AISave:
GuiControl,AI:, AISave, Save_File
Return

AIClear:
FileMove, % Temp, % TempBack, 1
FileAppend, , % Temp, UTF-8
GuiControl, AI:, Edit4,
logicalhistory:=[]
Return
	
SusOnOff:
Suspend, Toggle
if (A_IsSuspended == 1)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOn
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOff
Return

Always:
WinSet, AlwaysOnTop, Toggle, AI
WinGet, ExStyle, ExStyle, AI
if (ExStyle == 0x00000180)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOff
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOn
Return
 
Timers:
Gui, Timers:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, y25, Rest Timer:`t`n(in seconds)
Gui, Add, Text, y75 xs, Window Not Active:`t`n(in milliseconds)
Gui, Add, Text, y125 xs, Process Loop timer:`t`n(in milliseconds)
Gui, Add, Edit, w250 r3 ys-15 -VScroll, This timer slows the script before it gets to the main loop function. It's used to help in processing the global function "Speller."
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the script when the it is not active.
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the main processing loop while typing. It's dependent on a difference created in the main edit control.
Gui, Add, Edit, ys xs+400 w50 y25
Gui, Add, UpDown, vRangeInSeconds Range1-50, 10
Gui, Add, Edit, ys xs+400 w50 y75
Gui, Add, UpDown, vRangeInMillisecondsOfActive Range1-1000, 500
Gui, Add, Edit, ys xs+400 w50 y125
Gui, Add, UpDown, vRangeInMillisecondsOfProcess Range1-100, 25
Gui, Add, Text, xm+10 ym+180, Select the above values to your personal preferences and click save to keep the changes.
Gui, Add, Text, xm+80 ym+215, (Note you have to restart the program to force the changes)
Gui, Add, Button, ym+210 xs+425 gSave, Save
Gui, Add, Button, ym+210 xs+370 gCancel, Cancel
Gui, Margin, 20, 50
Gui, Show, h250 w500, Timers
Control, Disable ,, Edit1, Timers
Control, Disable ,, Edit2, Timers
Control, Disable ,, Edit3, Timers
Return

Minimize:
MsgBox, 262208, Under Construction, This particular feature is under construction. When I am done with it the button will minimize to the "Editor" that is connected to the program by default. If the "locked" window is selected it will minimize to that window first.. I also intend to make it say maximize while minimzed so it has both features.
Return

Reload:
^r::
Reload
Return

Cancel:
Gui, Timers:Destroy
Return

Save:
Gui, Submit, NoHide
RangeInSeconds:=(RangeInSeconds*1000)
IniWrite, % RangeInSeconds, % Settings, Timers, Key1
IniWrite, % RangeInMillisecondsOfActive, % Settings, Timers, Key2
IniWrite, % RangeInMillisecondsOfProcess, % Settings, Timers, Key3
Gui, Timers:Destroy
Return

FileSelected: 
Gui, Submit, NoHide
GuiControl, AI:, Information, Working..
FileRead, contents, % FileSelected
if (ChangeType == "Get Variables")
{
	if (Gui == 1)
		filters.= "[Filter='Gui'],"
	if (Explicit == 1)
		filters.= "[Filter='explicit'],"
	if (ImplicitExplicit == 1)
		filters.= "[Filter='implicit-explicit'],"
	wi:=
	if (filters != "")
	{
		Control, Disable ,, ListBox1, AI
		contents:= GetVariables(contents, filters)
		GuiControl, AI:, Words,
		GuiControl, AI:, Words, % contents
		whichbutton:=GetControl("ButtCount")
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					thisbutton:= "\|/SoftReturn\|/"
				if (butt == "Enter")
					thisbutton:= "\|/hardReturn\|/"
				if (butt == "Unknown")
					thisbutton:= " \|/SoftReturn\|/"
			}
		}
		StringReplace, contents, contents, `n, %thisbutton%, ALL
		FileMove, % Temp, % TempBack, 1
		FileAppend, % contents, % Temp, UTF-8
	}
}
else if (ChangeType == "Get Function") ;ChangeType gChangeType, Get Variables||Get Function|Create Test File
{
	ControlGet, row, CurrentLine, , Edit3, AI
	ControlGet, rowtext, Line, % row, Edit3, AI
	if (rowtext == "")
	{
		MsgBox, Please insert the function label name
		Return
	}
	if (AssociateV == 1)
		thisignore:=% "Do_Not"
	function:=GetThisFunction(rowtext, thisignore, contents)
	GuiControl, AI:, Words, % function
	FileMove, % Temp, % TempBack, 1
	FileAppend, % function, % Temp, UTF-8
}
else if (ChangeType == "Create Test File")
{
	thesecontents:= GetTestFile(contents)
	Loop, Parse, % thesecontents, `n
	{
		if (A_LoopField == "")
			Continue
		if (A_LoopField == "Return")
			thisfile:=% thisfile A_LoopField "`n`n"
		else if (A_LoopField != "Return")
			thisfile:=% thisfile A_LoopField "`n"
	}
	FileMove, Test.ahk, % TempBack, 1
	FileAppend, % thisfile, *Test.ahk, UTF-8
}
GuiControl, AI:, Button2, 0
GuiControl, AI:, Button3, 0
GuiControl, AI:, Button4, 0
GuiControl, AI:, Button5, 0
GuiControl, AI:, Edit3,
GuiControl, AI:, WordKeeper, 7h151s@a#res37
GuiControl, AI:, Information, Done
Control, Enable ,, ListBox1, AI
Return

GetMoveWindow(DefaultLoc, Whichone, fullwindow)
{
	WinGetPos , winPosX, winPosY, windowwidth, windowheight, % fullwindow
	WinGetPos , AIPosX, AIPosY, AIorignalwidth, AIorignalhieght, AI
	IniRead, DefaultLoc, % Settings, WinManager, Key1
	If (DefaultLoc != "ERROR")
		ThisWindowLoc(DefaultLoc,Whichone, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	else if (DefaultLoc == "ERROR")
	{
		MsgBox, 262212, Default location not set, You have not set up a default location for the window. Would you like to continue?
		IfMsgBox, Yes
		{
			Loop,
			{
				x++
				y:=0
				ThisWindowLoc(x, y, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
				MsgBox, 262144, first position, This is the first position of the window minimized.
				y:=1
				ThisWindowLoc(x, y, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
				MsgBox, 262211, Do you like that location?, This is the second position maximized.`nIf you like this position click yes.`nTo exit click Cancel`n%x% %y% 
				IfMsgBox Yes
				{
					IniWrite, % x, % Settings, WinManager, Key1
					Break
				}
				IfMsgBox Cancel
					Break
				if (x == 9)
					x:=0
			}
		}	
		IfMsgBox, No
			Return
	}
	Return
}
	

ThisWindowLoc(DefaultLoc, Whichone, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
{
	AIwidth:= 100
	AIheight:= 100
	if (DefaultLoc == 1)
	{
		MainWindowX:=(windowwidth-AIwidth+winPosX)
		MainWindowY:=(windowheight-AIheight+winPosY) ; bottom right corner
		GuiWindowX:=(windowwidth-AIorignalwidth+winPosX)
		GuiWindowY:=(windowheight-AIorignalhieght+winPosY)
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 2)
	{
		MainWindowX:=% winPosX
		MainWindowY:=(windowheight-AIheight+winPosY) ; bottom left corner
		GuiWindowX:=% winPosX
		GuiWindowY:=(windowheight-AIorignalhieght+winPosY)
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 3)
	{
		MainWindowX:=% winPosX
		MainWindowY:=% winPosY ; upper left corner
		GuiWindowX:=% winPosX
		GuiWindowY:=% winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 4)
	{
		MainWindowX:=(windowwidth-AIwidth+winPosX)
		MainWindowY:=% winPosY ; upper right corner.
		GuiWindowX:=(windowwidth-AIorignalwidth+winPosX)
		GuiWindowY:=% winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 5)
	{
		MainWindowX:=(windowwidth/2)-(AIwidth/2)
		MainWindowY:=% winPosY ; upper center
		GuiWindowX:=(windowwidth/2)-(AIorignalwidth/2)
		GuiWindowY:=% winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 6)
	{
		MainWindowX:=(windowwidth/2)-(AIwidth/2)
		MainWindowY:=(windowheight-AIheight+winPosY) ; lower center
		GuiWindowX:=(windowwidth/2)-(AIorignalwidth/2)
		GuiWindowY:=(windowheight-AIorignalhieght+winPosY)
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 7)
	{
		MainWindowX:=% winPosX
		MainWindowY:=(windowheight/2)-(AIheight/2)+winPosY ; left center
		GuiWindowX:=% winPosX
		GuiWindowY:=(windowheight/2)-(AIorignalhieght/2)+winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 8)
	{
		MainWindowX:=(windowwidth-AIwidth+winPosX)
		MainWindowY:=(windowheight/2)-(AIheight/2)+winPosY ;right center
		GuiWindowX:=(windowwidth-AIorignalwidth+winPosX)
		GuiWindowY:=(windowheight/2)-(AIorignalhieght/2)+winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 9)
	{
		MainWindowX:=(windowwidth/2)-(AIwidth/2)
		MainWindowY:=(windowheight/2)-(AIheight/2)+winPosY ; center center
		GuiWindowX:=(windowwidth/2)-(AIorignalwidth/2)
		GuiWindowY:=(windowheight/2)-(AIorignalhieght/2)+winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	Return
}

GetTestFile(data)
{
	IniRead, loopcount, % Settings, Looper, Key1
	if (loopcount != "ERROR")
	{
		Loop, % loopcount
		{
			IniRead, codex, % Settings, KeyCodes, Key%loopcount%
			codexlist.= codex "`n"
			loopcount--
		}
		IniRead, loopcount, % Settings, DroppedCodeCount, Key1
		if (loopcount != "ERROR")
		{
			Loop, % loopcount
			{
				IniRead, codedrop, % Settings, DroppedCode, Key%loopcount%
				codeylist.= codedrop "`n"
				loopcount--
			}
		}
		data:= StrReplace(data, "`r", "")
		Loop, Parse, % data, `n
		{
			y++
			codestring:=
			line:=% A_LoopField
			sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
			for index, sentence in sentences
			{
				if (index == 1)
					codestring:=% sentence
				if (index == 2)
					commentstring:=% sentence
			}
			keycodex:= StrReplace(codestring, ",",  " ")
			keycodex:= StrReplace(keycodex, "  ", " ")
			keycodex:= StrReplace(keycodex, "  ", " ")
			keycodex:=% Trim(keycodex)
			thesewords:= StrSplit(keycodex, A_Space)
			for index, keycode in thesewords
				if (index == 1)
					keycodex:=% keycode
			IfinString, codeylist, % keycodex
				codestring:=% ""
			IfinString, codexlist, % keycodex
			{
				filecontents:=% filecontents codestring "`n"
				codestring:=% ""
			}
			codestring:= CodeStringCheck(codestring)
			if (codestring != "")
			{
				IfinString, codestring, Return
				{
					if (thischecker == 1)
						IfNotInString, codestring, % "`t"
							thischecker:= 0
					codestring:=% ""
				}
				IfInString, codestring, Global
				{
					filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfInString, codestring, Gui
				{
					IfinString, codestring, Show
						filecontents:=% filecontents codestring "`nReturn`n`n"
					else
						filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfInString, codestring, Menu
				{
					filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfinString, codestring, :
				{
					IfInString, codestring, Gui
						codestring:=% ""
					if (thischecker != 1)
					{
						thischecker:= 1
						if (x != 1)
							x:=1
					}
					filecontents:=% filecontents codestring "`nReturn`n`n"
					codestring:=% ""
				}
				IfInString, filecontents, % codestring
					codestring:=% ""
			}
		}
	}
	else if (loopcount == "ERROR")
	{
		MsgBox, 70, Be sure before you continue., In the following message boxes you will be shown the beginning of your code. This will omit the comments and anything past the first comma as demiliters for your test.ahk creation. each type will be added to the Ini file settings and read for your future creations. You can always change this setting by selecting default in the default menu.`n`n**Also note This does skip continuation sections.
		IfMsgBox Continue
		{
			data:= StrReplace(data, "`r", "")
			Loop, Parse, % data, `n
			{
				y++
				line:=% A_LoopField
				sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
				for index, sentence in sentences
				{
					if (index == 1)
						codestring:=% sentence
					if (index == 2)
						commentstring:=% sentence
				}
				codestring:= CodeStringCheck(codestring)
				if (codestring != "")
				{
					IfinString, codestring, Return
					{
						if (thischecker == 1)
							IfNotInString, codestring, % "`t"
								thischecker:= 0
						codestring:=% ""
					}
					IfInString, codestring, Global
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, codestring, Gui
					{
						IfinString, codestring, Show
							filecontents:=% filecontents codestring "`nReturn`n`n"
						else
							filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, codestring, Menu
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfinString, codestring, :
					{
						IfInString, codestring, Gui
							codestring:=% ""
						if (thischecker != 1)
						{
							thischecker:= 1
							if (x != 1)
							{
								x:=1
								MsgBox, 32, g-Sublabels, sublabels are automatically added
							}
						}
						filecontents:=% filecontents codestring "`nReturn`n`n"
						codestring:=% ""
					}
					keycodex:= StrReplace(codestring, ",",  " ")
					keycodex:= StrReplace(keycodex, "  ", " ")
					keycodex:= StrReplace(keycodex, "  ", " ")
					keycodex:=% Trim(keycodex)
					thesewords:= StrSplit(keycodex, A_Space)
					for index, keycode in thesewords
						if (index == 1)
							keycodex:=% keycode
					IfinString, thisignoredlist, % keycodex
						codestring:=% ""
					IfinString, thisgottenlist, % keycodex
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, filecontents, % codestring
						codestring:=% ""
					if (codestring != "")
					{
						MsgBox, 36, Do you want to add this line?, % keycodex "`n`nFound on line: " y "`n`npress yes if you want to add the first (word) of this line to your delimiter fields."
						IfMsgBox Yes
						{
							z++
							IniWrite, % z, % Settings, Looper, Key1
							IniWrite, % keycodex, % Settings, KeyCodes, Key%z%
							thisgottenlist.= keycodex
							filecontents:=% filecontents codestring "`n"
						}
						else IfMsgBox No
						{
							w++
							IniWrite, % w, % Settings, DroppedCodeCount, Key1
							IniWrite, % keycodex, % Settings, DroppedCode, Key%w%
							thisignoredlist.= codestring " "
							Continue
						}
					}
				}
			}
		}
	}
	Return % filecontents
}

CodeStringCheck(codestring)
{
	IfInString, codestring, GuiControl
		codestring:=% ""
	IfinString, codestring, `t
		codestring:=% ""
	IfInString, codestring, Global
		Return % codestring
	IfInString, codestring, Gui ; It's likely a user may place any of the below special characters in a gui 4th parameter.
		Return % codestring
	IfInString, codestring, =
		codestring:=% ""
	IfInString, codestring, ( ;)
		codestring:=% ""
	IfInString, codestring, {
		codestring:=% ""
	IfInString, codestring, }
		codestring:=% ""
	IfInString, codestring, `%
		IfNotInString, codestring, SetWorkingDir
			codestring:=% ""
	IfinString, codestring, Loop
		codestring:=% ""
	IfinString, codestring, else
		codestring:=% ""
	IfinString, codestring, if%A_Space%
		codestring:=% ""
	IfinString, codestring, ::
		codestring:=% ""
	Return % codestring
}

GetThisFunction(function, get, data)
{
	function:= StrReplace(function, "`r`n", "")
	function:= StrReplace(function, "`n", "")
	functionlength:=StrLen(function)
	data:= StrReplace(data, "`r", "")
	function:= GetFunction(data, functionlength, function)
	thisfoundfunction.= function "`n"
	function:=""
	if (get == "Do_Not")
	{
		Loop,
		{
			Loop, Parse, % thisfoundfunction, `n
			{
				IfInString, A_LoopField, =
					IfInString, A_LoopField, (
					{
						foundpossible:= FunctionLabelGet(A_LoopField)
						Trim(foundpossible)
						IfNotInString, foundpossible, % A_Space
							IfNotInString, thesefound, % foundpossible
							{
								functionlength:=StrLen(foundpossible)
								function:= GetFunction(data, functionlength, foundpossible)
							}
						if (function != "")
							thisfoundfunction.= function "`n"
					}
				if (function != "")
					function:=
				thesefound.= foundpossible ", "
			}
			IfNotInString, thesefoundpast, % thesefound
				thesefoundpast.= thesefound
			IfinString, thesefoundpast, % thesefound
				Break
		}
	}
	Return % thisfoundfunction
}

GetFunction(data, functionlength, function)
{
	Loop, Parse, % data, `n
	{
		if (thisfunction == "")
		{
			linesubstring:= SubStr(A_LoopField, 1, functionlength)
			if (function == linesubstring)
			{
				thisfunction:= % A_LoopField "`n"
				z:=1
			}
		}
		else if (thisfunction != "")
		{
			thisfunction.= A_LoopField "`n"
			if (A_LoopField == "{")
				x++
			if (A_LoopField == "}")
				x--
			if (z == 1)&&(A_LoopField != "{")
				thisfunction:= ""
			z:=0
		}
		if ((x == 0)&&(thisfunction != ""))
		{
			thisfoundfunction:= % thisfunction
			thisfunction:= ""
		}
	}
	Return % thisfoundfunction
}

FunctionLabelGet(line)
{
	thissplitfunction:= StrSplit(line, "= ")
	for index, thissplit in thissplitfunction
		if (index == 2)
			thispart:=% thissplit
	thispartsplit:= StrSplit(thispart, "(") ;"
	for index, function in thispartsplit
		if (index == 1)
			Return % function
	Return
}

ChangeType:
Gui, Submit, NoHide
if (ChangeType == "Get Variables")
{
	GuiControl, AI:Text, Results, Get variables`n(Filter results by Checkbox)
	GuiControl, AI:Hide, FunctionName
	GuiControl, AI:Hide, FunctionLabel
	GuiControl, AI:Hide, Button2
	GuiControl, AI:Hide, Edit2
	GuiControl, AI:Show, Button5
	GuiControl, AI:Show, Button3
	GuiControl, AI:Show, Button4
}
if (ChangeType == "Get Function")
{
	GuiControl, AI:Text, Results, Get Function`n(Select a file to get a function)
	GuiControl, AI:Hide, Button5
	GuiControl, AI:Hide, Button3
	GuiControl, AI:hide, Button4
	GuiControl, AI:Show, FunctionName
	GuiControl, AI:Show, FunctionLabel
	GuiControl, AI:Show, Button2
	GuiControl, AI:Hide, Edit2
	GuiControl, Focus, Edit3
}
if (ChangeType == "Create Test File")
{
	GuiControl, AI:Text, results, Create a Test File`n(Create functionless test ahk)
	GuiControl, AI:Hide, Button5
	GuiControl, AI:Hide, Button3
	GuiControl, AI:hide, Button4
	GuiControl, AI:hide, FunctionName
	GuiControl, AI:hide, FunctionLabel
	GuiControl, AI:hide, Button2
	GuiControl, AI:Show, Edit2
}
Return

GetVariables(filecontents, filters)
{
	Loop, Parse, % filecontents, `r
	{
		linenumber++
		line:=% A_LoopField
		sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
		for index, sentence in sentences
		{
			if (index == 1)
				codestring:=% sentence
			if (index == 2)
				commentstring:=% sentence
		}
		VarSetCapacity(information, 0) 
		codestring:= RemoveCertainChars(codestring, "Start")
		IfInString, codestring, Dll
			Continue
		IfInString, codestring, Box`,
			Continue
		IfInString, codestring, StringReplace
			Continue
		IfInString, codestring, RegEx
			Continue
		IfInString, codestring, Ini
			Continue
		IfInString, codestring, =
		{
			IfInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Percent", linenumber)
				IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
			}
			else IfNotInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
			IfInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Quotes", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring 
			}
			else IfNotInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
		}
		else IfInString, codestring, [percent]
		{
			variablestring:= GetVariableString(codestring, "Percent", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring
		}
		else IfInString, codestring, [quotes]
		{
			variablestring:= GetVariableString(codestring, "Quotes", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring "found in quotes 2`n"
		}
		IfInString, codestring, Gui
			IfInString, codestring, `,
				IfInString, codestring, %A_Space%v
				{
					variablestring:= GetVariableString(codestring, "Gui", linenumber)
					IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
				}
	}
	thesefilters:=StrSplit(filters, ",")
	for index, filter in thesefilters
	{
		if (index == 1)
			if (filter != "")
				firstfilter:=% filter
		if (index == 2)
			if (filter != "")
				secondfilter:=% filter
		if (index == 3)
			if (filter != "")
				thirdfilter:=% filter
	}
	Loop, Parse, % variablelist, `n
	{
		thischeck:= ""
		information:= ""
		if (A_LoopField != "")
		{
			repeatcheck:= StrSplit(A_LoopField, "[thissplitter]")
			for index, repeat in repeatcheck
			{
				if (index == 1)
				{
					IfNotInString, completedlist, % repeat
						thischeck:=% repeat
					IfInString, completedlist, % repeat
					{
						checking:= MakeSure(completedlist, repeat)
						if (checking == "True")
							Continue
						else if (checking == "False")
							thischeck:=% repeat
					}
				}
				if (index == 2)
				{
					if (firstfilter != "")
						IfInString, repeat, % firstfilter
						{
							applyfilters:= StrSplit(repeat, firstfilter)
							for index, apply in applyfilters
								information.= apply
						}
					else if (secondfilter != "")
						IfInString, repeat, % secondfilter
						{
							applyfilters:= StrSplit(repeat, secondfilter)
							for index, apply in applyfilters
								information.= apply
						}
					else if (thirdfilter != "")
						IfInString, repeat, % thirdfilter
						{
							applyfilters:= StrSplit(repeat, thirdfilter)
							for index, apply in applyfilters
								information.= apply
						}
				}
			}
			if ((thischeck != "")&&(information != ""))
			{
				checklist:=% Trim(thischeck) "`n" Trim(information) "`n"
				IfNotInString, completedlist, % checklist
					completedlist.= checklist
			}
		}
	}
	completedlist:= RemoveCertainChars(completedlist, "End")
	Return % completedlist
}

MakeSure(listinprogress, checkword)
{
	Loop, Parse, % listinprogress, `n
	{
		if (checkword == A_LoopField)
			Return % "True"
	}
	Return % "False"
}

GetVariableString(codestring, whichone, linenumber)
{
	if (whichone == "Gui")
	{
		variablestrings:= StrSplit(codestring, ",")
		for index, variablestring in variablestrings
		{
			if (index > 4)
				Continue
			IfInString, variablestring, %A_Space%v
				thisvariablestring:=% variablestring
		}
		variablestring:= StrSplit(thisvariablestring, A_Space)
		for index, variable in variablestring
		{
			thisvariableletter:= SubStr(variable, 1, 1)
			if (thisvariableletter == "v")
				Return % variable "[thissplitter] Gui variable[Filter='Gui'] Line number is found at: " linenumber "`n"
		}
		Return % variable "[thissplitter] Gui variable Line number is found at: " linenumber "`n"
	}
	if (whichone == "Quotes")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [quotes]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		variablestrings:= StrSplit(codestring, "[quotes]")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 0)
				IfNotInString, variablestring, %A_Space%
					IfNotInString, variables, % variablestring
						variables.= "[quotes]" variablestring "[quotes][thissplitter] explicit[Filter='explicit'] variable Line number is found at: " linenumber "`n"
		}
		Return % variables
	}
	if (whichone == "Percent")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [percent]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		IfInString, codestring, `,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					IfInString, variablestring, [percent]
						IfNotInString, variablestring, =
							IfInString, variablestring, A_Space
								variables.= variablestring "[thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		IfNotInString, codestring, `,
		{
			IfInString, codestring, =
			{
				variablestrings:= StrSplit(codestring, "=")
				for index, variablestring in variablestrings
				{
					if (index == 1)
					{
						variables:= StrSplit(variablestring, A_Space)
						for index, variable in variables
							thisvariable:=% variable
					}
					if (index == 2)
						codestring:=% variablestring
				}
			}
			variablestrings:= StrSplit(codestring, "[percent]")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					variables.= "[percent]" variablestring "[percent][thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		if (thisvariable != "")
			variables.= thisvariable "[thissplitter]implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
		Return % variables
	}
	if (whichone == "Equals")
	{
		variablestrings:= StrSplit(codestring, "=")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 1)
				IfNotInString, variablestring, [quotes]
				{
					thisvariablestring:= StrSplit(variablestring, A_Space)
					for index, thisvariable in thisvariablestring
					{
						variable:=% thisvariable "[thissplitter] implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
					}
				}
		}
		Return % variable
	}
	Return % "Not Found"
}

RemoveCertainChars(string, special)
{
	if (special == "Start")
	{
		StringReplace, string, string, ", [quotes], ALL ; "
		StringReplace, string, string, `%%A_Space%, [percent], ALL
		StringReplace, string, string, `%, [percent], ALL
		StringReplace, string, string, %A_Space%:, :, ALL
		StringReplace, string, string, :=, =, ALL
		StringReplace, string, string, ==, =, ALL
		StringReplace, string, string, >, =, ALL
		StringReplace, string, string, <, =, ALL
		StringReplace, string, string, %A_Space%!=, =, ALL
		StringReplace, string, string, =%A_Space%, =, ALL
		StringReplace, string, string, %A_Space%=, =, ALL
		StringReplace, string, string, ), , ALL
		StringReplace, string, string, (, , ALL ;)
		StringReplace, string, string, `t, , ALL
	}
	if (special == "End")
	{
		StringReplace, string, string, [quotes], ", ALL ; "
		StringReplace, string, string, [percent], `%, ALL
		StringReplace, string, string, `,, , ALL
	}
	Return % string
}

GetButton_Count()
{
	Loop,
	{
		ButtonCountCheck:= GetControl("ButtCount")
		if (ButtonCountCheck != OldButtonCountCheck)
		{
			OldCount:=% Count
			OldButton:=% Button
			Sleep, 500
			ButtonCount_Split:= StrSplit(ButtonCountCheck, ",")
			For Index, ButtCount in ButtonCount_Split
			{
				if (Index == 1)
					Count:=% ButtCount
				if (Index == 2)
					Button:=% ButtCount
			}
		}
		else if (ButtonCountCheck == OldButtonCountCheck)
			Break
		if ((Button != OldButton)&&(Count > 1))
			Break
		OldButtonCountCheck:=% ButtonCountCheck
	}
	if (Button == OldButton)
	{
		ButtonCountReturn:=% Count "," Button
		GuiControl,AI:, ButtonCountCheck, % "0," Button
	}
	if (Button != OldButton)
	{
		NewCount:=% Count-OldCount
		GuiControl,AI:, ButtonCountCheck, % NewCount "," Button
		ButtonCountReturn:=% OldCount "," OldButton
	}
	Return
}

ApplyLogicalChange(activeuserinput, logicalhistory, numberofdifferences)
{
	x:= 0
	newhistoryrecord:=[]
	activeuserinputlastline:= GetLineCount(activeuserinput)
	logicalhistorylastline:= GetLineCount(logicalhistory)
	LastLine:= logicalhistory["linePos" logicalhistorylastline]
	Loop, % activeuserinputlastline
	{
		record:=
		x++ ; a lagged y variable needed to stagger history.
		occurenceuser:= activeuserinput["linePos" x]
		if (y > 0)
		{
			y:=(x-z) ; this will be an opposite staggered y (x+z) for deleted lines.
			historyrecord:= logicalhistory["linePos" y]
		}
		else
			historyrecord:= logicalhistory["linePos" x] ; even though the line now isn't right doesn't mean next time it won't be.
		splithistoryrecord:= StrSplit(historyrecord, ["(hardReturn)", "(softReturn)"])
		for index, splithistory in splithistoryrecord
		{
			if (Index == 1)
				record:= % splithistory
		}
		if ((occurenceuser != record)&&(numberofdifferences != 0)) ; the number of occurences go negative when lines get deleted... I haven't updated the below else for that yet.
		{
			LastLine:= logicalhistory["linePos" logicalhistorylastline] ; if a user is lagging the array make sure you are putting in last lines right.
			if ((LastLine == "(softReturn)")||(LastLine == "(hardReturn)")) ; the last line shouldn't be any other value.
			{
				z++ ; a z variable making sure we don't lose y and holding the number of occurences.
				if (z == 1) ; there's not enough time to add different enters in different spots (meaning the user couldn't add enough enters in the time this will be done).
					y:=% x
				IfInString, LastLine, (softReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
				IfInString, LastLine, (hardReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
				numberofdifferences--
				logicalhistorylastline--
			} ; the likely answer is a deleted line in occurenceuser. we need to add to the numberofdifferences. I'll also need to update this in the future for the array.
			else
				numberofdifferences++
		}
		else if ((occurenceuser != record)&&(numberofdifferences == 0)) ; meaning user has updated a line with a new record
		{
			newhistoryrecord["linePos" x]:= occurenceuser
			IfInString, record, (softReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
			IfInString, record, (hardReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
		} ; z from above holds all change counts. y from above holds the history record line back. technically y can equal x-z or just y++. I think for greater clarity it should be x-z because a user may choose to purposely lag the logicalhistoryarray Change function. Basically this function can be implimented at will as long as the keys are being kept up with and added to the historyarray in the main loop (of course that might also come with logical array issues).
		else if ((occurenceuser == record)&&(numberofdifferences == 0))
			newhistoryrecord["linePos" x]:= record
	}
	check:=GetControl("GetKeeper")
	if (check == "7h151s@a#res37")
		Return
	Return % newhistoryrecord ; There has been many different statements on using the % after Return or in ":=" as an operorator (it technically doesn't need to be done and can cause issues if done improperly). I use it because honestly it's like my signature to my work.
}

Doppler(usersentence, historysentence)
{
	livewords:=[]
	pastwords:=[]
	check:=GetControl("GetKeeper")
	if (check == "&not@a#rea1*sent3nc3")
	{
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			livewords["wordPos" key]:= userwords
		}
		historysplit:=StrSplit(historysentence, A_Space)
		for key, historywords in historysplit
		{
			pastwords["wordPos" key]:= historywords
		}
		usercount:=GetLineCount(livewords)
		historycount:= GetLineCount(pastwords)
		Loop, % usercount
		{
			x++
			userword:=livewords["wordPos" x]
			historyword:=pastwords["wordPos" x]
			userwordlength:=StrLen(userword)
			historywordlength:= StrLen(historyword)
			if ((userword != historyword)||(historycount < x))
				GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		}
		StringReplace, userword, userword, historyword, , ALL
	}
	else if (check != "&not@a#rea1*sent3nc3")
	{
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 1)
				historyword:=% chec
			if (index == 2)
				ouserword:=% chec
			if (index == 3)
				x:=% chec
		}
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			if (key == x)
				userword:=% userwords
		}
		GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		StringReplace, userword, userword, historyword, , ALL
	}
	userwordlength:=StrLen(userword)
	if (userwordlength < 2)
	{
		GuiControl, AI:, Information, Working...
		SpellChecker(0)
	}
	if (userwordlength > 3)
	{
		GuiControl, AI:, Information, Working.
		ourwords:=WordCheck(userword, userwordlength)
		if (ourwords == "")
			SpellChecker(0)
		else if (ourwords != "")
		{
			SpellChecker(userwordlength)
			GetControl(ourwords)
		}
	}
	Return
}

FixLogicalhistory_Array(historyarray, howmanylines)
{
	lastline:= GetLineCount(historyarray)
	whichbutton:= GetControl("ButtCount")
	Loop, % howmanylines
	{
		lastline++
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					historyarray["linePos" lastline]:= "(softReturn)"
				if (butt == "Enter")
					historyarray["linePos" lastline]:= "(hardReturn)"
			}
		}
	}
	Return % historyarray
}

ReturnLineArray(lines, user)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/SoftReturn\|/", "\|/userReturns\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

GetButtonCount(pressed)
{
	pressing:= StrSplit(pressed, ",")
	For Index, press in pressing
		if (Index == 1)
			Return % press
}

FindingRealLineLOL(occurenceuser, rowbefore, thisrow)
{
	IfInString, occurenceuser, %rowbefore%
	{
		rowlength:= StrLen(rowbefore)
		occurencelength:= StrLen(occurenceuser)
		subtractedlength:=(occurencelength-rowlength)
		thisstring:= SubStr(occurenceuser, subtractedlength, occurencelength)
		if (thisstring == rowbefore)
		{
			IfInString, occurenceuser, %thisrow%
				Return % "Found"
			IfNotInstring, occurenceuser, %thisrow%
				Return % "NextRow"
		}
	}
	if (rowbefore == "NextRow")
		IfInString, occurenceuser, %thisrow%
			Return % "Found"
	Return % "NotFound"
}

ProcessStart(contents, Rest)
{
	logicalhistory:= []
	WinSet, Transparent, 0, Words
	history:= GetHistory()
	logicalhistory:= ReturnLineArray(history, user)
	Control, Disable ,, Edit4, AI
	GuiControl, AI:, Edit4, % contents
	Sleep, % Rest
	Control, Enable ,, Edit4, AI
	GuiControl, AI:, Information, Done
	Control, Enable ,, ListBox1, AI
	Return % logicalhistory
}

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	if (n > 3)
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	if (n == 0)
		WinSet, Transparent, 0, Words
	WinGet, visible, Transparent, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	Return
}
Return

ReturnClearDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			hinput:= harray["linePos" x]
			hsplit:= StrSplit(hinput, ["(hardReturn)", "(softReturn)"])
			for Index, h in hsplit
			{
				if (Index == 1)
					checkh:= % h
			}
			uinput:= uarray["linePos" x]
			StringReplace, uinput, uinput, (softReturn), , ALL
			StringReplace, uinput, uinput, (hardReturn), , ALL
			l_checkh:= StrLen(checkh)
			l_uinput:= StrLen(uinput)
			if (uinput != checkh)
				Return % x
			if (l_checkh != l_uinput)
				Return % x
			if (x == v)
				Break
			checkh:=
		}
		Return % "0"
	}
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return % "True"
	}
}

GetLineCount(arraycount)
{
	LastLine:=0
	for Index, count in arraycount
		++LastLine
	Return % LastLine
}

GetControl(FocTex)
{
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, Edit3
	ControlGet, row, CurrentLine, , Edit3, AI
	ControlGet, rowtext, Line, % row, Edit3, AI
	GuiControlGet, Word, Words:, Listbox1
	StringReplace, text, text, `n, \|/userReturns\|/, ALL
	GuiControlGet, ButtonCountCheck, AI:, ButtonCountCheck
	GuiControlGet, Save_File, AI:, AISave
	GuiControlGet, DopplerGet, AI:, WordKeeper
	if (FocTex == "RowText")
		Return % rowtext
	if (FocTex == "GetKeeper")
		Return % DopplerGet
	if (FocTex == "AISave")
		Return % Save_File
	if (FocTex == "ButtCount")
		Return % ButtonCountCheck
	if (FocTex == "Row")
		Return % row
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	GuiControl, Words:, Listbox1, | 
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
	Return
}

HashContents(contents)
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, \|/CR+LF\|/, `n, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, `n, ALL
	Return % contents
}

GetHistory()
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, `r`n,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, (softReturn)\|/SoftReturn\|/, ALL
	StringReplace, contents, contents, \|/CR+LF\|/,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, (softReturn)\|/SoftReturn\|/, ALL
	Return % contents
}

RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitapp

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 23 Dec 2023, 00:58

Finally functional "Get tools" are added.

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability. ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
#InstallkeybdHook
#InstallMouseHook
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
Global Settings:= % Cache "\Settings.ini"
IniRead, Directory, % Settings, Directory, Key1
if (Directory != "ERROR")
	SetWorkingDir %Directory%
else
	SetWorkingDir %A_ScriptDir% 
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)
IniRead, Editor, % Settings, Editor, Key1
if (Editor == "ERROR")
	Editor:=% "Notepad.exe"
IniRead, Rest, % Settings, Timers, Key1
If (Rest == "ERROR")
{
	IniWrite, 10000, % Settings, Timers, Key1
	Rest:= 10000
}
IniRead, Notactive, % Settings, Timers, Key2
if (Notactive == "ERROR")
{
	IniWrite, 500, % Settings, Timers, Key2
	Notactive:= 500
}
IniRead, NoDif, % Settings, Timers, Key3
if (NoDif == "ERROR")
{
	IniWrite, 25, % Settings, Timers, Key3
	NoDif:= 25
}
IniRead, Always, % Settings, AlwaysOnTop, Key1
if (Always != "ERROR")
	GuestOn:=% Always
IniRead, DefaultLoc, % Settings, WinManager, Key1

Loop, Files, *.ahk, F R
{
	IfInString, A_LoopFileName, @
		Continue
	IfNotInString, wi, % A_LoopFileName
		wi=%wi%%A_LoopFileName%|
}

Menu, AIsMenu, Add, Minimize, Minimize
Menu, Settings, Add, Timers, Timers
Menu, Settings, Add, AlwaysOnTop`ton/off, Always
Menu, Settings, Add, Suspend`ton/off, SusOnOff
Menu, Settings, Add, Reload`tCtrl+r, Reload
Menu, AIsMenu, Add, Settings, :Settings
Menu, Default, Add, Default Editor, Editor
Menu, Default, Add, Default Settings, Default
Menu, AIsMenu, Add, Default, :Default

SetTitleMatchMode, 2
CoordMode, Caret, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Window
if (GuestOn == 1)
	Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
else if (GuestOn == 0)
	Gui, AI:New, -AlwaysOnTop +Resize +toolWindow
else
	Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, AI:Font, 0f0d03, Arial
Gui, Menu, AIsMenu
Gui, Add, Edit, r1 x25 y21 w150 ReadOnly vWorking, % A_WorkingDir
Gui, Add, DropDownList, x25 y55 w150 vChangeType gChangeType, Get Variables||Get Function|Create Test File
Gui, Add, GroupBox, x25 y90 h250 w150 wrap vResults, Get variables`n(Filter results by Checkbox)
Gui, Add, ListBox, r10 yp+35  xp+15 w120 gFileSelected vFileSelected, %wi%
Gui, Add, Edit, r4 yp+150 xp -VScroll vTestInfo w120,  Select a file to create a Test.ahk file with no function or sublabeled function.
Gui, Add, Text, yp xp vFunctionLabel, input the function lablel
Gui, Add, Edit, r1 w120 vFunctionName,
Gui, Add, Checkbox, vAssociateV, Associated functions
Gui, Add, Checkbox, yp-40 xp vGui, Gui Variables
Gui, Add, Checkbox, vExplicit, Explicit Variables
Gui, Add, Checkbox, vImplicitExplicit, Implicit-Explicit
Gui, Add, Text, -E0x200 x0 y0 vButtonCountCheck w0, 0,Unknown
Gui, Add, Text, -E0x200 vWordKeeper w0, &not@a#rea1*sent3nc3s
Gui, Add, Edit,  r18 ym+45 x200 vWords w325 hwndTracker,
Gui, Add, Edit, r4 ym+45 x200 w325 ReadOnly vPixMouse, (pixel color)`t(Mouse Position)
Gui, Add, Edit, r4 yp+70 x200 w325 ReadOnly vWinStats, x y h w (Coordinate mode)
Gui, Add, Edit, r8 yp+70 x200 w325 ReadOnly vWinText, Text on the locked screen:
Gui, Add, Button, gAISave, Save
Gui, Add, Text, vAISave w0, Don't save
Gui, Add, Button, x250 y317 gAIClear, Clear
Gui, Add, Edit,  r1 ym+15 x200 vWindowControl w325,
Gui, Add, Text, ym+315 x470 vInformation, Loading...
Gui, Add, Text, ym+17 x550 vWindowLabel gLock +Border Center h18, %A_Space%%A_Space%+`tAdd Window%A_Space%%A_Space%
Gui, Add, Edit, ym+45 x550 w150 vWelcome -VScroll ReadOnly, Welcome to my program. Above you will see a Label named Add Window. This is a control bar Click it to see other controls. Left and right navigation buttons are beside it to add further Controls. To the left of the screen you will notice your "Working directory" is added in case you need to know it. below is the default editor. In the center is collected information from "Get Variables", "Functions"... It can also be a scratch pad.`n I hope you enjoy using my program. Have a Good day!
Gui, Add, Text, ym+17 x660 w20 vRightnav gRightNav +Border Center h18,
Gui, Add, Text, ym+17 x679 w20 vLeftNave gLeftNav +Border Center h18, >
Gui, Add, GroupBox, ym+50 x550 h250 w150 wrap vGroupControls, Window Controls
Gui, Add, Checkbox, yp+40 xp+10 vGetWindow gLocktoWindow, Lock Window Control
Gui, Add, Checkbox, yp+20 xp vSnapWindow gSnapToWindow, Snap to Window
Gui, Add, Checkbox, yp+20 xp vSnapToEditor gSnapToEditor, Snap to Editor
Gui, Add, Checkbox, yp+20 xp vAutoEdit gAutoEdit, Enable Auto Edit
Gui, Add, Checkbox, yp+20 xp vEnableCC gEnableCC, Enable copy anywhere
Gui, Add, Checkbox, yp+20 xp vEnableVV gEnableVV, Enable paste 2nd Clip
Gui, Add, Edit, yp+20 xp r5 w130 -VScroll ReadOnly vControlInformation, Information about the above controls
Gui, Add, Edit, yp+105 xp-10 r1 w150 -VScroll ReadOnly vDefaultEdit, % Editor
Gui, Add, DropDownList, yp-240 xp+10 w130 vCoordinateM, CoordMode Screen||CoordMode Relative|CoordMode Window|CoordMode Client
Gui, Add, Checkbox, yp+30 xp vGetPix gGetPix, Get Pixel Color
Gui, Add, Checkbox, yp+20 xp vGetMouse gGetMouse, Get Mouse Pos
Gui, Add, Checkbox, yp+20 xp vGetWinS gGetWinS, Get Window Stats
Gui, Add, Checkbox, yp+20 xp vGetWinT gGetWinT, Get Window Text
Gui, Add, Checkbox, yp+20 xp vMultiSele gMultiSele, Multi-Select
Gui, Margin, 50, 30
Gui, Color, d6d5d0, f5f4f0
Gui, Show, h400, AI work
WinGetPos , AIPosX, AIPosY, AIorignalwidth, AIorignalhieght, AI
AddWindowGroupControl("Hide")
GetWindowGroupControl("Hide")
GuiControl, AI:Hide, PixMouse
GuiControl, AI:Hide, WinStats
GuiControl, AI:Hide, WinText
GuiControl, AI:Hide, GroupBox2
GuiControl, AI:Hide, FunctionName
GuiControl, AI:Hide, FunctionLabel
GuiControl, AI:Hide, ControlInformation
Control, Disable, , Edit10, AI
GuiControl, AI:Hide, Button2
GuiControl, AI:Hide, TestInfo
Control, Disable , , TestInfo, AI
Control, Disable , , Welcome, AI
GuiControl, Focus, Words
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, Add, Text, vClipBoard2 w0 h0 x5 y5,
Gui, Add, Text, vClipBoard3 w0 h0 x5 y5,
Gui, margin, 0, 0
Gui, Show, , Words
GuiControl, Words:Hide, ClipBoard2
GuiControl, Words:Hide, ClipBoard3

contents:=HashContents(contents)
logicalhistory:= []
logicalhistory:= ProcessStart(contents, Rest)
activeuserinput:= []
navigationLR:=[]

Loop,
{
	ThisModifier()
	ClipBoardFunction()
	thistrack:= Tracker(thistrack, DefaultLoc, Whichone, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	if (A_TimeIdle > 3000)
	{
		thisz++
		if (thisz == 1)
			GuiControl, AI:, Information, Done
		Sleep, % Notactive
		Continue
	}
	winwonder:=WinWonder()
	if (winwonder == "False")
	{
		SpellChecker(0)
		Sleep, % Notactive
		Continue
	}
	check:=GetControl("GetKeeper")
	usersentence:=GetControl("RowText")
	if (recordkeeper == "")
		recordkeeper:=% usersentence
	if (recordkeeper != usersentence)
	{
		Doppler(usersentence, recordkeeper)
		recordkeeper:=% usersentence
	}
	getuserinput:= GetControl("Text")
	activeuserinput:=ReturnLineArray(getuserinput, "user")
	historylastline:= GetLineCount(logicalhistory)
	activeuserlastline:= GetLineCount(activeuserinput)
	if (check == "7h151s@a#res37")
	{
		If (getuserinput == "")
		{
			Sleep, % Notactive
			Continue
		}
		GuiControl, AI:, WordKeeper, &not@a#rea1*sent3nc3
		contents:=HashContents(contents)
		logicalhistory:= ProcessStart(contents, Rest)
		Continue
	}
	if (usersentence != "")
	{
		if (activeuserlastline != historylastline)
		{
			logicallastlineaddition:=(activeuserlastline-historylastline)
			logicalhistory:= FixLogicalhistory_Array(logicalhistory, logicallastlineaddition) ; where last lines are being put in. and you will also want to function in lastline (Deleted_Line) to acompany the changes. if you are lagging ApplyLogicalChange().
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, logicallastlineaddition)
		}
		if (activeuserlastline == historylastline)
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, 0)
	}
	savecheck:= GetControl("AISave")
	if (savecheck == "Save_File")
	{
		historycount:=GetLineCount(logicalhistory)
		Loop, % historycount
		{
			x++
			sentences:= logicalhistory["linePos" x]
			StringReplace, sentences, sentences, (softReturn), \|/softReturn\|/, ALL
			StringReplace, sentences, sentences, (hardReturn), \|/CR+LF\|/, ALL
			FileContents:=% FileContents sentences
		}
		FileMove, % Temp, % TempBack, 1
		FileAppend, % FileContents, % Temp, UTF-8
		GuiControl,AI:, AISave, Don't Save
	}
}
Return

ThisModifier()
{
	GuiControlGet, Locked, AI:, GetWindow
	GuiControlGet, WinName, AI:, WindowControl
	GuiControlGet, PixButton, AI:, GetPix
	GuiControlGet, StatButton, AI:, GetWinS
	GuiControlGet, TextButton, AI:, GetWinT
	WinGetPos , WinX, WinY, WinWidth, WinHeight, AI
	PositionSquareX:=(WinX+WinWidth)
	PositionSquareY:=(WinY+WinHeight)
	MouseGetPos, positionX, positionY
	if ((Locked == 1)&&(WinName != ""))
	{
		if ((PixButton == 1)||(StatButton == 1)||(TextButton == 1))
		{
			If ((positionX < WinX)||(positionX > PositionSquareX)||(positionY < WinY)||(positionY > PositionSquareY))
			{
				IfWinActive, % WinName
					Hotkey, LButton, On
			}
			else
				Hotkey, LButton, Off
		}
		else
			Hotkey, LButton, Off
	}
	else
		Hotkey, LButton, Off
	Return
}

LButton::
GuiControlGet, ThisMode , AI:, CoordinateM
orignalMouseMode:=% A_CoordModeMouse
orignalPixelMode:=% A_CoordModePixel
if (ThisMode == "CoordMode Screen")
{
	CoordMode, Screen , Pixel
	CoordMode, Screen , Mouse
}
if (ThisMode == "CoordMode Relative")
{
	CoordMode, Relative , Pixel
	CoordMode, Relative , Mouse
}
if (ThisMode == "CoorMode Window")
{
	CoordMode, Window , Pixel
	CoordMode, Window , Mouse
}
if (ThisMode == "CoordMode Client")
{
	CoordMode, Client , Pixel
	CoordMode, Client , Mouse
}
MouseGetPos, positionX, positionY
GuiControlGet, WinName, AI:, WindowControl
WinGetPos , WinX, WinY, WinWidth, WinHeight, % WinName
GuiControlGet, PixButton, AI:, GetPix
if (PixButton == 1)
	PixelGetColor, color,%positionX%, %positionY%
GuiControlGet, StatButton, AI:, GetWinS
GuiControlGet, TextButton, AI:, GetWinT
GuiControlGet, Multi, AI:, MultiSele
GuiControlGet, MouseButton, AI:, GetMouse
GuiControlGet, PixMouse, AI:, PixMouse
if (Multi == 1)
{
	if ((PixButton == 1)&&(MouseButton == 1))
		GuiControl, AI:, PixMouse, % PixMouse "`n" color "`t" positionX ", " positionY
	if ((PixButton != 1)&&(MouseButton == 1))
		GuiControl, AI:, PixMouse, % PixMouse "`nNo color`t" positionX ", " positionY
	if ((PixButton == 1)&&(MouseButton != 1))
		GuiControl, AI:, PixMouse, % PixMouse "`n" color "`tNo mouse"
}
if (Multi != 1)
{
	if ((PixButton == 1)&&(MouseButton == 1))
		GuiControl, AI:, PixMouse, % "(pixel color)`t(Mouse Position)`n"  color "`t" positionX ", " positionY
	if ((PixButton != 1)&&(MouseButton == 1))
		GuiControl, AI:, PixMouse, % "(pixel color)`t(Mouse Position)`nNo color`t" positionX ", " positionY
	if ((PixButton == 1)&&(MouseButton != 1))
		GuiControl, AI:, PixMouse, % "(pixel color)`t(Mouse Position)`n" color "`tNo mouse"
}
GuiControlGet, WinStats, AI:, WinStats
WinStats:= StrReplace(WinStats, "x y h w (Coordinate mode)`n", "")
if ((Multi == 1)&&(StatButton == 1))
	GuiControl, AI:, WinStats, % "x" WinX ", y" WinY ", h" WinWidth ", w" WinHeight "`t(" ThisMode ")`n" WinStats
if ((Multi != 1)&&(StatButton == 1))
	GuiControl, AI:, WinStats, % "x" WinX ", y" WinY ", h" WinWidth ", w" WinHeight "`t(" ThisMode ")"
GuiControlGet, AIWinText, AI:, WinText
TextLength:= StrLen(AIWinText)
WinGetText, WinText , % WinName
if ((TextLength == 26)&&(WinText != "")&&(TextButton == 1))
	GuiControl, AI:, WinText, % WinText
CoordMode, Screen, Pixel
CoordMode, Screen, Mouse
Return

~LCtrl::
thiskeystate:= GetKeyState("LCtrl", P)
if (thiskeystate != 0)
{
	Loop,
	{
		GuiControlGet, EnableCC, AI:, EnableCC
		GuiControlGet, EnableVV, AI:, EnableVV
		CtrlC := Chr(3)
		if (EnableVV == 1)
		{
			CtrlVV:= (Chr(22) . Chr(22))
			CtrlVVV:= (Chr(22) . Chr(22) . Chr(22))
			ClipBoardFunction()
			GuiControlGet, ClipBoard2, Word:, ClipBoard2
			GuiControlGet, ClipBoard3, Word:, ClipBoard3
		}
		Input, userinput, L3 T0.75 M ; this has a 0.75 second timer... That feels a little natural. however on the person to person scale this might need adjusted.
		if (EnableVV == 1)
		{
			if (userinput == CtrlVV)
			{
				saveClip:=% ClipBoard
				ClipBoard:=% Clipboard2
				Send, ^v
				ClipBoard:=% saveClip
				saveClip:=
			}
			else if (userinput == CtrlVVV)
			{
				saveClip:=% ClipBoard
				ClipBoard:=% Clipboard3
				Send, ^v
				ClipBoard:=% saveClip
				saveClip:=
			}
		}
		else if ((userinput == CtrlC CtrlC)&&(EnableCC == 1))
		{
			logicalhistorylastline:= GetLineCount(logicalhistory)
			Loop, % logicalhistorylastline
			{
				thisx++
				saveline:= logicalhistory["linePos" thisx]
				saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
				saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
				thesecontents.= saveline
			}
			thesecontents:= SpecialReplace(thesecontents)
			MsgBox, % "The edit fields are ready to be sent. It autosends after this message. After you learn how this works you can delete this messge on line 237. Make sure the place you want your text sent is +lastfound"
			Send, % thesecontents
			thisx:=
			thesecontents:=
		}
		else if (userinput == CtrlC)
			Send, ^c
		else
			Send, ^%userinput%
		thiskeystate:= GetKeyState("LCtrl", P)
		if (thiskeystate == 0)
			Break
	}
}
Return
	
ClipBoardFunction()
{
	if ((ClipBoard != "")&&(ClipBoard != ClipBoard2))
	{
		if (ClipBoard2 == "" )
			ClipBoard2:=% ClipBoard1
		else if (ClipBoard2 != "")
		{
			ClipBoard3:=% ClipBoard2
			ClipBoard2:=% ClipBoard
		}
	}
	if (ClipBoard2 != "" )
		GuiControl,Word:, ClipBoard2, % ClipBoard2
	if (ClipBoard3 != "" )
		GuiControl,Word:, ClipBoard3, % ClipBoard3
	Return
}

$Backspace::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Backspace}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Backspace}
	}
	Return
}
else
	Send, {Backspace}
Return

$Space::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Space}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Space}
	}
	Return
}
else
	Send, {Space}
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		check:=GetControl("GetKeeper")
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 2)
				userword:=% chec
		}
		str:= StrLen(userword)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
	}
	else
	{
		Send, `t
	}
	Return
}
else
	Send, `t
Return

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	GuiControlGet, AutoEdit, AI:, AutoEdit
	If (AutoEdit == 1)
	{
		logicalhistorylastline:= GetLineCount(logicalhistory)
		Loop, % logicalhistorylastline
		{
			thisx++
			saveline:= logicalhistory["linePos" thisx]
			saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
			saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
			thesecontents.= saveline
		}
		thesecontents:= SpecialReplace(thesecontents)
		GuiControlGet, wintitle, AI:, WindowControl, WindowControl
		if (wintitle == "")
		{
			MsgBox, Please lock to a window first
			Return
		}
		WinActivate, % wintitle
		WinWait, % wintitle
		Send, % thesecontents
		FileMove, % Temp, % TempBack, 1
		FileAppend, , % Temp, UTF-8
		GuiControl, AI:, Words,
		logicalhistory:=[]
		thisx:=
		thesecontents:=
	}
	else if (AutoEdit == 0)
	{
		ButtonCountCheck:= GetControl("ButtCount")
		PressCount:=GetButtonCount(ButtonCountCheck)
		PressCount++
		WhichButtonCount:=% PressCount ",ShiftEnter"
		GuiControl, AI:, ButtonCountCheck, % WhichButtonCount
		KeyWait, Backspace, U
		GetButton_Count()
	}
}
Return

~Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	GuiControlGet, AutoEdit, AI:, AutoEdit
	If (AutoEdit == 1)
	{
		logicalhistorylastline:= GetLineCount(logicalhistory)
		Loop, % logicalhistorylastline
		{
			thisx++
			saveline:= logicalhistory["linePos" thisx]
			saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
			saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
			thesecontents.= saveline
		}
		thesecontents:= SpecialReplace(thesecontents)
		GuiControlGet, wintitle, AI:, WindowControl, WindowControl
		if (wintitle == "")
		{
			MsgBox, Please lock to a window first
			Return
		}
		WinActivate, % wintitle
		WinWait, % wintitle
		Send, % thesecontents "+{Enter}"
		FileMove, % Temp, % TempBack, 1
		FileAppend, , % Temp, UTF-8
		GuiControl, AI:, Words,
		logicalhistory:=[]
		thisx:=
		thesecontents:=
	}
	else if (AutoEdit == 0) ;
	{
		ButtonCountCheck:= GetControl("ButtCount")
		PressCount:=GetButtonCount(ButtonCountCheck)
		PressCount++
		WhichButtonCount:=% PressCount ",Enter"
		GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
		KeyWait, Backspace, U
		GetButton_Count()
	}
}
Return

SpecialReplace(thesecontents)
{
	fixedcharacters:= StrReplace(thesecontents, "!", "{!}")
	fixedcharacters:= StrReplace(fixedcharacters, "#", "{#}")
	fixedcharacters:= StrReplace(fixedcharacters, "+", "{+}")
	fixedcharacters:= StrReplace(fixedcharacters, "^", "{^}")
	fixedcharacters:= StrReplace(fixedcharacters, "{", "{{}") ; if this is done then output will be {{}
	fixedcharacters:= StrReplace(fixedcharacters, "}", "{}}") ; from the above if this is done output will be {{{}}
	fixedcharacters:= StrReplace(fixedcharacters, "{{{}}", "{{}")
	Sleep, 50
	Tabcontrol:= StrSplit(fixedcharacters, ["(hardReturn)", "(softReturn)"])
	for index, Tabs in Tabcontrol
	{
		IfinString, Tabs, % "`t" ; <----- it is assumed the editor you're using controls tab.
		{
			thiscount:= StrReplace(Tabs, "`t", "", thismany)
			thisstring:=% thiscount
			if (thismany != thatmany)
			{
				if (thismany > thatmany)
				{
					n:=(thismany-thatmany)
					thisbutton:=% "{Tab " n "}"
				}
				if (thismany < thatmany)
				{
					n:=(thatmany-thismany)
					thisbutton:=% "{Backspace " n "}"
				}
			}
		}
		IfNotInString, Tabs, % "`t"
		{
			if (thismany > 1)
				thisbutton:=% "{Backspace " n "}"
			else if (thismany == 1)
			{
				thismany:=0
				thisbutton:=% "{Backspace}"
			}
			else if (thismany == 0)
				thisbutton:=% ""
			thisstring:=% Tabs
		}
		thatmany:=% thismany
		edittext.= thisbutton thisstring
		thisbutton:= ""
	}
	edittext:= StrReplace(edittext, "[Enter]", "{Backspace}{Enter}")
	edittext:= StrReplace(edittext, "[ShiftEnter]", "{Backspace}+{Enter}")
	Return % edittext
}

EnableVV:
GuiControl, AI:, ControlInformation, This enables paste from second and third ClipBoard. {LCtrl}+vv and {LCtrl}+vvv. if clipboard2 or 3 sends acsii code
Return

SnapToWindow:
GuiControl, AI:, ControlInformation, This will place the Main Gui in one of 9 locations on the locked window.
GuiControl, AI:, Button11, 0
IniRead, DefaultLoc, % Settings, WinManager, Key1
GuiControlGet, fullwindow, AI:, WindowControl
if (fullwindow == "")
{
	MsgBox, 262144, Please lock to a window., Please first lock to a window.
	GuiControl, AI:, Button10, 0
	Return
}
GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
Return
	

SnapToEditor:
GuiControl, AI:, ControlInformation, This will place the Main Gui in one of 9 locations on the editor. Notepad is Default.
GuiControlGet, DefaultEdit, AI:, DefaultEdit
GuiControl, AI:, Button10, 0
IfInString, DefaultEdit, .
{
	windows:= StrSplit(DefaultEdit, ".")
	for index, window in windows
		if (index == 1)
			thiswindow:=% window
}
WinGetTitle, fullwindow, % "ahk_class" thiswindow
if (fullwindow == "")
{
	MsgBox, 4, Window Not Found!, % "The current Editor is not open:`nahk_class " thiswindow "`nWould you like to open it?"
	IfMsgBox Yes
		run, % DefaultEdit
	IfMsgBox No
		Return
	Loop,
	{
		Sleep, 150 ; prevent needless process
		WinGetTitle, fullwindow, % "ahk_class" thiswindow
		if (fullwindow != "")
			Break
		x++
		if (x > 15)
		{
			MsgBox, There is an error opening the window or a naming error. ;"
			Return
		}
	}
}
IfWinExist, % fullwindow
{
	IniRead, DefaultLoc, % Settings, WinManager, Key1
	GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
}
Return

AutoEdit:
GuiControl, AI:, ControlInformation, On Enter ({Enter} or +{Enter} this button sends to your default editor if it's active and Clears the window.
Return

EnableCC:
GuiControl, AI:, ControlInformation, This activates {LCtrl}+cc when you press that (anywhere) main edit contents are autosent to insert location.
Return

LocktoWindow:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This button locks the Gui to a running window. Just activate the window you want.
if (GetWindow == 1)
{
	WinGetActiveTitle, checkthistitle
	GuiControl, AI:, WindowControl, Select a window to lock to.
	Loop,
	{
		WinGetActiveTitle, newtitletocheck
		if (newtitletocheck == "")
			Continue
		if (checkthistitle != newtitletocheck)
			Break
	}
	GuiControl, AI:, WindowControl, % newtitletocheck
	GuiControl, Disable, WindowControl
}
if (GetWindow == 0)
{
	GuiControl, AI:, WindowControl,
	GuiControl, Enable, WindowControl
}
Return

GetPix:
GuiControl, AI:, ControlInformation, This enables get pixel color to the locked screen on click. Make sure you are using the mode you prefer.
Return

GetMouse:
GuiControl, AI:, ControlInformation, This enables get Mouse Pos on click to the locked window. Make sure you are using the mode you prefer.
Return

GetWinS:
GuiControl, AI:, ControlInformation, This will provide the locked windows height width and left corner x and y positions.
Return

GetWinT:
GuiControl, AI:, ControlInformation, This will give the text to the locked window (hidden and seen). 
Return

MultiSele:
GuiControl, AI:, ControlInformation, In the event you need more than one color or mouse position enable this to record multiple clicks.
Return

RightNav:
Gui, Submit, NoHide
LeftNav:
Gui, Submit, NoHide
GuiControlGet, thislabelmenu, AI:, WindowLabel
IfInString, thislabelmenu, +
{
	IfInString, thislabelmenu, Add Window
		navigationLR["AddWindow"]:= 0
	IfInString, thislabelmenu, Get Tools
		navigationLR["GetTools"]:= 0
}
IfInString, thislabelmenu, -
{
	IfInString, thislabelmenu, Add Window
		navigationLR["AddWindow"]:= 1
	IfInString, thislabelmenu, Get Tools
		navigationLR["GetTools"]:= 1
}
If (A_ThisLabel == "RightNav")
{
	labelname:= StrReplace(thislabelmenu, "`t      Get Tools", "`tAdd Window")
	addopen:= navigationLR["AddWindow"]
	GuiControl, AI:Hide, PixMouse
	GuiControl, AI:Hide, WinStats
	GuiControl, AI:Hide, WinText
	if ((addopen == "")||(addopen == 0))
	{
		labelname:= StrReplace(labelname, "-", "+")
		GetWindowGroupControl("Hide")
		AddWindowGroupControl("Hide")
		GuiControl, AI:, Welcome, Welcome to my program. Above you will see a Label named Add Window. This is a control bar Click it to see other controls. Left and right navigation buttons are beside it to add further Controls. To the left of the screen you will notice your "Working directory" is added in case you need to know it. below is the default editor. In the center is collected information from "Get Variables", "Functions"... It can also be a scratch pad.`n I hope you enjoy using my program. Have a Good day!
	}
	if (addopen == 1)
	{
		labelname:= StrReplace(labelname, "+", "-")
		GetWindowGroupControl("Hide")
		AddWindowGroupControl("Show")
	}
	GuiControl, AI:, WindowLabel, % labelname
	GuiControl, AI:, LeftNave,  >
	GuiControl, AI:, RightNav,
	GuiControl, AI:Show, Words
}
If (A_ThisLabel == "LeftNav")
{
	labelname:= StrReplace(thislabelmenu, "`tAdd Window", "`t      Get Tools")
	getopen:= navigationLR["GetTools"]
	GuiControl, AI:Show, PixMouse
	GuiControl, AI:Show, WinStats
	GuiControl, AI:Show, WinText
	if ((getopen == "")||(getopen == 0))
	{
		labelname:= StrReplace(labelname, "-", "+")
		AddWindowGroupControl("Hide")
		GuiControl, AI:, Welcome, This is where a variety of "Get" tools are located. First you have to have the window locked and acitve before the dropper tool will work. I plan to add that in the settings so it can automatically activate the window. Your mouse will be disabled until you either deactivate the window locked, unlock the window, deselect all tools (except multi-select). It will work in minimized mode too. At this point to clear you have to restart.
	}
	if (getopen == 1)
	{
		labelname:= StrReplace(labelname, "+", "-")
		AddWindowGroupControl("Hide")
		GetWindowGroupControl("Show")
	}
	GuiControl, AI:, WindowLabel, % labelname
	GuiControl, AI:, RightNav, <
	GuiControl, AI:Hide, Words
}
Return

Lock:
GuiControl, AI:, ControlInformation, Information about the above controls
GuiControlGet, thislabelmenu, AI:, WindowLabel
IfInString, thislabelmenu, Add Window
{
	IfInString, thislabelmenu, +
	{
		labelname:= StrReplace(thislabelmenu, "+", "-")
		GetWindowGroupControl("Hide")
		AddWindowGroupControl("Show")
		GuiControl, AI:, WindowLabel, % labelname
	}
	IfInString, thislabelmenu, -
	{
		labelname:= StrReplace(thislabelmenu, "-", "+")
		AddWindowGroupControl("Hide")
		GetWindowGroupControl("Hide")
		GuiControl, AI:, WindowLabel, % labelname
	}
}
IfInString, thislabelmenu, Get Tools
{
	IfInString, thislabelmenu, +
	{
		labelname:= StrReplace(thislabelmenu, "+", "-")
		AddWindowGroupControl("Hide")
		GetWindowGroupControl("Show")
		GuiControl, AI:, WindowLabel, % labelname
	}
	IfInString, thislabelmenu, -
	{
		labelname:= StrReplace(thislabelmenu, "-", "+")
		AddWindowGroupControl("Hide")
		GetWindowGroupControl("Hide")
		GuiControl, AI:, WindowLabel, % labelname
	}
}
Return

Editor:
IniRead, Editor, % Settings, Editor, Key1
if (Editor == "ERROR")
	Editor:=% "Notepad.exe"
Gui, Editor:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, x20 y23, Your default Editor is:
Gui, Add, Edit, x145 y20 w100, % Editor
Gui, Add, Button, x205 w40 gEditSave, Save
Gui, Add, Button, ys+24 x155 gEditCancel, Cancel
Gui, Margin, 20, 20
Gui, Show, x130, Editor
Return

EditSave:
GuiControlGet, Editor, , Working, Editor
IniWrite, % Editor, % Settings, Editor, Key1
GuiControl, AI:, ControlInformation, % Editor
Gui, Editor:Destroy
Return

EditCancel:
Gui, Editor:Destroy
Return

Default:
IniRead, Always, % Settings, AlwaysOnTop, Key1
if (Always != "ERROR")
	GuestOn:=% Always
IniRead, Directory, % Settings, Directory, Key1
if (Directory != "ERROR")
	MainDirectory:=% Directory
IniRead, loopxcount, % Settings, Looper, Key1
if (loopxcount != "ERROR")
{
	Loop, % loopxcount
	{
		IniRead, codex, % Settings, KeyCodes, Key%loopxcount%
		codexlist.=  codex "|"
		loopxcount--
	}
}
IniRead, loopycount, % Settings, DroppedCodeCount, Key1
if (loopycount != "ERROR")
{
	Loop, % loopycount
	{
		IniRead, codedrop, % Settings, DroppedCode, Key%loopycount%
		codeylist.= codedrop  "|"
		loopycount--
	}
}
Gui, Defaults:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Edit, y20 x85, Below are the default settings for the program.
Gui, Add, Text, x20, Default working directory:`t`n(place the full folder location.)`t
Gui, Add, Text, , Create test file parameters:`t`n(To add type one that doesn't exist.`t`n To remove select one from the list.)`t`nTo add more delimit by "|"
Gui, Add, Text, , Delimited words from create test file:`t`n(To add type one that doesn't exist.`t`n To remove select one from the list.)`t`nTo add more delimit by "|"
Gui, Add, Checkbox, x140 ym+210 vYesOrNo, Default AlwaysOnTop On
Gui, Add, Button, x310 ym+235 gDCancel, Cancel
Gui, Add, Button, wp hp yp x375 gDSave, Save
Gui, Add, Text, x120 ym+230 cRed, (Must click save to save changes!)`n  Must reload for directory change
if (MainDirectory != "")
	Gui, Add, Edit, xm+200 ym+45 w200 vDirectory, % MainDirectory
else
	Gui, Add, Edit, xm+200 ym+45 w200 vDirectory, % A_ScriptDir
Gui, Add, ComboBox, xm+200 ym+100 w200 vKodexList gListxChange, % codexlist
Gui, Add, ComboBox, xm+200 ym+165 w200 vKodeyList gListyChange, % codeylist
Gui, Margin, 20, 20
Gui, Show, , Defaults
Control, Disable ,, Working, Defaults
if (GuestOn == 1)
	GuiControl, Defaults:, Button1, 1
else if (GuestOn == 0)
	GuiControl, Defaults:, Button1, 0
else
	GuiControl, Defaults:, Button1, 1
Return

ListxChange:
Gui, Submit, NoHide
KodexList:= StrReplace(codexlist, KodexList, "")
GuiControl, Defaults:, KodexList, % KodexList
Return

ListyChange:
Gui, Submit, NoHide
KodeyList:= StrReplace(codeylist, KodeyList, "")
GuiControl, Defaults:, KodeyList, % KodeyList
Return

DCancel:
Gui, Defaults:Destroy
Return

DSave:
Gui, Submit, NoHide
IniDelete, % Settings, KeyCodes
IniDelete, % Settings, DroppedCode
IniDelete, % Settings, Directory
IniDelete, % Settings, AlwaysOnTop
IniDelete, % Settings, Looper
IniDelete, % Settings, DroppedCodeCount
IniWrite, % YesOrNo, % Settings, AlwaysOnTop, Key1
IniWrite, % Directory, % Settings, Directory, Key1
ControlGet, Kodex_List, List, , ComboBox1, Defaults
GuiControlGet, Personalizedx, , FunctionName, Defaults
personalx:= StrReplace(Personalizedx, "|", "`n")
Kodex_List:=% (personalx "`n" . Kodex_List)
Kodex_List:= StrReplace(Kodex_List, "`n`n", "`n")
Loop, Parse, % Kodex_List, `n
{
	z++
	IniWrite, % z, % Settings, Looper, Key1
	IniWrite, % A_LoopField, % Settings, KeyCodes, Key%z%
}
ControlGet, Kodey_List, List, , ComboBox2, Defaults
GuiControlGet, Personalizedy, , FunctionName, Defaults
personaly:= StrReplace(Personalizedy, "|", "`n")
Kodey_List:=% (personaly "`n" . Kodey_List)
Kodey_List:= StrReplace(Kodey_List, "`n`n", "`n")
Loop, Parse, % Kodey_List, `n
{
	w++
	IniWrite, % w, % Settings, DroppedCodeCount, Key1
	IniWrite, % A_LoopField, % Settings, DroppedCode, Key%w%
}
Gui, Defaults:Destroy
Return

AISave:
GuiControl,AI:, AISave, Save_File
Return

AIClear:
FileMove, % Temp, % TempBack, 1
FileAppend, , % Temp, UTF-8
GuiControl, AI:, Words,
logicalhistory:=[]
Return
	
SusOnOff:
Suspend, Toggle
if (A_IsSuspended == 1)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOn
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOff
Return

Always:
WinSet, AlwaysOnTop, Toggle, AI
WinGet, ExStyle, ExStyle, AI
if (ExStyle == 0x00000180)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOff
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOn
Return
 
Timers:
Gui, Timers:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, y25, Rest Timer:`t`n(in seconds)
Gui, Add, Text, y75 xs, Window Not Active:`t`n(in milliseconds)
Gui, Add, Text, y125 xs, Process Loop timer:`t`n(in milliseconds)
Gui, Add, Edit, w250 r3 ys-15 -VScroll, This timer slows the script before it gets to the main loop function. It's used to help in processing the global function "Speller."
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the script when the it is not active.
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the main processing loop while typing. It's dependent on a difference created in the main edit control.
Gui, Add, Edit, ys xs+400 w50 y25
Gui, Add, UpDown, vRangeInSeconds Range1-50, 10
Gui, Add, Edit, ys xs+400 w50 y75
Gui, Add, UpDown, vRangeInMillisecondsOfActive Range1-1000, 500
Gui, Add, Edit, ys xs+400 w50 y125
Gui, Add, UpDown, vRangeInMillisecondsOfProcess Range1-100, 25
Gui, Add, Text, xm+10 ym+180, Select the above values to your personal preferences and click save to keep the changes.
Gui, Add, Text, xm+80 ym+215, (Note you have to restart the program to force the changes)
Gui, Add, Button, ym+210 xs+425 gSave, Save
Gui, Add, Button, ym+210 xs+370 gCancel, Cancel
Gui, Margin, 20, 50
Gui, Show, h250 w500, Timers
Control, Disable ,, Working, Timers
Control, Disable ,, TestInfo, Timers
Control, Disable ,, FunctionName, Timers
Return

Minimize:
IniRead, DefaultLoc, % Settings, WinManager, Key1
if (whichone == "")
	whichone:= 1
if (whichone == 0)
{
	Menu, %A_ThisMenu%, Rename, Maximize, Minimize
	whichone:= 1
}
else if (whichone == 1)
{
	Menu, %A_ThisMenu%, Rename, Minimize, Maximize
	whichone:= 0
}
if (DefaultLoc == "ERROR")
{
	MsgBox, 262144, You haven't set up a Default location., You currently haven't set up a Default location for minimize. This will automatically minimize to one of three spots. The "Editor" program you have (Defalut); the "Locked" program (first option if locked): or the screen (last option if neither exist). It will activate the program and Toggles AlwaysOnTop based on the programs active status.`n`nNote**** Your "Editor" will always take precedence in AlwaysOnTop!
	GuiControlGet, Locked, AI:, WindowControl
	if (Locked == "")
		GuiControlGet, DefaultEdit, AI:, DefaultEdit
	IfInString, DefaultEdit, .
	{
		windows:= StrSplit(DefaultEdit, ".")
		for index, window in windows
			if (index == 1)
				thiswindow:=% window
	}
	if (Locked != "")
	{
		IfWinExist, % Locked
			WinActivate, % Locked
	}
	else IfWinExist, % thiswindow
	{
		WinGetTitle, fullwindow, % "ahk_class" thiswindow
		WinActivate, % fullwindow
		GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	}
	else
	{
		WinGetTitle, fullwindow, ahk_class Progman
		GetMoveWindow(DefalutLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	}
	Return
}
else if (DefalutLoc != "ERROR")
{
	GuiControlGet, WindowSnap, AI:, WindowControl
	GuiControlGet, Locked, AI:, DefaultEdit
	IfInString, Locked, .
	{
		windows:= StrSplit(Locked, ".")
		for index, window in windows
			if (index == 1)
				windowcheck:=% window
	}
	WinGet, windows, List,,, Program Manager
	Loop, % windows
	{
		WinID := windows%A_Index%
		WinGetTitle, ThisWindow, % "ahk_id " WinID
		if ((ThisWindow == WindowSnap)&&(WindowSnap != ""))
		{
			fullwindow:=% ThisWindow
			Break
		}
		IfInString, ThisWindow, % windowcheck
		{
			fullwindow:=% ThisWindow
			Break
		}
	}
	if (fullwindow == "")
		fullwindow:=%  "Program Manager"
	GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
}
Return

Reload:
^r::
Reload
Return

Cancel:
Gui, Timers:Destroy
Return

Save:
Gui, Submit, NoHide
RangeInSeconds:=(RangeInSeconds*1000)
IniWrite, % RangeInSeconds, % Settings, Timers, Key1
IniWrite, % RangeInMillisecondsOfActive, % Settings, Timers, Key2
IniWrite, % RangeInMillisecondsOfProcess, % Settings, Timers, Key3
Gui, Timers:Destroy
Return

FileSelected: 
Gui, Submit, NoHide
GuiControl, AI:, Information, Working..
FileRead, contents, % FileSelected
if (ChangeType == "Get Variables")
{
	if (Gui == 1)
		filters.= "[Filter='Gui'],"
	if (Explicit == 1)
		filters.= "[Filter='explicit'],"
	if (ImplicitExplicit == 1)
		filters.= "[Filter='implicit-explicit'],"
	wi:=
	if (filters != "")
	{
		Control, Disable ,, ListBox1, AI
		contents:= GetVariables(contents, filters)
		GuiControl, AI:, Words,
		GuiControl, AI:, Words, % contents
		whichbutton:=GetControl("ButtCount")
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					thisbutton:= "\|/SoftReturn\|/"
				if (butt == "Enter")
					thisbutton:= "\|/hardReturn\|/"
				if (butt == "Unknown")
					thisbutton:= " \|/SoftReturn\|/"
			}
		}
		StringReplace, contents, contents, `n, %thisbutton%, ALL
		FileMove, % Temp, % TempBack, 1
		FileAppend, % contents, % Temp, UTF-8
	}
}
else if (ChangeType == "Get Function") ;ChangeType gChangeType, Get Variables||Get Function|Create Test File
{
	ControlGet, row, CurrentLine, , FunctionName, AI
	ControlGet, rowtext, Line, % row, FunctionName, AI
	if (rowtext == "")
	{
		MsgBox, Please insert the function label name
		Return
	}
	if (AssociateV == 1)
		thisignore:=% "Do_Not"
	function:=GetThisFunction(rowtext, thisignore, contents)
	GuiControl, AI:, Words, % function
	FileMove, % Temp, % TempBack, 1
	FileAppend, % function, % Temp, UTF-8
}
else if (ChangeType == "Create Test File")
{
	thesecontents:= GetTestFile(contents)
	Loop, Parse, % thesecontents, `n
	{
		if (A_LoopField == "")
			Continue
		if (A_LoopField == "Return")
			thisfile:=% thisfile A_LoopField "`n`n"
		else if (A_LoopField != "Return")
			thisfile:=% thisfile A_LoopField "`n"
	}
	FileMove, Test.ahk, % TempBack, 1
	FileAppend, % thisfile, *Test.ahk, UTF-8
}
GuiControl, AI:, Button2, 0
GuiControl, AI:, Button3, 0
GuiControl, AI:, Button4, 0
GuiControl, AI:, Button5, 0
GuiControl, AI:, FunctionName,
GuiControl, AI:, WordKeeper, 7h151s@a#res37
GuiControl, AI:, Information, Done
Control, Enable ,, ListBox1, AI
Return

AddWindowGroupControl(control)
{
	if (control == "Show")
	{
		GuiControl, AI:Show, GroupControls
		GuiControl, AI:, GroupControls, Window Controls
		GuiControl, AI:Show, Button8
		GuiControl, AI:Show, Button9
		GuiControl, AI:Show, Button10
		GuiControl, AI:Show, Button11
		GuiControl, AI:Show, Button12
		GuiControl, AI:Show, Button13
		GuiControl, AI:Show, Button14
		GuiControl, AI:Hide, Welcome
		GuiControl, AI:Show, ControlInformation
	}
	if (control == "Hide")
	{
		GuiControl, AI:Hide, GroupControls
		GuiControl, AI:Hide, Button8
		GuiControl, AI:Hide, Button9
		GuiControl, AI:Hide, Button10
		GuiControl, AI:Hide, Button11
		GuiControl, AI:Hide, Button12
		GuiControl, AI:Hide, Button13 
		GuiControl, AI:Hide, Button14
		GuiControl, AI:Show, Welcome
		GuiControl, AI:Hide, ControlInformation
	}
	Return
}

GetWindowGroupControl(control)
{
	if (control == "Show")
	{
		GuiControl, AI:Show, GroupControls
		GuiControl, AI:, GroupControls, Window Stats
		GuiControl, AI:Show, ComboBox2
		GuiControl, AI:Show, Button15
		GuiControl, AI:Show, Button16
		GuiControl, AI:Show, Button17
		GuiControl, AI:Show, Button18
		GuiControl, AI:Show, Button19
		GuiControl, AI:Hide, Welcome
		GuiControl, AI:Show, ControlInformation
	}
	if (control == "Hide")
	{
		GuiControl, AI:Hide, GroupControls
		GuiControl, AI:Hide, ComboBox2
		GuiControl, AI:Hide, Button15
		GuiControl, AI:Hide, Button16
		GuiControl, AI:Hide, Button17
		GuiControl, AI:Hide, Button18
		GuiControl, AI:Hide, Button19
		GuiControl, AI:Show, Welcome
		GuiControl, AI:Hide, ControlInformation
	}
	Return
}

Tracker(thistrack, DefaultLoc, Whichone, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
{
	GuiControlGet, WindowSnap, AI:, WindowControl
	GuiControlGet, DefaultEdit, AI:, DefaultEdit
	GuiControlGet, winSnap, AI:, SnapWindow
	GuiControlGet, EditSnap, AI:, SnapToEditor
	windows:= StrSplit(DefaultEdit, ".")
	for index, window in windows
		if (index == 1)
			editwindow:=% window
	WinGet, windows, List,,, Program Manager
	Loop, % windows
	{
		WinID := windows%A_Index%
		WinGetTitle, ThisWindow, % "ahk_id " WinID
		if ((ThisWindow == WindowSnap)&&(ThisWindow != ""))
		{
			fullwindow:=% ThisWindow
			Break
		}
		IfInString, ThisWindow, % editwindow
		{
			fullwindow:=% ThisWindow
			Break
		}
	}
	if (thistrack != fullwindow)
		if ((EditSnap != "")||(WindowSnap != ""))
			IfWinActive, % fullwindow
				if ((winSnap == 1)||(EditSnap == 1))
				{
					WinSet, Transparent , Off, AI
					WinSet, AlwaysOnTop, on, AI
					GetMoveWindow(DefaultLoc, Whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
				}
	IfWinNotActive, % fullwindow
		IfWinNotActive, AI
			if ((winSnap == 1)||(EditSnap == 1))
			{
				WinSet, Transparent , 0, AI
				WinSet, AlwaysOnTop, off, AI
				fullwindow:=% ""
			}
	Return % fullwindow
}

GetMoveWindow(DefaultLoc, Whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
{
	if (fullwindow != "Program Manager")
		WinGetPos , winPosX, winPosY, windowwidth, windowheight, % fullwindow
	else
	{
		winPosX:=0
		winPosY:=0
		windowwidth:=(A_ScreenWidth-50)
		windowheight:=(A_ScreenHeight-50) ; offage is set for DPI and virtual windows. This should be enough for most windows but each person has their own settings.
	}
	If (DefaultLoc != "ERROR")
		ThisWindowLoc(DefaultLoc,Whichone, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	else if (DefaultLoc == "ERROR")
	{
		MsgBox, 262212, Default location not set, You have not set up a default location for the window. Would you like to continue?
		IfMsgBox, Yes
		{
			Loop,
			{
				x++
				y:=0
				ThisWindowLoc(x, y, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
				MsgBox, 262144, first position, This is the first position of the window minimized.
				y:=1
				ThisWindowLoc(x, y, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
				MsgBox, 262211, Do you like that location?, This is the second position maximized.`nIf you like this position click yes.`nTo exit click Cancel`n%x% %y% 
				IfMsgBox Yes
				{
					IniWrite, % x, % Settings, WinManager, Key1
					Break
				}
				IfMsgBox Cancel
					Break
				if (x == 9)
					x:=0
			}
		}	
		IfMsgBox, No
			Return
	}
	Return
}
	

ThisWindowLoc(DefaultLoc, Whichone, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
{
	AIwidth:= 100
	AIheight:= 100
	if (DefaultLoc == 1)
	{
		MainWindowX:=(windowwidth-AIwidth+winPosX)
		MainWindowY:=(windowheight-AIheight+winPosY) ; bottom right corner
		GuiWindowX:=(windowwidth-AIorignalwidth+winPosX)
		GuiWindowY:=(windowheight-AIorignalhieght+winPosY)
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 2)
	{
		MainWindowX:=% winPosX
		MainWindowY:=(windowheight-AIheight+winPosY) ; bottom left corner
		GuiWindowX:=% winPosX
		GuiWindowY:=(windowheight-AIorignalhieght+winPosY)
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 3)
	{
		MainWindowX:=% winPosX
		MainWindowY:=% winPosY ; upper left corner
		GuiWindowX:=% winPosX
		GuiWindowY:=% winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 4)
	{
		MainWindowX:=(windowwidth-AIwidth+winPosX)
		MainWindowY:=% winPosY ; upper right corner.
		GuiWindowX:=(windowwidth-AIorignalwidth+winPosX)
		GuiWindowY:=% winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 5)
	{
		MainWindowX:=(windowwidth/2)-(AIwidth/2)
		MainWindowY:=% winPosY ; upper center
		GuiWindowX:=(windowwidth/2)-(AIorignalwidth/2)
		GuiWindowY:=% winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 6)
	{
		MainWindowX:=(windowwidth/2)-(AIwidth/2)
		MainWindowY:=(windowheight-AIheight+winPosY) ; lower center
		GuiWindowX:=(windowwidth/2)-(AIorignalwidth/2)
		GuiWindowY:=(windowheight-AIorignalhieght+winPosY)
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 7)
	{
		MainWindowX:=% winPosX
		MainWindowY:=(windowheight/2)-(AIheight/2)+winPosY ; left center
		GuiWindowX:=% winPosX
		GuiWindowY:=(windowheight/2)-(AIorignalhieght/2)+winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 8)
	{
		MainWindowX:=(windowwidth-AIwidth+winPosX)
		MainWindowY:=(windowheight/2)-(AIheight/2)+winPosY ;right center
		GuiWindowX:=(windowwidth-AIorignalwidth+winPosX)
		GuiWindowY:=(windowheight/2)-(AIorignalhieght/2)+winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 9)
	{
		MainWindowX:=(windowwidth/2)-(AIwidth/2)
		MainWindowY:=(windowheight/2)-(AIheight/2)+winPosY ; center center
		GuiWindowX:=(windowwidth/2)-(AIorignalwidth/2)
		GuiWindowY:=(windowheight/2)-(AIorignalhieght/2)+winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	Return
}

GetTestFile(data)
{
	IniRead, loopcount, % Settings, Looper, Key1
	if (loopcount != "ERROR")
	{
		Loop, % loopcount
		{
			IniRead, codex, % Settings, KeyCodes, Key%loopcount%
			codexlist.= codex "`n"
			loopcount--
		}
		IniRead, loopcount, % Settings, DroppedCodeCount, Key1
		if (loopcount != "ERROR")
		{
			Loop, % loopcount
			{
				IniRead, codedrop, % Settings, DroppedCode, Key%loopcount%
				codeylist.= codedrop "`n"
				loopcount--
			}
		}
		data:= StrReplace(data, "`r", "")
		Loop, Parse, % data, `n
		{
			y++
			codestring:=
			line:=% A_LoopField
			sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
			for index, sentence in sentences
			{
				if (index == 1)
					codestring:=% sentence
				if (index == 2)
					commentstring:=% sentence
			}
			keycodex:= StrReplace(codestring, ",",  " ")
			keycodex:= StrReplace(keycodex, "  ", " ")
			keycodex:= StrReplace(keycodex, "  ", " ")
			keycodex:=% Trim(keycodex)
			thesewords:= StrSplit(keycodex, A_Space)
			for index, keycode in thesewords
				if (index == 1)
					keycodex:=% keycode
			IfinString, codeylist, % keycodex
				codestring:=% ""
			IfinString, codexlist, % keycodex
			{
				filecontents:=% filecontents codestring "`n"
				codestring:=% ""
			}
			codestring:= CodeStringCheck(codestring)
			if (codestring != "")
			{
				IfinString, codestring, Return
				{
					if (thischecker == 1)
						IfNotInString, codestring, % "`t"
							thischecker:= 0
					codestring:=% ""
				}
				IfInString, codestring, Global
				{
					filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfInString, codestring, Gui
				{
					IfinString, codestring, Show
						filecontents:=% filecontents codestring "`nReturn`n`n"
					else
						filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfInString, codestring, Menu
				{
					filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfinString, codestring, :
				{
					IfInString, codestring, Gui
						codestring:=% ""
					if (thischecker != 1)
					{
						thischecker:= 1
						if (x != 1)
							x:=1
					}
					filecontents:=% filecontents codestring "`nReturn`n`n"
					codestring:=% ""
				}
				IfInString, filecontents, % codestring
					codestring:=% ""
			}
		}
	}
	else if (loopcount == "ERROR")
	{
		MsgBox, 70, Be sure before you continue., In the following message boxes you will be shown the beginning of your code. This will omit the comments and anything past the first comma as demiliters for your test.ahk creation. each type will be added to the Ini file settings and read for your future creations. You can always change this setting by selecting default in the default menu.`n`n**Also note This does skip continuation sections.
		IfMsgBox Continue
		{
			data:= StrReplace(data, "`r", "")
			Loop, Parse, % data, `n
			{
				y++
				line:=% A_LoopField
				sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
				for index, sentence in sentences
				{
					if (index == 1)
						codestring:=% sentence
					if (index == 2)
						commentstring:=% sentence
				}
				codestring:= CodeStringCheck(codestring)
				if (codestring != "")
				{
					IfinString, codestring, Return
					{
						if (thischecker == 1)
							IfNotInString, codestring, % "`t"
								thischecker:= 0
						codestring:=% ""
					}
					IfInString, codestring, Global
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, codestring, Gui
					{
						IfinString, codestring, Show
							filecontents:=% filecontents codestring "`nReturn`n`n"
						else
							filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, codestring, Menu
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfinString, codestring, :
					{
						IfInString, codestring, Gui
							codestring:=% ""
						if (thischecker != 1)
						{
							thischecker:= 1
							if (x != 1)
							{
								x:=1
								MsgBox, 32, g-Sublabels, sublabels are automatically added
							}
						}
						filecontents:=% filecontents codestring "`nReturn`n`n"
						codestring:=% ""
					}
					keycodex:= StrReplace(codestring, ",",  " ")
					keycodex:= StrReplace(keycodex, "  ", " ")
					keycodex:= StrReplace(keycodex, "  ", " ")
					keycodex:=% Trim(keycodex)
					thesewords:= StrSplit(keycodex, A_Space)
					for index, keycode in thesewords
						if (index == 1)
							keycodex:=% keycode
					IfinString, thisignoredlist, % keycodex
						codestring:=% ""
					IfinString, thisgottenlist, % keycodex
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, filecontents, % codestring
						codestring:=% ""
					if (codestring != "")
					{
						MsgBox, 36, Do you want to add this line?, % keycodex "`n`nFound on line: " y "`n`npress yes if you want to add the first (word) of this line to your delimiter fields."
						IfMsgBox Yes
						{
							z++
							IniWrite, % z, % Settings, Looper, Key1
							IniWrite, % keycodex, % Settings, KeyCodes, Key%z%
							thisgottenlist.= keycodex
							filecontents:=% filecontents codestring "`n"
						}
						else IfMsgBox No
						{
							w++
							IniWrite, % w, % Settings, DroppedCodeCount, Key1
							IniWrite, % keycodex, % Settings, DroppedCode, Key%w%
							thisignoredlist.= codestring " "
							Continue
						}
					}
				}
			}
		}
	}
	Return % filecontents
}

CodeStringCheck(codestring)
{
	IfInString, codestring, GuiControl
		codestring:=% ""
	IfinString, codestring, `t
		codestring:=% ""
	IfInString, codestring, Global
		Return % codestring
	IfInString, codestring, Gui ; It's likely a user may place any of the below special characters in a gui 4th parameter.
		Return % codestring
	IfInString, codestring, =
		codestring:=% ""
	IfInString, codestring, ( ;)
		codestring:=% ""
	IfInString, codestring, {
		codestring:=% ""
	IfInString, codestring, }
		codestring:=% ""
	IfInString, codestring, `%
		IfNotInString, codestring, SetWorkingDir
			codestring:=% ""
	IfinString, codestring, Loop
		codestring:=% ""
	IfinString, codestring, else
		codestring:=% ""
	IfinString, codestring, if%A_Space%
		codestring:=% ""
	IfinString, codestring, ::
		codestring:=% ""
	Return % codestring
}

GetThisFunction(function, get, data)
{
	function:= StrReplace(function, "`r`n", "")
	function:= StrReplace(function, "`n", "")
	functionlength:=StrLen(function)
	data:= StrReplace(data, "`r", "")
	function:= GetFunction(data, functionlength, function)
	thisfoundfunction.= function "`n"
	function:=""
	if (get == "Do_Not")
	{
		Loop,
		{
			Loop, Parse, % thisfoundfunction, `n
			{
				IfInString, A_LoopField, =
					IfInString, A_LoopField, (
					{
						foundpossible:= FunctionLabelGet(A_LoopField)
						Trim(foundpossible)
						IfNotInString, foundpossible, % A_Space
							IfNotInString, thesefound, % foundpossible
							{
								functionlength:=StrLen(foundpossible)
								function:= GetFunction(data, functionlength, foundpossible)
							}
						if (function != "")
							thisfoundfunction.= function "`n"
					}
				if (function != "")
					function:=
				thesefound.= foundpossible ", "
			}
			IfNotInString, thesefoundpast, % thesefound
				thesefoundpast.= thesefound
			IfinString, thesefoundpast, % thesefound
				Break
		}
	}
	Return % thisfoundfunction
}

GetFunction(data, functionlength, function)
{
	Loop, Parse, % data, `n
	{
		if (thisfunction == "")
		{
			linesubstring:= SubStr(A_LoopField, 1, functionlength)
			if (function == linesubstring)
			{
				thisfunction:= % A_LoopField "`n"
				z:=1
			}
		}
		else if (thisfunction != "")
		{
			thisfunction.= A_LoopField "`n"
			if (A_LoopField == "{")
				x++
			if (A_LoopField == "}")
				x--
			if (z == 1)&&(A_LoopField != "{")
				thisfunction:= ""
			z:=0
		}
		if ((x == 0)&&(thisfunction != ""))
		{
			thisfoundfunction:= % thisfunction
			thisfunction:= ""
		}
	}
	Return % thisfoundfunction
}

FunctionLabelGet(line)
{
	thissplitfunction:= StrSplit(line, "= ")
	for index, thissplit in thissplitfunction
		if (index == 2)
			thispart:=% thissplit
	thispartsplit:= StrSplit(thispart, "(") ;"
	for index, function in thispartsplit
		if (index == 1)
			Return % function
	Return
}

ChangeType:
Gui, Submit, NoHide
if (ChangeType == "Get Variables")
{
	GuiControl, AI:Text, Results, Get variables`n(Filter results by Checkbox)
	GuiControl, AI:Hide, FunctionName
	GuiControl, AI:Hide, FunctionLabel
	GuiControl, AI:Hide, Button2
	GuiControl, AI:Hide, TestInfo
	GuiControl, AI:Show, Button5
	GuiControl, AI:Show, Button3
	GuiControl, AI:Show, Button4
}
if (ChangeType == "Get Function")
{
	GuiControl, AI:Text, Results, Get Function`n(Select a file to get a function)
	GuiControl, AI:Hide, Button5
	GuiControl, AI:Hide, Button3
	GuiControl, AI:hide, Button4
	GuiControl, AI:Show, FunctionName
	GuiControl, AI:Show, FunctionLabel
	GuiControl, AI:Show, Button2
	GuiControl, AI:Hide, TestInfo
	GuiControl, Focus, FunctionName
}
if (ChangeType == "Create Test File")
{
	GuiControl, AI:Text, results, Create a Test File`n(Create functionless test ahk)
	GuiControl, AI:Hide, Button5
	GuiControl, AI:Hide, Button3
	GuiControl, AI:hide, Button4
	GuiControl, AI:hide, FunctionName
	GuiControl, AI:hide, FunctionLabel
	GuiControl, AI:hide, Button2
	GuiControl, AI:Show, TestInfo
}
Return

GetVariables(filecontents, filters)
{
	Loop, Parse, % filecontents, `r
	{
		linenumber++
		line:=% A_LoopField
		sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
		for index, sentence in sentences
		{
			if (index == 1)
				codestring:=% sentence
			if (index == 2)
				commentstring:=% sentence
		}
		VarSetCapacity(information, 0) 
		codestring:= RemoveCertainChars(codestring, "Start")
		IfInString, codestring, Dll
			Continue
		IfInString, codestring, Box`,
			Continue
		IfInString, codestring, StringReplace
			Continue
		IfInString, codestring, RegEx
			Continue
		IfInString, codestring, Ini
			Continue
		IfInString, codestring, =
		{
			IfInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Percent", linenumber)
				IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
			}
			else IfNotInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
			IfInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Quotes", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring 
			}
			else IfNotInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
		}
		else IfInString, codestring, [percent]
		{
			variablestring:= GetVariableString(codestring, "Percent", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring
		}
		else IfInString, codestring, [quotes]
		{
			variablestring:= GetVariableString(codestring, "Quotes", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring "found in quotes 2`n"
		}
		IfInString, codestring, Gui
			IfInString, codestring, `,
				IfInString, codestring, %A_Space%v
				{
					variablestring:= GetVariableString(codestring, "Gui", linenumber)
					IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
				}
	}
	thesefilters:=StrSplit(filters, ",")
	for index, filter in thesefilters
	{
		if (index == 1)
			if (filter != "")
				firstfilter:=% filter
		if (index == 2)
			if (filter != "")
				secondfilter:=% filter
		if (index == 3)
			if (filter != "")
				thirdfilter:=% filter
	}
	Loop, Parse, % variablelist, `n
	{
		thischeck:= ""
		information:= ""
		if (A_LoopField != "")
		{
			repeatcheck:= StrSplit(A_LoopField, "[thissplitter]")
			for index, repeat in repeatcheck
			{
				if (index == 1)
				{
					IfNotInString, completedlist, % repeat
						thischeck:=% repeat
					IfInString, completedlist, % repeat
					{
						checking:= MakeSure(completedlist, repeat)
						if (checking == "True")
							Continue
						else if (checking == "False")
							thischeck:=% repeat
					}
				}
				if (index == 2)
				{
					if (firstfilter != "")
						IfInString, repeat, % firstfilter
						{
							applyfilters:= StrSplit(repeat, firstfilter)
							for index, apply in applyfilters
								information.= apply
						}
					else if (secondfilter != "")
						IfInString, repeat, % secondfilter
						{
							applyfilters:= StrSplit(repeat, secondfilter)
							for index, apply in applyfilters
								information.= apply
						}
					else if (thirdfilter != "")
						IfInString, repeat, % thirdfilter
						{
							applyfilters:= StrSplit(repeat, thirdfilter)
							for index, apply in applyfilters
								information.= apply
						}
				}
			}
			if ((thischeck != "")&&(information != ""))
			{
				checklist:=% Trim(thischeck) "`n" Trim(information) "`n"
				IfNotInString, completedlist, % checklist
					completedlist.= checklist
			}
		}
	}
	completedlist:= RemoveCertainChars(completedlist, "End")
	Return % completedlist
}

MakeSure(listinprogress, checkword)
{
	Loop, Parse, % listinprogress, `n
	{
		if (checkword == A_LoopField)
			Return % "True"
	}
	Return % "False"
}

GetVariableString(codestring, whichone, linenumber)
{
	if (whichone == "Gui")
	{
		variablestrings:= StrSplit(codestring, ",")
		for index, variablestring in variablestrings
		{
			if (index > 4)
				Continue
			IfInString, variablestring, %A_Space%v
				thisvariablestring:=% variablestring
		}
		variablestring:= StrSplit(thisvariablestring, A_Space)
		for index, variable in variablestring
		{
			thisvariableletter:= SubStr(variable, 1, 1)
			if (thisvariableletter == "v")
				Return % variable "[thissplitter] Gui variable[Filter='Gui'] Line number is found at: " linenumber "`n"
		}
		Return % variable "[thissplitter] Gui variable Line number is found at: " linenumber "`n"
	}
	if (whichone == "Quotes")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [quotes]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		variablestrings:= StrSplit(codestring, "[quotes]")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 0)
				IfNotInString, variablestring, %A_Space%
					IfNotInString, variables, % variablestring
						variables.= "[quotes]" variablestring "[quotes][thissplitter] explicit[Filter='explicit'] variable Line number is found at: " linenumber "`n"
		}
		Return % variables
	}
	if (whichone == "Percent")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [percent]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		IfInString, codestring, `,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					IfInString, variablestring, [percent]
						IfNotInString, variablestring, =
							IfInString, variablestring, A_Space
								variables.= variablestring "[thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		IfNotInString, codestring, `,
		{
			IfInString, codestring, =
			{
				variablestrings:= StrSplit(codestring, "=")
				for index, variablestring in variablestrings
				{
					if (index == 1)
					{
						variables:= StrSplit(variablestring, A_Space)
						for index, variable in variables
							thisvariable:=% variable
					}
					if (index == 2)
						codestring:=% variablestring
				}
			}
			variablestrings:= StrSplit(codestring, "[percent]")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					variables.= "[percent]" variablestring "[percent][thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		if (thisvariable != "")
			variables.= thisvariable "[thissplitter]implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
		Return % variables
	}
	if (whichone == "Equals")
	{
		variablestrings:= StrSplit(codestring, "=")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 1)
				IfNotInString, variablestring, [quotes]
				{
					thisvariablestring:= StrSplit(variablestring, A_Space)
					for index, thisvariable in thisvariablestring
					{
						variable:=% thisvariable "[thissplitter] implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
					}
				}
		}
		Return % variable
	}
	Return % "Not Found"
}

RemoveCertainChars(string, special)
{
	if (special == "Start")
	{
		StringReplace, string, string, ", [quotes], ALL ; "
		StringReplace, string, string, `%%A_Space%, [percent], ALL
		StringReplace, string, string, `%, [percent], ALL
		StringReplace, string, string, %A_Space%:, :, ALL
		StringReplace, string, string, :=, =, ALL
		StringReplace, string, string, ==, =, ALL
		StringReplace, string, string, >, =, ALL
		StringReplace, string, string, <, =, ALL
		StringReplace, string, string, %A_Space%!=, =, ALL
		StringReplace, string, string, =%A_Space%, =, ALL
		StringReplace, string, string, %A_Space%=, =, ALL
		StringReplace, string, string, ), , ALL
		StringReplace, string, string, (, , ALL ;)
		StringReplace, string, string, `t, , ALL
	}
	if (special == "End")
	{
		StringReplace, string, string, [quotes], ", ALL ; "
		StringReplace, string, string, [percent], `%, ALL
		StringReplace, string, string, `,, , ALL
	}
	Return % string
}

GetButton_Count()
{
	Loop,
	{
		ButtonCountCheck:= GetControl("ButtCount")
		if (ButtonCountCheck != OldButtonCountCheck)
		{
			OldCount:=% Count
			OldButton:=% Button
			Sleep, 500
			ButtonCount_Split:= StrSplit(ButtonCountCheck, ",")
			For Index, ButtCount in ButtonCount_Split
			{
				if (Index == 1)
					Count:=% ButtCount
				if (Index == 2)
					Button:=% ButtCount
			}
		}
		else if (ButtonCountCheck == OldButtonCountCheck)
			Break
		if ((Button != OldButton)&&(Count > 1))
			Break
		OldButtonCountCheck:=% ButtonCountCheck
	}
	if (Button == OldButton)
	{
		ButtonCountReturn:=% Count "," Button
		GuiControl,AI:, ButtonCountCheck, % "0," Button
	}
	if (Button != OldButton)
	{
		NewCount:=% Count-OldCount
		GuiControl,AI:, ButtonCountCheck, % NewCount "," Button
		ButtonCountReturn:=% OldCount "," OldButton
	}
	Return
}

ApplyLogicalChange(activeuserinput, logicalhistory, numberofdifferences)
{
	x:= 0
	newhistoryrecord:=[]
	activeuserinputlastline:= GetLineCount(activeuserinput)
	logicalhistorylastline:= GetLineCount(logicalhistory)
	LastLine:= logicalhistory["linePos" logicalhistorylastline]
	Loop, % activeuserinputlastline
	{
		record:=
		x++ ; a lagged y variable needed to stagger history.
		occurenceuser:= activeuserinput["linePos" x]
		if (y > 0)
		{
			y:=(x-z) ; this will be an opposite staggered y (x+z) for deleted lines.
			historyrecord:= logicalhistory["linePos" y]
		}
		else
			historyrecord:= logicalhistory["linePos" x] ; even though the line now isn't right doesn't mean next time it won't be.
		splithistoryrecord:= StrSplit(historyrecord, ["(hardReturn)", "(softReturn)"])
		for index, splithistory in splithistoryrecord
		{
			if (Index == 1)
				record:= % splithistory
		}
		if ((occurenceuser != record)&&(numberofdifferences != 0)) ; the number of occurences go negative when lines get deleted... I haven't updated the below else for that yet.
		{
			LastLine:= logicalhistory["linePos" logicalhistorylastline] ; if a user is lagging the array make sure you are putting in last lines right.
			if ((LastLine == "(softReturn)")||(LastLine == "(hardReturn)")) ; the last line shouldn't be any other value.
			{
				z++ ; a z variable making sure we don't lose y and holding the number of occurences.
				if (z == 1) ; there's not enough time to add different enters in different spots (meaning the user couldn't add enough enters in the time this will be done).
					y:=% x
				IfInString, LastLine, (softReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
				IfInString, LastLine, (hardReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
				numberofdifferences--
				logicalhistorylastline--
			} ; the likely answer is a deleted line in occurenceuser. we need to add to the numberofdifferences. I'll also need to update this in the future for the array.
			else
				numberofdifferences++
		}
		else if ((occurenceuser != record)&&(numberofdifferences == 0)) ; meaning user has updated a line with a new record
		{
			newhistoryrecord["linePos" x]:= occurenceuser
			IfInString, record, (softReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
			IfInString, record, (hardReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
		} ; z from above holds all change counts. y from above holds the history record line back. technically y can equal x-z or just y++. I think for greater clarity it should be x-z because a user may choose to purposely lag the logicalhistoryarray Change function. Basically this function can be implimented at will as long as the keys are being kept up with and added to the historyarray in the main loop (of course that might also come with logical array issues).
		else if ((occurenceuser == record)&&(numberofdifferences == 0))
			newhistoryrecord["linePos" x]:= record
	}
	check:=GetControl("GetKeeper")
	if (check == "7h151s@a#res37")
		Return
	Return % newhistoryrecord ; There has been many different statements on using the % after Return or in ":=" as an operorator (it technically doesn't need to be done and can cause issues if done improperly). I use it because honestly it's like my signature to my work.
}

Doppler(usersentence, historysentence)
{
	livewords:=[]
	pastwords:=[]
	check:=GetControl("GetKeeper")
	if (check == "&not@a#rea1*sent3nc3")
	{
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			livewords["wordPos" key]:= userwords
		}
		historysplit:=StrSplit(historysentence, A_Space)
		for key, historywords in historysplit
		{
			pastwords["wordPos" key]:= historywords
		}
		usercount:=GetLineCount(livewords)
		historycount:= GetLineCount(pastwords)
		Loop, % usercount
		{
			x++
			userword:=livewords["wordPos" x]
			historyword:=pastwords["wordPos" x]
			userwordlength:=StrLen(userword)
			historywordlength:= StrLen(historyword)
			if ((userword != historyword)||(historycount < x))
				GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		}
		StringReplace, userword, userword, historyword, , ALL
	}
	else if (check != "&not@a#rea1*sent3nc3")
	{
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 1)
				historyword:=% chec
			if (index == 2)
				ouserword:=% chec
			if (index == 3)
				x:=% chec
		}
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			if (key == x)
				userword:=% userwords
		}
		GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		StringReplace, userword, userword, historyword, , ALL
	}
	userwordlength:=StrLen(userword)
	if (userwordlength < 2)
	{
		GuiControl, AI:, Information, Working...
		SpellChecker(0)
	}
	if (userwordlength > 3)
	{
		GuiControl, AI:, Information, Working.
		ourwords:=WordCheck(userword, userwordlength)
		if (ourwords == "")
			SpellChecker(0)
		else if (ourwords != "")
		{
			SpellChecker(userwordlength)
			GetControl(ourwords)
		}
	}
	Return
}

FixLogicalhistory_Array(historyarray, howmanylines)
{
	lastline:= GetLineCount(historyarray)
	whichbutton:= GetControl("ButtCount")
	Loop, % howmanylines
	{
		lastline++
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					historyarray["linePos" lastline]:= "(softReturn)"
				if (butt == "Enter")
					historyarray["linePos" lastline]:= "(hardReturn)"
			}
		}
	}
	Return % historyarray
}

ReturnLineArray(lines, user)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/SoftReturn\|/", "\|/userReturns\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

GetButtonCount(pressed)
{
	pressing:= StrSplit(pressed, ",")
	For Index, press in pressing
		if (Index == 1)
			Return % press
}

FindingRealLineLOL(occurenceuser, rowbefore, thisrow)
{
	IfInString, occurenceuser, %rowbefore%
	{
		rowlength:= StrLen(rowbefore)
		occurencelength:= StrLen(occurenceuser)
		subtractedlength:=(occurencelength-rowlength)
		thisstring:= SubStr(occurenceuser, subtractedlength, occurencelength)
		if (thisstring == rowbefore)
		{
			IfInString, occurenceuser, %thisrow%
				Return % "Found"
			IfNotInstring, occurenceuser, %thisrow%
				Return % "NextRow"
		}
	}
	if (rowbefore == "NextRow")
		IfInString, occurenceuser, %thisrow%
			Return % "Found"
	Return % "NotFound"
}

ProcessStart(contents, Rest)
{
	logicalhistory:= []
	WinSet, Transparent, 0, Words
	history:= GetHistory()
	logicalhistory:= ReturnLineArray(history, user)
	Control, Disable ,, Words, AI
	GuiControl, AI:, Words, % contents
	Sleep, % Rest
	Control, Enable ,, Words, AI
	GuiControl, AI:, Information, Done
	Control, Enable ,, ListBox1, AI
	Return % logicalhistory
}

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	if (n > 3)
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	if (n == 0)
		WinSet, Transparent, 0, Words
	WinGet, visible, Transparent, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	Return
}
Return

ReturnClearDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			hinput:= harray["linePos" x]
			hsplit:= StrSplit(hinput, ["(hardReturn)", "(softReturn)"])
			for Index, h in hsplit
			{
				if (Index == 1)
					checkh:= % h
			}
			uinput:= uarray["linePos" x]
			StringReplace, uinput, uinput, (softReturn), , ALL
			StringReplace, uinput, uinput, (hardReturn), , ALL
			l_checkh:= StrLen(checkh)
			l_uinput:= StrLen(uinput)
			if (uinput != checkh)
				Return % x
			if (l_checkh != l_uinput)
				Return % x
			if (x == v)
				Break
			checkh:=
		}
		Return % "0"
	}
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return % "True"
	}
}

GetLineCount(arraycount)
{
	LastLine:=0
	for Index, count in arraycount
		++LastLine
	Return % LastLine
}

GetControl(FocTex)
{
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, FunctionName
	ControlGet, row, CurrentLine, , FunctionName, AI
	ControlGet, rowtext, Line, % row, FunctionName, AI
	GuiControlGet, Word, Words:, Listbox1
	StringReplace, text, text, `n, \|/userReturns\|/, ALL
	GuiControlGet, ButtonCountCheck, AI:, ButtonCountCheck
	GuiControlGet, Save_File, AI:, AISave
	GuiControlGet, DopplerGet, AI:, WordKeeper
	if (FocTex == "RowText")
		Return % rowtext
	if (FocTex == "GetKeeper")
		Return % DopplerGet
	if (FocTex == "AISave")
		Return % Save_File
	if (FocTex == "ButtCount")
		Return % ButtonCountCheck
	if (FocTex == "Row")
		Return % row
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	GuiControl, Words:, Listbox1, | 
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
	Return
}

HashContents(contents)
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, \|/CR+LF\|/, `n, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, `n, ALL
	Return % contents
}

GetHistory()
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, `r`n,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, (softReturn)\|/SoftReturn\|/, ALL
	StringReplace, contents, contents, \|/CR+LF\|/,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, (softReturn)\|/SoftReturn\|/, ALL
	Return % contents
}

RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitap
On to updating the settings to reflect a more user friendly experience with these new tools.

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 24 Dec 2023, 09:02

Finally settings all in one logical space.

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability. ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
#InstallkeybdHook
#InstallMouseHook
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
Global Settings:= % Cache "\Settings.ini"
IniRead, Directory, % Settings, Directory, Key1
if (Directory != "ERROR")
	SetWorkingDir %Directory%
else
	SetWorkingDir %A_ScriptDir% 
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)
IniRead, WinDrop, % Settings, WinManager, Key2
if (WinDrop != "ERROR")
	WinVictive:=% WinDrop
IniRead, Editor, % Settings, Editor, Key1
if (Editor == "ERROR")
	Editor:=% "Notepad.exe"
IniRead, Rest, % Settings, Timers, Key1
If (Rest == "ERROR")
{
	IniWrite, 10000, % Settings, Timers, Key1
	Rest:= 10000
}
IniRead, Notactive, % Settings, Timers, Key2
if (Notactive == "ERROR")
{
	IniWrite, 500, % Settings, Timers, Key2
	Notactive:= 500
}
IniRead, NoDif, % Settings, Timers, Key3
if (NoDif == "ERROR")
{
	IniWrite, 25, % Settings, Timers, Key3
	NoDif:= 25
}
IniRead, Always, % Settings, AlwaysOnTop, Key1
if (Always != "ERROR")
	GuestOn:=% Always
IniRead, DefaultLoc, % Settings, WinManager, Key1

Loop, Files, *.ahk, F R
{
	IfInString, A_LoopFileName, @
		Continue
	IfNotInString, wi, % A_LoopFileName
		wi=%wi%%A_LoopFileName%|
}

Menu, AIsMenu, Add, Minimize, Minimize
Menu, Settings, Add, Default Settings, Default
Menu, Settings, Add, Timers, Timers
Menu, Settings, Add, AlwaysOnTop`ton/off, Always
Menu, Settings, Add, Suspend`ton/off, SusOnOff
Menu, Settings, Add, Reload`tCtrl+r, Reload
Menu, AIsMenu, Add, Settings, :Settings

SetTitleMatchMode, 2
CoordMode, Caret, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Window
if (GuestOn == 1)
	Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
else if (GuestOn == 0)
	Gui, AI:New, -AlwaysOnTop +Resize +toolWindow
else
	Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, Menu, AIsMenu
Gui, Add, Edit, r1 x25 y21 w150 ReadOnly vWorking, % A_WorkingDir
Gui, Add, DropDownList, x25 y55 w150 vChangeType gChangeType, Get Variables||Get Function|Create Test File
Gui, Add, GroupBox, x25 y90 h250 w150 wrap vResults, Get variables`n(Filter results by Checkbox)
Gui, Add, ListBox, r10 yp+35  xp+15 w120 gFileSelected vFileSelected, %wi%
Gui, Add, Edit, r4 yp+150 xp -VScroll vTestInfo w120,  Select a file to create a Test.ahk file with no function or sublabeled function.
Gui, Add, Text, yp xp vFunctionLabel, input the function lablel
Gui, Add, Edit, r1 w120 vFunctionName,
Gui, Add, Checkbox, vAssociateV, Associated functions
Gui, Add, Checkbox, yp-40 xp vGui, Gui Variables
Gui, Add, Checkbox, vExplicit, Explicit Variables
Gui, Add, Checkbox, vImplicitExplicit, Implicit-Explicit
Gui, Add, Text, -E0x200 x0 y0 vButtonCountCheck w0, 0,Unknown
Gui, Add, Text, -E0x200 vWordKeeper w0, &not@a#rea1*sent3nc3s
Gui, Add, Edit,  r19 ym+45 x200 vWords w325 hwndTracker,
Gui, Add, Button, yp+1000 xp gAISave, Save
Gui, Add, Text, vAISave w0, Don't save
Gui, Add, Edit, r4 ym+45 x200 w325 ReadOnly t64 vPixMouse, (Mouse Position)`t(pixel color)`n
Gui, Add, Edit, r4 yp+70 x200 w325 ReadOnly vWinStats, x y h w (Coordinate mode)
Gui, Add, Edit, r8 yp+70 x200 w325 ReadOnly vWinText, Text on the locked screen:
Gui, Add, Button,xp y317 gAISave, Save
Gui, Add, Button,xp+50 yp gAIClear, Clear
Gui, Add, Edit,  r1 ym+15 x200 vWindowControl w325,
Gui, Add, Text, ym+315 x470 vInformation, Loading...
Gui, Add, Text, ym+17 x550 vWindowLabel gLock +Border Center h18, %A_Space%%A_Space%+`tAdd Window%A_Space%%A_Space%
Gui, Add, Edit, r19 ym+45 x550 w150 vWelcome -VScroll ReadOnly, Welcome to my program. Above you will see a Label named Add Window. This is a control bar Click it to see other controls. Left and right navigation buttons are beside it to add further Controls. To the left of the screen you will notice your "Working directory" is added in case you need to know it. below is the default editor. In the center is collected information from "Get Variables", "Functions"... It can also be a scratch pad.`n I hope you enjoy using my program. Have a Good day!
Gui, Add, Text, ym+17 x660 w20 vRightnav gRightNav +Border Center h18,
Gui, Add, Text, ym+17 x679 w20 vLeftNave gLeftNav +Border Center h18, >
Gui, Add, GroupBox, ym+50 x550 h250 w150 wrap vGroupControls, Window Controls
Gui, Add, Checkbox, yp+40 xp+10 vGetWindow gLocktoWindow, Lock Window Control
Gui, Add, Checkbox, yp+20 xp vSnapWindow gSnapToWindow, Snap to Window
Gui, Add, Checkbox, yp+20 xp vSnapToEditor gSnapToEditor, Snap to Editor
Gui, Add, Checkbox, yp+20 xp vAutoEdit gAutoEdit, Enable Auto Edit
Gui, Add, Checkbox, yp+20 xp vEnableCC gEnableCC, Enable copy anywhere
Gui, Add, Checkbox, yp+20 xp vEnableVV gEnableVV, Enable paste 2nd Clip
Gui, Add, Edit, yp+20 xp r5 w130 -VScroll ReadOnly vControlInformation, Information about the above controls
Gui, Add, Edit, yp+105 xp-10 r1 w150 -VScroll ReadOnly vDefaultEdit, % Editor
Gui, Add, DropDownList, yp-240 xp+10 w130 vCoordinateM gCoordinateM, CoordMode Screen||CoordMode Relative|CoordMode Window|CoordMode Client
Gui, Add, Checkbox, yp+30 xp vGetPix gGetPix, Get Pixel Color
Gui, Add, Checkbox, yp+20 xp vGetMouse gGetMouse, Get Mouse Pos
Gui, Add, Checkbox, yp+20 xp vGetWinS gGetWinS, Get Window Stats
Gui, Add, Checkbox, yp+20 xp vGetWinT gGetWinT, Get Window Text
Gui, Add, Checkbox, yp+20 xp vMultiSele gMultiSele, Multi-Select
Gui, Margin, 50, 30
Gui, Color, d6d5d0, f5f4f0
Gui, Show, h400, AI work
WinGetPos , AIPosX, AIPosY, AIorignalwidth, AIorignalhieght, AI
AddWindowGroupControl("Hide")
GetWindowGroupControl("Hide")
GuiControl, AI:Hide, PixMouse
GuiControl, AI:Hide, WinStats
GuiControl, AI:Hide, WinText
GuiControl, AI:Hide, GroupBox2
GuiControl, AI:Hide, FunctionName
GuiControl, AI:Hide, FunctionLabel
GuiControl, AI:Hide, ControlInformation
Control, Disable, , Edit10, AI
GuiControl, AI:Hide, AssociateV
GuiControl, AI:Hide, TestInfo
Control, Disable , , Edit2, AI
Control, Disable , , Welcome, AI
GuiControl, Focus, Words
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, Add, Text, vClipBoard2 w0 h0 x5 y5,
Gui, Add, Text, vClipBoard3 w0 h0 x5 y5,
Gui, margin, 0, 0
Gui, Show, , Words
GuiControl, Words:Hide, ClipBoard2
GuiControl, Words:Hide, ClipBoard3

contents:=HashContents(contents)
logicalhistory:= []
logicalhistory:= ProcessStart(contents, Rest)
activeuserinput:= []
navigationLR:=[]

Loop,
{
	ThisModifier(WinVictive)
	ClipBoardFunction()
	thistrack:= Tracker(thistrack, DefaultLoc, Whichone, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	if (A_TimeIdle > 3000)
	{
		thisz++
		if (thisz == 1)
			GuiControl, AI:, Information, Done
		Sleep, % Notactive
		Continue
	}
	winwonder:=WinWonder()
	if (winwonder == "False")
	{
		SpellChecker(0)
		Sleep, % Notactive
		Continue
	}
	check:=GetControl("GetKeeper")
	usersentence:=GetControl("RowText")
	if (recordkeeper == "")
		recordkeeper:=% usersentence
	if (recordkeeper != usersentence)
	{
		Doppler(usersentence, recordkeeper)
		recordkeeper:=% usersentence
	}
	getuserinput:= GetControl("Text")
	activeuserinput:=ReturnLineArray(getuserinput, "user")
	historylastline:= GetLineCount(logicalhistory)
	activeuserlastline:= GetLineCount(activeuserinput)
	if (check == "7h151s@a#res37")
	{
		If (getuserinput == "")
		{
			Sleep, % Notactive
			Continue
		}
		GuiControl, AI:, WordKeeper, &not@a#rea1*sent3nc3
		contents:=HashContents(contents)
		logicalhistory:= ProcessStart(contents, Rest)
		Continue
	}
	if (usersentence != "")
	{
		if (activeuserlastline != historylastline)
		{
			logicallastlineaddition:=(activeuserlastline-historylastline)
			logicalhistory:= FixLogicalhistory_Array(logicalhistory, logicallastlineaddition) ; where last lines are being put in. and you will also want to function in lastline (Deleted_Line) to acompany the changes. if you are lagging ApplyLogicalChange().
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, logicallastlineaddition)
		}
		if (activeuserlastline == historylastline)
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, 0)
	}
	savecheck:= GetControl("AISave")
	if (savecheck == "Save_File")
	{
		historycount:=GetLineCount(logicalhistory)
		Loop, % historycount
		{
			x++
			sentences:= logicalhistory["linePos" x]
			StringReplace, sentences, sentences, (softReturn), \|/softReturn\|/, ALL
			StringReplace, sentences, sentences, (hardReturn), \|/CR+LF\|/, ALL
			FileContents:=% FileContents sentences
		}
		FileMove, % Temp, % TempBack, 1
		FileAppend, % FileContents, % Temp, UTF-8
		GuiControl,AI:, AISave, Don't Save
	}
}
Return

ThisModifier(WinDrop)
{
	GuiControlGet, Locked, AI:, GetWindow
	GuiControlGet, WinName, AI:, WindowControl
	GuiControlGet, PixButton, AI:, GetPix
	GuiControlGet, StatButton, AI:, GetWinS
	GuiControlGet, TextButton, AI:, GetWinT
	WinGetPos , WinX, WinY, WinWidth, WinHeight, AI
	PositionSquareX:=(WinX+WinWidth)
	PositionSquareY:=(WinY+WinHeight)
	MouseGetPos, positionX, positionY
	if ((Locked == 1)&&(WinName != ""))
	{
		if ((PixButton == 1)||(StatButton == 1)||(TextButton == 1))
		{
			If ((positionX < WinX)||(positionX > PositionSquareX)||(positionY < WinY)||(positionY > PositionSquareY))
			{
				if ((WinDrop != "")&&(WinDrop == 0))
					Hotkey, LButton, On
				IfWinActive, % WinName
					Hotkey, LButton, On
				else
					Hotkey, LButton, Off
			}
			else
				Hotkey, LButton, Off
		}
		else
			Hotkey, LButton, Off
	}
	else
		Hotkey, LButton, Off
	Return
}

LButton::
GuiControlGet, ThisMode , AI:, CoordinateM
orignalMouseMode:=% A_CoordModeMouse
orignalPixelMode:=% A_CoordModePixel
if (ThisMode == "CoordMode Screen")
{
	CoordMode, Screen , Pixel
	CoordMode, Screen , Mouse
}
if (ThisMode == "CoordMode Relative")
{
	CoordMode, Relative , Pixel
	CoordMode, Relative , Mouse
}
if (ThisMode == "CoordMode Window")
{
	CoordMode, Window , Pixel
	CoordMode, Window , Mouse
}
if (ThisMode == "CoordMode Client")
{
	CoordMode, Client , Pixel
	CoordMode, Client , Mouse
}
MouseGetPos, positionX, positionY
GuiControlGet, PixButton, AI:, GetPix
if (PixButton == 1)
{
	PixelGetColor, color,%positionX%, %positionY%
	color:=% color "`n"
}
else
	color:=% "No color`n"
if (MouseButton == 1)
	MousePos:=% positionX ", " positionY "`t"
else
	MousePos:=% "No Mouse`t"
GuiControlGet, StatButton, AI:, GetWinS
GuiControlGet, TextButton, AI:, GetWinT
GuiControlGet, Multi, AI:, MultiSele
GuiControlGet, MouseButton, AI:, GetMouse
GuiControlGet, PixMouse, AI:, PixMouse
PixMouse:= StrReplace(PixMouse, "(Mouse Position)`t(pixel color)`n", "")
if ((Multi == 1)&&(PixButton == 1)||(MouseButton == 1))
	GuiControl, AI:, PixMouse, %  "(Mouse Position)`t(pixel color)`n" MousePos color PixMouse
if ((Multi != 1)&&(PixButton == 1)||(MouseButton == 1))
	GuiControl, AI:, PixMouse, %  "(Mouse Position)`t(pixel color)`n" MousePos color
GuiControlGet, WinStats, AI:, WinStats
GuiControlGet, WinName, AI:, WindowControl
WinGetPos , WinX, WinY, WinWidth, WinHeight, % WinName
WinStats:= StrReplace(WinStats, "x y h w (Coordinate mode)", "")
if ((Multi == 1)&&(StatButton == 1))
	GuiControl, AI:, WinStats, % "x" WinX ", y" WinY ", h" WinWidth ", w" WinHeight "`t(" ThisMode ")`n" WinStats
if ((Multi != 1)&&(StatButton == 1))
	GuiControl, AI:, WinStats, % "x" WinX ", y" WinY ", h" WinWidth ", w" WinHeight "`t(" ThisMode ")"
GuiControlGet, AIWinText, AI:, WinText
TextLength:= StrLen(AIWinText)
WinGetText, WinText , % WinName
if ((TextLength == 26)&&(WinText != "")&&(TextButton == 1))
	GuiControl, AI:, WinText, % WinText
CoordMode, Screen, Pixel
CoordMode, Screen, Mouse
Return

~LCtrl::
thiskeystate:= GetKeyState("LCtrl", P)
if (thiskeystate != 0)
{
	Loop,
	{
		GuiControlGet, EnableCC, AI:, EnableCC
		GuiControlGet, EnableVV, AI:, EnableVV
		CtrlC := Chr(3)
		if (EnableVV == 1)
		{
			CtrlVV:= (Chr(22) . Chr(22))
			CtrlVVV:= (Chr(22) . Chr(22) . Chr(22))
			ClipBoardFunction()
			GuiControlGet, ClipBoard2, Word:, ClipBoard2
			GuiControlGet, ClipBoard3, Word:, ClipBoard3
		}
		Input, userinput, L3 T0.75 M ; this has a 0.75 second timer... That feels a little natural. however on the person to person scale this might need adjusted.
		if (EnableVV == 1)
		{
			if (userinput == CtrlVV)
			{
				saveClip:=% ClipBoard
				ClipBoard:=% Clipboard2
				Send, ^v
				ClipBoard:=% saveClip
				saveClip:=
			}
			else if (userinput == CtrlVVV)
			{
				saveClip:=% ClipBoard
				ClipBoard:=% Clipboard3
				Send, ^v
				ClipBoard:=% saveClip
				saveClip:=
			}
		}
		else if ((userinput == CtrlC CtrlC)&&(EnableCC == 1))
		{
			logicalhistorylastline:= GetLineCount(logicalhistory)
			Loop, % logicalhistorylastline
			{
				thisx++
				saveline:= logicalhistory["linePos" thisx]
				saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
				saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
				thesecontents.= saveline
			}
			thesecontents:= SpecialReplace(thesecontents)
			MsgBox, % "The edit fields are ready to be sent. It autosends after this message. After you learn how this works you can delete this messge box. Make sure the place you want your text sent is +lastfound"
			Send, % thesecontents
			thisx:=
			thesecontents:=
		}
		else if (userinput == CtrlC)
			Send, ^c
		else
			Send, ^%userinput%
		thiskeystate:= GetKeyState("LCtrl", P)
		if (thiskeystate == 0)
			Break
	}
}
Return

ClipBoardFunction()
{
	if ((ClipBoard != "")&&(ClipBoard != ClipBoard2))
	{
		if (ClipBoard2 == "" )
			ClipBoard2:=% ClipBoard1
		else if (ClipBoard2 != "")
		{
			ClipBoard3:=% ClipBoard2
			ClipBoard2:=% ClipBoard
		}
	}
	if (ClipBoard2 != "" )
		GuiControl,Word:, ClipBoard2, % ClipBoard2
	if (ClipBoard3 != "" )
		GuiControl,Word:, ClipBoard3, % ClipBoard3
	Return
}

$Backspace::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Backspace}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Backspace}
	}
	Return
}
else
	Send, {Backspace}
Return

$Space::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Space}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Space}
	}
	Return
}
else
	Send, {Space}
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		check:=GetControl("GetKeeper")
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 2)
				userword:=% chec
		}
		str:= StrLen(userword)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
	}
	else
	{
		Send, `t
	}
	Return
}
else
	Send, `t
Return

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	GuiControlGet, AutoEdit, AI:, AutoEdit
	If (AutoEdit == 1)
	{
		logicalhistorylastline:= GetLineCount(logicalhistory)
		Loop, % logicalhistorylastline
		{
			thisx++
			saveline:= logicalhistory["linePos" thisx]
			saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
			saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
			thesecontents.= saveline
		}
		thesecontents:= SpecialReplace(thesecontents)
		GuiControlGet, wintitle, AI:, WindowControl, WindowControl
		if (wintitle == "")
		{
			MsgBox, Please lock to a window first
			Return
		}
		WinActivate, % wintitle
		WinWait, % wintitle
		Send, % thesecontents
		FileMove, % Temp, % TempBack, 1
		FileAppend, , % Temp, UTF-8
		GuiControl, AI:, Words,
		logicalhistory:=[]
		thisx:=
		thesecontents:=
	}
	else if (AutoEdit == 0)
	{
		ButtonCountCheck:= GetControl("ButtCount")
		PressCount:=GetButtonCount(ButtonCountCheck)
		PressCount++
		WhichButtonCount:=% PressCount ",ShiftEnter"
		GuiControl, AI:, ButtonCountCheck, % WhichButtonCount
		KeyWait, Backspace, U
		GetButton_Count()
	}
}
Return

~Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	GuiControlGet, AutoEdit, AI:, AutoEdit
	If (AutoEdit == 1)
	{
		logicalhistorylastline:= GetLineCount(logicalhistory)
		Loop, % logicalhistorylastline
		{
			thisx++
			saveline:= logicalhistory["linePos" thisx]
			saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
			saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
			thesecontents.= saveline
		}
		thesecontents:= SpecialReplace(thesecontents)
		GuiControlGet, wintitle, AI:, WindowControl, WindowControl
		if (wintitle == "")
		{
			MsgBox, Please lock to a window first
			Return
		}
		WinActivate, % wintitle
		WinWait, % wintitle
		Send, % thesecontents "+{Enter}"
		FileMove, % Temp, % TempBack, 1
		FileAppend, , % Temp, UTF-8
		GuiControl, AI:, Words,
		logicalhistory:=[]
		thisx:=
		thesecontents:=
	}
	else if (AutoEdit == 0) ;
	{
		ButtonCountCheck:= GetControl("ButtCount")
		PressCount:=GetButtonCount(ButtonCountCheck)
		PressCount++
		WhichButtonCount:=% PressCount ",Enter"
		GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
		KeyWait, Backspace, U
		GetButton_Count()
	}
}
Return

SpecialReplace(thesecontents)
{
	fixedcharacters:= StrReplace(thesecontents, "!", "{!}")
	fixedcharacters:= StrReplace(fixedcharacters, "#", "{#}")
	fixedcharacters:= StrReplace(fixedcharacters, "+", "{+}")
	fixedcharacters:= StrReplace(fixedcharacters, "^", "{^}")
	fixedcharacters:= StrReplace(fixedcharacters, "{", "{{}") ; if this is done then output will be {{}
	fixedcharacters:= StrReplace(fixedcharacters, "}", "{}}") ; from the above if this is done output will be {{{}}
	fixedcharacters:= StrReplace(fixedcharacters, "{{{}}", "{{}")
	Sleep, 50
	Tabcontrol:= StrSplit(fixedcharacters, ["(hardReturn)", "(softReturn)"])
	for index, Tabs in Tabcontrol
	{
		IfinString, Tabs, % "`t" ; <----- it is assumed the editor you're using controls tab.
		{
			thiscount:= StrReplace(Tabs, "`t", "", thismany)
			thisstring:=% thiscount
			if (thismany != thatmany)
			{
				if (thismany > thatmany)
				{
					n:=(thismany-thatmany)
					thisbutton:=% "{Tab " n "}"
				}
				if (thismany < thatmany)
				{
					n:=(thatmany-thismany)
					thisbutton:=% "{Backspace " n "}"
				}
			}
		}
		IfNotInString, Tabs, % "`t"
		{
			if (thismany > 1)
				thisbutton:=% "{Backspace " n "}"
			else if (thismany == 1)
			{
				thismany:=0
				thisbutton:=% "{Backspace}"
			}
			else if (thismany == 0)
				thisbutton:=% ""
			thisstring:=% Tabs
		}
		thatmany:=% thismany
		edittext.= thisbutton thisstring
		thisbutton:= ""
	}
	edittext:= StrReplace(edittext, "[Enter]", "{Backspace}{Enter}")
	edittext:= StrReplace(edittext, "[ShiftEnter]", "{Backspace}+{Enter}")
	Return % edittext
}

EnableVV:
GuiControl, AI:, ControlInformation, This enables paste from second and third ClipBoard. {LCtrl}+vv and {LCtrl}+vvv. if clipboard2 or 3 sends acsii code
Return

SnapToWindow:
GuiControl, AI:, ControlInformation, This will place the Main Gui in one of 9 locations on the locked window.
GuiControl, AI:, SnapToEditor, 0
IniRead, DefaultLoc, % Settings, WinManager, Key1
GuiControlGet, fullwindow, AI:, WindowControl
if (fullwindow == "")
{
	MsgBox, 262144, Please lock to a window., Please first lock to a window.
	GuiControl, AI:, SnapToEditor, 0
	Return
}
GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
Return
	

SnapToEditor:
GuiControl, AI:, ControlInformation, This will place the Main Gui in one of 9 locations on the editor. Notepad is Default.
GuiControlGet, DefaultEdit, AI:, DefaultEdit
GuiControl, AI:, SnapWindow, 0
IfInString, DefaultEdit, .
{
	windows:= StrSplit(DefaultEdit, ".")
	for index, window in windows
		if (index == 1)
			thiswindow:=% window
}
WinGetTitle, fullwindow, % "ahk_class" thiswindow
if (fullwindow == "")
{
	MsgBox, 4, Window Not Found!, % "The current Editor is not open:`nahk_class " thiswindow "`nWould you like to open it?"
	IfMsgBox Yes
		run, % DefaultEdit
	IfMsgBox No
		Return
	Loop,
	{
		Sleep, 150 ; prevent needless process
		WinGetTitle, fullwindow, % "ahk_class" thiswindow
		if (fullwindow != "")
			Break
		x++
		if (x > 15)
		{
			MsgBox, There is an error opening the window or a naming error.
			Return
		}
	}
}
IfWinExist, % fullwindow
{
	IniRead, DefaultLoc, % Settings, WinManager, Key1
	GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
}
Return

AutoEdit:
GuiControl, AI:, ControlInformation, On Enter ({Enter} or +{Enter} this button sends to your default editor if it's active and Clears the window.
Return

EnableCC:
GuiControl, AI:, ControlInformation, This activates {LCtrl}+cc when you press that (anywhere) main edit contents are autosent to insert location.
Return

LocktoWindow:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This button locks the Gui to a running window. Just activate the window you want.
if (GetWindow == 1)
{
	WinGetActiveTitle, checkthistitle
	GuiControl, AI:, WindowControl, Select a window to lock to.
	Loop,
	{
		WinGetActiveTitle, newtitletocheck
		if (newtitletocheck == "")
			Continue
		if (checkthistitle != newtitletocheck)
			Break
	}
	GuiControl, AI:, WindowControl, % newtitletocheck
	GuiControl, Disable, WindowControl
}
if (GetWindow == 0)
{
	GuiControl, AI:, WindowControl,
	GuiControl, Enable, WindowControl
}
Return

CoordinateM:
Gui, Submit, NoHide
if (CoordinateM == "CoordMode Screen")
	GuiControl, AI:, ControlInformation, Coordinates are relative to the Entire Screen.
if (CoordinateM == "CoordMode Relative")
	GuiControl, AI:, ControlInformation, Coordinates are relative to the Active Window
if (CoordinateM == "CoordMode Window")
	GuiControl, AI:, ControlInformation, Same as Relative and Recommended for clarity
if (CoordinateM == "CoordMode Client")
	GuiControl, AI:, ControlInformation, Coordinates are relative to the active client area minus title bar or menu. Look this up in autohokey for specifics.
Return

GetPix:
GuiControl, AI:, ControlInformation, This enables get pixel color to the locked screen on click. Make sure you are using the mode you prefer.
Return

GetMouse:
GuiControl, AI:, ControlInformation, This enables get Mouse Pos on click to the locked window. Make sure you are using the mode you prefer.
Return

GetWinS:
GuiControl, AI:, ControlInformation, This will provide the locked windows height width and left corner x and y positions.
Return

GetWinT:
GuiControl, AI:, ControlInformation, This will give the text to the locked window (hidden and seen). 
Return

MultiSele:
GuiControl, AI:, ControlInformation, In the event you need more than one color or mouse position enable this to record multiple clicks.
Return

RightNav:
Gui, Submit, NoHide
LeftNav:
Gui, Submit, NoHide
GuiControlGet, thislabelmenu, AI:, WindowLabel
IfInString, thislabelmenu, +
{
	IfInString, thislabelmenu, Add Window
		navigationLR["AddWindow"]:= 0
	IfInString, thislabelmenu, Get Tools
		navigationLR["GetTools"]:= 0
}
IfInString, thislabelmenu, -
{
	IfInString, thislabelmenu, Add Window
		navigationLR["AddWindow"]:= 1
	IfInString, thislabelmenu, Get Tools
		navigationLR["GetTools"]:= 1
}
If (A_ThisLabel == "RightNav")
{
	labelname:= StrReplace(thislabelmenu, "`t      Get Tools", "`tAdd Window")
	addopen:= navigationLR["AddWindow"]
	GuiControl, AI:Hide, PixMouse
	GuiControl, AI:Hide, WinStats
	GuiControl, AI:Hide, WinText
	if ((addopen == "")||(addopen == 0))
	{
		labelname:= StrReplace(labelname, "-", "+")
		GetWindowGroupControl("Hide")
		AddWindowGroupControl("Hide")
		GuiControl, AI:, Welcome, Welcome to my program. Above you will see a Label named Add Window. This is a control bar Click it to see other controls. Left and right navigation buttons are beside it to add further Controls. To the left of the screen you will notice your "Working directory" is added in case you need to know it. below is the default editor. In the center is collected information from "Get Variables", "Functions"... It can also be a scratch pad.`n I hope you enjoy using my program. Have a Good day!
	}
	if (addopen == 1)
	{
		labelname:= StrReplace(labelname, "+", "-")
		GetWindowGroupControl("Hide")
		AddWindowGroupControl("Show")
	}
	GuiControl, AI:, WindowLabel, % labelname
	GuiControl, AI:, LeftNave,  >
	GuiControl, AI:, RightNav,
	GuiControl, AI:Show, Words
}
If (A_ThisLabel == "LeftNav")
{
	labelname:= StrReplace(thislabelmenu, "`tAdd Window", "`t      Get Tools")
	getopen:= navigationLR["GetTools"]
	GuiControl, AI:Show, PixMouse
	GuiControl, AI:Show, WinStats
	GuiControl, AI:Show, WinText
	if ((getopen == "")||(getopen == 0))
	{
		labelname:= StrReplace(labelname, "-", "+")
		AddWindowGroupControl("Hide")
		GuiControl, AI:, Welcome, This is where a variety of "Get" tools are located. First you have to have the window locked and acitve before the dropper tool will work. I plan to add that in the settings so it can automatically activate the window. Your mouse will be disabled until you either deactivate the window locked, unlock the window, deselect all tools (except multi-select). It will work in minimized mode too. At this point to clear you have to restart.
	}
	if (getopen == 1)
	{
		labelname:= StrReplace(labelname, "+", "-")
		AddWindowGroupControl("Hide")
		GetWindowGroupControl("Show")
	}
	GuiControl, AI:, WindowLabel, % labelname
	GuiControl, AI:, RightNav, <
	GuiControl, AI:Hide, Words
}
Return

Lock:
GuiControl, AI:, ControlInformation, Information about the above controls
GuiControlGet, thislabelmenu, AI:, WindowLabel
IfInString, thislabelmenu, Add Window
{
	IfInString, thislabelmenu, +
	{
		labelname:= StrReplace(thislabelmenu, "+", "-")
		GetWindowGroupControl("Hide")
		AddWindowGroupControl("Show")
		GuiControl, AI:, WindowLabel, % labelname
	}
	IfInString, thislabelmenu, -
	{
		labelname:= StrReplace(thislabelmenu, "-", "+")
		AddWindowGroupControl("Hide")
		GetWindowGroupControl("Hide")
		GuiControl, AI:, WindowLabel, % labelname
	}
}
IfInString, thislabelmenu, Get Tools
{
	IfInString, thislabelmenu, +
	{
		labelname:= StrReplace(thislabelmenu, "+", "-")
		AddWindowGroupControl("Hide")
		GetWindowGroupControl("Show")
		GuiControl, AI:, WindowLabel, % labelname
	}
	IfInString, thislabelmenu, -
	{
		labelname:= StrReplace(thislabelmenu, "-", "+")
		AddWindowGroupControl("Hide")
		GetWindowGroupControl("Hide")
		GuiControl, AI:, WindowLabel, % labelname
	}
}
Return

Default:
IniRead, Always, % Settings, AlwaysOnTop, Key1
if (Always != "ERROR")
	GuestOn:=% Always
IniRead, Directory, % Settings, Directory, Key1
if (Directory != "ERROR")
	MainDirectory:=% Directory
else
	MainDirectory:= % A_ScriptDir
IniRead, Editor, % Settings, Editor, Key1
if (Editor != "ERROR")
	Editor:=% Editor
else
	Editor:=% "Notepad.exe"
IniRead, WinDrop, % Settings, WinManager, Key2
if (WinDrop != "ERROR")
	WinVictive:=% WinDrop
Gui, Defaults:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Edit, y20 x85, Below are the default settings for the program.
Gui, Add, Text, xp-65 yp+30, Your default Editor is:
Gui, Add, Text, xp yp+30, Default working directory:`t`n(place the full folder location.)`t
Gui, Add, Text, xp yp+50, Test File parameters:`t
Gui, Add, Text, xp yp+30, Activate Get tool without`n locked window active:`t
Gui, Add, Edit, x210 y51 w200 vEdit, % Editor
Gui, Add, Edit, xp yp+35 w200 vDirectory, % A_ScriptDir
Gui, Add, Checkbox, xp yp+45 gDelimit, Delimited
Gui, Add, Checkbox, xp+100 yp gConcantate, Concantated
Gui, Add, Checkbox, xp-100 yp+34 vWinactive, Activate always
Gui, Add, Checkbox, x140 ym+210 vYesOrNo, Default AlwaysOnTop On
Gui, Add, Button, x310 ym+235 gDCancel, Cancel
Gui, Add, Button, wp hp yp x375 gDSave, Save
Gui, Add, Text, x120 ym+230 cRed, (Must click save to save changes!)`n  Must reload for directory change
Gui, Margin, 20, 20
Gui, AI:Font, 0f0d03, Arial
Gui, Color, d6d5d0, f5f4f0
Gui, Show, , Defaults
Control, Disable ,, Edit1, Defaults
if (GuestOn == 1)
	GuiControl, Defaults:, YesOrNo, 1
else if (GuestOn == 0)
	GuiControl, Defaults:, YesOrNo, 0
else
	GuiControl, Defaults:, YesOrNo, 1
if (WinVictive == 1)
	GuiControl, Defaults:, Winactive, 1
else if (WinVictive == 0)
	GuiControl, Defaults:, Winactive, 0
else
	GuiControl, Defualts:, Winactive, 1
Return

Delimit:
IniRead, loopycount, % Settings, DroppedCodeCount, Key1
if (loopycount != "ERROR")
{
	Loop, % loopycount
	{
		IniRead, codedrop, % Settings, DroppedCode, Key%loopycount%
		codeylist.= codedrop  "|"
		loopycount--
	}
}
Gui, Delimits:New, +AlwaysOnTop +toolWindow
Gui, Add, Edit, y20 x20 -VScroll, Below is the Delimited lists from your create test file.`n Note the program is now set to add and delimit with`n               no condition on your decisions.`nTo Add multiple entries place pipes "|" with no spaces.
Gui, Add, Edit, xp+30 yp+80 w170 vDelAdd,
Gui, Add, Button, yp hp x220 gDelAdd, Add
Gui, Add, ListBox, x50 yp+35 w200 r6 vKodeyList gListyChange, % codeylist
Gui, Add, Button, xp+150 yp+110 gLCancel, Cancel
Gui, Add, Button, wp hp yp xp+50 gLSave, Save
Gui, Add, Text, x20 yp+5 cRed, (Must click save to save changes!)
Gui, AI:Font, 0f0d03, Arial
Gui, Color, d6d5d0, f5f4f0
Gui, Margin, 20, 20
Gui, Show, , Delimits
Control, Disable ,, Edit1, Delimits
Return

DelAdd:
Gui, Submit, NoHide
codeylist.= "|" DelAdd 
if (codeylist != "|")
	Sort, codeylist, U Z D|
GuiControl, Delimits:, KodeyList, % codeylist
GuiControl, Delimits:, DelAdd, 
Return

ListyChange:
Gui, Submit, NoHide
codeylist:= StrReplace(codeylist, KodeyList, "")
if (codeylist != "|")
	Sort, codeylist, U Z D|
GuiControl, Delimits:, KodeyList, % codeylist
Return

DelimitsGuiClose:
LCancel:
Gui, Delimits:Destroy
Return

LSave:
Gui, Submit, NoHide
IniDelete, % Settings, DroppedCodeCount
IniDelete, % Settings, DroppedCode
codeylist.= "|" DelAdd 
if (codeylist != "|")
	Sort, codeylist, U Z D|
codeylist:= StrReplace(codeylist, "|", "`n")
Loop, Parse, % codeylist, `n
{
	w++
	IniWrite, % A_LoopField, % Settings, DroppedCode, Key%w%
}
IniWrite, % w, % Settings, DroppedCodeCount, Key1
Gui, Delimits:Destroy
Return

Concantate:
IniRead, loopxcount, % Settings, Looper, Key1
if (loopxcount != "ERROR")
{
	Loop, % loopxcount
	{
		IniRead, codex, % Settings, KeyCodes, Key%loopxcount%
		codexlist.=  codex "|"
		loopxcount--
	}
}
Gui, Concantate:New, +AlwaysOnTop +toolWindow
Gui, Add, Edit, y20 x20 -VScroll, Below is the Delimited lists from your create test file.`n Note the program is now set to add and delimit with`n               no condition on your decisions.`nTo Add multiple entries place pipes "|" with no spaces.
Gui, Add, Edit, xp+30 yp+80 w170 vConAdd,
Gui, Add, Button, yp hp x220 gConAdd, Add
Gui, Add, ListBox, x50 yp+35 w200 r6 vKodexList gListxChange, % codexlist
Gui, Add, Button, xp+150 yp+110 gCCancel, Cancel
Gui, Add, Button, wp hp yp xp+50 gCSave, Save
Gui, Add, Text, x20 yp+5 cRed, (Must click save to save changes!)
Gui, AI:Font, 0f0d03, Arial
Gui, Color, d6d5d0, f5f4f0
Gui, Margin, 20, 20
Gui, Show, , Concantate
Control, Disable ,, Edit1, Concantate
Return

ConAdd:
Gui, Submit, NoHide
codexlist.= "|" ConAdd 
if (codexlist != "|")
	Sort, codexlist, U Z D|
GuiControl, Concantate:, KodexList, % codexlist
GuiControl, Concantate:, ConAdd, 
Return

ListxChange:
Gui, Submit, NoHide
codexlist:= StrReplace(codexlist, KodexList, "")
if (codexlist != "|")
	Sort, codexlist, U Z D|
GuiControl, Concantate:, KodexList, % codexlist
Return

CSave:
Gui, Submit, NoHide
IniDelete, % Settings, Looper
IniDelete, % Settings, KeyCodes
codexlist.= "|" ConAdd 
if (codexlist != "|")
	Sort, codexlist, U Z D|
codexlist:= StrReplace(codexlist, "|", "`n")
Loop, Parse, % codexlist, `n
{
	z++
	IniWrite, % A_LoopField, % Settings, KeyCodes, Key%z%
}
IniWrite, % z, % Settings, Looper, Key1
Gui, Concantate:Destroy
Return

ConcantateGuiClose:
CCancel:
Gui, Concantate:Destroy
Return

DefaultsGuiClose:
DCancel:
Gui, Defaults:Destroy
Return

DSave:
Gui, Submit, NoHide
IniDelete, % Settings, Editor
IniDelete, % Settings, WinManager, Key2
IniDelete, % Settings, Directory
IniDelete, % Settings, AlwaysOnTop
IniWrite, % Edit, % Settings, Editor, Key1
IniWrite, % Winactive, % Settings, WinManager, Key2
IniWrite, % YesOrNo, % Settings, AlwaysOnTop, Key1
IniWrite, % Directory, % Settings, Directory, Key1
Gui, Defaults:Destroy
Return

AISave:
GuiControl,AI:, AISave, Save_File
Return

AIClear:
FileMove, % Temp, % TempBack, 1
FileAppend, , % Temp, UTF-8
GuiControl, AI:, Words,
logicalhistory:=[]
Return
	
SusOnOff:
Suspend, Toggle
if (A_IsSuspended == 1)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOn
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOff
Return

Always:
WinSet, AlwaysOnTop, Toggle, AI
WinGet, ExStyle, ExStyle, AI
if (ExStyle == 0x00000180)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOff
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOn
Return
 
Timers:
Gui, Timers:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, y25, Rest Timer:`t`n(in seconds)
Gui, Add, Text, y75 xs, Window Not Active:`t`n(in milliseconds)
Gui, Add, Text, y125 xs, Process Loop timer:`t`n(in milliseconds)
Gui, Add, Edit, w250 r3 ys-15 -VScroll, This timer slows the script before it gets to the main loop function. It's used to help in processing the global function "Speller."
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the script when the it is not active.
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the main processing loop while typing. It's dependent on a difference created in the main edit control.
Gui, Add, Edit, ys xs+400 w50 y25
Gui, Add, UpDown, vRangeInSeconds Range1-50, 10
Gui, Add, Edit, ys xs+400 w50 y75
Gui, Add, UpDown, vRangeInMillisecondsOfActive Range1-1000, 500
Gui, Add, Edit, ys xs+400 w50 y125
Gui, Add, UpDown, vRangeInMillisecondsOfProcess Range1-100, 25
Gui, Add, Text, xm+10 ym+180, Select the above values to your personal preferences and click save to keep the changes.
Gui, Add, Text, xm+80 ym+215, (Note you have to restart the program to force the changes)
Gui, Add, Button, ym+210 xs+425 gSave, Save
Gui, Add, Button, ym+210 xs+370 gCancel, Cancel
Gui, Margin, 20, 50
Gui, Show, h250 w500, Timers
Control, Disable ,, Working, Timers
Control, Disable ,, TestInfo, Timers
Control, Disable ,, FunctionName, Timers
Return

Minimize:
IniRead, DefaultLoc, % Settings, WinManager, Key1
if (whichone == "")
	whichone:= 1
if (whichone == 0)
{
	Menu, %A_ThisMenu%, Rename, Maximize, Minimize
	whichone:= 1
}
else if (whichone == 1)
{
	Menu, %A_ThisMenu%, Rename, Minimize, Maximize
	whichone:= 0
}
if (DefaultLoc == "ERROR")
{
	MsgBox, 262144, You haven't set up a Default location., You currently haven't set up a Default location for minimize. This will automatically minimize to one of three spots. The "Editor" program you have (Defalut); the "Locked" program (first option if locked): or the screen (last option if neither exist). It will activate the program and Toggles AlwaysOnTop based on the programs active status.`n`nNote**** Your "Editor" will always take precedence in AlwaysOnTop!
	GuiControlGet, Locked, AI:, WindowControl
	if (Locked == "")
		GuiControlGet, DefaultEdit, AI:, DefaultEdit
	IfInString, DefaultEdit, .
	{
		windows:= StrSplit(DefaultEdit, ".")
		for index, window in windows
			if (index == 1)
				thiswindow:=% window
	}
	if (Locked != "")
	{
		IfWinExist, % Locked
			WinActivate, % Locked
	}
	else IfWinExist, % thiswindow
	{
		WinGetTitle, fullwindow, % "ahk_class" thiswindow
		WinActivate, % fullwindow
		GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	}
	else
	{
		WinGetTitle, fullwindow, ahk_class Progman
		GetMoveWindow(DefalutLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	}
	Return
}
else if (DefalutLoc != "ERROR")
{
	GuiControlGet, WindowSnap, AI:, WindowControl
	GuiControlGet, Locked, AI:, DefaultEdit
	IfInString, Locked, .
	{
		windows:= StrSplit(Locked, ".")
		for index, window in windows
			if (index == 1)
				windowcheck:=% window
	}
	WinGet, windows, List,,, Program Manager
	Loop, % windows
	{
		WinID := windows%A_Index%
		WinGetTitle, ThisWindow, % "ahk_id " WinID
		if ((ThisWindow == WindowSnap)&&(WindowSnap != ""))
		{
			fullwindow:=% ThisWindow
			Break
		}
		IfInString, ThisWindow, % windowcheck
		{
			fullwindow:=% ThisWindow
			Break
		}
	}
	WinGet, Minimized, MinMax , % fullwindow
	if ((fullwindow == "")||(Minimized == -1))
		fullwindow:=%  "Program Manager"
	GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
}
Return

Reload:
^r::
Reload
Return

Cancel:
Gui, Timers:Destroy
Return

Save:
Gui, Submit, NoHide
RangeInSeconds:=(RangeInSeconds*1000)
IniWrite, % RangeInSeconds, % Settings, Timers, Key1
IniWrite, % RangeInMillisecondsOfActive, % Settings, Timers, Key2
IniWrite, % RangeInMillisecondsOfProcess, % Settings, Timers, Key3
Gui, Timers:Destroy
Return

FileSelected: 
Gui, Submit, NoHide
GuiControl, AI:, Information, Working..
FileRead, contents, % FileSelected
if (ChangeType == "Get Variables")
{
	if (Gui == 1)
		filters.= "[Filter='Gui'],"
	if (Explicit == 1)
		filters.= "[Filter='explicit'],"
	if (ImplicitExplicit == 1)
		filters.= "[Filter='implicit-explicit'],"
	wi:=
	if (filters != "")
	{
		Control, Disable ,, ListBox1, AI
		contents:= GetVariables(contents, filters)
		GuiControl, AI:, Words,
		GuiControl, AI:, Words, % contents
		whichbutton:=GetControl("ButtCount")
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					thisbutton:= "\|/SoftReturn\|/"
				if (butt == "Enter")
					thisbutton:= "\|/hardReturn\|/"
				if (butt == "Unknown")
					thisbutton:= " \|/SoftReturn\|/"
			}
		}
		StringReplace, contents, contents, `n, %thisbutton%, ALL
		FileMove, % Temp, % TempBack, 1
		FileAppend, % contents, % Temp, UTF-8
	}
}
else if (ChangeType == "Get Function") ;ChangeType gChangeType, Get Variables||Get Function|Create Test File
{
	ControlGet, row, CurrentLine, , Edit3, AI
	ControlGet, rowtext, Line, % row, Edit3, AI
	if (rowtext == "")
	{
		MsgBox, Please insert the function label name
		Return
	}
	if (AssociateV == 1)
		thisignore:=% "Do_Not"
	function:=GetThisFunction(rowtext, thisignore, contents)
	GuiControl, AI:, Words, % function
	FileMove, % Temp, % TempBack, 1
	FileAppend, % function, % Temp, UTF-8
}
else if (ChangeType == "Create Test File")
{
	thesecontents:= GetTestFile(contents)
	Loop, Parse, % thesecontents, `n
	{
		if (A_LoopField == "")
			Continue
		if (A_LoopField == "Return")
			thisfile:=% thisfile A_LoopField "`n`n"
		else if (A_LoopField != "Return")
			thisfile:=% thisfile A_LoopField "`n"
	}
	FileMove, Test.ahk, % TempBack, 1
	FileAppend, % thisfile, *Test.ahk, UTF-8
}
GuiControl, AI:, AssociateV, 0
GuiControl, AI:, Gui, 0
GuiControl, AI:, Explicit, 0
GuiControl, AI:, ImplicitExplicit, 0
GuiControl, AI:, FunctionName,
GuiControl, AI:, WordKeeper, 7h151s@a#res37
GuiControl, AI:, Information, Done
Control, Enable ,, ListBox1, AI
Return

AddWindowGroupControl(control)
{
	if (control == "Show")
	{
		GuiControl, AI:Show, GroupControls
		GuiControl, AI:, GroupControls, Window Controls
		GuiControl, AI:Show, GetWindow
		GuiControl, AI:Show, SnapWindow
		GuiControl, AI:Show, SnapToEditor
		GuiControl, AI:Show, AutoEdit
		GuiControl, AI:Show, EnableCC
		GuiControl, AI:Show, EnableVV
		GuiControl, AI:Hide, Welcome
		GuiControl, AI:Show, ControlInformation
	}
	if (control == "Hide")
	{
		GuiControl, AI:Hide, GroupControls
		GuiControl, AI:Hide, GetWindow
		GuiControl, AI:Hide, SnapWindow
		GuiControl, AI:Hide, SnapToEditor
		GuiControl, AI:Hide, AutoEdit 
		GuiControl, AI:Hide, EnableCC
		GuiControl, AI:Hide, EnableVV
		GuiControl, AI:Show, Welcome
		GuiControl, AI:Hide, ControlInformation
	}
	Return
}

GetWindowGroupControl(control)
{
	if (control == "Show")
	{
		GuiControl, AI:Show, GroupControls
		GuiControl, AI:, GroupControls, Window Stats
		GuiControl, AI:Show, ComboBox2
		GuiControl, AI:Show, GetPix
		GuiControl, AI:Show, GetMouse
		GuiControl, AI:Show, GetWinS
		GuiControl, AI:Show, GetWinT
		GuiControl, AI:Show, MultiSele
		GuiControl, AI:Hide, Welcome
		GuiControl, AI:Show, ControlInformation
	}
	if (control == "Hide")
	{
		GuiControl, AI:Hide, GroupControls
		GuiControl, AI:Hide, ComboBox2
		GuiControl, AI:Hide, GetPix
		GuiControl, AI:Hide, GetMouse
		GuiControl, AI:Hide, GetWinS
		GuiControl, AI:Hide, GetWinT
		GuiControl, AI:Hide, MultiSele
		GuiControl, AI:Show, Welcome
		GuiControl, AI:Hide, ControlInformation
	}
	Return
}

Tracker(thistrack, DefaultLoc, Whichone, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
{
	GuiControlGet, WindowSnap, AI:, WindowControl
	GuiControlGet, DefaultEdit, AI:, DefaultEdit
	GuiControlGet, winSnap, AI:, SnapWindow
	GuiControlGet, EditSnap, AI:, SnapToEditor
	windows:= StrSplit(DefaultEdit, ".")
	for index, window in windows
		if (index == 1)
			editwindow:=% window
	WinGet, windows, List,,, Program Manager
	Loop, % windows
	{
		WinID := windows%A_Index%
		WinGetTitle, ThisWindow, % "ahk_id " WinID
		if ((ThisWindow == WindowSnap)&&(ThisWindow != ""))
		{
			fullwindow:=% ThisWindow
			Break
		}
		IfInString, ThisWindow, % editwindow
		{
			fullwindow:=% ThisWindow
			Break
		}
	}
	if (thistrack != fullwindow)
		if ((EditSnap != "")||(WindowSnap != ""))
			IfWinActive, % fullwindow
				if ((winSnap == 1)||(EditSnap == 1))
				{
					WinSet, Transparent , Off, AI
					WinSet, AlwaysOnTop, on, AI
					GetMoveWindow(DefaultLoc, Whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
				}
	IfWinNotActive, % fullwindow
		IfWinNotActive, AI
			if ((winSnap == 1)||(EditSnap == 1))
			{
				WinSet, Transparent , 0, AI
				WinSet, AlwaysOnTop, off, AI
				fullwindow:=% ""
			}
	Return % fullwindow
}

GetMoveWindow(DefaultLoc, Whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
{
	if (fullwindow != "Program Manager")
		WinGetPos , winPosX, winPosY, windowwidth, windowheight, % fullwindow
	else
	{
		winPosX:=0
		winPosY:=0
		windowwidth:=(A_ScreenWidth-50)
		windowheight:=(A_ScreenHeight-50) ; offage is set for DPI and virtual windows. This should be enough for most windows but each person has their own settings.
	}
	If (DefaultLoc != "ERROR")
		ThisWindowLoc(DefaultLoc,Whichone, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	else if (DefaultLoc == "ERROR")
	{
		MsgBox, 262212, Default location not set, You have not set up a default location for the window. Would you like to continue?
		IfMsgBox, Yes
		{
			Loop,
			{
				x++
				y:=0
				ThisWindowLoc(x, y, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
				MsgBox, 262144, first position, This is the first position of the window minimized.
				y:=1
				ThisWindowLoc(x, y, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
				MsgBox, 262211, Do you like that location?, This is the second position maximized.`nIf you like this position click yes.`nTo exit click Cancel`n%x% %y% 
				IfMsgBox Yes
				{
					IniWrite, % x, % Settings, WinManager, Key1
					Break
				}
				IfMsgBox Cancel
					Break
				if (x == 9)
					x:=0
			}
		}	
		IfMsgBox, No
			Return
	}
	Return
}
	

ThisWindowLoc(DefaultLoc, Whichone, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
{
	AIwidth:= 100
	AIheight:= 80
	if (DefaultLoc == 1)
	{
		MainWindowX:=(windowwidth-AIwidth+winPosX)
		MainWindowY:=(windowheight-AIheight+winPosY) ; bottom right corner
		GuiWindowX:=(windowwidth-AIorignalwidth+winPosX)
		GuiWindowY:=(windowheight-AIorignalhieght+winPosY)
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 2)
	{
		MainWindowX:=% winPosX
		MainWindowY:=(windowheight-AIheight+winPosY) ; bottom left corner
		GuiWindowX:=% winPosX
		GuiWindowY:=(windowheight-AIorignalhieght+winPosY)
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 3)
	{
		MainWindowX:=% winPosX
		MainWindowY:=% winPosY ; upper left corner
		GuiWindowX:=% winPosX
		GuiWindowY:=% winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 4)
	{
		MainWindowX:=(windowwidth-AIwidth+winPosX)
		MainWindowY:=% winPosY ; upper right corner.
		GuiWindowX:=(windowwidth-AIorignalwidth+winPosX)
		GuiWindowY:=% winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 5)
	{
		MainWindowX:=(windowwidth/2)-(AIwidth/2)
		MainWindowY:=% winPosY ; upper center
		GuiWindowX:=(windowwidth/2)-(AIorignalwidth/2)
		GuiWindowY:=% winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 6)
	{
		MainWindowX:=(windowwidth/2)-(AIwidth/2)
		MainWindowY:=(windowheight-AIheight+winPosY) ; lower center
		GuiWindowX:=(windowwidth/2)-(AIorignalwidth/2)
		GuiWindowY:=(windowheight-AIorignalhieght+winPosY)
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 7)
	{
		MainWindowX:=% winPosX
		MainWindowY:=(windowheight/2)-(AIheight/2)+winPosY ; left center
		GuiWindowX:=% winPosX
		GuiWindowY:=(windowheight/2)-(AIorignalhieght/2)+winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 8)
	{
		MainWindowX:=(windowwidth-AIwidth+winPosX)
		MainWindowY:=(windowheight/2)-(AIheight/2)+winPosY ;right center
		GuiWindowX:=(windowwidth-AIorignalwidth+winPosX)
		GuiWindowY:=(windowheight/2)-(AIorignalhieght/2)+winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 9)
	{
		MainWindowX:=(windowwidth/2)-(AIwidth/2)
		MainWindowY:=(windowheight/2)-(AIheight/2)+winPosY ; center center
		GuiWindowX:=(windowwidth/2)-(AIorignalwidth/2)
		GuiWindowY:=(windowheight/2)-(AIorignalhieght/2)+winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	Return
}

GetTestFile(data)
{
	IniRead, loopcount, % Settings, Looper, Key1
	if (loopcount != "ERROR")
	{
		Loop, % loopcount
		{
			IniRead, codex, % Settings, KeyCodes, Key%loopcount%
			codexlist.= codex "`n"
			loopcount--
		}
		IniRead, loopcount, % Settings, DroppedCodeCount, Key1
		if (loopcount != "ERROR")
		{
			Loop, % loopcount
			{
				IniRead, codedrop, % Settings, DroppedCode, Key%loopcount%
				codeylist.= codedrop "`n"
				loopcount--
			}
		}
		data:= StrReplace(data, "`r", "")
		Loop, Parse, % data, `n
		{
			y++
			codestring:=
			line:=% A_LoopField
			sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
			for index, sentence in sentences
			{
				if (index == 1)
					codestring:=% sentence
				if (index == 2)
					commentstring:=% sentence
			}
			keycodex:= StrReplace(codestring, ",",  " ")
			keycodex:= StrReplace(keycodex, "  ", " ")
			keycodex:= StrReplace(keycodex, "  ", " ")
			keycodex:=% Trim(keycodex)
			thesewords:= StrSplit(keycodex, A_Space)
			for index, keycode in thesewords
				if (index == 1)
					keycodex:=% keycode
			IfinString, codeylist, % keycodex
				codestring:=% ""
			IfinString, codexlist, % keycodex
			{
				filecontents:=% filecontents codestring "`n"
				codestring:=% ""
			}
			codestring:= CodeStringCheck(codestring)
			if (codestring != "")
			{
				IfinString, codestring, Return
				{
					if (thischecker == 1)
						IfNotInString, codestring, % "`t"
							thischecker:= 0
					codestring:=% ""
				}
				IfInString, codestring, Global
				{
					filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfInString, codestring, Gui
				{
					IfinString, codestring, Show
						filecontents:=% filecontents codestring "`nReturn`n`n"
					else
						filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfInString, codestring, Menu
				{
					filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfinString, codestring, :
				{
					if (thischecker != 1)
					{
						thischecker:= 1
						if (x != 1)
							x:=1
					}
					filecontents:=% filecontents codestring "`nReturn`n`n"
					codestring:=% ""
				}
				IfInString, filecontents, % codestring
					codestring:=% ""
			}
		}
	}
	else if (loopcount == "ERROR")
	{
		MsgBox, 70, Be sure before you continue., In the following message boxes you will be shown the beginning of your code. This will omit the comments and anything past the first comma as demiliters for your test.ahk creation. each type will be added to the Ini file settings and read for your future creations. You can always change this setting by selecting default in the default menu.`n`n**Also note This does skip continuation sections.
		IfMsgBox Continue
		{
			data:= StrReplace(data, "`r", "")
			Loop, Parse, % data, `n
			{
				y++
				line:=% A_LoopField
				sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
				for index, sentence in sentences
				{
					if (index == 1)
						codestring:=% sentence
					if (index == 2)
						commentstring:=% sentence
				}
				codestring:= CodeStringCheck(codestring)
				if (codestring != "")
				{
					IfinString, codestring, Return
					{
						if (thischecker == 1)
							IfNotInString, codestring, % "`t"
								thischecker:= 0
						codestring:=% ""
					}
					IfInString, codestring, Global
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, codestring, Gui
					{
						IfinString, codestring, Show
							filecontents:=% filecontents codestring "`nReturn`n`n"
						else
							filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, codestring, Menu
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfinString, codestring, :
					{
						if (thischecker != 1)
						{
							thischecker:= 1
							if (x != 1)
							{
								x:=1
								MsgBox, 32, g-Sublabels, sublabels are automatically added
							}
						}
						filecontents:=% filecontents codestring "`nReturn`n`n"
						codestring:=% ""
					}
					keycodex:= StrReplace(codestring, ",",  " ")
					keycodex:= StrReplace(keycodex, "  ", " ")
					keycodex:= StrReplace(keycodex, "  ", " ")
					keycodex:=% Trim(keycodex)
					thesewords:= StrSplit(keycodex, A_Space)
					for index, keycode in thesewords
						if (index == 1)
							keycodex:=% keycode
					IfinString, thisignoredlist, % keycodex
						codestring:=% ""
					IfinString, thisgottenlist, % keycodex
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, filecontents, % codestring
						codestring:=% ""
					if (codestring != "")
					{
						MsgBox, 36, Do you want to add this line?, % keycodex "`n`nFound on line: " y "`n`npress yes if you want to add the first (word) of this line to your delimiter fields."
						IfMsgBox Yes
						{
							z++
							IniWrite, % z, % Settings, Looper, Key1
							IniWrite, % keycodex, % Settings, KeyCodes, Key%z%
							thisgottenlist.= keycodex
							filecontents:=% filecontents codestring "`n"
						}
						else IfMsgBox No
						{
							w++
							IniWrite, % w, % Settings, DroppedCodeCount, Key1
							IniWrite, % keycodex, % Settings, DroppedCode, Key%w%
							thisignoredlist.= codestring " "
							Continue
						}
					}
				}
			}
		}
	}
	Return % filecontents
}

CodeStringCheck(codestring)
{
	IfInString, codestring, GuiControl
		codestring:=% ""
	IfinString, codestring, `t
		codestring:=% ""
	IfInString, codestring, Global
		Return % codestring
	IfInString, codestring, Gui ; It's likely a user may place any of the below special characters in a gui 4th parameter.
		Return % codestring
	IfInString, codestring, =
		codestring:=% ""
	IfInString, codestring, ( ;)
		codestring:=% ""
	IfInString, codestring, {
		codestring:=% ""
	IfInString, codestring, }
		codestring:=% ""
	IfInString, codestring, `%
		IfNotInString, codestring, SetWorkingDir
			codestring:=% ""
	IfinString, codestring, Loop
		codestring:=% ""
	IfinString, codestring, else
		codestring:=% ""
	IfinString, codestring, if%A_Space%
		codestring:=% ""
	IfinString, codestring, ::
		codestring:=% ""
	Return % codestring
}

GetThisFunction(function, get, data)
{
	function:= StrReplace(function, "`r`n", "")
	function:= StrReplace(function, "`n", "")
	functionlength:=StrLen(function)
	data:= StrReplace(data, "`r", "")
	function:= GetFunction(data, functionlength, function)
	thisfoundfunction.= function "`n"
	function:=""
	if (get == "Do_Not")
	{
		Loop,
		{
			Loop, Parse, % thisfoundfunction, `n
			{
				IfInString, A_LoopField, =
					IfInString, A_LoopField, (
					{
						foundpossible:= FunctionLabelGet(A_LoopField)
						Trim(foundpossible)
						IfNotInString, foundpossible, % A_Space
							IfNotInString, thesefound, % foundpossible
							{
								functionlength:=StrLen(foundpossible)
								function:= GetFunction(data, functionlength, foundpossible)
							}
						if (function != "")
							thisfoundfunction.= function "`n"
					}
				if (function != "")
					function:=
				thesefound.= foundpossible ", "
			}
			IfNotInString, thesefoundpast, % thesefound
				thesefoundpast.= thesefound
			IfinString, thesefoundpast, % thesefound
				Break
		}
	}
	Return % thisfoundfunction
}

GetFunction(data, functionlength, function)
{
	Loop, Parse, % data, `n
	{
		if (thisfunction == "")
		{
			linesubstring:= SubStr(A_LoopField, 1, functionlength)
			if (function == linesubstring)
			{
				thisfunction:= % A_LoopField "`n"
				z:=1
			}
		}
		else if (thisfunction != "")
		{
			thisfunction.= A_LoopField "`n"
			if (A_LoopField == "{")
				x++
			if (A_LoopField == "}")
				x--
			if (z == 1)&&(A_LoopField != "{")
				thisfunction:= ""
			z:=0
		}
		if ((x == 0)&&(thisfunction != ""))
		{
			thisfoundfunction:= % thisfunction
			thisfunction:= ""
		}
	}
	Return % thisfoundfunction
}

FunctionLabelGet(line)
{
	thissplitfunction:= StrSplit(line, "= ")
	for index, thissplit in thissplitfunction
		if (index == 2)
			thispart:=% thissplit
	thispartsplit:= StrSplit(thispart, "(") ;"
	for index, function in thispartsplit
		if (index == 1)
			Return % function
	Return
}

ChangeType:
Gui, Submit, NoHide
if (ChangeType == "Get Variables")
{
	GuiControl, AI:Text, Results, Get variables`n(Filter results by Checkbox)
	GuiControl, AI:Hide, FunctionName
	GuiControl, AI:Hide, FunctionLabel
	GuiControl, AI:Hide, TestInfo
	GuiControl, AI:Hide, AssociateV
	GuiControl, AI:Show, Gui
	GuiControl, AI:Show, Explicit
	GuiControl, AI:Show, ImplicitExplicit
}
if (ChangeType == "Get Function")
{
	GuiControl, AI:Text, Results, Get Function`n(Select a file to get a function)
	GuiControl, AI:Show, FunctionName
	GuiControl, AI:Show, FunctionLabel
	GuiControl, AI:Hide, TestInfo
	GuiControl, AI:Show, AssociateV
	GuiControl, AI:Hide, Gui
	GuiControl, AI:hide, Explicit
	GuiControl, AI:Hide, ImplicitExplicit
	GuiControl, Focus, FunctionName
}
if (ChangeType == "Create Test File")
{
	GuiControl, AI:Text, results, Create a Test File`n(Create functionless test ahk)
	GuiControl, AI:hide, Gui
	GuiControl, AI:Hide, Explicit
	GuiControl, AI:hide, ImplicitExplicit
	GuiControl, AI:Hide, AssociateV
	GuiControl, AI:hide, FunctionName
	GuiControl, AI:hide, FunctionLabel
	GuiControl, AI:Show, TestInfo
}
Return

GetVariables(filecontents, filters)
{
	Loop, Parse, % filecontents, `r
	{
		linenumber++
		line:=% A_LoopField
		sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
		for index, sentence in sentences
		{
			if (index == 1)
				codestring:=% sentence
			if (index == 2)
				commentstring:=% sentence
		}
		VarSetCapacity(information, 0) 
		codestring:= RemoveCertainChars(codestring, "Start")
		IfInString, codestring, Dll
			Continue
		IfInString, codestring, Box`,
			Continue
		IfInString, codestring, StringReplace
			Continue
		IfInString, codestring, RegEx
			Continue
		IfInString, codestring, Ini
			Continue
		IfInString, codestring, =
		{
			IfInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Percent", linenumber)
				IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
			}
			else IfNotInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
			IfInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Quotes", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring 
			}
			else IfNotInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
		}
		else IfInString, codestring, [percent]
		{
			variablestring:= GetVariableString(codestring, "Percent", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring
		}
		else IfInString, codestring, [quotes]
		{
			variablestring:= GetVariableString(codestring, "Quotes", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring "found in quotes 2`n"
		}
		IfInString, codestring, Gui
			IfInString, codestring, `,
				IfInString, codestring, %A_Space%v
				{
					variablestring:= GetVariableString(codestring, "Gui", linenumber)
					IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
				}
	}
	thesefilters:=StrSplit(filters, ",")
	for index, filter in thesefilters
	{
		if (index == 1)
			if (filter != "")
				firstfilter:=% filter
		if (index == 2)
			if (filter != "")
				secondfilter:=% filter
		if (index == 3)
			if (filter != "")
				thirdfilter:=% filter
	}
	Loop, Parse, % variablelist, `n
	{
		thischeck:= ""
		information:= ""
		if (A_LoopField != "")
		{
			repeatcheck:= StrSplit(A_LoopField, "[thissplitter]")
			for index, repeat in repeatcheck
			{
				if (index == 1)
				{
					IfNotInString, completedlist, % repeat
						thischeck:=% repeat
					IfInString, completedlist, % repeat
					{
						checking:= MakeSure(completedlist, repeat)
						if (checking == "True")
							Continue
						else if (checking == "False")
							thischeck:=% repeat
					}
				}
				if (index == 2)
				{
					if (firstfilter != "")
						IfInString, repeat, % firstfilter
						{
							applyfilters:= StrSplit(repeat, firstfilter)
							for index, apply in applyfilters
								information.= apply
						}
					else if (secondfilter != "")
						IfInString, repeat, % secondfilter
						{
							applyfilters:= StrSplit(repeat, secondfilter)
							for index, apply in applyfilters
								information.= apply
						}
					else if (thirdfilter != "")
						IfInString, repeat, % thirdfilter
						{
							applyfilters:= StrSplit(repeat, thirdfilter)
							for index, apply in applyfilters
								information.= apply
						}
				}
			}
			if ((thischeck != "")&&(information != ""))
			{
				checklist:=% Trim(thischeck) "`n" Trim(information) "`n"
				IfNotInString, completedlist, % checklist
					completedlist.= checklist
			}
		}
	}
	completedlist:= RemoveCertainChars(completedlist, "End")
	Return % completedlist
}

MakeSure(listinprogress, checkword)
{
	Loop, Parse, % listinprogress, `n
	{
		if (checkword == A_LoopField)
			Return % "True"
	}
	Return % "False"
}

GetVariableString(codestring, whichone, linenumber)
{
	if (whichone == "Gui")
	{
		variablestrings:= StrSplit(codestring, ",")
		for index, variablestring in variablestrings
		{
			if (index > 4)
				Continue
			IfInString, variablestring, %A_Space%v
				thisvariablestring:=% variablestring
		}
		variablestring:= StrSplit(thisvariablestring, A_Space)
		for index, variable in variablestring
		{
			thisvariableletter:= SubStr(variable, 1, 1)
			if (thisvariableletter == "v")
				Return % variable "[thissplitter] Gui variable[Filter='Gui'] Line number is found at: " linenumber "`n"
		}
		Return % variable "[thissplitter] Gui variable Line number is found at: " linenumber "`n"
	}
	if (whichone == "Quotes")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [quotes]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		variablestrings:= StrSplit(codestring, "[quotes]")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 0)
				IfNotInString, variablestring, %A_Space%
					IfNotInString, variables, % variablestring
						variables.= "[quotes]" variablestring "[quotes][thissplitter] explicit[Filter='explicit'] variable Line number is found at: " linenumber "`n"
		}
		Return % variables
	}
	if (whichone == "Percent")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [percent]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		IfInString, codestring, `,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					IfInString, variablestring, [percent]
						IfNotInString, variablestring, =
							IfInString, variablestring, A_Space
								variables.= variablestring "[thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		IfNotInString, codestring, `,
		{
			IfInString, codestring, =
			{
				variablestrings:= StrSplit(codestring, "=")
				for index, variablestring in variablestrings
				{
					if (index == 1)
					{
						variables:= StrSplit(variablestring, A_Space)
						for index, variable in variables
							thisvariable:=% variable
					}
					if (index == 2)
						codestring:=% variablestring
				}
			}
			variablestrings:= StrSplit(codestring, "[percent]")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					variables.= "[percent]" variablestring "[percent][thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		if (thisvariable != "")
			variables.= thisvariable "[thissplitter]implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
		Return % variables
	}
	if (whichone == "Equals")
	{
		variablestrings:= StrSplit(codestring, "=")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 1)
				IfNotInString, variablestring, [quotes]
				{
					thisvariablestring:= StrSplit(variablestring, A_Space)
					for index, thisvariable in thisvariablestring
					{
						variable:=% thisvariable "[thissplitter] implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
					}
				}
		}
		Return % variable
	}
	Return % "Not Found"
}

RemoveCertainChars(string, special)
{
	if (special == "Start")
	{
		StringReplace, string, string, ", [quotes], ALL ; "
		StringReplace, string, string, `%%A_Space%, [percent], ALL
		StringReplace, string, string, `%, [percent], ALL
		StringReplace, string, string, %A_Space%:, :, ALL
		StringReplace, string, string, :=, =, ALL
		StringReplace, string, string, ==, =, ALL
		StringReplace, string, string, >, =, ALL
		StringReplace, string, string, <, =, ALL
		StringReplace, string, string, %A_Space%!=, =, ALL
		StringReplace, string, string, =%A_Space%, =, ALL
		StringReplace, string, string, %A_Space%=, =, ALL
		StringReplace, string, string, ), , ALL
		StringReplace, string, string, (, , ALL ;)
		StringReplace, string, string, `t, , ALL
	}
	if (special == "End")
	{
		StringReplace, string, string, [quotes], ", ALL ; "
		StringReplace, string, string, [percent], `%, ALL
		StringReplace, string, string, `,, , ALL
	}
	Return % string
}

GetButton_Count()
{
	Loop,
	{
		ButtonCountCheck:= GetControl("ButtCount")
		if (ButtonCountCheck != OldButtonCountCheck)
		{
			OldCount:=% Count
			OldButton:=% Button
			Sleep, 500
			ButtonCount_Split:= StrSplit(ButtonCountCheck, ",")
			For Index, ButtCount in ButtonCount_Split
			{
				if (Index == 1)
					Count:=% ButtCount
				if (Index == 2)
					Button:=% ButtCount
			}
		}
		else if (ButtonCountCheck == OldButtonCountCheck)
			Break
		if ((Button != OldButton)&&(Count > 1))
			Break
		OldButtonCountCheck:=% ButtonCountCheck
	}
	if (Button == OldButton)
	{
		ButtonCountReturn:=% Count "," Button
		GuiControl,AI:, ButtonCountCheck, % "0," Button
	}
	if (Button != OldButton)
	{
		NewCount:=% Count-OldCount
		GuiControl,AI:, ButtonCountCheck, % NewCount "," Button
		ButtonCountReturn:=% OldCount "," OldButton
	}
	Return
}

ApplyLogicalChange(activeuserinput, logicalhistory, numberofdifferences)
{
	x:= 0
	newhistoryrecord:=[]
	activeuserinputlastline:= GetLineCount(activeuserinput)
	logicalhistorylastline:= GetLineCount(logicalhistory)
	LastLine:= logicalhistory["linePos" logicalhistorylastline]
	Loop, % activeuserinputlastline
	{
		record:=
		x++ ; a lagged y variable needed to stagger history.
		occurenceuser:= activeuserinput["linePos" x]
		if (y > 0)
		{
			y:=(x-z) ; this will be an opposite staggered y (x+z) for deleted lines.
			historyrecord:= logicalhistory["linePos" y]
		}
		else
			historyrecord:= logicalhistory["linePos" x] ; even though the line now isn't right doesn't mean next time it won't be.
		splithistoryrecord:= StrSplit(historyrecord, ["(hardReturn)", "(softReturn)"])
		for index, splithistory in splithistoryrecord
		{
			if (Index == 1)
				record:= % splithistory
		}
		if ((occurenceuser != record)&&(numberofdifferences != 0)) ; the number of occurences go negative when lines get deleted... I haven't updated the below else for that yet.
		{
			LastLine:= logicalhistory["linePos" logicalhistorylastline] ; if a user is lagging the array make sure you are putting in last lines right.
			if ((LastLine == "(softReturn)")||(LastLine == "(hardReturn)")) ; the last line shouldn't be any other value.
			{
				z++ ; a z variable making sure we don't lose y and holding the number of occurences.
				if (z == 1) ; there's not enough time to add different enters in different spots (meaning the user couldn't add enough enters in the time this will be done).
					y:=% x
				IfInString, LastLine, (softReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
				IfInString, LastLine, (hardReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
				numberofdifferences--
				logicalhistorylastline--
			} ; the likely answer is a deleted line in occurenceuser. we need to add to the numberofdifferences. I'll also need to update this in the future for the array.
			else
				numberofdifferences++
		}
		else if ((occurenceuser != record)&&(numberofdifferences == 0)) ; meaning user has updated a line with a new record
		{
			newhistoryrecord["linePos" x]:= occurenceuser
			IfInString, record, (softReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
			IfInString, record, (hardReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
		} ; z from above holds all change counts. y from above holds the history record line back. technically y can equal x-z or just y++. I think for greater clarity it should be x-z because a user may choose to purposely lag the logicalhistoryarray Change function. Basically this function can be implimented at will as long as the keys are being kept up with and added to the historyarray in the main loop (of course that might also come with logical array issues).
		else if ((occurenceuser == record)&&(numberofdifferences == 0))
			newhistoryrecord["linePos" x]:= record
	}
	check:=GetControl("GetKeeper")
	if (check == "7h151s@a#res37")
		Return
	Return % newhistoryrecord ; There has been many different statements on using the % after Return or in ":=" as an operorator (it technically doesn't need to be done and can cause issues if done improperly). I use it because honestly it's like my signature to my work.
}

Doppler(usersentence, historysentence)
{
	livewords:=[]
	pastwords:=[]
	check:=GetControl("GetKeeper")
	if (check == "&not@a#rea1*sent3nc3")
	{
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			livewords["wordPos" key]:= userwords
		}
		historysplit:=StrSplit(historysentence, A_Space)
		for key, historywords in historysplit
		{
			pastwords["wordPos" key]:= historywords
		}
		usercount:=GetLineCount(livewords)
		historycount:= GetLineCount(pastwords)
		Loop, % usercount
		{
			x++
			userword:=livewords["wordPos" x]
			historyword:=pastwords["wordPos" x]
			userwordlength:=StrLen(userword)
			historywordlength:= StrLen(historyword)
			if ((userword != historyword)||(historycount < x))
				GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		}
		StringReplace, userword, userword, historyword, , ALL
	}
	else if (check != "&not@a#rea1*sent3nc3")
	{
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 1)
				historyword:=% chec
			if (index == 2)
				ouserword:=% chec
			if (index == 3)
				x:=% chec
		}
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			if (key == x)
				userword:=% userwords
		}
		GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		StringReplace, userword, userword, historyword, , ALL
	}
	userwordlength:=StrLen(userword)
	if (userwordlength < 2)
	{
		GuiControl, AI:, Information, Working...
		SpellChecker(0)
	}
	if (userwordlength > 3)
	{
		GuiControl, AI:, Information, Working.
		ourwords:=WordCheck(userword, userwordlength)
		if (ourwords == "")
			SpellChecker(0)
		else if (ourwords != "")
		{
			SpellChecker(userwordlength)
			GetControl(ourwords)
		}
	}
	Return
}

FixLogicalhistory_Array(historyarray, howmanylines)
{
	lastline:= GetLineCount(historyarray)
	whichbutton:= GetControl("ButtCount")
	Loop, % howmanylines
	{
		lastline++
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					historyarray["linePos" lastline]:= "(softReturn)"
				if (butt == "Enter")
					historyarray["linePos" lastline]:= "(hardReturn)"
			}
		}
	}
	Return % historyarray
}

ReturnLineArray(lines, user)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/SoftReturn\|/", "\|/userReturns\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

GetButtonCount(pressed)
{
	pressing:= StrSplit(pressed, ",")
	For Index, press in pressing
		if (Index == 1)
			Return % press
}

FindingRealLineLOL(occurenceuser, rowbefore, thisrow)
{
	IfInString, occurenceuser, %rowbefore%
	{
		rowlength:= StrLen(rowbefore)
		occurencelength:= StrLen(occurenceuser)
		subtractedlength:=(occurencelength-rowlength)
		thisstring:= SubStr(occurenceuser, subtractedlength, occurencelength)
		if (thisstring == rowbefore)
		{
			IfInString, occurenceuser, %thisrow%
				Return % "Found"
			IfNotInstring, occurenceuser, %thisrow%
				Return % "NextRow"
		}
	}
	if (rowbefore == "NextRow")
		IfInString, occurenceuser, %thisrow%
			Return % "Found"
	Return % "NotFound"
}

ProcessStart(contents, Rest)
{
	logicalhistory:= []
	WinSet, Transparent, 0, Words
	history:= GetHistory()
	logicalhistory:= ReturnLineArray(history, user)
	Control, Disable ,, Words, AI
	GuiControl, AI:, Words, % contents
	Sleep, % Rest
	Control, Enable ,, Words, AI
	GuiControl, AI:, Information, Done
	Control, Enable ,, ListBox1, AI
	Return % logicalhistory
}

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	if (n > 3)
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	if (n == 0)
		WinSet, Transparent, 0, Words
	WinGet, visible, Transparent, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	Return
}
Return

ReturnClearDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			hinput:= harray["linePos" x]
			hsplit:= StrSplit(hinput, ["(hardReturn)", "(softReturn)"])
			for Index, h in hsplit
			{
				if (Index == 1)
					checkh:= % h
			}
			uinput:= uarray["linePos" x]
			StringReplace, uinput, uinput, (softReturn), , ALL
			StringReplace, uinput, uinput, (hardReturn), , ALL
			l_checkh:= StrLen(checkh)
			l_uinput:= StrLen(uinput)
			if (uinput != checkh)
				Return % x
			if (l_checkh != l_uinput)
				Return % x
			if (x == v)
				Break
			checkh:=
		}
		Return % "0"
	}
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return % "True"
	}
}

GetLineCount(arraycount)
{
	LastLine:=0
	for Index, count in arraycount
		++LastLine
	Return % LastLine
}

GetControl(FocTex)
{
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, FunctionName
	ControlGet, row, CurrentLine, , FunctionName, AI
	ControlGet, rowtext, Line, % row, FunctionName, AI
	GuiControlGet, Word, Words:, Listbox1
	StringReplace, text, text, `n, \|/userReturns\|/, ALL
	GuiControlGet, ButtonCountCheck, AI:, ButtonCountCheck
	GuiControlGet, Save_File, AI:, AISave
	GuiControlGet, DopplerGet, AI:, WordKeeper
	if (FocTex == "RowText")
		Return % rowtext
	if (FocTex == "GetKeeper")
		Return % DopplerGet
	if (FocTex == "AISave")
		Return % Save_File
	if (FocTex == "ButtCount")
		Return % ButtonCountCheck
	if (FocTex == "Row")
		Return % row
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	GuiControl, Words:, Listbox1, | 
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
	Return
}

HashContents(contents)
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, \|/CR+LF\|/, `n, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, `n, ALL
	Return % contents
}

GetHistory()
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, `r`n,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, (softReturn)\|/SoftReturn\|/, ALL
	StringReplace, contents, contents, \|/CR+LF\|/,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, (softReturn)\|/SoftReturn\|/, ALL
	Return % contents
}

RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitapp
This has been a lot of fun building. I did find some other issues (minimize making the program disappear if the edit window was gone and it wasn't locked and snapped). I fixed those issues. I have also fixed some forgotten button updates (decided to just use variable names instead). I plan on adding more to. I also added a better {tab} function to the Mouse and Pixel Edit box (turns out the default 32 wasn't enough).

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 26 Dec 2023, 07:04

Have you ever been in the middle of working on something have to leave and then find where you were? Me too.... So I have added Profiles. This new feature will allow you to add the current window and all it's settings.

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability. ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
#InstallkeybdHook
#InstallMouseHook
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
Global Settings:= % Cache "\Settings.ini"
IniRead, Directory, % Settings, Directory, Key1
if (Directory != "ERROR")
	SetWorkingDir %Directory%
else
	SetWorkingDir %A_ScriptDir% 
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)
IniRead, WinDrop, % Settings, WinManager, Key2
if (WinDrop != "ERROR")
	WinVictive:=% WinDrop
IniRead, Editor, % Settings, Editor, Key1
if (Editor == "ERROR")
	Editor:=% "Notepad.exe"
IniRead, Rest, % Settings, Timers, Key1
If (Rest == "ERROR")
{
	IniWrite, 10000, % Settings, Timers, Key1
	Rest:= 10000
}
IniRead, Notactive, % Settings, Timers, Key2
if (Notactive == "ERROR")
{
	IniWrite, 500, % Settings, Timers, Key2
	Notactive:= 500
}
IniRead, NoDif, % Settings, Timers, Key3
if (NoDif == "ERROR")
{
	IniWrite, 25, % Settings, Timers, Key3
	NoDif:= 25
}
IniRead, Always, % Settings, AlwaysOnTop, Key1
if (Always != "ERROR")
	GuestOn:=% Always
IniRead, DefaultLoc, % Settings, WinManager, Key1

Loop, Files, *.ahk, F R
{
	IfInString, A_LoopFileName, @
		Continue
	IfNotInString, wi, % A_LoopFileName
		wi=%wi%%A_LoopFileName%|
}

Menu, AIsMenu, Add, Minimize, Minimize
Menu, Settings, Add, Default Settings, Default
Menu, Settings, Add, Timers, Timers
Menu, Settings, Add, AlwaysOnTop`ton/off, Always
Menu, Settings, Add, Suspend`ton/off, SusOnOff
Menu, Settings, Add, Reload`tCtrl+r, Reload
Menu, AIsMenu, Add, Settings, :Settings

SetTitleMatchMode, 2
CoordMode, Caret, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Window
if (GuestOn == 1)
	Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
else if (GuestOn == 0)
	Gui, AI:New, -AlwaysOnTop +Resize +toolWindow
else
	Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, Menu, AIsMenu
Gui, Add, Edit, r1 x25 y21 w150 ReadOnly vWorking, % A_WorkingDir
Gui, Add, DropDownList, x25 y55 w150 vChangeType gChangeType, Get Variables||Get Function|Create Test File
Gui, Add, GroupBox, x25 y90 h250 w150 wrap vResults, Get variables`n(Filter results by Checkbox)
Gui, Add, ListBox, r10 yp+35  xp+15 w120 gFileSelected vFileSelected, %wi%
Gui, Add, Edit, r4 yp+150 xp -VScroll vTestInfo w120,  Select a file to create a Test.ahk file with no function or sublabeled function.
Gui, Add, Text, yp xp vFunctionLabel, input the function lablel
Gui, Add, Edit, r1 w120 vFunctionName,
Gui, Add, Checkbox, vAssociateV, Associated functions
Gui, Add, Checkbox, yp-40 xp vGui, Gui Variables
Gui, Add, Checkbox, vExplicit, Explicit Variables
Gui, Add, Checkbox, vImplicitExplicit, Implicit-Explicit
Gui, Add, Text, -E0x200 x0 y0 vButtonCountCheck w0, 0,Unknown
Gui, Add, Text, -E0x200 vWordKeeper w0, &not@a#rea1*sent3nc3s
Gui, Add, Edit,  r19 ym+45 x200 vWords w325 hwndTracker,
Gui, Add, Button, yp+1000 xp gAISave, Save
Gui, Add, Text, vAISave w0, Don't save
Gui, Add, Edit, r4 ym+45 x200 w325 ReadOnly t64 vPixMouse, (Mouse Position)`t(pixel color)`n
Gui, Add, Edit, r4 yp+70 x200 w325 ReadOnly vWinStats, x y h w (Coordinate mode)
Gui, Add, Edit, r8 yp+70 x200 w325 ReadOnly vWinText, Text on the locked screen:
Gui, Add, Button,xp y317 gAISave, Save
Gui, Add, Button,xp+50 yp gAIClear, Clear
Gui, Add, Edit,  r1 ym+15 x200 vWindowControl w325,
Gui, Add, Text, ym+315 x470 vInformation, Loading...
Gui, Add, Text, ym+17 x550 vWindowLabel gLock +Border Center h18, %A_Space% +`t Add Window%A_Space%
Gui, Add, Edit, r19 ym+45 x550 w150 vWelcome -VScroll ReadOnly, Welcome to my program. Above you will see a Label named Add Window. This is a control bar Click it to see other controls. Left and right navigation buttons are beside it to add further Controls. To the left of the screen you will notice your "Working directory" is added in case you need to know it. below is the default editor. In the center is collected information from "Get Variables", "Functions"... It can also be a scratch pad.`n I hope you enjoy using my program. Have a Good day!
Gui, Add, Text, ym+17 x659 w20 vRightnav gRightNav +Border Center h18,
Gui, Add, Text, ym+17 x679 w20 vLeftNave gLeftNav +Border Center h18, >
Gui, Add, GroupBox, ym+50 x550 h250 w150 wrap vGroupControls, Window Controls
Gui, Add, Checkbox, yp+40 xp+10 vGetWindow gLocktoWindow, Lock Window Control
Gui, Add, Checkbox, yp+20 xp vSnapWindow gSnapToWindow, Snap to Window
Gui, Add, Checkbox, yp+20 xp vSnapToEditor gSnapToEditor, Snap to Editor
Gui, Add, Checkbox, yp+20 xp vAutoEdit gAutoEdit, Enable Auto Edit
Gui, Add, Checkbox, yp+20 xp vEnableCC gEnableCC, Enable copy anywhere
Gui, Add, Checkbox, yp+20 xp vEnableVV gEnableVV, Enable paste 2nd Clip
Gui, Add, Edit, yp+20 xp r5 w130 -VScroll ReadOnly vControlInformation, Information about the above controls
Gui, Add, Edit, yp+105 xp-10 r1 w150 -VScroll ReadOnly vDefaultEdit, % Editor
Gui, Add, DropDownList, yp-240 xp+10 w130 vCoordinateM gCoordinateM, CoordMode Screen||CoordMode Relative|CoordMode Window|CoordMode Client
Gui, Add, Checkbox, yp+30 xp vGetPix gGetPix, Get Pixel Color
Gui, Add, Checkbox, yp+20 xp vGetMouse gGetMouse, Get Mouse Pos
Gui, Add, Checkbox, yp+20 xp vGetWinS gGetWinS, Get Window Stats
Gui, Add, Checkbox, yp+20 xp vGetWinT gGetWinT, Get Window Text
Gui, Add, Checkbox, yp+20 xp vMultiSele gMultiSele, Multi-Select
Gui, Add, ListBox, yp-110 xp w130 r5 vProfList,
Gui, Add, Button, yp+75 xp w44 vProfAdd gProfAdd, Add
Gui, Add, Button, yp xp+44 hp wp vProfDele gProfDele, Delete
Gui, Add, Button, yp xp+44 hp wp vProfMod gProfMod, Modify
Gui, Add, Button, yp+23 xp-88 hp wp vProfBack gProfBack, Backup
Gui, Add, Button, yp xp+44 hp wp vProfStart gProfStart, Start
Gui, Add, Button, yp xp+44 hp wp vProfRun gProfRun, Run
Gui, Margin, 50, 30
Gui, Color, d6d5d0, f5f4f0
Gui, Show, h400, AI work
WinGetPos , AIPosX, AIPosY, AIorignalwidth, AIorignalhieght, AI
AddWindowGroupControl("Hide")
GetWindowGroupControl("Hide")
WindowProfGroupControl("Hide")
GuiControl, AI:Hide, PixMouse
GuiControl, AI:Hide, WinStats
GuiControl, AI:Hide, WinText
GuiControl, AI:Hide, GroupBox2
GuiControl, AI:Hide, FunctionName
GuiControl, AI:Hide, FunctionLabel
GuiControl, AI:Hide, ControlInformation
Control, Disable, , Edit10, AI
GuiControl, AI:Hide, AssociateV
GuiControl, AI:Hide, TestInfo
Control, Disable , , Edit2, AI
Control, Disable , , Welcome, AI
GuiControl, Focus, Words
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, Add, Text, vClipBoard2 w0 h0 x5 y5,
Gui, Add, Text, vClipBoard3 w0 h0 x5 y5,
Gui, margin, 0, 0
Gui, Show, , Words
GuiControl, Words:Hide, ClipBoard2
GuiControl, Words:Hide, ClipBoard3

contents:=HashContents(contents)
logicalhistory:= []
logicalhistory:= ProcessStart(contents, Rest)
activeuserinput:= []
navigationLR:= []
WinProfiles:=WinProf()
GuiControl, AI:, ProfList, % WinProfiles

Loop,
{
	ThisModifier(WinVictive)
	ClipBoardFunction()
	thistrack:= Tracker(thistrack, DefaultLoc, Whichone, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	if (A_TimeIdle > 3000)
	{
		thisz++
		if (thisz == 1)
			GuiControl, AI:, Information, Done
		Sleep, % Notactive
		Continue
	}
	winwonder:=WinWonder()
	if (winwonder == "False")
	{
		SpellChecker(0)
		Sleep, % Notactive
		Continue
	}
	check:=GetControl("GetKeeper")
	usersentence:=GetControl("RowText")
	if (recordkeeper == "")
		recordkeeper:=% usersentence
	if (recordkeeper != usersentence)
	{
		Doppler(usersentence, recordkeeper)
		recordkeeper:=% usersentence
	}
	getuserinput:= GetControl("Text")
	activeuserinput:=ReturnLineArray(getuserinput, "user")
	historylastline:= GetLineCount(logicalhistory)
	activeuserlastline:= GetLineCount(activeuserinput)
	if (check == "7h151s@a#res37")
	{
		If (getuserinput == "")
		{
			Sleep, % Notactive
			Continue
		}
		GuiControl, AI:, WordKeeper, &not@a#rea1*sent3nc3
		contents:=HashContents(contents)
		logicalhistory:= ProcessStart(contents, Rest)
		Continue
	}
	if (usersentence != "")
	{
		if (activeuserlastline != historylastline)
		{
			logicallastlineaddition:=(activeuserlastline-historylastline)
			logicalhistory:= FixLogicalhistory_Array(logicalhistory, logicallastlineaddition) ; where last lines are being put in. and you will also want to function in lastline (Deleted_Line) to acompany the changes. if you are lagging ApplyLogicalChange().
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, logicallastlineaddition)
		}
		if (activeuserlastline == historylastline)
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, 0)
	}
	savecheck:= GetControl("AISave")
	if (savecheck == "Save_File")
	{
		historycount:=GetLineCount(logicalhistory)
		Loop, % historycount
		{
			x++
			sentences:= logicalhistory["linePos" x]
			StringReplace, sentences, sentences, (softReturn), \|/softReturn\|/, ALL
			StringReplace, sentences, sentences, (hardReturn), \|/CR+LF\|/, ALL
			FileContents:=% FileContents sentences
		}
		FileMove, % Temp, % TempBack, 1
		FileAppend, % FileContents, % Temp, UTF-8
		GuiControl,AI:, AISave, Don't Save
	}
}
Return

ThisModifier(WinDrop)
{
	GuiControlGet, Locked, AI:, GetWindow
	GuiControlGet, WinName, AI:, WindowControl
	GuiControlGet, PixButton, AI:, GetPix
	GuiControlGet, StatButton, AI:, GetWinS
	GuiControlGet, TextButton, AI:, GetWinT
	WinGetPos , WinX, WinY, WinWidth, WinHeight, AI
	PositionSquareX:=(WinX+WinWidth)
	PositionSquareY:=(WinY+WinHeight)
	MouseGetPos, positionX, positionY
	if ((Locked == 1)&&(WinName != ""))
	{
		if ((PixButton == 1)||(StatButton == 1)||(TextButton == 1))
		{
			If ((positionX < WinX)||(positionX > PositionSquareX)||(positionY < WinY)||(positionY > PositionSquareY))
			{
				if ((WinDrop != "")&&(WinDrop == 0))
					Hotkey, LButton, On
				else
				{
					IfWinActive, % WinName
						Hotkey, LButton, On
					else
						Hotkey, LButton, Off
				}
			}
			else
				Hotkey, LButton, Off
		}
		else
			Hotkey, LButton, Off
	}
	else
		Hotkey, LButton, Off
	Return
}

LButton::
GuiControlGet, ThisMode , AI:, CoordinateM
GuiControlGet, WinName, AI:, WindowControl
IfWinNotActive, % WinName
	If (WinVictive == 0)
		WinActivate, % WinName
if (ThisMode == "CoordMode Screen")
{
	CoordMode, Screen , Pixel
	CoordMode, Screen , Mouse
}
if (ThisMode == "CoordMode Relative")
{
	CoordMode, Relative , Pixel
	CoordMode, Relative , Mouse
}
if (ThisMode == "CoordMode Window")
{
	CoordMode, Window , Pixel
	CoordMode, Window , Mouse
}
if (ThisMode == "CoordMode Client")
{
	CoordMode, Client , Pixel
	CoordMode, Client , Mouse
}
MouseGetPos, positionX, positionY
GuiControlGet, PixButton, AI:, GetPix
if (PixButton == 1)
{
	PixelGetColor, color,%positionX%, %positionY%
	color:=% color "`n"
}
else
	color:=% "No color`n"
if (MouseButton == 1)
	MousePos:=% positionX ", " positionY "`t"
else
	MousePos:=% "No Mouse`t"
GuiControlGet, StatButton, AI:, GetWinS
GuiControlGet, TextButton, AI:, GetWinT
GuiControlGet, Multi, AI:, MultiSele
GuiControlGet, MouseButton, AI:, GetMouse
GuiControlGet, PixMouse, AI:, PixMouse
PixMouse:= StrReplace(PixMouse, "(Mouse Position)`t(pixel color)`n", "")
if (Multi == 1)
	if ((PixButton == 1)||(MouseButton == 1))
		GuiControl, AI:, PixMouse, %  "(Mouse Position)`t(pixel color)`n" MousePos color PixMouse
if (Multi != 1)
	if ((PixButton == 1)||(MouseButton == 1))
		GuiControl, AI:, PixMouse, %  "(Mouse Position)`t(pixel color)`n" MousePos color
GuiControlGet, WinStats, AI:, WinStats
WinGetPos , WinX, WinY, WinWidth, WinHeight, % WinName
WinStats:= StrReplace(WinStats, "x y h w (Coordinate mode)", "")
if ((Multi == 1)&&(StatButton == 1))
	GuiControl, AI:, WinStats, % "x" WinX ", y" WinY ", h" WinWidth ", w" WinHeight "`t(" ThisMode ")`n" WinStats
if ((Multi != 1)&&(StatButton == 1))
	GuiControl, AI:, WinStats, % "x" WinX ", y" WinY ", h" WinWidth ", w" WinHeight "`t(" ThisMode ")"
GuiControlGet, AIWinText, AI:, WinText
TextLength:= StrLen(AIWinText)
WinGetText, WinText , % WinName
if ((TextLength == 26)&&(WinText != "")&&(TextButton == 1))
	GuiControl, AI:, WinText, % WinText
CoordMode, Screen, Pixel
CoordMode, Screen, Mouse
Return

~LCtrl::
thiskeystate:= GetKeyState("LCtrl", P)
if (thiskeystate != 0)
{
	Loop,
	{
		GuiControlGet, EnableCC, AI:, EnableCC
		GuiControlGet, EnableVV, AI:, EnableVV
		CtrlC := Chr(3)
		if (EnableVV == 1)
		{
			CtrlVV:= (Chr(22) . Chr(22))
			CtrlVVV:= (Chr(22) . Chr(22) . Chr(22))
			ClipBoardFunction()
			GuiControlGet, ClipBoard2, Word:, ClipBoard2
			GuiControlGet, ClipBoard3, Word:, ClipBoard3
		}
		Input, userinput, L3 T0.75 M ; this has a 0.75 second timer... That feels a little natural. however on the person to person scale this might need adjusted.
		if (EnableVV == 1)
		{
			if (userinput == CtrlVV)
			{
				saveClip:=% ClipBoard
				ClipBoard:=% Clipboard2
				Send, ^v
				ClipBoard:=% saveClip
				saveClip:=
			}
			else if (userinput == CtrlVVV)
			{
				saveClip:=% ClipBoard
				ClipBoard:=% Clipboard3
				Send, ^v
				ClipBoard:=% saveClip
				saveClip:=
			}
		}
		else if ((userinput == CtrlC CtrlC)&&(EnableCC == 1))
		{
			logicalhistorylastline:= GetLineCount(logicalhistory)
			Loop, % logicalhistorylastline
			{
				thisx++
				saveline:= logicalhistory["linePos" thisx]
				saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
				saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
				thesecontents.= saveline
			}
			thesecontents:= SpecialReplace(thesecontents)
			MsgBox, % "The edit fields are ready to be sent. It autosends after this message. After you learn how this works you can delete this messge box. Make sure the place you want your text sent is +lastfound"
			Send, % thesecontents
			thisx:=
			thesecontents:=
		}
		else if (userinput == CtrlC)
			Send, ^c
		else
			Send, ^%userinput%
		thiskeystate:= GetKeyState("LCtrl", P)
		if (thiskeystate == 0)
			Break
	}
}
Return

ClipBoardFunction()
{
	if ((ClipBoard != "")&&(ClipBoard != ClipBoard2))
	{
		if (ClipBoard2 == "" )
			ClipBoard2:=% ClipBoard1
		else if (ClipBoard2 != "")
		{
			ClipBoard3:=% ClipBoard2
			ClipBoard2:=% ClipBoard
		}
	}
	if (ClipBoard2 != "" )
		GuiControl,Word:, ClipBoard2, % ClipBoard2
	if (ClipBoard3 != "" )
		GuiControl,Word:, ClipBoard3, % ClipBoard3
	Return
}

$Backspace::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Backspace}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Backspace}
	}
	Return
}
else
	Send, {Backspace}
Return

$Space::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Space}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Space}
	}
	Return
}
else
	Send, {Space}
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		check:=GetControl("GetKeeper")
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 2)
				userword:=% chec
		}
		str:= StrLen(userword)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
	}
	else
	{
		Send, `t
	}
	Return
}
else
	Send, `t
Return

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	GuiControlGet, AutoEdit, AI:, AutoEdit
	If (AutoEdit == 1)
	{
		logicalhistorylastline:= GetLineCount(logicalhistory)
		Loop, % logicalhistorylastline
		{
			thisx++
			saveline:= logicalhistory["linePos" thisx]
			saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
			saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
			thesecontents.= saveline
		}
		thesecontents:= SpecialReplace(thesecontents)
		GuiControlGet, wintitle, AI:, WindowControl, WindowControl
		if (wintitle == "")
		{
			MsgBox, Please lock to a window first
			Return
		}
		WinActivate, % wintitle
		WinWait, % wintitle
		Send, % thesecontents
		FileMove, % Temp, % TempBack, 1
		FileAppend, , % Temp, UTF-8
		GuiControl, AI:, Words,
		logicalhistory:=[]
		thisx:=
		thesecontents:=
	}
	else if (AutoEdit == 0)
	{
		ButtonCountCheck:= GetControl("ButtCount")
		PressCount:=GetButtonCount(ButtonCountCheck)
		PressCount++
		WhichButtonCount:=% PressCount ",ShiftEnter"
		GuiControl, AI:, ButtonCountCheck, % WhichButtonCount
		KeyWait, Backspace, U
		GetButton_Count()
	}
}
Return

~Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	GuiControlGet, AutoEdit, AI:, AutoEdit
	If (AutoEdit == 1)
	{
		logicalhistorylastline:= GetLineCount(logicalhistory)
		Loop, % logicalhistorylastline
		{
			thisx++
			saveline:= logicalhistory["linePos" thisx]
			saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
			saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
			thesecontents.= saveline
		}
		thesecontents:= SpecialReplace(thesecontents)
		GuiControlGet, wintitle, AI:, WindowControl, WindowControl
		if (wintitle == "")
		{
			MsgBox, Please lock to a window first
			Return
		}
		WinActivate, % wintitle
		WinWait, % wintitle
		Send, % thesecontents "+{Enter}"
		FileMove, % Temp, % TempBack, 1
		FileAppend, , % Temp, UTF-8
		GuiControl, AI:, Words,
		logicalhistory:=[]
		thisx:=
		thesecontents:=
	}
	else if (AutoEdit == 0) ;
	{
		ButtonCountCheck:= GetControl("ButtCount")
		PressCount:=GetButtonCount(ButtonCountCheck)
		PressCount++
		WhichButtonCount:=% PressCount ",Enter"
		GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
		KeyWait, Backspace, U
		GetButton_Count()
	}
}
Return

SpecialReplace(thesecontents)
{
	fixedcharacters:= StrReplace(thesecontents, "!", "{!}")
	fixedcharacters:= StrReplace(fixedcharacters, "#", "{#}")
	fixedcharacters:= StrReplace(fixedcharacters, "+", "{+}")
	fixedcharacters:= StrReplace(fixedcharacters, "^", "{^}")
	fixedcharacters:= StrReplace(fixedcharacters, "{", "{{}") ; if this is done then output will be {{}
	fixedcharacters:= StrReplace(fixedcharacters, "}", "{}}") ; from the above if this is done output will be {{{}}
	fixedcharacters:= StrReplace(fixedcharacters, "{{{}}", "{{}")
	Sleep, 50
	Tabcontrol:= StrSplit(fixedcharacters, ["(hardReturn)", "(softReturn)"])
	for index, Tabs in Tabcontrol
	{
		IfinString, Tabs, % "`t" ; <----- it is assumed the editor you're using controls tab.
		{
			thiscount:= StrReplace(Tabs, "`t", "", thismany)
			thisstring:=% thiscount
			if (thismany != thatmany)
			{
				if (thismany > thatmany)
				{
					n:=(thismany-thatmany)
					thisbutton:=% "{Tab " n "}"
				}
				if (thismany < thatmany)
				{
					n:=(thatmany-thismany)
					thisbutton:=% "{Backspace " n "}"
				}
			}
		}
		IfNotInString, Tabs, % "`t"
		{
			if (thismany > 1)
				thisbutton:=% "{Backspace " n "}"
			else if (thismany == 1)
			{
				thismany:=0
				thisbutton:=% "{Backspace}"
			}
			else if (thismany == 0)
				thisbutton:=% ""
			thisstring:=% Tabs
		}
		thatmany:=% thismany
		edittext.= thisbutton thisstring
		thisbutton:= ""
	}
	edittext:= StrReplace(edittext, "[Enter]", "{Backspace}{Enter}")
	edittext:= StrReplace(edittext, "[ShiftEnter]", "{Backspace}+{Enter}")
	Return % edittext
}

ProfList:
Gui, Submit, NoHide
FileRead, contents, % Cache "\Profiles.Storage"
if (ErrorLevel == 0)
{
	;Loop, Parse, % contents, `n
}
Return

ProfAdd:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This adds the current locked window and all the settings, text, and get tools information and saves it.
if (WindowControl != "")
{
	FormatTime, time, , YWeek
	NTime.= time
	FormatTime, time, , ddhhmmss
	NTime.= time
	historycount:=GetLineCount(logicalhistory)
	Loop, % historycount
	{
		x++
		sentences:= logicalhistory["linePos" x]
		sentences:= StrReplace(sentences, "(softReturn)(softReturn)", "(softReturn)")
		sentences:= StrReplace(sentences, "(hardReturn)(hardReturn)", "(hardReturn)")
		sentences:= StrReplace(sentences, "(softReturn)", "\|/softReturn\|/")
		sentences:= StrReplace(sentences, "(hardReturn)", "\|/CR+LF\|/")
		FileContents:=% FileContents sentences
	}
	Spliter:=% "&not@a#rea1*??sent3nc3"
	EndSplit:=% "[End-Splitter-Loop]"
	SaveData:=% WindowControl Spliter NTime Spliter GetWindow Spliter SnapWindow Spliter SnapToEditor Spliter AutoEdit Spliter EnableCC Spliter EnableVV Spliter PixMouse Spliter WinStats Spliter WinText Spliter FileContents Spliter CoordinateM Spliter GetPix Spliter GetMouse Spliter GetWinS Spliter GetWinT Spliter MultiSele Spliter RunProgramName EndSplit
	GuiControl, AI:, ProfList, % WindowControl "`t" NTime "|"
	SaveData:= StrReplace(SaveData, "`n", "\|/MyReturns\|/")
	FileAppend, % SaveData, % Cache "\Profiles.Storage", UTF-8
}
else
	MsgBox, 262144, Please lock to a window., Please first lock to a window.
Return

ProfDele:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This deletes a selected profile entry.
if (ProfList != "")
{
	profdate:= StrSplit(ProfList, "`t")
	for index, prof in profdate
	{
		if (Index == 1)
			thisprof:=% prof
		if (Index == 3)
			thisdate:=% prof
	}
	FileRead, contents, % Cache "\Profiles.Storage"
	if (ErrorLevel == 0)
	{
		Profiles:= StrSplit(contents, "[End-Splitter-Loop]")
		for index, profile in profiles
		{
			profilestrings:= StrSplit(profile, "&not@a#rea1*??sent3nc3")
			for index, profilepart in profilestrings
			{
				if (thisprof == profilepart)
				{
					thisprofile:= ""
					Break
				}
				thisprofile:=% profile
			}
			if (thisprofile != "")
			{
				IfNotInString, updatedlist, % profcheck "`t" datecheck "|"
					updatedlist.= profcheck "`t" datecheck "|"
				Currentlist.= profile "[End=Splitter-Loop]"
			}
		}
		if (updatedlist == "")
			updatedlist.= "|"
		GuiControl, AI:, ProfList, % updatedlist
		FileMove, % Cache "\Profiles.Storage", % TempBack, 1
		FileAppend, % Currentlist, % Cache "\Profiles.Storage", UTF-8
	}
}
else
	MsgBox, 262144, Please select, Please select a profile to delete.
updatedlist.= 
Currentlist.= 
Return

ProfMod:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This allows a user to modify a selected profile entry.
if (ProfList != "")
{
	profdate:= StrSplit(ProfList, "`t")
	for index, prof in profdate
	{
		if (Index == 1)
			thisprof:=% prof
		if (Index == 3)
			thisdate:=% prof
	}
	FileRead, contents, % Cache "\Profiles.Storage"
	if (ErrorLevel == 0)
	{
		Profiles:= StrSplit(contents, "[End-Splitter-Loop]")
		for index, profile in Profiles
		{
			profilestrings:= StrSplit(profile, "&not@a#rea1*??sent3nc3")
			for index, profilepart in profilestrings
			{
				if (profilepart == thisprof)
					profcheck:=% profilepart
				if (profcheck != "")
					if (thisdate == profilepart)
					{
						thismod:=% profile
						Break
					}
			}
			profcheck:= ""
		}
	}
}
else
{
	MsgBox, 262144, Please select, Please select a profile to modify.
	Return
}
Gui, Modify:New, +AlwaysOnTop +Resize +toolWindow
ModArray:=[]
thesemods:= StrSplit(thismod, "&not@a#rea1*??sent3nc3")
for index, mods in thesemods
	ModArray[Index]:= mods
windowmod:= ModArray[1]
Gui, Add, Edit, xm+20 vModWindow w300 r1, % windowmod
timemod:= ModArray[2]
Gui, Add, Edit, vModTime w100, % timemod
windowbutton:= ModArray[3]
Gui, Add, Checkbox, ym+30 xm+170 vModlock checked%windowbutton%, Locked to window
SnapWindowMod:= ModArray[4]
Gui, Add, Checkbox, vModWindowSnap checked%SnapWindowMod%,  Snap to window
SnapToEditorMod:= ModArray[5]
Gui, Add, Checkbox, vModSnapToEditor checked%SnapToEditorMod%, Snap to editor
AutoEditMod:= ModArray[6]
Gui, Add, Checkbox, vModAutoEdit checked%AutoEditMod%, Auto Edit
EnableCCMod:= ModArray[7]
Gui, Add, Checkbox, vModEnableCC checked%EnableCCMod%, Enable copy anywhere
EnableVVMod:= ModArray[8]
Gui, Add, Checkbox, vModEnableVV checked%EnableVVMod%, Enable paste 2nd Clip
PixMouseMod:= ModArray[9]
Gui, Add, Edit, ym+55 xm+20 vModPixMouse ReadOnly w112 r1, % PixMouseMod
WinStatsMod:= ModArray[10]
Gui, Add, Edit, vModWinStats ReadOnly wp r1, % WinStatsMod
WinTextMod:= ModArray[11]
Gui, Add, Edit, vModWinText ReadOnly wp r1, % WinTextMod
FileContentsMod:= ModArray[12]
Gui, Add, Edit, vModFileContents ReadOnly wp r1, % FileContentsMod
CoordinateMMod:= ModArray[13]
coordslistm:=% "CoordMode Screen`nCoordMode Relative`nCoordMode Window`nCoordMode Client"
Loop, Parse, % coordslistm, `n
{
	if (A_LoopField == CoordinateMMod)
		coordslist.= A_LoopField "||"
	else
		coordslist.= A_LoopField "|"
}
Gui, Add, DropDownList, vModCoordinateM, % coordslist
coordslist:=
GetPixMod:= ModArray[14]
Gui, Add, Checkbox, vModGetPix checked%GetPixMod%, Get Pixel Color
GetMouseMod:= ModArray[15]
Gui, Add, Checkbox, vModGetMouse checked%GetMouseMod%, Get Mouse Pos
GetWinSMod:= ModArray[16]
Gui, Add, Checkbox, vModGetWinS checked%GetWinSMod%, Get Window Stats
GetWinTMod:= ModArray[17]
Gui, Add, Checkbox, vModGetWinT checked%GetWinTMod%, Get Window Text
MultiSeleMod:= ModArray[18]
Gui, Add, Checkbox, vModMultiSele checked%MultiSeleMod%, Multi-Select
RunProgramNameMod:= ModArray[19]
Gui, Add, Edit, vModRunProgramName w145 r1,
Gui, Add, Button, vPixMouseClear ym+55 xm+129 hp, Clear
Gui, Add, Button, vWinStatsClear hp, Clear
Gui, Add, Button, vTextModClear hp, Clear
Gui, Add, Button, vFileContentsClear hp, Clear
Gui, Add, Edit, vModInformation -VScroll ReadOnly r9 ym+150 xm+170 w145, This is a quick snapshot of this profile saved. Review the data clear text, change check box selections, add run program installer, even edit the profile's win title. After modifications are made click update at the bottom to save the changes.
Gui, Add, Edit, vProgramLoad -VScroll ReadOnly r1 ym+285 xm+170 w100, run program *.EXE
Gui, Add, Button, gUpdater xm+270 yp hp, Update
Gui, Color, d6d5d0, f5f4f0
Gui, Margin, 20, 20
Gui, Show, , Modifications
Control, Disable, , Edit9, Modifications
Control, Disable, , Edit8, Modifications
ModArray:=[]
thismod:= ""
contents:= ""
Return

Updater:
Gui, Submit, NoHide
if (ProfList != "")
{
	Spliter:=% "&not@a#rea1*??sent3nc3"
	EndSplit:=% "[End-Splitter-Loop]"
	SaveData:=% ModWindow Spliter ModTime Spliter Modlock Spliter ModWindowSnap Spliter ModSnapToEditor Spliter ModAutoEdit Spliter ModEnableCC Spliter ModEnableVV Spliter ModPixMouse Spliter ModWinStats Spliter ModWinText Spliter ModFileContents Spliter ModCoordinateM Spliter ModGetPix Spliter ModGetMouse Spliter ModGetWinS Spliter ModGetWinT Spliter ModMultiSele Spliter ModRunProgramName EndSplit
	profdate:= StrSplit(ProfList, "`t")
	for index, prof in profdate
	{
		if (Index == 1)
			thisprof:=% prof
		if (Index == 3)
			thisdate:=% prof
	}
	FileRead, contents, % Cache "\Profiles.Storage"
	if (ErrorLevel == 0)
	{
		Profiles:= StrSplit(contents, "[End-Splitter-Loop]")
		for index, profile in profiles
		{
			profilestrings:= StrSplit(profile, "&not@a#rea1*??sent3nc3")
			for index, profilepart in profilestrings
			{
				if (profilepart == thisprof)
					profcheck:=% profilepart
				if (profcheck != "")
					if (thisdate == profilepart)
					{
						thismod:=% SaveData
						profcheck:= ""
						Break
					}
			}
			if (profcheck != "")
			{
				IfNotInString, updatedlist, % profcheck "`t" datecheck "|"
					updatedlist.= profcheck "`t" datecheck "|"
				Currentlist.= profile "[End=Splitter-Loop]"
			}
			if (thismod != "")
			{
				IfNotInString, updatedlist, % ModWindow "`t" ModTime "|"
					updatedlist.= ModWindow "`t" ModTime "|"
				Currentlist.= thismod
			}
			thismod:= ""
			profcheck:= ""
		}
		if (updatedlist == "")
			updatedlist.= "|"
		GuiControl, AI:, ProfList, % "|" updatedlist
		FileMove, % Cache "\Profiles.Storage", % TempBack, 1
		FileAppend, % Currentlist, % Cache "\Profiles.Storage", UTF-8
	}
	Currentlist.= 
	updatedlist:=
	Gui, Modify:Destroy
}
Return

ModifyGuiClose:
Gui, Modify:Destroy
Return

ProfBack:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This backs up the profile entries to a readable txt file in the %A_ScriptDir%. Also Note it does not overwrite it.
Spliter:=% "&not@a#rea1*??sent3nc3"
EndSplit:=% "[End-Splitter-Loop]"
FileRead, contents, % Cache "\Profiles.Storage"
if (ErrorLevel == 0)
{
	Profiles:= StrSplit(contents, "[End-Splitter-Loop]")
	for index, profile in profiles
	{
		profilestrings:= StrSplit(profile, "&not@a#rea1*??sent3nc3")
		for index, profilepart in profilestrings
		{
			profiles.= profilepart "`n"
		}
		profiles.= "`n"
	}
	FileAppend, % profiles, % A_ScriptDir "\Backup.txt", UTF-8
}
Return

ProfStart:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This sets the Gui to the settings of the profile selected.
if (ProfList != "")
{
	profdate:= StrSplit(ProfList, "`t")
	for index, prof in profdate
	{
		if (Index == 1)
			thisprof:=% prof
		if (Index == 3)
			thisdate:=% prof
	}
	FileRead, contents, % Cache "\Profiles.Storage"
	if (ErrorLevel == 0)
	{
		Profiles:= StrSplit(contents, "[End-Splitter-Loop]")
		for index, profile in Profiles
		{
			profilestrings:= StrSplit(profile, "&not@a#rea1*??sent3nc3")
			for index, profilepart in profilestrings
			{
				if (profilepart == thisprof)
					profcheck:=% profilepart
				if (profcheck != "")
					if (thisdate == profilepart)
					{
						thismod:=% profile
						Break
					}
			}
			profcheck:= ""
		}
	}
}
else
{
	MsgBox, 262144, Please select, Please select a profile to Start.
	Return
}
ModArray:=[]
thesemods:= StrSplit(thismod, "&not@a#rea1*??sent3nc3")
for index, mods in thesemods
	ModArray[Index]:= mods
windowmod:= ModArray[1]
GuiControl, AI:, WindowControl, % windowmod
windowbutton:= ModArray[3]
GuiControl, AI:, GetWindow, % windowbutton
SnapWindowButton:= ModArray[4]
GuiControl, AI:, SnapWindow, % SnapWindowButton
SnapEditorButton:= ModArray[5]
GuiControl, AI:, SnapToEditor, % SnapEditorButton
AutoEditButton:= ModArray[6]
GuiControl, AI:, AutoEdit, % AutoEditButton
EnableCCButton:= ModArray[7]
GuiControl, AI:, EnableCC, % EnableCCButton
EnableVVButton:= ModArray[8]
GuiControl, AI:, EnableVV, % EnableVVButton
PixMouseEdit:= ModArray[9]
PixMouseEdit:= StrReplace(PixMouseEdit, "\|/MyReturns\|/", "`n")
GuiControl, AI:, PixMouse, % PixMouseEdit
WinStatsEdit:= ModArray[10]
WinStatsEdit:= StrReplace(WinStatsEdit, "\|/MyReturns\|/", "`n")
GuiControl, AI:, WinStats, % WinStatsEdit
WinTextEdit:= ModArray[11]
WinTextEdit:= StrReplace(WinTextEdit, "\|/MyReturns\|/", "`n")
GuiControl, AI:, WinText, % WinTextEdit
FileContentsMod:= ModArray[12]
logicalhistory:= []
fix:=
StringReplace, FileContentsMod, FileContentsMod, \|/CR+LF\|/,(hardReturn)\|/CR+LF\|/, ALL
StringReplace, FileContentsMod, FileContentsMod, \|/SoftReturn\|/, (softReturn)\|/SoftReturn\|/, ALL
logicalfix:= StrSplit(FileContentsMod, ["\|/CR+LF\|/","\|/softReturn\|/"])
for index, logical in logicalfix
	logicalhistory["linePos" Index]:= logical
FileContentsMod:= StrReplace(FileContentsMod, "(hardReturn)\|/CR+LF\|/", "`n")
FileContentsMod:= StrReplace(FileContentsMod, "(softReturn)\|/SoftReturn\|/", "`n")
MsgBox, % FileContentsMod
GuiControl, AI:, Words, % FileContentsMod
CoordinateMMod:= ModArray[13]
coordslistm:=% "CoordMode Screen`nCoordMode Relative`nCoordMode Window`nCoordMode Client"
Loop, Parse, % coordslistm, `n
{
	if (A_LoopField == CoordinateMMod)
		coordslist.= A_LoopField "||"
	else
		coordslist.= A_LoopField "|"
}
GuiControl, AI:, CoordinateM, % "|" coordslist
coordslist:=
GetPixButton:= ModArray[14]
GuiControl, AI:, GetPix, % GetPixButton
GetMouseButton:= ModArray[15]
GuiControl, AI:, GetMouse, % GetMouseButton
GetWinSButton:= ModArray[16]
GuiControl, AI:, GetWinS, % GetWinSButton
GetWinTButton:= ModArray[17]
GuiControl, AI:, GetWinT, % GetWinTButton
MultiSeleButton:= ModArray[18]
GuiControl, AI:, MultiSele, % MultiSeleButton
Return

ProfRun:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This runs the associated program to the named entry (Modify may need to be used to make this work).
if (ProfList != "")
{
	profdate:= StrSplit(ProfList, "`t")
	for index, prof in profdate
	{
		if (Index == 1)
			thisprof:=% prof
		if (Index == 3)
			thisdate:=% prof
	}
	FileRead, contents, % Cache "\Profiles.Storage"
	if (ErrorLevel == 0)
	{
		Profiles:= StrSplit(contents, "[End-Splitter-Loop]")
		for index, profile in Profiles
		{
			profilestrings:= StrSplit(profile, "&not@a#rea1*??sent3nc3")
			for index, profilepart in profilestrings
			{
				if (profilepart == thisprof)
					profcheck:=% profilepart
				if (profcheck != "")
					if (thisdate == profilepart)
					{
						thismod:=% profile
						Break
					}
			}
			profcheck:= ""
		}
	}
}
else
{
	MsgBox, 262144, Please select, Please select a profile to Run.
	Return
}
ModArray:=[]
thesemods:= StrSplit(thismod, "&not@a#rea1*??sent3nc3")
for index, mods in thesemods
	ModArray[Index]:= mods
runinstaller:= ModArray[19]
if (runinstaller == "")
{
	MsgBox, 262144, Error Modify, There currently is no way to run the program.
	Return
}
Run, % runinstaller
Return

EnableVV:
GuiControl, AI:, ControlInformation, This enables paste from second and third ClipBoard. {LCtrl}+vv and {LCtrl}+vvv. if clipboard2 or 3 sends acsii code
Return

SnapToWindow:
GuiControl, AI:, ControlInformation, This will place the Main Gui in one of 9 locations on the locked window.
GuiControl, AI:, SnapToEditor, 0
IniRead, DefaultLoc, % Settings, WinManager, Key1
GuiControlGet, fullwindow, AI:, WindowControl
if (fullwindow == "")
{
	MsgBox, 262144, Please lock to a window., Please first lock to a window.
	GuiControl, AI:, SnapToEditor, 0
	Return
}
GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
Return
	

SnapToEditor:
GuiControl, AI:, ControlInformation, This will place the Main Gui in one of 9 locations on the editor. Notepad is Default.
GuiControlGet, DefaultEdit, AI:, DefaultEdit
GuiControl, AI:, SnapWindow, 0
IfInString, DefaultEdit, .
{
	windows:= StrSplit(DefaultEdit, ".")
	for index, window in windows
		if (index == 1)
			thiswindow:=% window
}
WinGetTitle, fullwindow, % "ahk_class" thiswindow
if (fullwindow == "")
{
	MsgBox, 4, Window Not Found!, % "The current Editor is not open:`nahk_class " thiswindow "`nWould you like to open it?"
	IfMsgBox Yes
		run, % DefaultEdit
	IfMsgBox No
		Return
	Loop,
	{
		Sleep, 150 ; prevent needless process
		WinGetTitle, fullwindow, % "ahk_class" thiswindow
		if (fullwindow != "")
			Break
		x++
		if (x > 15)
		{
			MsgBox, There is an error opening the window or a naming error.
			Return
		}
	}
}
IfWinExist, % fullwindow
{
	IniRead, DefaultLoc, % Settings, WinManager, Key1
	GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
}
Return

AutoEdit:
GuiControl, AI:, ControlInformation, On Enter ({Enter} or +{Enter} this button sends to your default editor if it's active and Clears the window.
Return

EnableCC:
GuiControl, AI:, ControlInformation, This activates {LCtrl}+cc when you press that (anywhere) main edit contents are autosent to insert location.
Return

LocktoWindow:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This button locks the Gui to a running window. Just activate the window you want.
if (GetWindow == 1)
{
	WinGetActiveTitle, checkthistitle
	GuiControl, AI:, WindowControl, Select a window to lock to.
	Loop,
	{
		WinGetActiveTitle, newtitletocheck
		if (newtitletocheck == "")
			Continue
		if (checkthistitle != newtitletocheck)
			Break
	}
	GuiControl, AI:, WindowControl, % newtitletocheck
	GuiControl, Disable, WindowControl
}
if (GetWindow == 0)
{
	GuiControl, AI:, WindowControl,
	GuiControl, Enable, WindowControl
}
Return

CoordinateM:
Gui, Submit, NoHide
if (CoordinateM == "CoordMode Screen")
	GuiControl, AI:, ControlInformation, Coordinates are relative to the Entire Screen.
if (CoordinateM == "CoordMode Relative")
	GuiControl, AI:, ControlInformation, Coordinates are relative to the Active Window
if (CoordinateM == "CoordMode Window")
	GuiControl, AI:, ControlInformation, Same as Relative and Recommended for clarity
if (CoordinateM == "CoordMode Client")
	GuiControl, AI:, ControlInformation, Coordinates are relative to the active client area minus title bar or menu. Look this up in autohokey for specifics.
Return

GetPix:
GuiControl, AI:, ControlInformation, This enables get pixel color to the locked screen on click. Make sure you are using the mode you prefer.
Return

GetMouse:
GuiControl, AI:, ControlInformation, This enables get Mouse Pos on click to the locked window. Make sure you are using the mode you prefer.
Return

GetWinS:
GuiControl, AI:, ControlInformation, This will provide the locked windows height width and left corner x and y positions.
Return

GetWinT:
GuiControl, AI:, ControlInformation, This will give the text to the locked window (hidden and seen). 
Return

MultiSele:
GuiControl, AI:, ControlInformation, In the event you need more than one color or mouse position enable this to record multiple clicks.
Return

RightNav:
Gui, Submit, NoHide
LeftNav:
Gui, Submit, NoHide
GuiControlGet, thislabelmenu, AI:, WindowLabel
IfInString, thislabelmenu, +
{
	IfInString, thislabelmenu, Add Window
		AddWindow:= 0
	IfInString, thislabelmenu, Get Tools
		GetTools:= 0
	IfinString, thislabelmenu, Window Profiles
		WindowProfs:= 0
}
IfInString, thislabelmenu, -
{
	IfInString, thislabelmenu, Add Window
		AddWindow:= 1
	IfInString, thislabelmenu, Get Tools
		GetTools:= 1
	IfinString, thislabelmenu, Window Profiles
		WindowProfs:= 1
}
If (A_ThisLabel == "RightNav")
{
	IfinString, thislabelmenu, Get Tools
	{
		labelname:= StrReplace(thislabelmenu, "`t      Get Tools", "`t Add Window")
		if ((AddWindow == "")||(AddWindow == 0))
		{
			labelname:= StrReplace(labelname, "-", "+")
			GetWindowGroupControl("Hide")
			AddWindowGroupControl("Hide")
			GuiControl, AI:, Welcome, Welcome to my program. Above you will see a Label named Add Window. This is a control bar Click it to see other controls. Left and right navigation buttons are beside it to add further Controls. To the left of the screen you will notice your "Working directory" is added in case you need to know it. below is the default editor. In the center is collected information from "Get Variables", "Functions"... It can also be a scratch pad.`n I hope you enjoy using my program. Have a Good day!
		}
		if (AddWindow == 1)
		{
			labelname:= StrReplace(labelname, "+", "-")
			GetWindowGroupControl("Hide")
			AddWindowGroupControl("Show")
		}
		GuiControl, AI:, LeftNave,  >
		GuiControl, AI:, RightNav,
		GuiControl, AI:Show, Words
		GuiControl, AI:, WindowLabel, % labelname
	}
	IfinString, thislabelmenu, Window Profiles
	{
		labelname:= StrReplace(thislabelmenu, "     Window Profiles", "`t      Get Tools")
		if ((GetTools == "")||(GetTools == 0))
		{
			labelname:= StrReplace(labelname, "-", "+")
			WindowProfGroupControl("Hide")
			GetWindowGroupControl("Hide")
			GuiControl, AI:, Welcome, This is where a variety of "Get" tools are located. First you have to have the window locked and acitve before the dropper tool will work. I plan to add that in the settings so it can automatically activate the window. Your mouse will be disabled until you either deactivate the window locked, unlock the window, deselect all tools (except multi-select). It will work in minimized mode too. At this point to clear you have to restart.
		}
		if (GetTools == 1)
		{
			labelname:= StrReplace(labelname, "+", "-")
			WindowProfGroupControl("Hide")
			GetWindowGroupControl("Show")
		}
		GuiControl, AI:, WindowLabel, % labelname
		GuiControl, AI:, RightNav, <
		GuiControl, AI:Hide, Words
	}
}
If (A_ThisLabel == "LeftNav")
{
	IfinString, thislabelmenu, Add Window
	{
		labelname:= StrReplace(thislabelmenu, "`t Add Window", "`t      Get Tools")
		if ((GetTools == "")||(GetTools == 0))
		{
			labelname:= StrReplace(labelname, "-", "+")
			AddWindowGroupControl("Hide")
			GetWindowGroupControl("Hide")
			GuiControl, AI:, Welcome, This is where a variety of "Get" tools are located. First you have to have the window locked and acitve before the dropper tool will work. I plan to add that in the settings so it can automatically activate the window. Your mouse will be disabled until you either deactivate the window locked, unlock the window, deselect all tools (except multi-select). It will work in minimized mode too. At this point to clear you have to restart.
		}
		if (GetTools == 1)
		{
			labelname:= StrReplace(labelname, "+", "-")
			AddWindowGroupControl("Hide")
			GetWindowGroupControl("Show")
		}
		GuiControl, AI:, WindowLabel, % labelname
		GuiControl, AI:, RightNav, <
		GuiControl, AI:Hide, Words
	}
	IfinString, thislabelmenu, Get Tools
	{
		labelname:= StrReplace(thislabelmenu, "`t      Get Tools", "     Window Profiles")
		if ((WindowProfs == "")||(WindowProfs == 0))
		{
			labelname:= StrReplace(labelname, "-", "+")
			GetWindowGroupControl("Hide")
			WindowProfGroupControl("Hide")
			GuiControl, AI:, Welcome, This is where window Profiles will be stored saved or deleted. It is assumed that a user may work on a window for more than one day and want a log of the data they aquired using this (or even a default setup for a particular window). This section will store that data and recall the settings, data, and editboxes.
		}
		if (WindowProfs == 1)
		{
			labelname:= StrReplace(labelname, "+", "-")
			GetWindowGroupControl("Hide")
			WindowProfGroupControl("Show")
		}
		GuiControl, AI:, WindowLabel, % labelname
		GuiControl, AI:Show, Words
	}
}
labelname:= ""
Return

Lock:
GuiControl, AI:, ControlInformation, Information about the above controls
GuiControlGet, thislabelmenu, AI:, WindowLabel
IfInString, thislabelmenu, Add Window
{
	IfInString, thislabelmenu, +
	{
		labelname:= StrReplace(thislabelmenu, "+", "-")
		GetWindowGroupControl("Hide")
		AddWindowGroupControl("Show")
		GuiControl, AI:, WindowLabel, % labelname
	}
	IfInString, thislabelmenu, -
	{
		labelname:= StrReplace(thislabelmenu, "-", "+")
		AddWindowGroupControl("Hide")
		GetWindowGroupControl("Hide")
		GuiControl, AI:, WindowLabel, % labelname
	}
}
IfInString, thislabelmenu, Get Tools
{
	IfInString, thislabelmenu, +
	{
		labelname:= StrReplace(thislabelmenu, "+", "-")
		AddWindowGroupControl("Hide")
		GetWindowGroupControl("Show")
		GuiControl, AI:, WindowLabel, % labelname
	}
	IfInString, thislabelmenu, -
	{
		labelname:= StrReplace(thislabelmenu, "-", "+")
		AddWindowGroupControl("Hide")
		GetWindowGroupControl("Hide")
		GuiControl, AI:, WindowLabel, % labelname
	}
}
IfInString, thislabelmenu, Window Profiles
{
	IfInString, thislabelmenu, +
	{
		labelname:= StrReplace(thislabelmenu, "+", "- ")
		GetWindowGroupControl("Hide")
		WindowProfGroupControl("Show")
		GuiControl, AI:, WindowLabel, % labelname
	}
	IfInString, thislabelmenu, -
	{
		labelname:= StrReplace(thislabelmenu, "- ", "+")
		WindowProfGroupControl("Hide")
		GetWindowGroupControl("Hide")
		GuiControl, AI:, WindowLabel, % labelname
	}
}
Return

Default:
IniRead, Always, % Settings, AlwaysOnTop, Key1
if (Always != "ERROR")
	GuestOn:=% Always
IniRead, Directory, % Settings, Directory, Key1
if (Directory != "ERROR")
	MainDirectory:=% Directory
else
	MainDirectory:= % A_ScriptDir
IniRead, Editor, % Settings, Editor, Key1
if (Editor != "ERROR")
	Editor:=% Editor
else
	Editor:=% "Notepad.exe"
IniRead, WinDrop, % Settings, WinManager, Key2
if (WinDrop != "ERROR")
	WinVictive:=% WinDrop
Gui, Defaults:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Edit, y20 x85, Below are the default settings for the program.
Gui, Add, Text, xp-65 yp+30, Your default Editor is:
Gui, Add, Text, xp yp+30, Default working directory:`t`n(place the full folder location.)`t
Gui, Add, Text, xp yp+50, Test File parameters:`t
Gui, Add, Text, xp yp+30, Activate Get tool without`n locked window active:`t
Gui, Add, Edit, x210 y51 w200 vEdit, % Editor
Gui, Add, Edit, xp yp+35 w200 vDirectory, % A_ScriptDir
Gui, Add, Checkbox, xp yp+45 gDelimit, Delimited
Gui, Add, Checkbox, xp+100 yp gConcantate, Concantated
Gui, Add, Checkbox, xp-100 yp+34 vWinactive, Activate always
Gui, Add, Checkbox, x140 ym+210 vYesOrNo, Default AlwaysOnTop On
Gui, Add, Button, x310 ym+235 gDCancel, Cancel
Gui, Add, Button, wp hp yp x375 gDSave, Save
Gui, Add, Text, x120 ym+230 cRed, (Must click save to save changes!)`n  Must reload for directory change
Gui, Margin, 20, 20
Gui, AI:Font, 0f0d03, Arial
Gui, Color, d6d5d0, f5f4f0
Gui, Show, , Defaults
Control, Disable ,, Edit1, Defaults
if (GuestOn == 1)
	GuiControl, Defaults:, YesOrNo, 1
else if (GuestOn == 0)
	GuiControl, Defaults:, YesOrNo, 0
else
	GuiControl, Defaults:, YesOrNo, 1
if (WinVictive == 1)
	GuiControl, Defaults:, Winactive, 1
else if (WinVictive == 0)
	GuiControl, Defaults:, Winactive, 0
else
	GuiControl, Defualts:, Winactive, 1
Return

Delimit:
IniRead, loopycount, % Settings, DroppedCodeCount, Key1
if (loopycount != "ERROR")
{
	Loop, % loopycount
	{
		IniRead, codedrop, % Settings, DroppedCode, Key%loopycount%
		codeylist.= codedrop  "|"
		loopycount--
	}
}
Gui, Delimits:New, +AlwaysOnTop +toolWindow
Gui, Add, Edit, y20 x20 -VScroll, Below is the Delimited lists from your create test file.`n Note the program is now set to add and delimit with`n               no condition on your decisions.`nTo Add multiple entries place pipes "|" with no spaces.
Gui, Add, Edit, xp+30 yp+80 w170 vDelAdd,
Gui, Add, Button, yp hp x220 gDelAdd, Add
Gui, Add, ListBox, x50 yp+35 w200 r6 vKodeyList gListyChange, % codeylist
Gui, Add, Button, xp+150 yp+110 gLCancel, Cancel
Gui, Add, Button, wp hp yp xp+50 gLSave, Save
Gui, Add, Text, x20 yp+5 cRed, (Must click save to save changes!)
Gui, AI:Font, 0f0d03, Arial
Gui, Color, d6d5d0, f5f4f0
Gui, Margin, 20, 20
Gui, Show, , Delimits
Control, Disable ,, Edit1, Delimits
Return

DelAdd:
Gui, Submit, NoHide
codeylist.= "|" DelAdd 
if (codeylist != "|")
	Sort, codeylist, U Z D|
GuiControl, Delimits:, KodeyList, % codeylist
GuiControl, Delimits:, DelAdd, 
Return

ListyChange:
Gui, Submit, NoHide
codeylist:= StrReplace(codeylist, KodeyList, "")
if (codeylist != "|")
	Sort, codeylist, U Z D|
GuiControl, Delimits:, KodeyList, % codeylist
Return

DelimitsGuiClose:
LCancel:
Gui, Delimits:Destroy
Return

LSave:
Gui, Submit, NoHide
IniDelete, % Settings, DroppedCodeCount
IniDelete, % Settings, DroppedCode
codeylist.= "|" DelAdd 
if (codeylist != "|")
	Sort, codeylist, U Z D|
codeylist:= StrReplace(codeylist, "|", "`n")
Loop, Parse, % codeylist, `n
{
	w++
	IniWrite, % A_LoopField, % Settings, DroppedCode, Key%w%
}
IniWrite, % w, % Settings, DroppedCodeCount, Key1
Gui, Delimits:Destroy
Return

Concantate:
IniRead, loopxcount, % Settings, Looper, Key1
if (loopxcount != "ERROR")
{
	Loop, % loopxcount
	{
		IniRead, codex, % Settings, KeyCodes, Key%loopxcount%
		codexlist.=  codex "|"
		loopxcount--
	}
}
Gui, Concantate:New, +AlwaysOnTop +toolWindow
Gui, Add, Edit, y20 x20 -VScroll, Below is the Delimited lists from your create test file.`n Note the program is now set to add and delimit with`n               no condition on your decisions.`nTo Add multiple entries place pipes "|" with no spaces.
Gui, Add, Edit, xp+30 yp+80 w170 vConAdd,
Gui, Add, Button, yp hp x220 gConAdd, Add
Gui, Add, ListBox, x50 yp+35 w200 r6 vKodexList gListxChange, % codexlist
Gui, Add, Button, xp+150 yp+110 gCCancel, Cancel
Gui, Add, Button, wp hp yp xp+50 gCSave, Save
Gui, Add, Text, x20 yp+5 cRed, (Must click save to save changes!)
Gui, AI:Font, 0f0d03, Arial
Gui, Color, d6d5d0, f5f4f0
Gui, Margin, 20, 20
Gui, Show, , Concantate
Control, Disable ,, Edit1, Concantate
Return

ConAdd:
Gui, Submit, NoHide
codexlist.= "|" ConAdd 
if (codexlist != "|")
	Sort, codexlist, U Z D|
GuiControl, Concantate:, KodexList, % codexlist
GuiControl, Concantate:, ConAdd, 
Return

ListxChange:
Gui, Submit, NoHide
codexlist:= StrReplace(codexlist, KodexList, "")
if (codexlist != "|")
	Sort, codexlist, U Z D|
GuiControl, Concantate:, KodexList, % codexlist
Return

CSave:
Gui, Submit, NoHide
IniDelete, % Settings, Looper
IniDelete, % Settings, KeyCodes
codexlist.= "|" ConAdd 
if (codexlist != "|")
	Sort, codexlist, U Z D|
codexlist:= StrReplace(codexlist, "|", "`n")
Loop, Parse, % codexlist, `n
{
	z++
	IniWrite, % A_LoopField, % Settings, KeyCodes, Key%z%
}
IniWrite, % z, % Settings, Looper, Key1
Gui, Concantate:Destroy
Return

ConcantateGuiClose:
CCancel:
Gui, Concantate:Destroy
Return

DefaultsGuiClose:
DCancel:
Gui, Defaults:Destroy
Return

DSave:
Gui, Submit, NoHide
IniDelete, % Settings, Editor
IniDelete, % Settings, WinManager, Key2
IniDelete, % Settings, Directory
IniDelete, % Settings, AlwaysOnTop
IniWrite, % Edit, % Settings, Editor, Key1
IniWrite, % Winactive, % Settings, WinManager, Key2
IniWrite, % YesOrNo, % Settings, AlwaysOnTop, Key1
IniWrite, % Directory, % Settings, Directory, Key1
Gui, Defaults:Destroy
Return

AISave:
GuiControl,AI:, AISave, Save_File
Return

AIClear:
FileMove, % Temp, % TempBack, 1
FileAppend, , % Temp, UTF-8
GuiControl, AI:, Words,
logicalhistory:=[]
Return
	
SusOnOff:
Suspend, Toggle
if (A_IsSuspended == 1)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOn
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOff
Return

Always:
WinSet, AlwaysOnTop, Toggle, AI
WinGet, ExStyle, ExStyle, AI
if (ExStyle == 0x00000180)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOff
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOn
Return
 
Timers:
Gui, Timers:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, y25, Rest Timer:`t`n(in seconds)
Gui, Add, Text, y75 xs, Window Not Active:`t`n(in milliseconds)
Gui, Add, Text, y125 xs, Process Loop timer:`t`n(in milliseconds)
Gui, Add, Edit, w250 r3 ys-15 -VScroll, This timer slows the script before it gets to the main loop function. It's used to help in processing the global function "Speller."
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the script when the it is not active.
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the main processing loop while typing. It's dependent on a difference created in the main edit control.
Gui, Add, Edit, ys xs+400 w50 y25
Gui, Add, UpDown, vRangeInSeconds Range1-50, 10
Gui, Add, Edit, ys xs+400 w50 y75
Gui, Add, UpDown, vRangeInMillisecondsOfActive Range1-1000, 500
Gui, Add, Edit, ys xs+400 w50 y125
Gui, Add, UpDown, vRangeInMillisecondsOfProcess Range1-100, 25
Gui, Add, Text, xm+10 ym+180, Select the above values to your personal preferences and click save to keep the changes.
Gui, Add, Text, xm+80 ym+215, (Note you have to restart the program to force the changes)
Gui, Add, Button, ym+210 xs+425 gSave, Save
Gui, Add, Button, ym+210 xs+370 gCancel, Cancel
Gui, Margin, 20, 50
Gui, Show, h250 w500, Timers
Control, Disable ,, Working, Timers
Control, Disable ,, TestInfo, Timers
Control, Disable ,, FunctionName, Timers
Return

Minimize:
IniRead, DefaultLoc, % Settings, WinManager, Key1
if (whichone == "")
	whichone:= 1
if (whichone == 0)
{
	Menu, %A_ThisMenu%, Rename, Maximize, Minimize
	whichone:= 1
}
else if (whichone == 1)
{
	Menu, %A_ThisMenu%, Rename, Minimize, Maximize
	whichone:= 0
}
if (DefaultLoc == "ERROR")
{
	MsgBox, 262144, You haven't set up a Default location., You currently haven't set up a Default location for minimize. This will automatically minimize to one of three spots. The "Editor" program you have (Defalut); the "Locked" program (first option if locked): or the screen (last option if neither exist). It will activate the program and Toggles AlwaysOnTop based on the programs active status.`n`nNote**** Your "Editor" will always take precedence in AlwaysOnTop!
	GuiControlGet, Locked, AI:, WindowControl
	if (Locked == "")
		GuiControlGet, DefaultEdit, AI:, DefaultEdit
	IfInString, DefaultEdit, .
	{
		windows:= StrSplit(DefaultEdit, ".")
		for index, window in windows
			if (index == 1)
				thiswindow:=% window
	}
	if (Locked != "")
	{
		IfWinExist, % Locked
			WinActivate, % Locked
	}
	else IfWinExist, % thiswindow
	{
		WinGetTitle, fullwindow, % "ahk_class" thiswindow
		WinActivate, % fullwindow
		GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	}
	else
	{
		WinGetTitle, fullwindow, ahk_class Progman
		GetMoveWindow(DefalutLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	}
	Return
}
else if (DefalutLoc != "ERROR")
{
	GuiControlGet, WindowSnap, AI:, WindowControl
	GuiControlGet, Locked, AI:, DefaultEdit
	IfInString, Locked, .
	{
		windows:= StrSplit(Locked, ".")
		for index, window in windows
			if (index == 1)
				windowcheck:=% window
	}
	WinGet, windows, List,,, Program Manager
	Loop, % windows
	{
		WinID := windows%A_Index%
		WinGetTitle, ThisWindow, % "ahk_id " WinID
		if ((ThisWindow == WindowSnap)&&(WindowSnap != ""))
		{
			fullwindow:=% ThisWindow
			Break
		}
		IfInString, ThisWindow, % windowcheck
		{
			fullwindow:=% ThisWindow
			Break
		}
	}
	WinGet, Minimized, MinMax , % fullwindow
	if ((fullwindow == "")||(Minimized == -1))
		fullwindow:=%  "Program Manager"
	GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
}
Return

Reload:
^r::
Reload
Return

Cancel:
Gui, Timers:Destroy
Return

Save:
Gui, Submit, NoHide
RangeInSeconds:=(RangeInSeconds*1000)
IniWrite, % RangeInSeconds, % Settings, Timers, Key1
IniWrite, % RangeInMillisecondsOfActive, % Settings, Timers, Key2
IniWrite, % RangeInMillisecondsOfProcess, % Settings, Timers, Key3
Gui, Timers:Destroy
Return

FileSelected: 
Gui, Submit, NoHide
GuiControl, AI:, Information, Working..
FileRead, contents, % FileSelected
if (ChangeType == "Get Variables")
{
	if (Gui == 1)
		filters.= "[Filter='Gui'],"
	if (Explicit == 1)
		filters.= "[Filter='explicit'],"
	if (ImplicitExplicit == 1)
		filters.= "[Filter='implicit-explicit'],"
	wi:=
	if (filters != "")
	{
		Control, Disable ,, ListBox1, AI
		contents:= GetVariables(contents, filters)
		GuiControl, AI:, Words,
		GuiControl, AI:, Words, % contents
		whichbutton:=GetControl("ButtCount")
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					thisbutton:= "\|/SoftReturn\|/"
				if (butt == "Enter")
					thisbutton:= "\|/hardReturn\|/"
				if (butt == "Unknown")
					thisbutton:= " \|/SoftReturn\|/"
			}
		}
		StringReplace, contents, contents, `n, %thisbutton%, ALL
		FileMove, % Temp, % TempBack, 1
		FileAppend, % contents, % Temp, UTF-8
	}
}
else if (ChangeType == "Get Function") ;ChangeType gChangeType, Get Variables||Get Function|Create Test File
{
	ControlGet, row, CurrentLine, , Edit3, AI
	ControlGet, rowtext, Line, % row, Edit3, AI
	if (rowtext == "")
	{
		MsgBox, Please insert the function label name
		Return
	}
	if (AssociateV == 1)
		thisignore:=% "Do_Not"
	function:=GetThisFunction(rowtext, thisignore, contents)
	GuiControl, AI:, Words, % function
	FileMove, % Temp, % TempBack, 1
	FileAppend, % function, % Temp, UTF-8
}
else if (ChangeType == "Create Test File")
{
	thesecontents:= GetTestFile(contents)
	Loop, Parse, % thesecontents, `n
	{
		if (A_LoopField == "")
			Continue
		if (A_LoopField == "Return")
			thisfile:=% thisfile A_LoopField "`n`n"
		else if (A_LoopField != "Return")
			thisfile:=% thisfile A_LoopField "`n"
	}
	FileMove, Test.ahk, % TempBack, 1
	FileAppend, % thisfile, *Test.ahk, UTF-8
}
GuiControl, AI:, AssociateV, 0
GuiControl, AI:, Gui, 0
GuiControl, AI:, Explicit, 0
GuiControl, AI:, ImplicitExplicit, 0
GuiControl, AI:, FunctionName,
GuiControl, AI:, WordKeeper, 7h151s@a#res37
GuiControl, AI:, Information, Done
Control, Enable ,, ListBox1, AI
Return

WindowProfGroupControl(control)
{
	if (control == "Show")
	{
		GuiControl, AI:Show, GroupControls
		GuiControl, AI:, GroupControls, Window Profiles
		GuiControl, AI:Show, ProfList
		GuiControl, AI:Show, ProfAdd
		GuiControl, AI:Show, ProfDele
		GuiControl, AI:Show, ProfMod
		GuiControl, AI:Show, ProfBack
		GuiControl, AI:Show, ProfStart
		GuiControl, AI:Show, ProfRun
		GuiControl, AI:Hide, PixMouse
		GuiControl, AI:Hide, WinStats
		GuiControl, AI:Hide, WinText
		GuiControl, AI:Hide, Welcome
		GuiControl, AI:Show, ControlInformation
	}
	if (control == "Hide")
	{
		GuiControl, AI:Hide, GroupControls
		GuiControl, AI:Show, Welcome
		GuiControl, AI:Hide, ProfList
		GuiControl, AI:Hide, ProfAdd
		GuiControl, AI:Hide, ProfDele
		GuiControl, AI:Hide, ProfMod
		GuiControl, AI:Hide, ProfBack
		GuiControl, AI:Hide, ProfStart
		GuiControl, AI:Hide, ProfRun
		GuiControl, AI:Hide, PixMouse
		GuiControl, AI:Hide, WinStats
		GuiControl, AI:Hide, WinText
		GuiControl, AI:Hide, ControlInformation
	}
	Return
}

AddWindowGroupControl(control)
{
	if (control == "Show")
	{
		GuiControl, AI:Show, GroupControls
		GuiControl, AI:, GroupControls, Window Controls
		GuiControl, AI:Show, GetWindow
		GuiControl, AI:Show, SnapWindow
		GuiControl, AI:Show, SnapToEditor
		GuiControl, AI:Show, AutoEdit
		GuiControl, AI:Show, EnableCC
		GuiControl, AI:Show, EnableVV
		GuiControl, AI:Hide, PixMouse
		GuiControl, AI:Hide, WinStats
		GuiControl, AI:Hide, WinText
		GuiControl, AI:Hide, Welcome
		GuiControl, AI:Show, ControlInformation
	}
	if (control == "Hide")
	{
		GuiControl, AI:Hide, GroupControls
		GuiControl, AI:Hide, GetWindow
		GuiControl, AI:Hide, SnapWindow
		GuiControl, AI:Hide, SnapToEditor
		GuiControl, AI:Hide, AutoEdit 
		GuiControl, AI:Hide, EnableCC
		GuiControl, AI:Hide, EnableVV
		GuiControl, AI:Hide, PixMouse
		GuiControl, AI:Hide, WinStats
		GuiControl, AI:Hide, WinText
		GuiControl, AI:Show, Welcome
		GuiControl, AI:Hide, ControlInformation
	}
	Return
}

GetWindowGroupControl(control)
{
	if (control == "Show")
	{
		GuiControl, AI:Show, GroupControls
		GuiControl, AI:, GroupControls, Window Stats
		GuiControl, AI:Show, ComboBox2
		GuiControl, AI:Show, GetPix
		GuiControl, AI:Show, GetMouse
		GuiControl, AI:Show, GetWinS
		GuiControl, AI:Show, GetWinT
		GuiControl, AI:Show, MultiSele
		GuiControl, AI:Show, PixMouse
		GuiControl, AI:Show, WinStats
		GuiControl, AI:Show, WinText
		GuiControl, AI:Hide, Welcome
		GuiControl, AI:Show, ControlInformation
	}
	if (control == "Hide")
	{
		GuiControl, AI:Hide, GroupControls
		GuiControl, AI:Hide, ComboBox2
		GuiControl, AI:Hide, GetPix
		GuiControl, AI:Hide, GetMouse
		GuiControl, AI:Hide, GetWinS
		GuiControl, AI:Hide, GetWinT
		GuiControl, AI:Hide, MultiSele
		GuiControl, AI:Show, PixMouse
		GuiControl, AI:Show, WinStats
		GuiControl, AI:Show, WinText
		GuiControl, AI:Show, Welcome
		GuiControl, AI:Hide, ControlInformation
	}
	Return
}

Tracker(thistrack, DefaultLoc, Whichone, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
{
	GuiControlGet, WindowSnap, AI:, WindowControl
	GuiControlGet, DefaultEdit, AI:, DefaultEdit
	GuiControlGet, winSnap, AI:, SnapWindow
	GuiControlGet, EditSnap, AI:, SnapToEditor
	windows:= StrSplit(DefaultEdit, ".")
	for index, window in windows
		if (index == 1)
			editwindow:=% window
	WinGet, windows, List,,, Program Manager
	Loop, % windows
	{
		WinID := windows%A_Index%
		WinGetTitle, ThisWindow, % "ahk_id " WinID
		if ((ThisWindow == WindowSnap)&&(ThisWindow != ""))
		{
			fullwindow:=% ThisWindow
			Break
		}
		IfInString, ThisWindow, % editwindow
		{
			fullwindow:=% ThisWindow
			Break
		}
	}
	if (thistrack != fullwindow)
		if ((EditSnap != "")||(WindowSnap != ""))
			IfWinActive, % fullwindow
				if ((winSnap == 1)||(EditSnap == 1))
				{
					WinSet, Transparent , Off, AI
					WinSet, AlwaysOnTop, on, AI
					GetMoveWindow(DefaultLoc, Whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
				}
	IfWinNotActive, % fullwindow
		IfWinNotActive, AI
			if ((winSnap == 1)||(EditSnap == 1))
			{
				WinSet, Transparent , 0, AI
				WinSet, AlwaysOnTop, off, AI
				fullwindow:=% ""
			}
	Return % fullwindow
}

GetMoveWindow(DefaultLoc, Whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
{
	if (fullwindow != "Program Manager")
		WinGetPos , winPosX, winPosY, windowwidth, windowheight, % fullwindow
	else
	{
		winPosX:=0
		winPosY:=0
		windowwidth:=(A_ScreenWidth-50)
		windowheight:=(A_ScreenHeight-50) ; offage is set for DPI and virtual windows. This should be enough for most windows but each person has their own settings.
	}
	If (DefaultLoc != "ERROR")
		ThisWindowLoc(DefaultLoc,Whichone, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	else if (DefaultLoc == "ERROR")
	{
		MsgBox, 262212, Default location not set, You have not set up a default location for the window. Would you like to continue?
		IfMsgBox, Yes
		{
			Loop,
			{
				x++
				y:=0
				ThisWindowLoc(x, y, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
				MsgBox, 262144, first position, This is the first position of the window minimized.
				y:=1
				ThisWindowLoc(x, y, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
				MsgBox, 262211, Do you like that location?, This is the second position maximized.`nIf you like this position click yes.`nTo exit click Cancel`n%x% %y% 
				IfMsgBox Yes
				{
					IniWrite, % x, % Settings, WinManager, Key1
					Break
				}
				IfMsgBox Cancel
					Break
				if (x == 9)
					x:=0
			}
		}	
		IfMsgBox, No
			Return
	}
	Return
}
	

ThisWindowLoc(DefaultLoc, Whichone, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
{
	AIwidth:= 100
	AIheight:= 80
	if (DefaultLoc == 1)
	{
		MainWindowX:=(windowwidth-AIwidth+winPosX)
		MainWindowY:=(windowheight-AIheight+winPosY) ; bottom right corner
		GuiWindowX:=(windowwidth-AIorignalwidth+winPosX)
		GuiWindowY:=(windowheight-AIorignalhieght+winPosY)
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 2)
	{
		MainWindowX:=% winPosX
		MainWindowY:=(windowheight-AIheight+winPosY) ; bottom left corner
		GuiWindowX:=% winPosX
		GuiWindowY:=(windowheight-AIorignalhieght+winPosY)
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 3)
	{
		MainWindowX:=% winPosX
		MainWindowY:=% winPosY ; upper left corner
		GuiWindowX:=% winPosX
		GuiWindowY:=% winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 4)
	{
		MainWindowX:=(windowwidth-AIwidth+winPosX)
		MainWindowY:=% winPosY ; upper right corner.
		GuiWindowX:=(windowwidth-AIorignalwidth+winPosX)
		GuiWindowY:=% winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 5)
	{
		MainWindowX:=(windowwidth/2)-(AIwidth/2)
		MainWindowY:=% winPosY ; upper center
		GuiWindowX:=(windowwidth/2)-(AIorignalwidth/2)
		GuiWindowY:=% winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 6)
	{
		MainWindowX:=(windowwidth/2)-(AIwidth/2)
		MainWindowY:=(windowheight-AIheight+winPosY) ; lower center
		GuiWindowX:=(windowwidth/2)-(AIorignalwidth/2)
		GuiWindowY:=(windowheight-AIorignalhieght+winPosY)
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 7)
	{
		MainWindowX:=% winPosX
		MainWindowY:=(windowheight/2)-(AIheight/2)+winPosY ; left center
		GuiWindowX:=% winPosX
		GuiWindowY:=(windowheight/2)-(AIorignalhieght/2)+winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 8)
	{
		MainWindowX:=(windowwidth-AIwidth+winPosX)
		MainWindowY:=(windowheight/2)-(AIheight/2)+winPosY ;right center
		GuiWindowX:=(windowwidth-AIorignalwidth+winPosX)
		GuiWindowY:=(windowheight/2)-(AIorignalhieght/2)+winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 9)
	{
		MainWindowX:=(windowwidth/2)-(AIwidth/2)
		MainWindowY:=(windowheight/2)-(AIheight/2)+winPosY ; center center
		GuiWindowX:=(windowwidth/2)-(AIorignalwidth/2)
		GuiWindowY:=(windowheight/2)-(AIorignalhieght/2)+winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	Return
}

GetTestFile(data)
{
	IniRead, loopcount, % Settings, Looper, Key1
	if (loopcount != "ERROR")
	{
		Loop, % loopcount
		{
			IniRead, codex, % Settings, KeyCodes, Key%loopcount%
			codexlist.= codex "`n"
			loopcount--
		}
		IniRead, loopcount, % Settings, DroppedCodeCount, Key1
		if (loopcount != "ERROR")
		{
			Loop, % loopcount
			{
				IniRead, codedrop, % Settings, DroppedCode, Key%loopcount%
				codeylist.= codedrop "`n"
				loopcount--
			}
		}
		data:= StrReplace(data, "`r", "")
		Loop, Parse, % data, `n
		{
			y++
			codestring:=
			line:=% A_LoopField
			sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
			for index, sentence in sentences
			{
				if (index == 1)
					codestring:=% sentence
				if (index == 2)
					commentstring:=% sentence
			}
			keycodex:= StrReplace(codestring, ",",  " ")
			keycodex:= StrReplace(keycodex, "  ", " ")
			keycodex:= StrReplace(keycodex, "  ", " ")
			keycodex:=% Trim(keycodex)
			thesewords:= StrSplit(keycodex, A_Space)
			for index, keycode in thesewords
				if (index == 1)
					keycodex:=% keycode
			IfinString, codeylist, % keycodex
				codestring:=% ""
			IfinString, codexlist, % keycodex
			{
				filecontents:=% filecontents codestring "`n"
				codestring:=% ""
			}
			codestring:= CodeStringCheck(codestring)
			if (codestring != "")
			{
				IfinString, codestring, Return
				{
					if (thischecker == 1)
						IfNotInString, codestring, % "`t"
							thischecker:= 0
					codestring:=% ""
				}
				IfInString, codestring, Global
				{
					filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfInString, codestring, Gui
				{
					IfinString, codestring, Show
						filecontents:=% filecontents codestring "`nReturn`n`n"
					else
						filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfInString, codestring, Menu
				{
					filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfinString, codestring, :
				{
					if (thischecker != 1)
					{
						thischecker:= 1
						if (x != 1)
							x:=1
					}
					filecontents:=% filecontents codestring "`nReturn`n`n"
					codestring:=% ""
				}
				IfInString, filecontents, % codestring
					codestring:=% ""
			}
		}
	}
	else if (loopcount == "ERROR")
	{
		MsgBox, 70, Be sure before you continue., In the following message boxes you will be shown the beginning of your code. This will omit the comments and anything past the first comma as demiliters for your test.ahk creation. each type will be added to the Ini file settings and read for your future creations. You can always change this setting by selecting default in the default menu.`n`n**Also note This does skip continuation sections.
		IfMsgBox Continue
		{
			data:= StrReplace(data, "`r", "")
			Loop, Parse, % data, `n
			{
				y++
				line:=% A_LoopField
				sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
				for index, sentence in sentences
				{
					if (index == 1)
						codestring:=% sentence
					if (index == 2)
						commentstring:=% sentence
				}
				codestring:= CodeStringCheck(codestring)
				if (codestring != "")
				{
					IfinString, codestring, Return
					{
						if (thischecker == 1)
							IfNotInString, codestring, % "`t"
								thischecker:= 0
						codestring:=% ""
					}
					IfInString, codestring, Global
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, codestring, Gui
					{
						IfinString, codestring, Show
							filecontents:=% filecontents codestring "`nReturn`n`n"
						else
							filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, codestring, Menu
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfinString, codestring, :
					{
						if (thischecker != 1)
						{
							thischecker:= 1
							if (x != 1)
							{
								x:=1
								MsgBox, 32, g-Sublabels, sublabels are automatically added
							}
						}
						filecontents:=% filecontents codestring "`nReturn`n`n"
						codestring:=% ""
					}
					keycodex:= StrReplace(codestring, ",",  " ")
					keycodex:= StrReplace(keycodex, "  ", " ")
					keycodex:= StrReplace(keycodex, "  ", " ")
					keycodex:=% Trim(keycodex)
					thesewords:= StrSplit(keycodex, A_Space)
					for index, keycode in thesewords
						if (index == 1)
							keycodex:=% keycode
					IfinString, thisignoredlist, % keycodex
						codestring:=% ""
					IfinString, thisgottenlist, % keycodex
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, filecontents, % codestring
						codestring:=% ""
					if (codestring != "")
					{
						MsgBox, 36, Do you want to add this line?, % keycodex "`n`nFound on line: " y "`n`npress yes if you want to add the first (word) of this line to your delimiter fields."
						IfMsgBox Yes
						{
							z++
							IniWrite, % z, % Settings, Looper, Key1
							IniWrite, % keycodex, % Settings, KeyCodes, Key%z%
							thisgottenlist.= keycodex
							filecontents:=% filecontents codestring "`n"
						}
						else IfMsgBox No
						{
							w++
							IniWrite, % w, % Settings, DroppedCodeCount, Key1
							IniWrite, % keycodex, % Settings, DroppedCode, Key%w%
							thisignoredlist.= codestring " "
							Continue
						}
					}
				}
			}
		}
	}
	Return % filecontents
}

CodeStringCheck(codestring)
{
	IfInString, codestring, GuiControl
		codestring:=% ""
	IfinString, codestring, `t
		codestring:=% ""
	IfInString, codestring, Global
		Return % codestring
	IfInString, codestring, Gui ; It's likely a user may place any of the below special characters in a gui 4th parameter.
		Return % codestring
	IfInString, codestring, =
		codestring:=% ""
	IfInString, codestring, ( ;)
		codestring:=% ""
	IfInString, codestring, {
		codestring:=% ""
	IfInString, codestring, }
		codestring:=% ""
	IfInString, codestring, `%
		IfNotInString, codestring, SetWorkingDir
			codestring:=% ""
	IfinString, codestring, Loop
		codestring:=% ""
	IfinString, codestring, else
		codestring:=% ""
	IfinString, codestring, if%A_Space%
		codestring:=% ""
	IfinString, codestring, ::
		codestring:=% ""
	Return % codestring
}

GetThisFunction(function, get, data)
{
	function:= StrReplace(function, "`r`n", "")
	function:= StrReplace(function, "`n", "")
	functionlength:=StrLen(function)
	data:= StrReplace(data, "`r", "")
	function:= GetFunction(data, functionlength, function)
	thisfoundfunction.= function "`n"
	function:=""
	if (get == "Do_Not")
	{
		Loop,
		{
			Loop, Parse, % thisfoundfunction, `n
			{
				IfInString, A_LoopField, =
					IfInString, A_LoopField, (
					{
						foundpossible:= FunctionLabelGet(A_LoopField)
						Trim(foundpossible)
						IfNotInString, foundpossible, % A_Space
							IfNotInString, thesefound, % foundpossible
							{
								functionlength:=StrLen(foundpossible)
								function:= GetFunction(data, functionlength, foundpossible)
							}
						if (function != "")
							thisfoundfunction.= function "`n"
					}
				if (function != "")
					function:=
				thesefound.= foundpossible ", "
			}
			IfNotInString, thesefoundpast, % thesefound
				thesefoundpast.= thesefound
			IfinString, thesefoundpast, % thesefound
				Break
		}
	}
	Return % thisfoundfunction
}

GetFunction(data, functionlength, function)
{
	Loop, Parse, % data, `n
	{
		if (thisfunction == "")
		{
			linesubstring:= SubStr(A_LoopField, 1, functionlength)
			if (function == linesubstring)
			{
				thisfunction:= % A_LoopField "`n"
				z:=1
			}
		}
		else if (thisfunction != "")
		{
			thisfunction.= A_LoopField "`n"
			if (A_LoopField == "{")
				x++
			if (A_LoopField == "}")
				x--
			if (z == 1)&&(A_LoopField != "{")
				thisfunction:= ""
			z:=0
		}
		if ((x == 0)&&(thisfunction != ""))
		{
			thisfoundfunction:= % thisfunction
			thisfunction:= ""
		}
	}
	Return % thisfoundfunction
}

FunctionLabelGet(line)
{
	thissplitfunction:= StrSplit(line, "= ")
	for index, thissplit in thissplitfunction
		if (index == 2)
			thispart:=% thissplit
	thispartsplit:= StrSplit(thispart, "(") ;"
	for index, function in thispartsplit
		if (index == 1)
			Return % function
	Return
}

ChangeType:
Gui, Submit, NoHide
if (ChangeType == "Get Variables")
{
	GuiControl, AI:Text, Results, Get variables`n(Filter results by Checkbox)
	GuiControl, AI:Hide, FunctionName
	GuiControl, AI:Hide, FunctionLabel
	GuiControl, AI:Hide, TestInfo
	GuiControl, AI:Hide, AssociateV
	GuiControl, AI:Show, Gui
	GuiControl, AI:Show, Explicit
	GuiControl, AI:Show, ImplicitExplicit
}
if (ChangeType == "Get Function")
{
	GuiControl, AI:Text, Results, Get Function`n(Select a file to get a function)
	GuiControl, AI:Show, FunctionName
	GuiControl, AI:Show, FunctionLabel
	GuiControl, AI:Hide, TestInfo
	GuiControl, AI:Show, AssociateV
	GuiControl, AI:Hide, Gui
	GuiControl, AI:hide, Explicit
	GuiControl, AI:Hide, ImplicitExplicit
	GuiControl, Focus, FunctionName
}
if (ChangeType == "Create Test File")
{
	GuiControl, AI:Text, results, Create a Test File`n(Create functionless test ahk)
	GuiControl, AI:hide, Gui
	GuiControl, AI:Hide, Explicit
	GuiControl, AI:hide, ImplicitExplicit
	GuiControl, AI:Hide, AssociateV
	GuiControl, AI:hide, FunctionName
	GuiControl, AI:hide, FunctionLabel
	GuiControl, AI:Show, TestInfo
}
Return

GetVariables(filecontents, filters)
{
	Loop, Parse, % filecontents, `r
	{
		linenumber++
		line:=% A_LoopField
		sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
		for index, sentence in sentences
		{
			if (index == 1)
				codestring:=% sentence
			if (index == 2)
				commentstring:=% sentence
		}
		VarSetCapacity(information, 0) 
		codestring:= RemoveCertainChars(codestring, "Start")
		IfInString, codestring, Dll
			Continue
		IfInString, codestring, Box`,
			Continue
		IfInString, codestring, StringReplace
			Continue
		IfInString, codestring, RegEx
			Continue
		IfInString, codestring, Ini
			Continue
		IfInString, codestring, =
		{
			IfInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Percent", linenumber)
				IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
			}
			else IfNotInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
			IfInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Quotes", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring 
			}
			else IfNotInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
		}
		else IfInString, codestring, [percent]
		{
			variablestring:= GetVariableString(codestring, "Percent", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring
		}
		else IfInString, codestring, [quotes]
		{
			variablestring:= GetVariableString(codestring, "Quotes", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring "found in quotes 2`n"
		}
		IfInString, codestring, Gui
			IfInString, codestring, `,
				IfInString, codestring, %A_Space%v
				{
					variablestring:= GetVariableString(codestring, "Gui", linenumber)
					IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
				}
	}
	thesefilters:=StrSplit(filters, ",")
	for index, filter in thesefilters
	{
		if (index == 1)
			if (filter != "")
				firstfilter:=% filter
		if (index == 2)
			if (filter != "")
				secondfilter:=% filter
		if (index == 3)
			if (filter != "")
				thirdfilter:=% filter
	}
	Loop, Parse, % variablelist, `n
	{
		thischeck:= ""
		information:= ""
		if (A_LoopField != "")
		{
			repeatcheck:= StrSplit(A_LoopField, "[thissplitter]")
			for index, repeat in repeatcheck
			{
				if (index == 1)
				{
					IfNotInString, completedlist, % repeat
						thischeck:=% repeat
					IfInString, completedlist, % repeat
					{
						checking:= MakeSure(completedlist, repeat)
						if (checking == "True")
							Continue
						else if (checking == "False")
							thischeck:=% repeat
					}
				}
				if (index == 2)
				{
					if (firstfilter != "")
						IfInString, repeat, % firstfilter
						{
							applyfilters:= StrSplit(repeat, firstfilter)
							for index, apply in applyfilters
								information.= apply
						}
					else if (secondfilter != "")
						IfInString, repeat, % secondfilter
						{
							applyfilters:= StrSplit(repeat, secondfilter)
							for index, apply in applyfilters
								information.= apply
						}
					else if (thirdfilter != "")
						IfInString, repeat, % thirdfilter
						{
							applyfilters:= StrSplit(repeat, thirdfilter)
							for index, apply in applyfilters
								information.= apply
						}
				}
			}
			if ((thischeck != "")&&(information != ""))
			{
				checklist:=% Trim(thischeck) "`n" Trim(information) "`n"
				IfNotInString, completedlist, % checklist
					completedlist.= checklist
			}
		}
	}
	completedlist:= RemoveCertainChars(completedlist, "End")
	Return % completedlist
}

MakeSure(listinprogress, checkword)
{
	Loop, Parse, % listinprogress, `n
	{
		if (checkword == A_LoopField)
			Return % "True"
	}
	Return % "False"
}

GetVariableString(codestring, whichone, linenumber)
{
	if (whichone == "Gui")
	{
		variablestrings:= StrSplit(codestring, ",")
		for index, variablestring in variablestrings
		{
			if (index > 4)
				Continue
			IfInString, variablestring, %A_Space%v
				thisvariablestring:=% variablestring
		}
		variablestring:= StrSplit(thisvariablestring, A_Space)
		for index, variable in variablestring
		{
			thisvariableletter:= SubStr(variable, 1, 1)
			if (thisvariableletter == "v")
				Return % variable "[thissplitter] Gui variable[Filter='Gui'] Line number is found at: " linenumber "`n"
		}
		Return % variable "[thissplitter] Gui variable Line number is found at: " linenumber "`n"
	}
	if (whichone == "Quotes")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [quotes]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		variablestrings:= StrSplit(codestring, "[quotes]")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 0)
				IfNotInString, variablestring, %A_Space%
					IfNotInString, variables, % variablestring
						variables.= "[quotes]" variablestring "[quotes][thissplitter] explicit[Filter='explicit'] variable Line number is found at: " linenumber "`n"
		}
		Return % variables
	}
	if (whichone == "Percent")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [percent]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		IfInString, codestring, `,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					IfInString, variablestring, [percent]
						IfNotInString, variablestring, =
							IfInString, variablestring, A_Space
								variables.= variablestring "[thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		IfNotInString, codestring, `,
		{
			IfInString, codestring, =
			{
				variablestrings:= StrSplit(codestring, "=")
				for index, variablestring in variablestrings
				{
					if (index == 1)
					{
						variables:= StrSplit(variablestring, A_Space)
						for index, variable in variables
							thisvariable:=% variable
					}
					if (index == 2)
						codestring:=% variablestring
				}
			}
			variablestrings:= StrSplit(codestring, "[percent]")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					variables.= "[percent]" variablestring "[percent][thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		if (thisvariable != "")
			variables.= thisvariable "[thissplitter]implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
		Return % variables
	}
	if (whichone == "Equals")
	{
		variablestrings:= StrSplit(codestring, "=")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 1)
				IfNotInString, variablestring, [quotes]
				{
					thisvariablestring:= StrSplit(variablestring, A_Space)
					for index, thisvariable in thisvariablestring
					{
						variable:=% thisvariable "[thissplitter] implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
					}
				}
		}
		Return % variable
	}
	Return % "Not Found"
}

RemoveCertainChars(string, special)
{
	if (special == "Start")
	{
		StringReplace, string, string, ", [quotes], ALL ; "
		StringReplace, string, string, `%%A_Space%, [percent], ALL
		StringReplace, string, string, `%, [percent], ALL
		StringReplace, string, string, %A_Space%:, :, ALL
		StringReplace, string, string, :=, =, ALL
		StringReplace, string, string, ==, =, ALL
		StringReplace, string, string, >, =, ALL
		StringReplace, string, string, <, =, ALL
		StringReplace, string, string, %A_Space%!=, =, ALL
		StringReplace, string, string, =%A_Space%, =, ALL
		StringReplace, string, string, %A_Space%=, =, ALL
		StringReplace, string, string, ), , ALL
		StringReplace, string, string, (, , ALL ;)
		StringReplace, string, string, `t, , ALL
	}
	if (special == "End")
	{
		StringReplace, string, string, [quotes], ", ALL ; "
		StringReplace, string, string, [percent], `%, ALL
		StringReplace, string, string, `,, , ALL
	}
	Return % string
}

GetButton_Count()
{
	Loop,
	{
		ButtonCountCheck:= GetControl("ButtCount")
		if (ButtonCountCheck != OldButtonCountCheck)
		{
			OldCount:=% Count
			OldButton:=% Button
			Sleep, 500
			ButtonCount_Split:= StrSplit(ButtonCountCheck, ",")
			For Index, ButtCount in ButtonCount_Split
			{
				if (Index == 1)
					Count:=% ButtCount
				if (Index == 2)
					Button:=% ButtCount
			}
		}
		else if (ButtonCountCheck == OldButtonCountCheck)
			Break
		if ((Button != OldButton)&&(Count > 1))
			Break
		OldButtonCountCheck:=% ButtonCountCheck
	}
	if (Button == OldButton)
	{
		ButtonCountReturn:=% Count "," Button
		GuiControl,AI:, ButtonCountCheck, % "0," Button
	}
	if (Button != OldButton)
	{
		NewCount:=% Count-OldCount
		GuiControl,AI:, ButtonCountCheck, % NewCount "," Button
		ButtonCountReturn:=% OldCount "," OldButton
	}
	Return
}

ApplyLogicalChange(activeuserinput, logicalhistory, numberofdifferences)
{
	x:= 0
	newhistoryrecord:=[]
	activeuserinputlastline:= GetLineCount(activeuserinput)
	logicalhistorylastline:= GetLineCount(logicalhistory)
	LastLine:= logicalhistory["linePos" logicalhistorylastline]
	Loop, % activeuserinputlastline
	{
		record:=
		x++ ; a lagged y variable needed to stagger history.
		occurenceuser:= activeuserinput["linePos" x]
		if (y > 0)
		{
			y:=(x-z) ; this will be an opposite staggered y (x+z) for deleted lines.
			historyrecord:= logicalhistory["linePos" y]
		}
		else
			historyrecord:= logicalhistory["linePos" x] ; even though the line now isn't right doesn't mean next time it won't be.
		splithistoryrecord:= StrSplit(historyrecord, ["(hardReturn)", "(softReturn)"])
		for index, splithistory in splithistoryrecord
		{
			if (Index == 1)
				record:= % splithistory
		}
		if ((occurenceuser != record)&&(numberofdifferences != 0)) ; the number of occurences go negative when lines get deleted... I haven't updated the below else for that yet.
		{
			LastLine:= logicalhistory["linePos" logicalhistorylastline] ; if a user is lagging the array make sure you are putting in last lines right.
			if ((LastLine == "(softReturn)")||(LastLine == "(hardReturn)")) ; the last line shouldn't be any other value.
			{
				z++ ; a z variable making sure we don't lose y and holding the number of occurences.
				if (z == 1) ; there's not enough time to add different enters in different spots (meaning the user couldn't add enough enters in the time this will be done).
					y:=% x
				IfInString, LastLine, (softReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
				IfInString, LastLine, (hardReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
				numberofdifferences--
				logicalhistorylastline--
			} ; the likely answer is a deleted line in occurenceuser. we need to add to the numberofdifferences. I'll also need to update this in the future for the array.
			else
				numberofdifferences++
		}
		else if ((occurenceuser != record)&&(numberofdifferences == 0)) ; meaning user has updated a line with a new record
		{
			newhistoryrecord["linePos" x]:= occurenceuser
			IfInString, record, (softReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
			IfInString, record, (hardReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
		} ; z from above holds all change counts. y from above holds the history record line back. technically y can equal x-z or just y++. I think for greater clarity it should be x-z because a user may choose to purposely lag the logicalhistoryarray Change function. Basically this function can be implimented at will as long as the keys are being kept up with and added to the historyarray in the main loop (of course that might also come with logical array issues).
		else if ((occurenceuser == record)&&(numberofdifferences == 0))
			newhistoryrecord["linePos" x]:= record
	}
	check:=GetControl("GetKeeper")
	if (check == "7h151s@a#res37")
		Return
	Return % newhistoryrecord ; There has been many different statements on using the % after Return or in ":=" as an operorator (it technically doesn't need to be done and can cause issues if done improperly). I use it because honestly it's like my signature to my work.
}

Doppler(usersentence, historysentence)
{
	livewords:=[]
	pastwords:=[]
	check:=GetControl("GetKeeper")
	if (check == "&not@a#rea1*sent3nc3")
	{
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			livewords["wordPos" key]:= userwords
		}
		historysplit:=StrSplit(historysentence, A_Space)
		for key, historywords in historysplit
		{
			pastwords["wordPos" key]:= historywords
		}
		usercount:=GetLineCount(livewords)
		historycount:= GetLineCount(pastwords)
		Loop, % usercount
		{
			x++
			userword:=livewords["wordPos" x]
			historyword:=pastwords["wordPos" x]
			userwordlength:=StrLen(userword)
			historywordlength:= StrLen(historyword)
			if ((userword != historyword)||(historycount < x))
				GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		}
		StringReplace, userword, userword, historyword, , ALL
	}
	else if (check != "&not@a#rea1*sent3nc3")
	{
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 1)
				historyword:=% chec
			if (index == 2)
				ouserword:=% chec
			if (index == 3)
				x:=% chec
		}
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			if (key == x)
				userword:=% userwords
		}
		GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		StringReplace, userword, userword, historyword, , ALL
	}
	userwordlength:=StrLen(userword)
	if (userwordlength < 2)
	{
		GuiControl, AI:, Information, Working...
		SpellChecker(0)
	}
	if (userwordlength > 3)
	{
		GuiControl, AI:, Information, Working.
		ourwords:=WordCheck(userword, userwordlength)
		if (ourwords == "")
			SpellChecker(0)
		else if (ourwords != "")
		{
			SpellChecker(userwordlength)
			GetControl(ourwords)
		}
	}
	Return
}

FixLogicalhistory_Array(historyarray, howmanylines)
{
	lastline:= GetLineCount(historyarray)
	whichbutton:= GetControl("ButtCount")
	Loop, % howmanylines
	{
		lastline++
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					historyarray["linePos" lastline]:= "(softReturn)"
				if (butt == "Enter")
					historyarray["linePos" lastline]:= "(hardReturn)"
			}
		}
	}
	Return % historyarray
}

ReturnLineArray(lines, user)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/SoftReturn\|/", "\|/userReturns\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

GetButtonCount(pressed)
{
	pressing:= StrSplit(pressed, ",")
	For Index, press in pressing
		if (Index == 1)
			Return % press
}

FindingRealLineLOL(occurenceuser, rowbefore, thisrow)
{
	IfInString, occurenceuser, %rowbefore%
	{
		rowlength:= StrLen(rowbefore)
		occurencelength:= StrLen(occurenceuser)
		subtractedlength:=(occurencelength-rowlength)
		thisstring:= SubStr(occurenceuser, subtractedlength, occurencelength)
		if (thisstring == rowbefore)
		{
			IfInString, occurenceuser, %thisrow%
				Return % "Found"
			IfNotInstring, occurenceuser, %thisrow%
				Return % "NextRow"
		}
	}
	if (rowbefore == "NextRow")
		IfInString, occurenceuser, %thisrow%
			Return % "Found"
	Return % "NotFound"
}

ProcessStart(contents, Rest)
{
	logicalhistory:= []
	WinSet, Transparent, 0, Words
	history:= GetHistory()
	logicalhistory:= ReturnLineArray(history, user)
	Control, Disable ,, Words, AI
	GuiControl, AI:, Words, % contents
	Sleep, % Rest
	Control, Enable ,, Words, AI
	GuiControl, AI:, Information, Done
	Control, Enable ,, ListBox1, AI
	Return % logicalhistory
}

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	if (n > 3)
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	if (n == 0)
		WinSet, Transparent, 0, Words
	WinGet, visible, Transparent, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	Return
}
Return

ReturnClearDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			hinput:= harray["linePos" x]
			hsplit:= StrSplit(hinput, ["(hardReturn)", "(softReturn)"])
			for Index, h in hsplit
			{
				if (Index == 1)
					checkh:= % h
			}
			uinput:= uarray["linePos" x]
			StringReplace, uinput, uinput, (softReturn), , ALL
			StringReplace, uinput, uinput, (hardReturn), , ALL
			l_checkh:= StrLen(checkh)
			l_uinput:= StrLen(uinput)
			if (uinput != checkh)
				Return % x
			if (l_checkh != l_uinput)
				Return % x
			if (x == v)
				Break
			checkh:=
		}
		Return % "0"
	}
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return % "True"
	}
}

GetLineCount(arraycount)
{
	LastLine:=0
	for Index, count in arraycount
		++LastLine
	Return % LastLine
}

GetControl(FocTex)
{
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, FunctionName
	ControlGet, row, CurrentLine, , FunctionName, AI
	ControlGet, rowtext, Line, % row, FunctionName, AI
	GuiControlGet, Word, Words:, Listbox1
	StringReplace, text, text, `n, \|/userReturns\|/, ALL
	GuiControlGet, ButtonCountCheck, AI:, ButtonCountCheck
	GuiControlGet, Save_File, AI:, AISave
	GuiControlGet, DopplerGet, AI:, WordKeeper
	if (FocTex == "RowText")
		Return % rowtext
	if (FocTex == "GetKeeper")
		Return % DopplerGet
	if (FocTex == "AISave")
		Return % Save_File
	if (FocTex == "ButtCount")
		Return % ButtonCountCheck
	if (FocTex == "Row")
		Return % row
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	GuiControl, Words:, Listbox1, | 
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
	Return
}

WinProf()
{
	FileRead, contents, % Cache "\Profiles.Storage"
	if (ErrorLevel == 0)
	{
		Profiles:= StrSplit(contents, "[End-Splitter-Loop]")
		for index, profile in profiles
		{
			profilestrings:= StrSplit(profile, "&not@a#rea1*??sent3nc3")
			for index, profilepart in profilestrings
			{
				if (index == 1)
					profcheck:=% profilepart
				if (index == 2)
					datecheck:=% profilepart
			}
			if (profcheck != "")
				IfNotInString, updatedlist, % profcheck "`t" datecheck "|"
					updatedlist.= profcheck "`t" datecheck "|"
		}
	}
	Return % updatedlist
}

HashContents(contents)
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, \|/CR+LF\|/, `n, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, `n, ALL
	Return % contents
}

GetHistory()
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, `r`n,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, (softReturn)\|/SoftReturn\|/, ALL
	StringReplace, contents, contents, \|/CR+LF\|/,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, (softReturn)\|/SoftReturn\|/, ALL
	Return % contents
}

RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitapp

l6908lay
Posts: 42
Joined: 09 Apr 2023, 05:16

Re: A helpful editing tool.

Post by l6908lay » 29 Dec 2023, 07:43

after a lot of rechecking and redoing this is probably the best updated version from previous versions. there were some issues in the logical array, clipboard function, hotkey in ctrl, autoedit, get function, variables, mostly because of renamed keys and forgotten parts from copy and paste between programs.

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability. ; Ensures a consistent starting directory.
#SingleInstance force ; this prevents the script from popping up the dialogue box warning if you start the program without shutting it down.
#MaxMem
#InstallkeybdHook
#InstallMouseHook
DetectHiddenWindows, On ; unnecessary but left just in case of future changes.

Global Cache:=% A_WorkingDir "\Cache"
if !FileExist(Cache)
	FileCreateDir, % Cache
Global Temp:=% Cache "\Temp.txt"
Global TempBack:=% Cache "\Tem.txt"
Global Settings:= % Cache "\Settings.ini"
IniRead, Directory, % Settings, Directory, Key1
if (Directory != "ERROR")
	SetWorkingDir %Directory%
else
	SetWorkingDir %A_ScriptDir% 
rawtext:= DesGet()
Global Speller:= RawTextFix(rawtext)
IniRead, WinDrop, % Settings, WinManager, Key2
if (WinDrop != "ERROR")
	WinVictive:=% WinDrop
IniRead, Editor, % Settings, Editor, Key1
if (Editor == "ERROR")
	Editor:=% "Notepad.exe"
IniRead, Rest, % Settings, Timers, Key1
If (Rest == "ERROR")
{
	IniWrite, 10000, % Settings, Timers, Key1
	Rest:= 10000
}
IniRead, Notactive, % Settings, Timers, Key2
if (Notactive == "ERROR")
{
	IniWrite, 500, % Settings, Timers, Key2
	Notactive:= 500
}
IniRead, NoDif, % Settings, Timers, Key3
if (NoDif == "ERROR")
{
	IniWrite, 25, % Settings, Timers, Key3
	NoDif:= 25
}
IniRead, Always, % Settings, AlwaysOnTop, Key1
if (Always != "ERROR")
	GuestOn:=% Always
IniRead, DefaultLoc, % Settings, WinManager, Key1

Loop, Files, *.ahk, F R
{
	IfInString, A_LoopFileName, @
		Continue
	IfNotInString, wi, % A_LoopFileName
		wi=%wi%%A_LoopFileName%|
}

Menu, AIsMenu, Add, Minimize, Minimize
Menu, Settings, Add, Default Settings, Default
Menu, Settings, Add, Timers, Timers
Menu, Settings, Add, AlwaysOnTop`ton/off, Always
Menu, Settings, Add, Suspend`ton/off, SusOnOff
Menu, Settings, Add, Reload`tCtrl+r, Reload
Menu, AIsMenu, Add, Settings, :Settings

SetTitleMatchMode, 2
CoordMode, Caret, Screen
CoordMode, Mouse, Screen
CoordMode, ToolTip, Window
if (GuestOn == 1)
	Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
else if (GuestOn == 0)
	Gui, AI:New, -AlwaysOnTop +Resize +toolWindow
else
	Gui, AI:New, +AlwaysOnTop +Resize +toolWindow
Gui, Menu, AIsMenu
Gui, Add, Edit, r1 x25 y21 w150 ReadOnly vWorking, % A_WorkingDir
Gui, Add, DropDownList, x25 y55 w150 vChangeType gChangeType, Get Variables||Get Function|Create Test File
Gui, Add, GroupBox, x25 y90 h250 w150 wrap vResults, Get variables`n(Filter results by Checkbox)
Gui, Add, ListBox, r10 yp+35  xp+15 w120 gFileSelected vFileSelected, %wi%
Gui, Add, Edit, r4 yp+150 xp -VScroll vTestInfo w120,  Select a file to create a Test.ahk file with no function or sublabeled function.
Gui, Add, Text, yp xp vFunctionLabel, input the function lablel
Gui, Add, Edit, r1 w120 vFunctionName,
Gui, Add, Checkbox, vAssociateV, Associated functions
Gui, Add, Checkbox, yp-40 xp vGui, Gui Variables
Gui, Add, Checkbox, vExplicit, Explicit Variables
Gui, Add, Checkbox, vImplicitExplicit, Implicit-Explicit
Gui, Add, Text, -E0x200 x0 y0 vButtonCountCheck w0, 0,Unknown
Gui, Add, Text, -E0x200 vWordKeeper w0, &not@a#rea1*sent3nc3s
Gui, Add, Edit,  r19 ym+45 x200 vWords w325 hwndTracker,
Gui, Add, Button, yp+1000 xp gAISave, Save
Gui, Add, Text, vAISave w0, Don't save
Gui, Add, Edit, r4 ym+45 x200 w325 ReadOnly t64 vPixMouse, (Mouse Position)`t(pixel color)`n
Gui, Add, Edit, r4 yp+70 x200 w325 ReadOnly vWinStats, x y h w (Coordinate mode)
Gui, Add, Edit, r8 yp+70 x200 w325 ReadOnly vWinText, Text on the locked screen:
Gui, Add, Button, xp+120 y317 gEmptyClip, Empty Clip
Gui, Add, Button, xp-120 yp hp wp gAISave, Save
Gui, Add, Button,xp+60 wp yp gAIClear, Clear
Gui, Add, Edit,  r1 ym+15 x200 vWindowControl w325,
Gui, Add, Text, ym+315 x470 vInformation, Loading...
Gui, Add, Text, ym+17 x550 vWindowLabel gLock +Border Center h18, %A_Space% +`t Add Window%A_Space%
Gui, Add, Edit, r19 ym+45 x550 w150 vWelcome -VScroll ReadOnly, Welcome to my program. Above you will see a Label named Add Window. This is a control bar Click it to see other controls. Left and right navigation buttons are beside it to add further Controls. To the left of the screen you will notice your "Working directory" is added in case you need to know it. below is the default editor. In the center is collected information from "Get Variables", "Functions"... It can also be a scratch pad.`n I hope you enjoy using my program. Have a Good day!
Gui, Add, Text, ym+17 x659 w20 vRightnav gRightNav +Border Center h18,
Gui, Add, Text, ym+17 x679 w20 vLeftNave gLeftNav +Border Center h18, >
Gui, Add, GroupBox, ym+50 x550 h250 w150 wrap vGroupControls, Window Controls
Gui, Add, Checkbox, yp+40 xp+10 vGetWindow gLocktoWindow, Lock Window Control
Gui, Add, Checkbox, yp+20 xp vSnapWindow gSnapToWindow, Snap to Window
Gui, Add, Checkbox, yp+20 xp vSnapToEditor gSnapToEditor, Snap to Editor
Gui, Add, Checkbox, yp+20 xp vAutoEdit gAutoEdit, Enable Auto Edit
Gui, Add, Checkbox, yp+20 xp vEnableCC gEnableCC, Enable copy anywhere
Gui, Add, Checkbox, yp+20 xp vEnableVV gEnableVV, Enable paste 2nd Clip
Gui, Add, Edit, yp+20 xp r5 w130 -VScroll ReadOnly vControlInformation, Information about the above controls
Gui, Add, Edit, yp+105 xp-10 r1 w150 -VScroll ReadOnly vDefaultEdit, % Editor
Gui, Add, DropDownList, yp-240 xp+10 w130 vCoordinateM gCoordinateM, CoordMode Screen||CoordMode Relative|CoordMode Window|CoordMode Client
Gui, Add, Checkbox, yp+30 xp vGetPix gGetPix, Get Pixel Color
Gui, Add, Checkbox, yp+20 xp vGetMouse gGetMouse, Get Mouse Pos
Gui, Add, Checkbox, yp+20 xp vGetWinS gGetWinS, Get Window Stats
Gui, Add, Checkbox, yp+20 xp vGetWinT gGetWinT, Get Window Text
Gui, Add, Checkbox, yp+20 xp vMultiSele gMultiSele, Multi-Select
Gui, Add, ListBox, yp-110 xp w130 r5 vProfList,
Gui, Add, Button, yp+75 xp w44 vProfAdd gProfAdd, Add
Gui, Add, Button, yp xp+44 hp wp vProfDele gProfDele, Delete
Gui, Add, Button, yp xp+44 hp wp vProfMod gProfMod, Modify
Gui, Add, Button, yp+23 xp-88 hp wp vProfBack gProfBack, Backup
Gui, Add, Button, yp xp+44 hp wp vProfStart gProfStart, Start
Gui, Add, Button, yp xp+44 hp wp vProfRun gProfRun, Run
Gui, Add, Text, vClipBoard1 w0 h0 x5 y5,
Gui, Add, Text, vClipBoard2 w0 h0 x5 y5,
Gui, Add, Text, vClipBoard3 w0 h0 x5 y5,
Gui, Margin, 50, 30
Gui, Color, d6d5d0, f5f4f0
Gui, Show, h400, AI work
WinGetPos , AIPosX, AIPosY, AIorignalwidth, AIorignalhieght, AI
AddWindowGroupControl("Hide")
GetWindowGroupControl("Hide")
WindowProfGroupControl("Hide")
GuiControl, AI:Hide, FunctionName
GuiControl, AI:Hide, FunctionLabel
GuiControl, AI:Hide, ControlInformation
Control, Disable, , Edit10, AI
GuiControl, AI:Hide, AssociateV
GuiControl, AI:Hide, TestInfo
Control, Disable , , Edit2, AI
Control, Disable , , Welcome, AI
Gui, Words:New, +AlwaysOnTop -SysMenu -Caption +toolWindow +Resize
Gui, Add, Listbox, r3 gWord vWord x0 y0,
Gui, margin, 0, 0
Gui, Show, , Words
GuiControl, AI:Focus, Words

contents:=HashContents(contents)
logicalhistory:= []
logicalhistory:= ProcessStart(contents, Rest)
activeuserinput:= []
navigationLR:= []
WinProfiles:=WinProf()
GuiControl, AI:, ProfList, % WinProfiles

Loop,
{
	ThisModifier(WinVictive)
	thistrack:= Tracker(thistrack, DefaultLoc, Whichone, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	if (A_TimeIdle > 3000)
	{
		thisz++
		if (thisz == 1)
			GuiControl, AI:, Information, Done
		Sleep, % Notactive
		Continue
	}
	winwonder:=WinWonder()
	if (winwonder == "False")
	{
		SpellChecker(0)
		Sleep, % Notactive
		Continue
	}
	check:=GetControl("GetKeeper")
	usersentence:=GetControl("RowText")
	if (recordkeeper == "")
		recordkeeper:=% usersentence
	if (recordkeeper != usersentence)
	{
		Doppler(usersentence, recordkeeper)
		recordkeeper:=% usersentence
	}
	getuserinput:= GetControl("Text")
	activeuserinput:=ReturnLineArray(getuserinput, "user")
	historylastline:= GetLineCount(logicalhistory)
	activeuserlastline:= GetLineCount(activeuserinput)
	if (check == "7h151s@a#res37")
	{
		If (getuserinput == "")
		{
			Sleep, % Notactive
			Continue
		}
		GuiControl, AI:, WordKeeper, &not@a#rea1*sent3nc3
		contents:=HashContents(contents)
		logicalhistory:= ProcessStart(contents, Rest)
		Continue
	}
	if (usersentence != "")
	{
		if (activeuserlastline != historylastline)
		{
			logicallastlineaddition:=(activeuserlastline-historylastline)
			logicalhistory:= FixLogicalhistory_Array(logicalhistory, logicallastlineaddition) ; where last lines are being put in. and you will also want to function in lastline (Deleted_Line) to acompany the changes. if you are lagging ApplyLogicalChange().
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, logicallastlineaddition)
		}
		if (activeuserlastline == historylastline)
			logicalhistory:= ApplyLogicalChange(activeuserinput, logicalhistory, 0)
	}
	savecheck:= GetControl("AISave")
	if (savecheck == "Save_File")
	{
		historycount:=GetLineCount(logicalhistory)
		Loop, % historycount
		{
			x++
			sentences:= logicalhistory["linePos" x]
			StringReplace, sentences, sentences, (softReturn), \|/softReturn\|/, ALL
			StringReplace, sentences, sentences, (hardReturn), \|/CR+LF\|/, ALL
			FileContents:=% FileContents sentences
		}
		FileMove, % Temp, % TempBack, 1
		FileAppend, % FileContents, % Temp, UTF-8
		GuiControl,AI:, AISave, Don't Save
	}
}
Return

ThisModifier(WinDrop)
{
	GuiControlGet, Locked, AI:, GetWindow
	GuiControlGet, WinName, AI:, WindowControl
	GuiControlGet, PixButton, AI:, GetPix
	GuiControlGet, StatButton, AI:, GetWinS
	GuiControlGet, TextButton, AI:, GetWinT
	WinGetPos , WinX, WinY, WinWidth, WinHeight, AI
	PositionSquareX:=(WinX+WinWidth)
	PositionSquareY:=(WinY+WinHeight)
	MouseGetPos, positionX, positionY
	if ((Locked == 1)&&(WinName != ""))
		if ((PixButton == 1)||(StatButton == 1)||(TextButton == 1))
			If ((positionX < WinX)||(positionX > PositionSquareX)||(positionY < WinY)||(positionY > PositionSquareY))
			{
				if ((WinVictive != "")&&(WinVictive == 0))
				{
					Hotkey, LButton, On
					Return
				}
				else
				{
					IfWinActive, % WinName
					{
						Hotkey, LButton, On
						Return
					}
				}
			}
	Hotkey, LButton, Off
	Return
}

LButton::
GuiControlGet, ThisMode , AI:, CoordinateM
GuiControlGet, WinName, AI:, WindowControl
IfWinNotActive, % WinName
	If (WinVictive == 0)
		WinActivate, % WinName
if (ThisMode == "CoordMode Screen")
{
	CoordMode, Screen , Pixel
	CoordMode, Screen , Mouse
}
if (ThisMode == "CoordMode Relative")
{
	CoordMode, Relative , Pixel
	CoordMode, Relative , Mouse
}
if (ThisMode == "CoordMode Window")
{
	CoordMode, Window , Pixel
	CoordMode, Window , Mouse
}
if (ThisMode == "CoordMode Client")
{
	CoordMode, Client , Pixel
	CoordMode, Client , Mouse
}
MouseGetPos, positionX, positionY
GuiControlGet, PixButton, AI:, GetPix
if (PixButton == 1)
{
	PixelGetColor, color,%positionX%, %positionY%
	color:=% color "`n"
}
else
	color:=% "No color`n"
if (MouseButton == 1)
	MousePos:=% positionX ", " positionY "`t"
else
	MousePos:=% "No Mouse`t"
GuiControlGet, StatButton, AI:, GetWinS
GuiControlGet, TextButton, AI:, GetWinT
GuiControlGet, Multi, AI:, MultiSele
GuiControlGet, MouseButton, AI:, GetMouse
GuiControlGet, PixMouse, AI:, PixMouse
PixMouse:= StrReplace(PixMouse, "(Mouse Position)`t(pixel color)`n", "")
if (Multi == 1)
	if ((PixButton == 1)||(MouseButton == 1))
		GuiControl, AI:, PixMouse, %  "(Mouse Position)`t(pixel color)`n" MousePos color PixMouse
if (Multi != 1)
	if ((PixButton == 1)||(MouseButton == 1))
		GuiControl, AI:, PixMouse, %  "(Mouse Position)`t(pixel color)`n" MousePos color
GuiControlGet, WinStats, AI:, WinStats
WinGetPos , WinX, WinY, WinWidth, WinHeight, % WinName
WinStats:= StrReplace(WinStats, "x y h w (Coordinate mode)", "")
if ((Multi == 1)&&(StatButton == 1))
	GuiControl, AI:, WinStats, % "x" WinX ", y" WinY ", h" WinWidth ", w" WinHeight "`t(" ThisMode ")`n" WinStats
if ((Multi != 1)&&(StatButton == 1))
	GuiControl, AI:, WinStats, % "x" WinX ", y" WinY ", h" WinWidth ", w" WinHeight "`t(" ThisMode ")"
GuiControlGet, AIWinText, AI:, WinText
TextLength:= StrLen(AIWinText)
WinGetText, WinText , % WinName
if ((TextLength <= 26)&&(WinText != "")&&(TextButton == 1))
	GuiControl, AI:, WinText, % WinText
CoordMode, Screen, Pixel
CoordMode, Screen, Mouse
Return

~LCtrl::
thiskeystate:= GetKeyState("LCtrl", P)
if (thiskeystate != 0)
{
	GuiControlGet, EnableCC, AI:, EnableCC
	GuiControlGet, EnableVV, AI:, EnableVV
	CtrlC := Chr(3)
	CrlV:= Chr(22)
	CtrlVV:= CrlV CrlV
	CtrlVVV:= CrlV CrlV CrlV
	Loop,
	{
		Input, userinput, L3 T0.75 M ; this has a 0.75 second timer... That feels a little natural. however on the person to person scale this might need adjusted.
		if (EnableVV == 1)
		{
			GuiControlGet, saveclip2, AI:, ClipBoard2
			GuiControlGet, saveclip3, AI:, ClipBoard3
			if (userinput == CtrlVV)
			{
				Send, % saveclip2
				Continue
			}
			else if (userinput == CtrlVVV)
			{
				Send, % saveclip3
				Continue
			}
			else if (userinput == CrlV)
			{
				Send, % ClipBoard
				Continue
			}
		}
		else if ((userinput == CtrlC CtrlC)&&(EnableCC == 1))
		{
			logicalhistorylastline:= GetLineCount(logicalhistory)
			Loop, % logicalhistorylastline
			{
				thisx++
				saveline:= logicalhistory["linePos" thisx]
				saveline:=StrReplace(saveline, "(hardReturn)(hardReturn)", " (hardReturn)")
				saveline:= StrReplace(saveline, "(softReturn)(softReturn)", " (softReturn)")
				saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
				saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
				thesecontents.= saveline
			}
			thesecontents:= SpecialReplace(thesecontents)
			MsgBox, 262144, Message on Control+cc, % "The edit fields are ready to be sent. It autosends after this message. After you learn how this works you can delete this messge box. Make sure the place you want your text sent is +lastfound"
			Send, % thesecontents
			thisx:=
			thesecontents:=
			Continue
		}
		else if (userinput == CtrlC)
		{
			Send, ^c
			ClipBoardFunction()
			Continue
		}
		else
			Send, ^%userinput%
		thiskeystate:= GetKeyState("LCtrl", P)
		if (thiskeystate == 0)
			Break
	}
}
Return

ClipBoardFunction()
{
	GuiControlGet, saveclip1, AI:, ClipBoard1
	GuiControlGet, saveclip2, AI:, ClipBoard2
	GuiControlGet, saveclip3, AI:, ClipBoard3
	if ((ClipBoard != "")||(ClipBoard != saveclip1))
	{
		if (saveclip2 != "")
			saveclip3:=% saveclip2
		if (saveclip1 != "")
			saveclip2:=% saveclip1
		if (ClipBoard != saveclip1)
			saveclip1:=% ClipBoard
	}
	if (saveclip1 != "")
		GuiControl,AI:, ClipBoard1, % saveclip1
	if (saveclip2 != "" )
		GuiControl,AI:, ClipBoard2, % saveclip2
	if (saveclip3 != "" )
		GuiControl,AI:, ClipBoard3, % saveclip3
	Return
}

$Backspace::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Backspace}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Backspace}
	}
	Return
}
else
	Send, {Backspace}
Return

$Space::
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  {Space}, AI
	}
	else
	{
		check:=GetControl("GetKeeper")
		if (check != "&not@a#rea1*sent3nc3")
			GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		recordkeeper:= ""
		Send, {Space}
	}
	Return
}
else
	Send, {Space}
Return

$Tab::
Word:
winwonder:=WinWonder()
if (winwonder != "False")
{
	WinGet, visible, Transparent, Words
	if (visible != 0)
	{
		check:=GetControl("GetKeeper")
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 2)
				userword:=% chec
		}
		str:= StrLen(userword)
		correctword:= GetControl("Word")
		InFocus:= GetControl("Focus")
		ControlSend, % InFocus,  +{Left %str%}%correctword%, AI
		GuiControl, AI:, WordKeeper, % "&not@a#rea1*sent3nc3"
		SpellChecker(0)
		recordkeeper:= ""
	}
	else
	{
		Send, `t
	}
	Return
}
else
	Send, `t
Return

~+Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	GuiControlGet, AutoEdit, AI:, AutoEdit
	If (AutoEdit == 1)
	{
		logicalhistorylastline:= GetLineCount(logicalhistory)
		Loop, % logicalhistorylastline
		{
			thisx++
			saveline:= logicalhistory["linePos" thisx]
			saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
			saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
			thesecontents.= saveline
		}
		thesecontents:= SpecialReplace(thesecontents)
		GuiControlGet, wintitle, AI:, WindowControl, WindowControl
		if (wintitle == "")
		{
			MsgBox, 262144, Lock to window, Please lock to a window first
			Return
		}
		IfWinNotActive, % wintitle
			WinActivate, % wintitle
		Send, % thesecontents "+{Enter}"
		GuiControl, AI:, Words,
		logicalhistory:=[]
		thisx:=
		thesecontents:=
	}
	else if (AutoEdit == 0)
	{
		ButtonCountCheck:= GetControl("ButtCount")
		PressCount:=GetButtonCount(ButtonCountCheck)
		PressCount++
		WhichButtonCount:=% PressCount ",ShiftEnter"
		GuiControl, AI:, ButtonCountCheck, % WhichButtonCount
		KeyWait, Backspace, U
		GetButton_Count()
	}
}
Return

~Enter::
winwonder:=WinWonder()
if (winwonder != "False")
{
	GuiControlGet, AutoEdit, AI:, AutoEdit
	If (AutoEdit == 1)
	{
		logicalhistorylastline:= GetLineCount(logicalhistory)
		Loop, % logicalhistorylastline
		{
			thisx++
			saveline:= logicalhistory["linePos" thisx]
			saveline:=StrReplace(saveline, "(hardReturn)", " [Enter](hardReturn)")
			saveline:= StrReplace(saveline, "(softReturn)", " [ShiftEnter](softReturn)")
			thesecontents.= saveline
		}
		thesecontents:= SpecialReplace(thesecontents)
		GuiControlGet, wintitle, AI:, WindowControl, WindowControl
		if (wintitle == "")
		{
			MsgBox, 262144, Lock to window, Please lock to a window first
			Return
		}
		IfWinNotActive, % wintitle
			WinActivate, % wintitle
		Send, % thesecontents "{Enter}"
		WinActivate, AI
		GuiControl, AI:, Words,
		logicalhistory:=[]
		thisx:=
		thesecontents:=
	}
	else if (AutoEdit == 0) ;
	{
		ButtonCountCheck:= GetControl("ButtCount")
		PressCount:=GetButtonCount(ButtonCountCheck)
		PressCount++
		WhichButtonCount:=% PressCount ",Enter"
		GuiControl,AI:, ButtonCountCheck, % WhichButtonCount
		KeyWait, Backspace, U
		GetButton_Count()
	}
}
Return

SpecialReplace(thesecontents)
{
	fixedcharacters:= StrReplace(thesecontents, "!", "{!}")
	fixedcharacters:= StrReplace(fixedcharacters, "#", "{#}")
	fixedcharacters:= StrReplace(fixedcharacters, "+", "{+}")
	fixedcharacters:= StrReplace(fixedcharacters, "^", "{^}")
	fixedcharacters:= StrReplace(fixedcharacters, "{", "{{}") ; if this is done then output will be {{}
	fixedcharacters:= StrReplace(fixedcharacters, "}", "{}}") ; from the above if this is done output will be {{{}}
	fixedcharacters:= StrReplace(fixedcharacters, "{{{}}", "{{}")
	Sleep, 50
	Tabcontrol:= StrSplit(fixedcharacters, ["(hardReturn)", "(softReturn)"])
	for index, Tabs in Tabcontrol
	{
		IfinString, Tabs, % "`t" ; <----- it is assumed the editor you're using controls tab.
		{
			thiscount:= StrReplace(Tabs, "`t", "", thismany)
			thisstring:=% thiscount
			if (thismany != thatmany)
			{
				if (thismany > thatmany)
				{
					n:=(thismany-thatmany)
					thisbutton:=% "{Tab " n "}"
				}
				if (thismany < thatmany)
				{
					n:=(thatmany-thismany)
					thisbutton:=% "{Backspace " n "}"
				}
			}
		}
		IfNotInString, Tabs, % "`t"
		{
			if (thismany > 1)
				thisbutton:=% "{Backspace " n "}"
			else if (thismany == 1)
			{
				thismany:=0
				thisbutton:=% "{Backspace}"
			}
			else if (thismany == 0)
				thisbutton:=% ""
			thisstring:=% Tabs
		}
		thatmany:=% thismany
		edittext.= thisbutton thisstring
		thisbutton:= ""
	}
	edittext:= StrReplace(edittext, "[Enter]", "{Backspace}{Enter}")
	edittext:= StrReplace(edittext, "[ShiftEnter]", "{Backspace}+{Enter}")
	Return % edittext
}

EmptyClip:
GuiControl,AI:, ClipBoard2,
GuiControl,AI:, ClipBoard3,
GuiControl, AI:, ClipBoard1
ClipBoard:= ""
Return


ProfList:
Gui, Submit, NoHide
Return

ProfAdd:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This adds the current locked window and all the settings, text, and get tools information and saves it.
if (WindowControl != "")
{
	FormatTime, time, , YWeek
	NTime.= time
	FormatTime, time, , ddhhmmss
	NTime.= time
	historycount:=GetLineCount(logicalhistory)
	WindowControl:=StrReplace(WindowControl, "|", "{This-Pipe}")
	Loop, % historycount
	{
		x++
		sentences:= logicalhistory["linePos" x]
		sentences:= StrReplace(sentences, "(softReturn)(softReturn)", "(softReturn)")
		sentences:= StrReplace(sentences, "(hardReturn)(hardReturn)", "(hardReturn)")
		sentences:= StrReplace(sentences, "(softReturn)", "\|/softReturn\|/")
		sentences:= StrReplace(sentences, "(hardReturn)", "\|/CR+LF\|/")
		FileContents:=% FileContents sentences
	}
	Spliter:=% "&not@a#rea1*??sent3nc3"
	EndSplit:=% "[End-Splitter-Loop]"
	SaveData:=% WindowControl Spliter NTime Spliter GetWindow Spliter SnapWindow Spliter SnapToEditor Spliter AutoEdit Spliter EnableCC Spliter EnableVV Spliter PixMouse Spliter WinStats Spliter WinText Spliter FileContents Spliter CoordinateM Spliter GetPix Spliter GetMouse Spliter GetWinS Spliter GetWinT Spliter MultiSele Spliter RunProgramName EndSplit
	GuiControl, AI:, ProfList, % WindowControl "`t" NTime "|"
	SaveData:= StrReplace(SaveData, "`n", "\|/MyReturns\|/")
	FileAppend, % SaveData, % Cache "\Profiles.Storage", UTF-8
	GuiControl, Choose, AI:ProfList, 0
	Ntime:=
}
else
	MsgBox, 262144, Please lock to a window., Please first lock to a window.
Return

ProfDele:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This deletes a selected profile entry.
if (ProfList != "")
{
	profdate:= StrSplit(ProfList, "`t")
	for index, prof in profdate
	{
		if (Index == 1)
			thisprof:=% prof
		if (Index == 2)
			thisdate:=% prof
	}
	thisprof:=StrReplace(thisprof, "|", "{This-Pipe}")
	FileRead, contents, % Cache "\Profiles.Storage"
	if (ErrorLevel == 0)
	{
		Profiles:= StrSplit(contents, "[End-Splitter-Loop]")
		for index, profile in profiles
		{
			profilestrings:= StrSplit(profile, "&not@a#rea1*??sent3nc3")
			for index, profilepart in profilestrings
			{
				if (index == 1)
					name:=% profilepart
				if (index == 2)
					date:=% profilepart
			}
			if ((thisdate != date)&&(name != thisprof))
			{
				IfNotInString, updatedlist, % name "`t" date "|"
					updatedlist.= name "`t" date "|"
				Currentlist.= profile "[End-Splitter-Loop]"
			}
		}
		if (updatedlist == "")
			updatedlist.= "|"
		GuiControl, AI:, ProfList, % "|" updatedlist
		FileMove, % Cache "\Profiles.Storage", % TempBack, 1
		FileAppend, % Currentlist, % Cache "\Profiles.Storage", UTF-8
		GuiControl, Choose, AI:ProfList, 0
	}
}
else
	MsgBox, 262144, Please select, Please select a profile to delete.
updatedlist:= 
Currentlist:= 
Return

ProfMod:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This allows a user to modify a selected profile entry.
if (ProfList != "")
{
	profdate:= StrSplit(ProfList, "`t")
	for index, prof in profdate
	{
		if (Index == 1)
			thisprof:=% prof
		if (Index == 2)
			thisdate:=% prof
	}
	thisprof:=StrReplace(thisprof, "|", "{This-Pipe}")
	FileRead, contents, % Cache "\Profiles.Storage"
	if (ErrorLevel == 0)
	{
		Profiles:= StrSplit(contents, "[End-Splitter-Loop]")
		for index, profile in Profiles
		{
			profilestrings:= StrSplit(profile, "&not@a#rea1*??sent3nc3")
			for index, profilepart in profilestrings
			{
				if (index == 1)
					name:=% profilepart
				if (index == 2)
					date:=% profilepart
			}
			if ((thisdate == date)&&(name == thisprof))
			{
				thismod:=% profile
				break
			}
		}
	}
}
else
{
	MsgBox, 262144, Please select, Please select a profile to modify.
	Return
}
Gui, Modify:New, +AlwaysOnTop +Resize +toolWindow
ModArray:=[]
thesemods:= StrSplit(thismod, "&not@a#rea1*??sent3nc3")
for index, mods in thesemods
	ModArray[Index]:= mods
windowmod:= ModArray[1]
windowmod:=StrReplace(windowmod, "{This-Pipe}", "|")
Gui, Add, Edit, xm+20 vModWindow w300 r1, % windowmod
timemod:= ModArray[2]
Gui, Add, Edit, vModTime w100, % timemod
windowbutton:= ModArray[3]
Gui, Add, Checkbox, ym+30 xm+170 vModlock checked%windowbutton%, Locked to window
SnapWindowMod:= ModArray[4]
Gui, Add, Checkbox, vModWindowSnap checked%SnapWindowMod%,  Snap to window
SnapToEditorMod:= ModArray[5]
Gui, Add, Checkbox, vModSnapToEditor checked%SnapToEditorMod%, Snap to editor
AutoEditMod:= ModArray[6]
Gui, Add, Checkbox, vModAutoEdit checked%AutoEditMod%, Auto Edit
EnableCCMod:= ModArray[7]
Gui, Add, Checkbox, vModEnableCC checked%EnableCCMod%, Enable copy anywhere
EnableVVMod:= ModArray[8]
Gui, Add, Checkbox, vModEnableVV checked%EnableVVMod%, Enable paste 2nd Clip
PixMouseMod:= ModArray[9]
Gui, Add, Edit, ym+55 xm+20 vModPixMouse ReadOnly w112 r1, % PixMouseMod
WinStatsMod:= ModArray[10]
Gui, Add, Edit, vModWinStats ReadOnly wp r1, % WinStatsMod
WinTextMod:= ModArray[11]
Gui, Add, Edit, vModWinText ReadOnly wp r1, % WinTextMod
FileContentsMod:= ModArray[12]
Gui, Add, Edit, vModFileContents ReadOnly wp r1, % FileContentsMod
CoordinateMMod:= ModArray[13]
coordslistm:=% "CoordMode Screen`nCoordMode Relative`nCoordMode Window`nCoordMode Client"
Loop, Parse, % coordslistm, `n
{
	if (A_LoopField == CoordinateMMod)
		coordslist.= A_LoopField "||"
	else
		coordslist.= A_LoopField "|"
}
Gui, Add, DropDownList, vModCoordinateM, % coordslist
coordslist:=
GetPixMod:= ModArray[14]
Gui, Add, Checkbox, vModGetPix checked%GetPixMod%, Get Pixel Color
GetMouseMod:= ModArray[15]
Gui, Add, Checkbox, vModGetMouse checked%GetMouseMod%, Get Mouse Pos
GetWinSMod:= ModArray[16]
Gui, Add, Checkbox, vModGetWinS checked%GetWinSMod%, Get Window Stats
GetWinTMod:= ModArray[17]
Gui, Add, Checkbox, vModGetWinT checked%GetWinTMod%, Get Window Text
MultiSeleMod:= ModArray[18]
Gui, Add, Checkbox, vModMultiSele checked%MultiSeleMod%, Multi-Select
RunProgramNameMod:= ModArray[19]
Gui, Add, Edit, vModRunProgramName w145 r1,
Gui, Add, Button, gPixMouseClear ym+55 xm+129 hp, Clear
Gui, Add, Button, gWinStatsClear hp, Clear
Gui, Add, Button, gTextModClear hp, Clear
Gui, Add, Button, gFileContentsClear hp, Clear
Gui, Add, Edit, vModInformation -VScroll ReadOnly r9 ym+150 xm+170 w145, This is a quick snapshot of this profile saved. Review the data clear text, change check box selections, add run program installer, even edit the profile's win title. After modifications are made click update at the bottom to save the changes.
Gui, Add, Edit, vProgramLoad -VScroll ReadOnly r1 ym+285 xm+170 w100, run program *.EXE
Gui, Add, Button, gUpdater xm+270 yp hp, Update
Gui, Color, d6d5d0, f5f4f0
Gui, Margin, 20, 20
Gui, Show, , Modifications
Control, Disable, , Edit9, Modifications
Control, Disable, , Edit8, Modifications
ModArray:=[]
thismod:= ""
contents:= ""
Return

PixMouseClear:
Gui, Submit, NoHide
GuiControl, Modify:, ModPixMouse, 
Return

WinStatsClear:
Gui, Submit, NoHide
GuiControl, Modify:, ModWinStats, 
Return

TextModClear:
Gui, Submit, NoHide
GuiControl, Modify:, ModWinText, 
Return

FileContentsClear:
Gui, Submit, NoHide
GuiControl, Modify:, ModFileContents, 
Return

Updater:
Gui, Submit, NoHide
if (ProfList != "")
{
	Spliter:=% "&not@a#rea1*??sent3nc3"
	EndSplit:=% "[End-Splitter-Loop]"
	IfinString, ModWindow, |
		ModWindow:=StrReplace(ModWindow, "|", "{This-Pipe}")
	SaveData:=% ModWindow Spliter ModTime Spliter Modlock Spliter ModWindowSnap Spliter ModSnapToEditor Spliter ModAutoEdit Spliter ModEnableCC Spliter ModEnableVV Spliter ModPixMouse Spliter ModWinStats Spliter ModWinText Spliter ModFileContents Spliter ModCoordinateM Spliter ModGetPix Spliter ModGetMouse Spliter ModGetWinS Spliter ModGetWinT Spliter ModMultiSele Spliter ModRunProgramName EndSplit
	profdate:= StrSplit(ProfList, "`t")
	for index, prof in profdate
	{
		if (Index == 1)
			thisprof:=% prof
		if (Index == 2)
			thisdate:=% prof
	}
	FileRead, contents, % Cache "\Profiles.Storage"
	if (ErrorLevel == 0)
	{
		Profiles:= StrSplit(contents, "[End-Splitter-Loop]")
		for index, profile in Profiles
		{
			profilestrings:= StrSplit(profile, "&not@a#rea1*??sent3nc3")
			for index, profilepart in profilestrings
			{
				if (index == 1)
					name:=% profilepart
				if (index == 2)
					date:=% profilepart
			}
			if ((thisdate != date)&&(name != thisprof))
			{
				IfNotInString, updatedlist, % name "`t" date "|"
					updatedlist.= name "`t" date "|"
				IfNotInString, Currentlist, % profile
					Currentlist.= profile "[End-Splitter-Loop]"
			}
			else if ((thisdate == date)&&(name == thisprof))
			{
				IfNotInString, updatedlist, % ModWindow "`t" ModTime "|"
				{
					ModWindow:=StrReplace(ModWindow, "|", "{This-Pipe}")
					updatedlist.= ModWindow "`t" ModTime "|"
				}
				IfNotInString, Currentlist, % SaveData
					Currentlist.= SaveData
			}
		}
		if (updatedlist == "")
			updatedlist.= "|"
		GuiControl, AI:, ProfList, % "|" updatedlist
		FileMove, % Cache "\Profiles.Storage", % TempBack, 1
		FileAppend, % Currentlist, % Cache "\Profiles.Storage", UTF-8
		GuiControl, Choose, AI:ProfList, 0
	}
	Currentlist.= 
	updatedlist:=
	Gui, Modify:Destroy
}
Return

ModifyGuiClose:
Gui, Modify:Destroy
Return

ProfBack:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This backs up the profile entries to a readable txt file in the %A_ScriptDir%. Also Note it does not overwrite it.
Spliter:=% "&not@a#rea1*??sent3nc3"
EndSplit:=% "[End-Splitter-Loop]"
FileRead, contents, % Cache "\Profiles.Storage"
if (ErrorLevel == 0)
{
	Profiles:= StrSplit(contents, "[End-Splitter-Loop]")
	for index, profile in profiles
	{
		profile:=StrReplace(profile, "{This-Pipe}", "|")
		profilestrings:= StrSplit(profile, "&not@a#rea1*??sent3nc3")
		for index, profilepart in profilestrings
		{
			if (index == 1)
				profilepart:=StrReplace(profilepart, "{This-Pipe}", "|")
			profiles.= profilepart "`n"
		}
		profiles.= "`n"
	}
	FileAppend, % profiles, % A_ScriptDir "\Backup.txt", UTF-8
	GuiControl, Choose, AI:ProfList, 0
}
Return

ProfStart:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This sets the Gui to the settings of the profile selected.
if (ProfList != "")
{
	profdate:= StrSplit(ProfList, "`t")
	for index, prof in profdate
	{
		if (Index == 1)
			thisprof:=% prof
		if (Index == 2)
			thisdate:=% prof
	}
	thisprof:=StrReplace(thisprof, "|", "{This-Pipe}")
	FileRead, contents, % Cache "\Profiles.Storage"
	if (ErrorLevel == 0)
	{
		Profiles:= StrSplit(contents, "[End-Splitter-Loop]")
		for index, profile in Profiles
		{
			profilestrings:= StrSplit(profile, "&not@a#rea1*??sent3nc3")
			for index, profilepart in profilestrings
			{
				if (index == 1)
					name:=% profilepart
				if (index == 2)
					date:=% profilepart
			}
			if ((thisdate == date)&&(name == thisprof))
			{
				thismod:=% profile
				Break
			}
		}
	}
}
else
{
	MsgBox, 262144, Please select, Please select a profile to Start.
	Return
}
ModArray:=[]
thesemods:= StrSplit(thismod, "&not@a#rea1*??sent3nc3")
for index, mods in thesemods
	ModArray[Index]:= mods
windowmod:= ModArray[1]
windowmod:=StrReplace(windowmod, "{This-Pipe}", "|")
GuiControl, AI:, WindowControl, % windowmod
if (windowmod != "")
	GuiControl, Disable, WindowControl
windowbutton:= ModArray[3]
GuiControl, AI:, GetWindow, % windowbutton
SnapWindowButton:= ModArray[4]
GuiControl, AI:, SnapWindow, % SnapWindowButton
SnapEditorButton:= ModArray[5]
GuiControl, AI:, SnapToEditor, % SnapEditorButton
AutoEditButton:= ModArray[6]
GuiControl, AI:, AutoEdit, % AutoEditButton
EnableCCButton:= ModArray[7]
GuiControl, AI:, EnableCC, % EnableCCButton
EnableVVButton:= ModArray[8]
GuiControl, AI:, EnableVV, % EnableVVButton
PixMouseEdit:= ModArray[9]
PixMouseEdit:= StrReplace(PixMouseEdit, "\|/MyReturns\|/", "`n")
GuiControl, AI:, PixMouse, % PixMouseEdit
WinStatsEdit:= ModArray[10]
WinStatsEdit:= StrReplace(WinStatsEdit, "\|/MyReturns\|/", "`n")
GuiControl, AI:, WinStats, % WinStatsEdit
WinTextEdit:= ModArray[11]
WinTextEdit:= StrReplace(WinTextEdit, "\|/MyReturns\|/", "`n")
GuiControl, AI:, WinText, % WinTextEdit
FileContentsMod:= ModArray[12]
logicalhistory:= []
fix:=
StringReplace, FileContentsMod, FileContentsMod, \|/CR+LF\|/,(hardReturn)\|/CR+LF\|/, ALL
StringReplace, FileContentsMod, FileContentsMod, \|/SoftReturn\|/, (softReturn)\|/SoftReturn\|/, ALL
logicalfix:= StrSplit(FileContentsMod, ["\|/CR+LF\|/","\|/softReturn\|/"])
for index, logical in logicalfix
	logicalhistory["linePos" Index]:= logical
FileContentsMod:= StrReplace(FileContentsMod, "(hardReturn)\|/CR+LF\|/", "`n")
FileContentsMod:= StrReplace(FileContentsMod, "(softReturn)\|/SoftReturn\|/", "`n")
GuiControl, AI:, Words, % FileContentsMod
CoordinateMMod:= ModArray[13]
coordslistm:=% "CoordMode Screen`nCoordMode Relative`nCoordMode Window`nCoordMode Client"
Loop, Parse, % coordslistm, `n
{
	if (A_LoopField == CoordinateMMod)
		coordslist.= A_LoopField "||"
	else
		coordslist.= A_LoopField "|"
}
GuiControl, AI:, CoordinateM, % "|" coordslist
coordslist:=
GetPixButton:= ModArray[14]
GuiControl, AI:, GetPix, % GetPixButton
GetMouseButton:= ModArray[15]
GuiControl, AI:, GetMouse, % GetMouseButton
GetWinSButton:= ModArray[16]
GuiControl, AI:, GetWinS, % GetWinSButton
GetWinTButton:= ModArray[17]
GuiControl, AI:, GetWinT, % GetWinTButton
MultiSeleButton:= ModArray[18]
GuiControl, AI:, MultiSele, % MultiSeleButton
GuiControl, Choose, AI:ProfList, 0
Return

ProfRun:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This runs the associated program to the named entry (Modify may need to be used to make this work).
if (ProfList != "")
{
	profdate:= StrSplit(ProfList, "`t")
	for index, prof in profdate
	{
		if (Index == 1)
			thisprof:=% prof
		if (Index == 2)
			thisdate:=% prof
	}
	FileRead, contents, % Cache "\Profiles.Storage"
	if (ErrorLevel == 0)
	{
		Profiles:= StrSplit(contents, "[End-Splitter-Loop]")
		for index, profile in Profiles
		{
			profilestrings:= StrSplit(profile, "&not@a#rea1*??sent3nc3")
			for index, profilepart in profilestrings
			{
				if (index == 1)
					name:=% profilepart
				if (index == 2)
					date:=% profilepart
			}
			if ((name == thisprof)&&(thisdate == date))
			{
				thismod:=% profile
				Break
			}
		}
	}
}
else
{
	MsgBox, 262144, Please select, Please select a profile to Run.
	Return
}
ModArray:=[]
thesemods:= StrSplit(thismod, "&not@a#rea1*??sent3nc3")
for index, mods in thesemods
	ModArray[Index]:= mods
runinstaller:= ModArray[19]
if (runinstaller == "")
{
	MsgBox, 262144, Error Modify, There currently is no way to run the program.
	Return
}
Run, % runinstaller
GuiControl, Choose, AI:ProfList, 0
Return

EnableVV:
GuiControl, AI:, ControlInformation, This enables paste from second and third ClipBoard. {LCtrl}+vv and {LCtrl}+vvv. if clipboard2 or 3 sends acsii code
Return

SnapToWindow:
GuiControl, AI:, ControlInformation, This will place the Main Gui in one of 9 locations on the locked window.
GuiControl, AI:, SnapToEditor, 0
IniRead, DefaultLoc, % Settings, WinManager, Key1
GuiControlGet, fullwindow, AI:, WindowControl
if (fullwindow == "")
{
	MsgBox, 262144, Please lock to a window., Please first lock to a window.
	GuiControl, AI:, SnapWindow, 0
	Return
}
GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
Return
	

SnapToEditor:
GuiControl, AI:, ControlInformation, This will place the Main Gui in one of 9 locations on the editor. Notepad is Default.
GuiControlGet, DefaultEdit, AI:, DefaultEdit
GuiControl, AI:, SnapWindow, 0
IfInString, DefaultEdit, .
{
	windows:= StrSplit(DefaultEdit, ".")
	for index, window in windows
		if (index == 1)
			thiswindow:=% window
}
WinGetTitle, fullwindow, % "ahk_class" thiswindow
if (fullwindow == "")
{
	MsgBox, 4, Window Not Found!, % "The current Editor is not open:`nahk_class " thiswindow "`nWould you like to open it?"
	IfMsgBox Yes
		run, % DefaultEdit
	IfMsgBox No
		Return
	Loop,
	{
		Sleep, 150 ; prevent needless process
		WinGetTitle, fullwindow, % "ahk_class" thiswindow
		if (fullwindow != "")
			Break
		x++
		if (x > 15)
		{
			MsgBox, There is an error opening the window or a naming error.
			Return
		}
	}
}
IfWinExist, % fullwindow
{
	IniRead, DefaultLoc, % Settings, WinManager, Key1
	GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
}
Return

AutoEdit:
GuiControl, AI:, ControlInformation, On Enter ({Enter} or +{Enter} this button sends to your default editor if it's active and Clears the window.
Return

EnableCC:
GuiControl, AI:, ControlInformation, This activates {LCtrl}+cc when you press that (anywhere) main edit contents are autosent to insert location.
Return

LocktoWindow:
Gui, Submit, NoHide
GuiControl, AI:, ControlInformation, This button locks the Gui to a running window. Just activate the window you want.
if (GetWindow == 1)
{
	WinGetActiveTitle, checkthistitle
	GuiControl, AI:, WindowControl, Select a window to lock to.
	Loop,
	{
		WinGetActiveTitle, newtitletocheck
		if (newtitletocheck == "")
			Continue
		if (checkthistitle != newtitletocheck)
			Break
	}
	GuiControl, AI:, WindowControl, % newtitletocheck
	GuiControl, Disable, WindowControl
}
if (GetWindow == 0)
{
	GuiControl, AI:, WindowControl,
	GuiControl, Enable, WindowControl
	GuiControl, AI:, SnapWindow, 0
}
Return

CoordinateM:
Gui, Submit, NoHide
if (CoordinateM == "CoordMode Screen")
	GuiControl, AI:, ControlInformation, Coordinates are relative to the Entire Screen.
if (CoordinateM == "CoordMode Relative")
	GuiControl, AI:, ControlInformation, Coordinates are relative to the Active Window
if (CoordinateM == "CoordMode Window")
	GuiControl, AI:, ControlInformation, Same as Relative and Recommended for clarity
if (CoordinateM == "CoordMode Client")
	GuiControl, AI:, ControlInformation, Coordinates are relative to the active client area minus title bar or menu. Look this up in autohokey for specifics.
Return

GetPix:
GuiControl, AI:, ControlInformation, This enables get pixel color to the locked screen on click. Make sure you are using the mode you prefer.
Return

GetMouse:
GuiControl, AI:, ControlInformation, This enables get Mouse Pos on click to the locked window. Make sure you are using the mode you prefer.
Return

GetWinS:
GuiControl, AI:, ControlInformation, This will provide the locked windows height width and left corner x and y positions.
Return

GetWinT:
GuiControl, AI:, ControlInformation, This will give the text to the locked window (hidden and seen). 
Return

MultiSele:
GuiControl, AI:, ControlInformation, In the event you need more than one color or mouse position enable this to record multiple clicks.
Return

RightNav:
Gui, Submit, NoHide
LeftNav:
Gui, Submit, NoHide
GuiControlGet, thislabelmenu, AI:, WindowLabel
IfInString, thislabelmenu, +
{
	IfInString, thislabelmenu, Add Window
		AddWindow:= 0
	IfInString, thislabelmenu, Get Tools
		GetTools:= 0
	IfinString, thislabelmenu, Window Profiles
		WindowProfs:= 0
}
IfInString, thislabelmenu, -
{
	IfInString, thislabelmenu, Add Window
		AddWindow:= 1
	IfInString, thislabelmenu, Get Tools
		GetTools:= 1
	IfinString, thislabelmenu, Window Profiles
		WindowProfs:= 1
}
If (A_ThisLabel == "RightNav")
{
	IfinString, thislabelmenu, Get Tools
	{
		labelname:= StrReplace(thislabelmenu, "`t      Get Tools", "`t Add Window")
		if ((AddWindow == "")||(AddWindow == 0))
		{
			labelname:= StrReplace(labelname, "-", "+")
			GetWindowGroupControl("Hide")
			AddWindowGroupControl("Hide")
			GuiControl, AI:, Welcome, Welcome to my program. Above you will see a Label named Add Window. This is a control bar Click it to see other controls. Left and right navigation buttons are beside it to add further Controls. To the left of the screen you will notice your "Working directory" is added in case you need to know it. below is the default editor. In the center is collected information from "Get Variables", "Functions"... It can also be a scratch pad.`n I hope you enjoy using my program. Have a Good day!
			GuiControl, AI:Focus, Words
		}
		if (AddWindow == 1)
		{
			labelname:= StrReplace(labelname, "+", "-")
			GetWindowGroupControl("Hide")
			AddWindowGroupControl("Show")
			GuiControl, AI:Focus, Words
		}
		GuiControl, AI:, RightNav,
		GuiControl, AI:Show, Words
		GuiControl, AI:, WindowLabel, % labelname
	}
	IfinString, thislabelmenu, Window Profiles
	{
		labelname:= StrReplace(thislabelmenu, "     Window Profiles", "`t      Get Tools")
		if ((GetTools == "")||(GetTools == 0))
		{
			labelname:= StrReplace(labelname, "-", "+")
			WindowProfGroupControl("Hide")
			GetWindowGroupControl("Hide")
			GuiControl, AI:, Welcome, This is where a variety of "Get" tools are located. First you have to have the window locked and acitve before the dropper tool will work. I plan to add that in the settings so it can automatically activate the window. Your mouse will be disabled until you either deactivate the window locked, unlock the window, deselect all tools (except multi-select). It will work in minimized mode too. At this point to clear you have to restart.
		}
		if (GetTools == 1)
		{
			labelname:= StrReplace(labelname, "+", "-")
			WindowProfGroupControl("Hide")
			GetWindowGroupControl("Show")
		}
		GuiControl, AI:, WindowLabel, % labelname
		GuiControl, AI:Hide, Words
	}
}
If (A_ThisLabel == "LeftNav")
{
	IfinString, thislabelmenu, Add Window
	{
		labelname:= StrReplace(thislabelmenu, "`t Add Window", "`t      Get Tools")
		if ((GetTools == "")||(GetTools == 0))
		{
			labelname:= StrReplace(labelname, "-", "+")
			AddWindowGroupControl("Hide")
			GetWindowGroupControl("Hide")
			GuiControl, AI:, Welcome, This is where a variety of "Get" tools are located. First you have to have the window locked and acitve before the dropper tool will work. I plan to add that in the settings so it can automatically activate the window. Your mouse will be disabled until you either deactivate the window locked, unlock the window, deselect all tools (except multi-select). It will work in minimized mode too. At this point to clear you have to restart.
		}
		if (GetTools == 1)
		{
			labelname:= StrReplace(labelname, "+", "-")
			AddWindowGroupControl("Hide")
			GetWindowGroupControl("Show")
		}
		GuiControl, AI:, WindowLabel, % labelname
		GuiControl, AI:, RightNav, <
		GuiControl, AI:Hide, Words
	}
	IfinString, thislabelmenu, Get Tools
	{
		labelname:= StrReplace(thislabelmenu, "`t      Get Tools", "     Window Profiles")
		if ((WindowProfs == "")||(WindowProfs == 0))
		{
			labelname:= StrReplace(labelname, "-", "+")
			GetWindowGroupControl("Hide")
			WindowProfGroupControl("Hide")
			GuiControl, AI:, Welcome, This is where window Profiles will be stored saved or deleted. It is assumed that a user may work on a window for more than one day and want a log of the data they aquired using this (or even a default setup for a particular window). This section will store that data and recall the settings, data, and editboxes.
			GuiControl, AI:Focus, Words
		}
		if (WindowProfs == 1)
		{
			labelname:= StrReplace(labelname, "+", "-")
			GetWindowGroupControl("Hide")
			WindowProfGroupControl("Show")
			GuiControl, AI:Focus, Words
		}
		GuiControl, AI:, WindowLabel, % labelname
		GuiControl, AI:Show, Words
	}
}
labelname:= ""
Return

Lock:
GuiControl, AI:, ControlInformation, Information about the above controls
GuiControlGet, thislabelmenu, AI:, WindowLabel
IfInString, thislabelmenu, Add Window
{
	IfInString, thislabelmenu, +
	{
		labelname:= StrReplace(thislabelmenu, "+", "-")
		GetWindowGroupControl("Hide")
		AddWindowGroupControl("Show")
		GuiControl, AI:, WindowLabel, % labelname
	}
	IfInString, thislabelmenu, -
	{
		labelname:= StrReplace(thislabelmenu, "-", "+")
		GetWindowGroupControl("Hide")
		AddWindowGroupControl("Hide")
		GuiControl, AI:, WindowLabel, % labelname
	}
}
IfInString, thislabelmenu, Get Tools
{
	IfInString, thislabelmenu, +
	{
		labelname:= StrReplace(thislabelmenu, "+", "-")
		AddWindowGroupControl("Hide")
		GetWindowGroupControl("Show")
		GuiControl, AI:, WindowLabel, % labelname
	}
	IfInString, thislabelmenu, -
	{
		labelname:= StrReplace(thislabelmenu, "-", "+")
		AddWindowGroupControl("Hide")
		GetWindowGroupControl("Hide")
		GuiControl, AI:, WindowLabel, % labelname
	}
}
IfInString, thislabelmenu, Window Profiles
{
	IfInString, thislabelmenu, +
	{
		labelname:= StrReplace(thislabelmenu, "+", "- ")
		GetWindowGroupControl("Hide")
		WindowProfGroupControl("Show")
		GuiControl, AI:, WindowLabel, % labelname
	}
	IfInString, thislabelmenu, -
	{
		labelname:= StrReplace(thislabelmenu, "- ", "+")
		GetWindowGroupControl("Hide")
		WindowProfGroupControl("Hide")
		GuiControl, AI:, WindowLabel, % labelname
	}
}
Return

Default:
IniRead, Always, % Settings, AlwaysOnTop, Key1
if (Always != "ERROR")
	GuestOn:=% Always
IniRead, Directory, % Settings, Directory, Key1
if (Directory != "ERROR")
	MainDirectory:=% Directory
else
	MainDirectory:= % A_ScriptDir
IniRead, Editor, % Settings, Editor, Key1
if (Editor != "ERROR")
	Editor:=% Editor
else
	Editor:=% "Notepad.exe"
IniRead, WinDrop, % Settings, WinManager, Key2
if (WinDrop != "ERROR")
	WinVictive:=% WinDrop
Gui, Defaults:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Edit, y20 x85, Below are the default settings for the program.
Gui, Add, Text, xp-65 yp+30, Your default Editor is:
Gui, Add, Text, xp yp+30, Default working directory:`t`n(place the full folder location.)`t
Gui, Add, Text, xp yp+50, Test File parameters:`t
Gui, Add, Text, xp yp+30, Activate Get tool without`n locked window active:`t
Gui, Add, Edit, x210 y51 w200 vEdit, % Editor
Gui, Add, Edit, xp yp+35 w200 vDirectory, % A_ScriptDir
Gui, Add, Checkbox, xp yp+45 gDelimit, Delimited
Gui, Add, Checkbox, xp+100 yp gConcantate, Concantated
Gui, Add, Checkbox, xp-100 yp+34 vWinactive, Activate always
Gui, Add, Checkbox, x140 ym+210 vYesOrNo, Default AlwaysOnTop On
Gui, Add, Button, x310 ym+235 gDCancel, Cancel
Gui, Add, Button, wp hp yp x375 gDSave, Save
Gui, Add, Text, x120 ym+230 cRed, (Must click save to save changes!)`n  Must reload for directory change
Gui, Margin, 20, 20
Gui, AI:Font, 0f0d03, Arial
Gui, Color, d6d5d0, f5f4f0
Gui, Show, , Defaults
Control, Disable ,, Edit1, Defaults
if (GuestOn == 1)
	GuiControl, Defaults:, YesOrNo, 1
else if (GuestOn == 0)
	GuiControl, Defaults:, YesOrNo, 0
else
	GuiControl, Defaults:, YesOrNo, 1
if (WinVictive == 1)
	GuiControl, Defaults:, Winactive, 1
else if (WinVictive == 0)
	GuiControl, Defaults:, Winactive, 0
else
	GuiControl, Defualts:, Winactive, 1
Return

Delimit:
IniRead, loopycount, % Settings, DroppedCodeCount, Key1
if (loopycount != "ERROR")
{
	Loop, % loopycount
	{
		IniRead, codedrop, % Settings, DroppedCode, Key%loopycount%
		codeylist.= codedrop  "|"
		loopycount--
	}
}
Gui, Delimits:New, +AlwaysOnTop +toolWindow
Gui, Add, Edit, y20 x20 -VScroll, Below is the Delimited lists from your create test file.`n Note the program is now set to add and delimit with`n               no condition on your decisions.`nTo Add multiple entries place pipes "|" with no spaces.
Gui, Add, Edit, xp+30 yp+80 w170 vDelAdd,
Gui, Add, Button, yp hp x220 gDelAdd, Add
Gui, Add, ListBox, x50 yp+35 w200 r6 vKodeyList gListyChange, % codeylist
Gui, Add, Button, xp+150 yp+110 gLCancel, Cancel
Gui, Add, Button, wp hp yp xp+50 gLSave, Save
Gui, Add, Text, x20 yp+5 cRed, (Must click save to save changes!)
Gui, AI:Font, 0f0d03, Arial
Gui, Color, d6d5d0, f5f4f0
Gui, Margin, 20, 20
Gui, Show, , Delimits
Control, Disable ,, Edit1, Delimits
Return

DelAdd:
Gui, Submit, NoHide
codeylist.= "|" DelAdd 
if (codeylist != "|")
	Sort, codeylist, U Z D|
GuiControl, Delimits:, KodeyList, % codeylist
GuiControl, Delimits:, DelAdd, 
Return

ListyChange:
Gui, Submit, NoHide
codeylist:= StrReplace(codeylist, KodeyList, "")
if (codeylist != "|")
	Sort, codeylist, U Z D|
GuiControl, Delimits:, KodeyList, % codeylist
Return

DelimitsGuiClose:
LCancel:
Gui, Delimits:Destroy
Return

LSave:
Gui, Submit, NoHide
IniDelete, % Settings, DroppedCodeCount
IniDelete, % Settings, DroppedCode
codeylist.= "|" DelAdd 
if (codeylist != "|")
	Sort, codeylist, U Z D|
codeylist:= StrReplace(codeylist, "|", "`n")
Loop, Parse, % codeylist, `n
{
	w++
	IniWrite, % A_LoopField, % Settings, DroppedCode, Key%w%
}
IniWrite, % w, % Settings, DroppedCodeCount, Key1
Gui, Delimits:Destroy
Return

Concantate:
IniRead, loopxcount, % Settings, Looper, Key1
if (loopxcount != "ERROR")
{
	Loop, % loopxcount
	{
		IniRead, codex, % Settings, KeyCodes, Key%loopxcount%
		codexlist.=  codex "|"
		loopxcount--
	}
}
Gui, Concantate:New, +AlwaysOnTop +toolWindow
Gui, Add, Edit, y20 x20 -VScroll, Below is the Delimited lists from your create test file.`n Note the program is now set to add and delimit with`n               no condition on your decisions.`nTo Add multiple entries place pipes "|" with no spaces.
Gui, Add, Edit, xp+30 yp+80 w170 vConAdd,
Gui, Add, Button, yp hp x220 gConAdd, Add
Gui, Add, ListBox, x50 yp+35 w200 r6 vKodexList gListxChange, % codexlist
Gui, Add, Button, xp+150 yp+110 gCCancel, Cancel
Gui, Add, Button, wp hp yp xp+50 gCSave, Save
Gui, Add, Text, x20 yp+5 cRed, (Must click save to save changes!)
Gui, AI:Font, 0f0d03, Arial
Gui, Color, d6d5d0, f5f4f0
Gui, Margin, 20, 20
Gui, Show, , Concantate
Control, Disable ,, Edit1, Concantate
Return

ConAdd:
Gui, Submit, NoHide
codexlist.= "|" ConAdd 
if (codexlist != "|")
	Sort, codexlist, U Z D|
GuiControl, Concantate:, KodexList, % codexlist
GuiControl, Concantate:, ConAdd, 
Return

ListxChange:
Gui, Submit, NoHide
codexlist:= StrReplace(codexlist, KodexList, "")
if (codexlist != "|")
	Sort, codexlist, U Z D|
GuiControl, Concantate:, KodexList, % codexlist
Return

CSave:
Gui, Submit, NoHide
IniDelete, % Settings, Looper
IniDelete, % Settings, KeyCodes
codexlist.= "|" ConAdd 
if (codexlist != "|")
	Sort, codexlist, U Z D|
codexlist:= StrReplace(codexlist, "|", "`n")
Loop, Parse, % codexlist, `n
{
	z++
	IniWrite, % A_LoopField, % Settings, KeyCodes, Key%z%
}
IniWrite, % z, % Settings, Looper, Key1
Gui, Concantate:Destroy
Return

ConcantateGuiClose:
CCancel:
Gui, Concantate:Destroy
Return

DefaultsGuiClose:
DCancel:
Gui, Defaults:Destroy
Return

DSave:
Gui, Submit, NoHide
IniDelete, % Settings, Editor
IniDelete, % Settings, WinManager, Key2
IniDelete, % Settings, Directory
IniDelete, % Settings, AlwaysOnTop
IniWrite, % Edit, % Settings, Editor, Key1
IniWrite, % Winactive, % Settings, WinManager, Key2
IniWrite, % YesOrNo, % Settings, AlwaysOnTop, Key1
IniWrite, % Directory, % Settings, Directory, Key1
Gui, Defaults:Destroy
Return

AISave:
GuiControl,AI:, AISave, Save_File
Return

AIClear:
FileMove, % Temp, % TempBack, 1
FileAppend, , % Temp, UTF-8
GuiControl, AI:, Words,
logicalhistory:=[]
Return
	
SusOnOff:
Suspend, Toggle
if (A_IsSuspended == 1)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOn
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, Suspend`tOff
Return

Always:
WinSet, AlwaysOnTop, Toggle, AI
WinGet, ExStyle, ExStyle, AI
if (ExStyle == 0x00000180)
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOff
else
	Menu, %A_ThisMenu%, Rename, %A_ThisMenuItem%, AlwaysOnTop`tOn
Return
 
Timers:
Gui, Timers:New,  +AlwaysOnTop +Resize +toolWindow
Gui, Add, Text, y25, Rest Timer:`t`n(in seconds)
Gui, Add, Text, y75 xs, Window Not Active:`t`n(in milliseconds)
Gui, Add, Text, y125 xs, Process Loop timer:`t`n(in milliseconds)
Gui, Add, Edit, w250 r3 ys-15 -VScroll, This timer slows the script before it gets to the main loop function. It's used to help in processing the global function "Speller."
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the script when the it is not active.
Gui, Add, Edit, w250 r3 -VScroll, This timer slows the main processing loop while typing. It's dependent on a difference created in the main edit control.
Gui, Add, Edit, ys xs+400 w50 y25
Gui, Add, UpDown, vRangeInSeconds Range1-50, 10
Gui, Add, Edit, ys xs+400 w50 y75
Gui, Add, UpDown, vRangeInMillisecondsOfActive Range1-1000, 500
Gui, Add, Edit, ys xs+400 w50 y125
Gui, Add, UpDown, vRangeInMillisecondsOfProcess Range1-100, 25
Gui, Add, Text, xm+10 ym+180, Select the above values to your personal preferences and click save to keep the changes.
Gui, Add, Text, xm+80 ym+215, (Note you have to restart the program to force the changes)
Gui, Add, Button, ym+210 xs+425 gSave, Save
Gui, Add, Button, ym+210 xs+370 gCancel, Cancel
Gui, Margin, 20, 50
Gui, Show, h250 w500, Timers
Control, Disable ,, Working, Timers
Control, Disable ,, TestInfo, Timers
Control, Disable ,, FunctionName, Timers
Return

Minimize:
IniRead, DefaultLoc, % Settings, WinManager, Key1
if (whichone == "")
	whichone:= 1
if (whichone == 0)
{
	Menu, %A_ThisMenu%, Rename, Maximize, Minimize
	whichone:= 1
}
else if (whichone == 1)
{
	Menu, %A_ThisMenu%, Rename, Minimize, Maximize
	whichone:= 0
}
if (DefaultLoc == "ERROR")
{
	MsgBox, 262144, You haven't set up a Default location., You currently haven't set up a Default location for minimize. This will automatically minimize to one of three spots. The "Editor" program you have (Defalut); the "Locked" program (first option if locked): or the screen (last option if neither exist). It will activate the program and Toggles AlwaysOnTop based on the programs active status.`n`nNote**** Your "Editor" will always take precedence in AlwaysOnTop!
	GuiControlGet, Locked, AI:, WindowControl
	if (Locked == "")
		GuiControlGet, DefaultEdit, AI:, DefaultEdit
	IfInString, DefaultEdit, .
	{
		windows:= StrSplit(DefaultEdit, ".")
		for index, window in windows
			if (index == 1)
				thiswindow:=% window
	}
	if (Locked != "")
	{
		IfWinExist, % Locked
			WinActivate, % Locked
	}
	else IfWinExist, % thiswindow
	{
		WinGetTitle, fullwindow, % "ahk_class" thiswindow
		WinActivate, % fullwindow
		GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	}
	else
	{
		WinGetTitle, fullwindow, ahk_class Progman
		GetMoveWindow(DefalutLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	}
	Return
}
else if (DefalutLoc != "ERROR")
{
	GuiControlGet, WindowSnap, AI:, WindowControl
	GuiControlGet, Locked, AI:, DefaultEdit
	IfInString, Locked, .
	{
		windows:= StrSplit(Locked, ".")
		for index, window in windows
			if (index == 1)
				windowcheck:=% window
	}
	WinGet, windows, List,,, Program Manager
	Loop, % windows
	{
		WinID := windows%A_Index%
		WinGetTitle, ThisWindow, % "ahk_id " WinID
		if ((ThisWindow == WindowSnap)&&(WindowSnap != ""))
		{
			fullwindow:=% ThisWindow
			Break
		}
		IfInString, ThisWindow, % windowcheck
		{
			fullwindow:=% ThisWindow
			Break
		}
	}
	WinGet, Minimized, MinMax , % fullwindow
	if ((fullwindow == "")||(Minimized == -1))
		fullwindow:=%  "Program Manager"
	GetMoveWindow(DefaultLoc, whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
}
Return

Reload:
^r::
Reload
Return

Cancel:
Gui, Timers:Destroy
Return

Save:
Gui, Submit, NoHide
RangeInSeconds:=(RangeInSeconds*1000)
IniWrite, % RangeInSeconds, % Settings, Timers, Key1
IniWrite, % RangeInMillisecondsOfActive, % Settings, Timers, Key2
IniWrite, % RangeInMillisecondsOfProcess, % Settings, Timers, Key3
Gui, Timers:Destroy
Return

FileSelected: 
Gui, Submit, NoHide
GuiControl, AI:, Information, Working..
FileRead, contents, % FileSelected
if (ChangeType == "Get Variables")
{
	if (Gui == 1)
		filters.= "[Filter='Gui'],"
	if (Explicit == 1)
		filters.= "[Filter='explicit'],"
	if (ImplicitExplicit == 1)
		filters.= "[Filter='implicit-explicit'],"
	wi:=
	if (filters != "")
	{
		Control, Disable ,, ListBox1, AI
		contents:= GetVariables(contents, filters)
		GuiControl, AI:, Words,
		GuiControl, AI:, Words, % contents
		whichbutton:=GetControl("ButtCount")
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					thisbutton:= "\|/SoftReturn\|/"
				if (butt == "Enter")
					thisbutton:= "\|/hardReturn\|/"
				if (butt == "Unknown")
					thisbutton:= " \|/SoftReturn\|/"
			}
		}
		StringReplace, contents, contents, `n, %thisbutton%, ALL
		FileMove, % Temp, % TempBack, 1
		FileAppend, % contents, % Temp, UTF-8
	}
}
else if (ChangeType == "Get Function") ;ChangeType gChangeType, Get Variables||Get Function|Create Test File
{
	ControlGet, row, CurrentLine, , Edit3, AI
	ControlGet, rowtext, Line, % row, Edit3, AI
	if (rowtext == "")
	{
		MsgBox, Please insert the function label name
		Return
	}
	if (AssociateV == 1)
		thisignore:=% "Do_Not"
	function:=GetThisFunction(rowtext, thisignore, contents)
	GuiControl, AI:, Words, % function
	FileMove, % Temp, % TempBack, 1
	FileAppend, % function, % Temp, UTF-8
}
else if (ChangeType == "Create Test File")
{
	thesecontents:= GetTestFile(contents)
	Loop, Parse, % thesecontents, `n
	{
		if (A_LoopField == "")
			Continue
		if (A_LoopField == "Return")
			thisfile:=% thisfile A_LoopField "`n`n"
		else if (A_LoopField != "Return")
			thisfile:=% thisfile A_LoopField "`n"
	}
	FileMove, Test.ahk, % TempBack, 1
	FileAppend, % thisfile, *Test.ahk, UTF-8
}
GuiControl, AI:, AssociateV, 0
GuiControl, AI:, Gui, 0
GuiControl, AI:, Explicit, 0
GuiControl, AI:, ImplicitExplicit, 0
GuiControl, AI:, FunctionName,
GuiControl, AI:, WordKeeper, 7h151s@a#res37
GuiControl, AI:, Information, Done
Control, Enable ,, ListBox1, AI
Return

WindowProfGroupControl(control)
{
	if (control == "Show")
	{
		GuiControl, AI:Show, GroupControls
		GuiControl, AI:, GroupControls, Window Profiles
		GuiControl, AI:Show, ProfList
		GuiControl, AI:Show, ProfAdd
		GuiControl, AI:Show, ProfDele
		GuiControl, AI:Show, ProfMod
		GuiControl, AI:Show, ProfBack
		GuiControl, AI:Show, ProfStart
		GuiControl, AI:Show, ProfRun
		GuiControl, AI:Hide, PixMouse
		GuiControl, AI:Hide, WinStats
		GuiControl, AI:Hide, WinText
		GuiControl, AI:Hide, Welcome
		GuiControl, AI:Show, ControlInformation
	}
	if (control == "Hide")
	{
		GuiControl, AI:Hide, GroupControls
		GuiControl, AI:Show, Welcome
		GuiControl, AI:Hide, ProfList
		GuiControl, AI:Hide, ProfAdd
		GuiControl, AI:Hide, ProfDele
		GuiControl, AI:Hide, ProfMod
		GuiControl, AI:Hide, ProfBack
		GuiControl, AI:Hide, ProfStart
		GuiControl, AI:Hide, ProfRun
		GuiControl, AI:Hide, PixMouse
		GuiControl, AI:Hide, WinStats
		GuiControl, AI:Hide, WinText
		GuiControl, AI:Hide, ControlInformation
	}
	Return
}

AddWindowGroupControl(control)
{
	if (control == "Show")
	{
		GuiControl, AI:Show, GroupControls
		GuiControl, AI:, GroupControls, Window Controls
		GuiControl, AI:Show, GetWindow
		GuiControl, AI:Show, SnapWindow
		GuiControl, AI:Show, SnapToEditor
		GuiControl, AI:Show, AutoEdit
		GuiControl, AI:Show, EnableCC
		GuiControl, AI:Show, EnableVV
		GuiControl, AI:Hide, PixMouse
		GuiControl, AI:Hide, WinStats
		GuiControl, AI:Hide, WinText
		GuiControl, AI:Hide, Welcome
		GuiControl, AI:Show, ControlInformation
	}
	if (control == "Hide")
	{
		GuiControl, AI:Hide, GroupControls
		GuiControl, AI:Hide, GetWindow
		GuiControl, AI:Hide, SnapWindow
		GuiControl, AI:Hide, SnapToEditor
		GuiControl, AI:Hide, AutoEdit 
		GuiControl, AI:Hide, EnableCC
		GuiControl, AI:Hide, EnableVV
		GuiControl, AI:Hide, PixMouse
		GuiControl, AI:Hide, WinStats
		GuiControl, AI:Hide, WinText
		GuiControl, AI:Show, Welcome
		GuiControl, AI:Hide, ControlInformation
	}
	Return
}

GetWindowGroupControl(control)
{
	if (control == "Show")
	{
		GuiControl, AI:Show, GroupControls
		GuiControl, AI:, GroupControls, Window Stats
		GuiControl, AI:Show, ComboBox2
		GuiControl, AI:Show, GetPix
		GuiControl, AI:Show, GetMouse
		GuiControl, AI:Show, GetWinS
		GuiControl, AI:Show, GetWinT
		GuiControl, AI:Show, MultiSele
		GuiControl, AI:Show, PixMouse
		GuiControl, AI:Show, WinStats
		GuiControl, AI:Show, WinText
		GuiControl, AI:Hide, Welcome
		GuiControl, AI:Show, ControlInformation
	}
	if (control == "Hide")
	{
		GuiControl, AI:Hide, GroupControls
		GuiControl, AI:Hide, ComboBox2
		GuiControl, AI:Hide, GetPix
		GuiControl, AI:Hide, GetMouse
		GuiControl, AI:Hide, GetWinS
		GuiControl, AI:Hide, GetWinT
		GuiControl, AI:Hide, MultiSele
		GuiControl, AI:Show, PixMouse
		GuiControl, AI:Show, WinStats
		GuiControl, AI:Show, WinText
		GuiControl, AI:Show, Welcome
		GuiControl, AI:Hide, ControlInformation
	}
	Return
}

Tracker(thistrack, DefaultLoc, Whichone, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
{
	GuiControlGet, WindowSnap, AI:, WindowControl
	GuiControlGet, DefaultEdit, AI:, DefaultEdit
	GuiControlGet, winSnap, AI:, SnapWindow
	GuiControlGet, EditSnap, AI:, SnapToEditor
	windows:= StrSplit(DefaultEdit, ".")
	for index, window in windows
		if (index == 1)
			editwindow:=% window
	WinGet, windows, List,,, Program Manager
	Loop, % windows
	{
		WinID := windows%A_Index%
		WinGetTitle, ThisWindow, % "ahk_id " WinID
		if ((ThisWindow == WindowSnap)&&(ThisWindow != ""))
		{
			fullwindow:=% ThisWindow
			Break
		}
		IfInString, ThisWindow, % editwindow
		{
			fullwindow:=% ThisWindow
			Break
		}
	}
	if (thistrack != fullwindow)
	{
		if ((EditSnap != "")||(WindowSnap != ""))
		{
				if ((winSnap == 1)||(EditSnap == 1))
				{
					WinSet, Transparent , Off, AI
					WinSet, AlwaysOnTop, on, AI
					GetMoveWindow(DefaultLoc, Whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
				}
			IfWinNotActive, % fullwindow
				IfWinNotActive, AI
					if ((winSnap == 1)||(EditSnap == 1))
					{
						WinSet, Transparent , 0, AI
						WinSet, AlwaysOnTop, off, AI
						fullwindow:=% ""
					}
		}
	}
	Return % fullwindow
}

GetMoveWindow(DefaultLoc, Whichone, fullwindow, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
{
	if (fullwindow != "Program Manager")
		WinGetPos , winPosX, winPosY, windowwidth, windowheight, % fullwindow
	else
	{
		winPosX:=0
		winPosY:=0
		windowwidth:=(A_ScreenWidth-50)
		windowheight:=(A_ScreenHeight-50) ; offage is set for DPI and virtual windows. This should be enough for most windows but each person has their own settings.
	}
	If (DefaultLoc != "ERROR")
		ThisWindowLoc(DefaultLoc,Whichone, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
	else if (DefaultLoc == "ERROR")
	{
		MsgBox, 262212, Default location not set, You have not set up a default location for the window. Would you like to continue?
		IfMsgBox, Yes
		{
			Loop,
			{
				x++
				y:=0
				ThisWindowLoc(x, y, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
				MsgBox, 262144, first position, This is the first position of the window minimized.
				y:=1
				ThisWindowLoc(x, y, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
				MsgBox, 262211, Do you like that location?, This is the second position maximized.`nIf you like this position click yes.`nTo exit click Cancel`n%x% %y% 
				IfMsgBox Yes
				{
					IniWrite, % x, % Settings, WinManager, Key1
					Break
				}
				IfMsgBox Cancel
					Break
				if (x == 9)
					x:=0
			}
		}	
		IfMsgBox, No
			Return
	}
	Return
}
	

ThisWindowLoc(DefaultLoc, Whichone, winPosX, winPosY, windowwidth, windowheight, AIPosX, AIPosY, AIorignalwidth, AIorignalhieght)
{
	AIwidth:= 100
	AIheight:= 80
	if (DefaultLoc == 1)
	{
		MainWindowX:=(windowwidth-AIwidth+winPosX)
		MainWindowY:=(windowheight-AIheight+winPosY) ; bottom right corner
		GuiWindowX:=(windowwidth-AIorignalwidth+winPosX)
		GuiWindowY:=(windowheight-AIorignalhieght+winPosY)
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 2)
	{
		MainWindowX:=% winPosX
		MainWindowY:=(windowheight-AIheight+winPosY) ; bottom left corner
		GuiWindowX:=% winPosX
		GuiWindowY:=(windowheight-AIorignalhieght+winPosY)
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 3)
	{
		MainWindowX:=% winPosX
		MainWindowY:=% winPosY ; upper left corner
		GuiWindowX:=% winPosX
		GuiWindowY:=% winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 4)
	{
		MainWindowX:=(windowwidth-AIwidth+winPosX)
		MainWindowY:=% winPosY ; upper right corner.
		GuiWindowX:=(windowwidth-AIorignalwidth+winPosX)
		GuiWindowY:=% winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 5)
	{
		MainWindowX:=(windowwidth/2)-(AIwidth/2)
		MainWindowY:=% winPosY ; upper center
		GuiWindowX:=(windowwidth/2)-(AIorignalwidth/2)
		GuiWindowY:=% winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 6)
	{
		MainWindowX:=(windowwidth/2)-(AIwidth/2)
		MainWindowY:=(windowheight-AIheight+winPosY) ; lower center
		GuiWindowX:=(windowwidth/2)-(AIorignalwidth/2)
		GuiWindowY:=(windowheight-AIorignalhieght+winPosY)
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 7)
	{
		MainWindowX:=% winPosX
		MainWindowY:=(windowheight/2)-(AIheight/2)+winPosY ; left center
		GuiWindowX:=% winPosX
		GuiWindowY:=(windowheight/2)-(AIorignalhieght/2)+winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 8)
	{
		MainWindowX:=(windowwidth-AIwidth+winPosX)
		MainWindowY:=(windowheight/2)-(AIheight/2)+winPosY ;right center
		GuiWindowX:=(windowwidth-AIorignalwidth+winPosX)
		GuiWindowY:=(windowheight/2)-(AIorignalhieght/2)+winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	if (DefaultLoc == 9)
	{
		MainWindowX:=(windowwidth/2)-(AIwidth/2)
		MainWindowY:=(windowheight/2)-(AIheight/2)+winPosY ; center center
		GuiWindowX:=(windowwidth/2)-(AIorignalwidth/2)
		GuiWindowY:=(windowheight/2)-(AIorignalhieght/2)+winPosY
		if (Whichone == 0)
			WinMove, AI, , %MainWindowX%, %MainWindowY%, %AIwidth%, %AIheight%
		else
			WinMove, AI, , %GuiWindowX%, %GuiWindowY%, %AIorignalwidth%, %AIorignalhieght%
		Return
	}
	Return
}

GetTestFile(data)
{
	IniRead, loopcount, % Settings, Looper, Key1
	if (loopcount != "ERROR")
	{
		Loop, % loopcount
		{
			IniRead, codex, % Settings, KeyCodes, Key%loopcount%
			codexlist.= codex "`n"
			loopcount--
		}
		IniRead, loopcount, % Settings, DroppedCodeCount, Key1
		if (loopcount != "ERROR")
		{
			Loop, % loopcount
			{
				IniRead, codedrop, % Settings, DroppedCode, Key%loopcount%
				codeylist.= codedrop "`n"
				loopcount--
			}
		}
		data:= StrReplace(data, "`r", "")
		Loop, Parse, % data, `n
		{
			y++
			codestring:=
			line:=% A_LoopField
			sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
			for index, sentence in sentences
			{
				if (index == 1)
					codestring:=% sentence
				if (index == 2)
					commentstring:=% sentence
			}
			keycodex:= StrReplace(codestring, ",",  " ")
			keycodex:= StrReplace(keycodex, "  ", " ")
			keycodex:= StrReplace(keycodex, "  ", " ")
			keycodex:=% Trim(keycodex)
			thesewords:= StrSplit(keycodex, A_Space)
			for index, keycode in thesewords
				if (index == 1)
					keycodex:=% keycode
			IfinString, codeylist, % keycodex
				codestring:=% ""
			IfinString, codexlist, % keycodex
			{
				filecontents:=% filecontents codestring "`n"
				codestring:=% ""
			}
			codestring:= CodeStringCheck(codestring)
			if (codestring != "")
			{
				IfinString, codestring, Return
				{
					if (thischecker == 1)
						IfNotInString, codestring, % "`t"
							thischecker:= 0
					codestring:=% ""
				}
				IfInString, codestring, Global
				{
					filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfInString, codestring, Gui
				{
					IfinString, codestring, Show
						filecontents:=% filecontents codestring "`nReturn`n`n"
					else
						filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfInString, codestring, Menu
				{
					filecontents:=% filecontents codestring "`n"
					codestring:=% ""
				}
				IfinString, codestring, :
				{
					if (thischecker != 1)
					{
						thischecker:= 1
						if (x != 1)
							x:=1
					}
					filecontents:=% filecontents codestring "`nReturn`n`n"
					codestring:=% ""
				}
				IfInString, filecontents, % codestring
					codestring:=% ""
			}
		}
	}
	else if (loopcount == "ERROR")
	{
		MsgBox, 70, Be sure before you continue., In the following message boxes you will be shown the beginning of your code. This will omit the comments and anything past the first comma as demiliters for your test.ahk creation. each type will be added to the Ini file settings and read for your future creations. You can always change this setting by selecting default in the default menu.`n`n**Also note This does skip continuation sections.
		IfMsgBox Continue
		{
			data:= StrReplace(data, "`r", "")
			Loop, Parse, % data, `n
			{
				y++
				line:=% A_LoopField
				sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
				for index, sentence in sentences
				{
					if (index == 1)
						codestring:=% sentence
					if (index == 2)
						commentstring:=% sentence
				}
				codestring:= CodeStringCheck(codestring)
				if (codestring != "")
				{
					IfinString, codestring, Return
					{
						if (thischecker == 1)
							IfNotInString, codestring, % "`t"
								thischecker:= 0
						codestring:=% ""
					}
					IfInString, codestring, Global
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, codestring, Gui
					{
						IfinString, codestring, Show
							filecontents:=% filecontents codestring "`nReturn`n`n"
						else
							filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, codestring, Menu
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfinString, codestring, :
					{
						if (thischecker != 1)
						{
							thischecker:= 1
							if (x != 1)
							{
								x:=1
								MsgBox, 32, g-Sublabels, sublabels are automatically added
							}
						}
						filecontents:=% filecontents codestring "`nReturn`n`n"
						codestring:=% ""
					}
					keycodex:= StrReplace(codestring, ",",  " ")
					keycodex:= StrReplace(keycodex, "  ", " ")
					keycodex:= StrReplace(keycodex, "  ", " ")
					keycodex:=% Trim(keycodex)
					thesewords:= StrSplit(keycodex, A_Space)
					for index, keycode in thesewords
						if (index == 1)
							keycodex:=% keycode
					IfinString, thisignoredlist, % keycodex
						codestring:=% ""
					IfinString, thisgottenlist, % keycodex
					{
						filecontents:=% filecontents codestring "`n"
						codestring:=% ""
					}
					IfInString, filecontents, % codestring
						codestring:=% ""
					if (codestring != "")
					{
						MsgBox, 36, Do you want to add this line?, % keycodex "`n`nFound on line: " y "`n`npress yes if you want to add the first (word) of this line to your delimiter fields."
						IfMsgBox Yes
						{
							z++
							IniWrite, % z, % Settings, Looper, Key1
							IniWrite, % keycodex, % Settings, KeyCodes, Key%z%
							thisgottenlist.= keycodex
							filecontents:=% filecontents codestring "`n"
						}
						else IfMsgBox No
						{
							w++
							IniWrite, % w, % Settings, DroppedCodeCount, Key1
							IniWrite, % keycodex, % Settings, DroppedCode, Key%w%
							thisignoredlist.= codestring " "
							Continue
						}
					}
				}
			}
		}
	}
	Return % filecontents
}

CodeStringCheck(codestring)
{
	IfInString, codestring, GuiControl
		codestring:=% ""
	IfinString, codestring, `t
		codestring:=% ""
	IfInString, codestring, Global
		Return % codestring
	IfInString, codestring, Gui ; It's likely a user may place any of the below special characters in a gui 4th parameter.
		Return % codestring
	IfInString, codestring, =
		codestring:=% ""
	IfInString, codestring, ( ;)
		codestring:=% ""
	IfInString, codestring, {
		codestring:=% ""
	IfInString, codestring, }
		codestring:=% ""
	IfInString, codestring, `%
		IfNotInString, codestring, SetWorkingDir
			codestring:=% ""
	IfinString, codestring, Loop
		codestring:=% ""
	IfinString, codestring, else
		codestring:=% ""
	IfinString, codestring, if%A_Space%
		codestring:=% ""
	IfinString, codestring, ::
		codestring:=% ""
	Return % codestring
}

GetThisFunction(function, get, data)
{
	function:= StrReplace(function, "`r`n", "")
	function:= StrReplace(function, "`n", "")
	functionlength:=StrLen(function)
	data:= StrReplace(data, "`r", "")
	function:= GetFunction(data, functionlength, function)
	thisfoundfunction.= function "`n"
	function:=""
	if (get == "Do_Not")
	{
		Loop,
		{
			Loop, Parse, % thisfoundfunction, `n
			{
				IfInString, A_LoopField, =
					IfInString, A_LoopField, (
					{
						foundpossible:= FunctionLabelGet(A_LoopField)
						Trim(foundpossible)
						IfNotInString, foundpossible, % A_Space
							IfNotInString, thesefound, % foundpossible
							{
								functionlength:=StrLen(foundpossible)
								function:= GetFunction(data, functionlength, foundpossible)
							}
						if (function != "")
							thisfoundfunction.= function "`n"
					}
				if (function != "")
					function:=
				thesefound.= foundpossible ", "
			}
			IfNotInString, thesefoundpast, % thesefound
				thesefoundpast.= thesefound
			IfinString, thesefoundpast, % thesefound
				Break
		}
	}
	Return % thisfoundfunction
}

GetFunction(data, functionlength, function)
{
	Loop, Parse, % data, `n
	{
		if (thisfunction == "")
		{
			linesubstring:= SubStr(A_LoopField, 1, functionlength)
			if (function == linesubstring)
			{
				thisfunction:= % A_LoopField "`n"
				z:=1
			}
		}
		else if (thisfunction != "")
		{
			thisfunction.= A_LoopField "`n"
			if (A_LoopField == "{")
				x++
			if (A_LoopField == "}")
				x--
			if (z == 1)&&(A_LoopField != "{")
				thisfunction:= ""
			z:=0
		}
		if ((x == 0)&&(thisfunction != ""))
		{
			thisfoundfunction:= % thisfunction
			thisfunction:= ""
		}
	}
	Return % thisfoundfunction
}

FunctionLabelGet(line)
{
	thissplitfunction:= StrSplit(line, "= ")
	for index, thissplit in thissplitfunction
		if (index == 2)
			thispart:=% thissplit
	thispartsplit:= StrSplit(thispart, "(") ;"
	for index, function in thispartsplit
		if (index == 1)
			Return % function
	Return
}

ChangeType:
Gui, Submit, NoHide
if (ChangeType == "Get Variables")
{
	GuiControl, AI:Text, Results, Get variables`n(Filter results by Checkbox)
	GuiControl, AI:Hide, FunctionName
	GuiControl, AI:Hide, FunctionLabel
	GuiControl, AI:Hide, TestInfo
	GuiControl, AI:Hide, AssociateV
	GuiControl, AI:Show, Gui
	GuiControl, AI:Show, Explicit
	GuiControl, AI:Show, ImplicitExplicit
}
if (ChangeType == "Get Function")
{
	GuiControl, AI:Text, Results, Get Function`n(Select a file to get a function)
	GuiControl, AI:Show, FunctionName
	GuiControl, AI:Show, FunctionLabel
	GuiControl, AI:Hide, TestInfo
	GuiControl, AI:Show, AssociateV
	GuiControl, AI:Hide, Gui
	GuiControl, AI:hide, Explicit
	GuiControl, AI:Hide, ImplicitExplicit
	GuiControl, Focus, FunctionName
}
if (ChangeType == "Create Test File")
{
	GuiControl, AI:Text, results, Create a Test File`n(Create functionless test ahk)
	GuiControl, AI:hide, Gui
	GuiControl, AI:Hide, Explicit
	GuiControl, AI:hide, ImplicitExplicit
	GuiControl, AI:Hide, AssociateV
	GuiControl, AI:hide, FunctionName
	GuiControl, AI:hide, FunctionLabel
	GuiControl, AI:Show, TestInfo
}
Return

GetVariables(filecontents, filters)
{
	Loop, Parse, % filecontents, `r
	{
		linenumber++
		line:=% A_LoopField
		sentences:= StrSplit(line, ";") ; <---- replace for whatever comment char you use like ("\\, \*)  "
		for index, sentence in sentences
		{
			if (index == 1)
				codestring:=% sentence
			if (index == 2)
				commentstring:=% sentence
		}
		VarSetCapacity(information, 0) 
		codestring:= RemoveCertainChars(codestring, "Start")
		IfInString, codestring, Dll
			Continue
		IfInString, codestring, Box`,
			Continue
		IfInString, codestring, StringReplace
			Continue
		IfInString, codestring, RegEx
			Continue
		IfInString, codestring, Ini
			Continue
		IfInString, codestring, =
		{
			IfInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Percent", linenumber)
				IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
			}
			else IfNotInString, codestring, [percent]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
			IfInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Quotes", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring 
			}
			else IfNotInString, codestring, [quotes]
			{
				variablestring:= GetVariableString(codestring, "Equals", linenumber)
				IfNotInString, variablelist, % variablestring
					variablelist.= variablestring
			}
		}
		else IfInString, codestring, [percent]
		{
			variablestring:= GetVariableString(codestring, "Percent", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring
		}
		else IfInString, codestring, [quotes]
		{
			variablestring:= GetVariableString(codestring, "Quotes", linenumber)
			IfNotInString, variablelist, % variablestring
				variablelist.= variablestring "found in quotes 2`n"
		}
		IfInString, codestring, Gui
			IfInString, codestring, `,
				IfInString, codestring, %A_Space%v
				{
					variablestring:= GetVariableString(codestring, "Gui", linenumber)
					IfNotInString, variablelist, % variablestring
						variablelist.= variablestring
				}
	}
	thesefilters:=StrSplit(filters, ",")
	for index, filter in thesefilters
	{
		if (index == 1)
			if (filter != "")
				firstfilter:=% filter
		if (index == 2)
			if (filter != "")
				secondfilter:=% filter
		if (index == 3)
			if (filter != "")
				thirdfilter:=% filter
	}
	Loop, Parse, % variablelist, `n
	{
		thischeck:= ""
		information:= ""
		if (A_LoopField != "")
		{
			repeatcheck:= StrSplit(A_LoopField, "[thissplitter]")
			for index, repeat in repeatcheck
			{
				if (index == 1)
				{
					IfNotInString, completedlist, % repeat
						thischeck:=% repeat
					IfInString, completedlist, % repeat
					{
						checking:= MakeSure(completedlist, repeat)
						if (checking == "True")
							Continue
						else if (checking == "False")
							thischeck:=% repeat
					}
				}
				if (index == 2)
				{
					if (firstfilter != "")
						IfInString, repeat, % firstfilter
						{
							applyfilters:= StrSplit(repeat, firstfilter)
							for index, apply in applyfilters
								information.= apply
						}
					else if (secondfilter != "")
						IfInString, repeat, % secondfilter
						{
							applyfilters:= StrSplit(repeat, secondfilter)
							for index, apply in applyfilters
								information.= apply
						}
					else if (thirdfilter != "")
						IfInString, repeat, % thirdfilter
						{
							applyfilters:= StrSplit(repeat, thirdfilter)
							for index, apply in applyfilters
								information.= apply
						}
				}
			}
			if ((thischeck != "")&&(information != ""))
			{
				checklist:=% Trim(thischeck) "`n" Trim(information) "`n"
				IfNotInString, completedlist, % checklist
					completedlist.= checklist
			}
		}
	}
	completedlist:= RemoveCertainChars(completedlist, "End")
	Return % completedlist
}

MakeSure(listinprogress, checkword)
{
	Loop, Parse, % listinprogress, `n
	{
		if (checkword == A_LoopField)
			Return % "True"
	}
	Return % "False"
}

GetVariableString(codestring, whichone, linenumber)
{
	if (whichone == "Gui")
	{
		variablestrings:= StrSplit(codestring, ",")
		for index, variablestring in variablestrings
		{
			if (index > 4)
				Continue
			IfInString, variablestring, %A_Space%v
				thisvariablestring:=% variablestring
		}
		variablestring:= StrSplit(thisvariablestring, A_Space)
		for index, variable in variablestring
		{
			thisvariableletter:= SubStr(variable, 1, 1)
			if (thisvariableletter == "v")
				Return % variable "[thissplitter] Gui variable[Filter='Gui'] Line number is found at: " linenumber "`n"
		}
		Return % variable "[thissplitter] Gui variable Line number is found at: " linenumber "`n"
	}
	if (whichone == "Quotes")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [quotes]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		variablestrings:= StrSplit(codestring, "[quotes]")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 0)
				IfNotInString, variablestring, %A_Space%
					IfNotInString, variables, % variablestring
						variables.= "[quotes]" variablestring "[quotes][thissplitter] explicit[Filter='explicit'] variable Line number is found at: " linenumber "`n"
		}
		Return % variables
	}
	if (whichone == "Percent")
	{
		IfInString, codestring, Gui`,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				if (index > 4)
					Continue
				IfInString, variablestring, [percent]
					thisvariablestring:=% variablestring
			}
			codestring:=% thisvariablestring
		}
		IfInString, codestring, `,
		{
			variablestrings:= StrSplit(codestring, ",")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					IfInString, variablestring, [percent]
						IfNotInString, variablestring, =
							IfInString, variablestring, A_Space
								variables.= variablestring "[thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		IfNotInString, codestring, `,
		{
			IfInString, codestring, =
			{
				variablestrings:= StrSplit(codestring, "=")
				for index, variablestring in variablestrings
				{
					if (index == 1)
					{
						variables:= StrSplit(variablestring, A_Space)
						for index, variable in variables
							thisvariable:=% variable
					}
					if (index == 2)
						codestring:=% variablestring
				}
			}
			variablestrings:= StrSplit(codestring, "[percent]")
			for index, variablestring in variablestrings
			{
				x:=Mod(index, 2)
				if (x == 0)
					variables.= "[percent]" variablestring "[percent][thissplitter] implicit[Filter='implicit-explicit'] variable explicitly used Line number is found at: " linenumber "`n"
			}
		}
		if (thisvariable != "")
			variables.= thisvariable "[thissplitter]implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
		Return % variables
	}
	if (whichone == "Equals")
	{
		variablestrings:= StrSplit(codestring, "=")
		for index, variablestring in variablestrings
		{
			x:=Mod(index, 2)
			if (x == 1)
				IfNotInString, variablestring, [quotes]
				{
					thisvariablestring:= StrSplit(variablestring, A_Space)
					for index, thisvariable in thisvariablestring
					{
						variable:=% thisvariable "[thissplitter] implicit[Filter='implicit-explicit'] variable given explicit value Line number is found at: " linenumber "`n"
					}
				}
		}
		Return % variable
	}
	Return % "Not Found"
}

RemoveCertainChars(string, special)
{
	if (special == "Start")
	{
		StringReplace, string, string, ", [quotes], ALL ; "
		StringReplace, string, string, `%%A_Space%, [percent], ALL
		StringReplace, string, string, `%, [percent], ALL
		StringReplace, string, string, %A_Space%:, :, ALL
		StringReplace, string, string, :=, =, ALL
		StringReplace, string, string, ==, =, ALL
		StringReplace, string, string, >, =, ALL
		StringReplace, string, string, <, =, ALL
		StringReplace, string, string, %A_Space%!=, =, ALL
		StringReplace, string, string, =%A_Space%, =, ALL
		StringReplace, string, string, %A_Space%=, =, ALL
		StringReplace, string, string, ), , ALL
		StringReplace, string, string, (, , ALL ;)
		StringReplace, string, string, `t, , ALL
	}
	if (special == "End")
	{
		StringReplace, string, string, [quotes], ", ALL ; "
		StringReplace, string, string, [percent], `%, ALL
		StringReplace, string, string, `,, , ALL
	}
	Return % string
}

GetButton_Count()
{
	Loop,
	{
		ButtonCountCheck:= GetControl("ButtCount")
		if (ButtonCountCheck != OldButtonCountCheck)
		{
			OldCount:=% Count
			OldButton:=% Button
			Sleep, 500
			ButtonCount_Split:= StrSplit(ButtonCountCheck, ",")
			For Index, ButtCount in ButtonCount_Split
			{
				if (Index == 1)
					Count:=% ButtCount
				if (Index == 2)
					Button:=% ButtCount
			}
		}
		else if (ButtonCountCheck == OldButtonCountCheck)
			Break
		if ((Button != OldButton)&&(Count > 1))
			Break
		OldButtonCountCheck:=% ButtonCountCheck
	}
	if (Button == OldButton)
	{
		ButtonCountReturn:=% Count "," Button
		GuiControl,AI:, ButtonCountCheck, % "0," Button
	}
	if (Button != OldButton)
	{
		NewCount:=% Count-OldCount
		GuiControl,AI:, ButtonCountCheck, % NewCount "," Button
		ButtonCountReturn:=% OldCount "," OldButton
	}
	Return
}

ApplyLogicalChange(activeuserinput, logicalhistory, numberofdifferences)
{
	x:= 0
	newhistoryrecord:=[]
	activeuserinputlastline:= GetLineCount(activeuserinput)
	logicalhistorylastline:= GetLineCount(logicalhistory)
	LastLine:= logicalhistory["linePos" logicalhistorylastline]
	Loop, % activeuserinputlastline
	{
		record:=
		x++ ; a lagged y variable needed to stagger history.
		occurenceuser:= activeuserinput["linePos" x]
		if (y > 0)
		{
			y:=(x-z) ; this will be an opposite staggered y (x+z) for deleted lines.
			historyrecord:= logicalhistory["linePos" y]
		}
		else
			historyrecord:= logicalhistory["linePos" x] ; even though the line now isn't right doesn't mean next time it won't be.
		splithistoryrecord:= StrSplit(historyrecord, ["(hardReturn)", "(softReturn)"])
		for index, splithistory in splithistoryrecord
		{
			if (Index == 1)
				record:= % splithistory
		}
		if ((occurenceuser != record)&&(numberofdifferences != 0)&&(activeuserinputlastline != 1)) ; the number of occurences go negative when lines get deleted... I haven't updated the below else for that yet.
		{
			LastLine:= logicalhistory["linePos" logicalhistorylastline] ; if a user is lagging the array make sure you are putting in last lines right.
			if ((LastLine == "(softReturn)")||(LastLine == "(hardReturn)")) ; the last line shouldn't be any other value.
			{
				z++ ; a z variable making sure we don't lose y and holding the number of occurences.
				if (z == 1) ; there's not enough time to add different enters in different spots (meaning the user couldn't add enough enters in the time this will be done).
					y:=% x
				IfInString, LastLine, (softReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
				IfInString, LastLine, (hardReturn)
					newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
				numberofdifferences--
				logicalhistorylastline--
			} ; the likely answer is a deleted line in occurenceuser. we need to add to the numberofdifferences. I'll also need to update this in the future for the array.
			else
				numberofdifferences++
		}
		else if ((occurenceuser != record)&&(numberofdifferences == 0)||(activeuserinputlastline == 1)) ; meaning user has updated a line with a new record
		{
			newhistoryrecord["linePos" x]:= occurenceuser
			IfInString, historyrecord, (softReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(softReturn)"
			IfInString, historyrecord, (hardReturn)
				newhistoryrecord["linePos" x]:= occurenceuser "(hardReturn)"
		} ; z from above holds all change counts. y from above holds the history record line back. technically y can equal x-z or just y++. I think for greater clarity it should be x-z because a user may choose to purposely lag the logicalhistoryarray Change function. Basically this function can be implimented at will as long as the keys are being kept up with and added to the historyarray in the main loop (of course that might also come with logical array issues).
		else if ((occurenceuser == record)&&(numberofdifferences == 0))
			newhistoryrecord["linePos" x]:= record
	}
	check:=GetControl("GetKeeper")
	if (check == "7h151s@a#res37")
		Return
	Return % newhistoryrecord ; There has been many different statements on using the % after Return or in ":=" as an operorator (it technically doesn't need to be done and can cause issues if done improperly). I use it because honestly it's like my signature to my work.
}

Doppler(usersentence, historysentence)
{
	livewords:=[]
	pastwords:=[]
	check:=GetControl("GetKeeper")
	if (check == "&not@a#rea1*sent3nc3")
	{
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			livewords["wordPos" key]:= userwords
		}
		historysplit:=StrSplit(historysentence, A_Space)
		for key, historywords in historysplit
		{
			pastwords["wordPos" key]:= historywords
		}
		usercount:=GetLineCount(livewords)
		historycount:= GetLineCount(pastwords)
		Loop, % usercount
		{
			x++
			userword:=livewords["wordPos" x]
			historyword:=pastwords["wordPos" x]
			userwordlength:=StrLen(userword)
			historywordlength:= StrLen(historyword)
			if ((userword != historyword)||(historycount < x))
				GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		}
		StringReplace, userword, userword, historyword, , ALL
	}
	else if (check != "&not@a#rea1*sent3nc3")
	{
		checksplit:= StrSplit(check, ",")
		for Index, chec in checksplit
		{
			if (index == 1)
				historyword:=% chec
			if (index == 2)
				ouserword:=% chec
			if (index == 3)
				x:=% chec
		}
		usersplit:= StrSplit(usersentence, A_Space)
		for key, userwords in usersplit
		{
			if (key == x)
				userword:=% userwords
		}
		GuiControl, AI:, WordKeeper, % historyword "," userword "," x
		StringReplace, userword, userword, historyword, , ALL
	}
	userwordlength:=StrLen(userword)
	if (userwordlength < 2)
	{
		GuiControl, AI:, Information, Working...
		SpellChecker(0)
	}
	if (userwordlength > 3)
	{
		GuiControl, AI:, Information, Working.
		ourwords:=WordCheck(userword, userwordlength)
		if (ourwords == "")
			SpellChecker(0)
		else if (ourwords != "")
		{
			SpellChecker(userwordlength)
			GetControl(ourwords)
		}
	}
	Return
}

FixLogicalhistory_Array(historyarray, howmanylines)
{
	lastline:= GetLineCount(historyarray)
	whichbutton:= GetControl("ButtCount")
	Loop, % howmanylines
	{
		lastline++
		button:= StrSplit(whichbutton, ",")
		for key, butt in button
		{
			if (key == 2)
			{
				if (butt == "ShiftEnter")
					historyarray["linePos" lastline]:= "(softReturn)"
				if (butt == "Enter")
					historyarray["linePos" lastline]:= "(hardReturn)"
			}
		}
	}
	Return % historyarray
}

ReturnLineArray(lines, user)
{
	linearray:=[]
	contents:= StrSplit(lines, ["\|/CR+LF\|/", "\|/SoftReturn\|/", "\|/userReturns\|/"])
	for key, con in contents
	{
		linearray["linePos" key]:= con
	}
	Return % linearray
}

GetButtonCount(pressed)
{
	pressing:= StrSplit(pressed, ",")
	For Index, press in pressing
		if (Index == 1)
			Return % press
}

FindingRealLineLOL(occurenceuser, rowbefore, thisrow)
{
	IfInString, occurenceuser, %rowbefore%
	{
		rowlength:= StrLen(rowbefore)
		occurencelength:= StrLen(occurenceuser)
		subtractedlength:=(occurencelength-rowlength)
		thisstring:= SubStr(occurenceuser, subtractedlength, occurencelength)
		if (thisstring == rowbefore)
		{
			IfInString, occurenceuser, %thisrow%
				Return % "Found"
			IfNotInstring, occurenceuser, %thisrow%
				Return % "NextRow"
		}
	}
	if (rowbefore == "NextRow")
		IfInString, occurenceuser, %thisrow%
			Return % "Found"
	Return % "NotFound"
}

ProcessStart(contents, Rest)
{
	logicalhistory:= []
	WinSet, Transparent, 0, Words
	history:= GetHistory()
	logicalhistory:= ReturnLineArray(history, user)
	Control, Disable ,, Words, AI
	GuiControl, AI:, Words, % contents
	Sleep, % Rest
	Control, Enable ,, Words, AI
	GuiControl, AI:, Information, Done
	Control, Enable ,, ListBox1, AI
	Return % logicalhistory
}

WordCheck(uword, str)
{
	Sort, Speller, U D|
	Loop, Parse, % Speller, |
	{
		mword:= SubStr(A_LoopField, 1, str)
		if (mword == uword)
		{
			z++
			IfNotInstring, ourlist, %A_LoopField%
			{
				if (z == 1)
					ourlist:= % ourlist A_LoopField "||"
				else if (z != 1)
					ourlist:= % ourlist A_LoopField "|"
			}
		}
	}
	if (ourlist == "")
		Return
	Return % ourlist
}

SpellChecker(n)
{
	Y:= (A_CaretY+11)
	X:= (A_CaretX-27)
	WinGetPos, WX, WY, , , Words
	if (n > 3)
	{
		WinSet, AlwaysOnTop, Off, AI
		WinSet, Transparent, 200, Words
		WinMove, Words, , % X, % Y
		winwonder:=WinWonder()
		if (winwonder == "False")
			WinActivate, AI
	}
	if (n == 0)
		WinSet, Transparent, 0, Words
	WinGet, visible, Transparent, Words
	if ((visible != 0)&&(WY != Y))
		WinMove, Words, , % X, % Y
	Return
}
Return

ReturnClearDif(harray, uarray, dif)
{
	v:=0
	for Index, u in uarray
		++v
	if (dif == "lines")
	{
		Loop,
		{
			x++
			hinput:= harray["linePos" x]
			hsplit:= StrSplit(hinput, ["(hardReturn)", "(softReturn)"])
			for Index, h in hsplit
			{
				if (Index == 1)
					checkh:= % h
			}
			uinput:= uarray["linePos" x]
			StringReplace, uinput, uinput, (softReturn), , ALL
			StringReplace, uinput, uinput, (hardReturn), , ALL
			l_checkh:= StrLen(checkh)
			l_uinput:= StrLen(uinput)
			if (uinput != checkh)
				Return % x
			if (l_checkh != l_uinput)
				Return % x
			if (x == v)
				Break
			checkh:=
		}
		Return % "0"
	}
}

CheckIt(user, y, nstring)
{
	Loop, Parse, % user, % A_Space
	{
		x++
		if (x == y)
			if (A_LoopField == nstring)
				Return % "True"
	}
}

GetLineCount(arraycount)
{
	LastLine:=0
	for Index, count in arraycount
		++LastLine
	Return % LastLine
}

GetControl(FocTex)
{
	GuiControlGet, InFocus, AI:Focus
	GuiControlGet, text, AI:, 
	ControlGet, row, CurrentLine, , Edit4, AI
	ControlGet, rowtext, Line, % row, Edit4, AI
	GuiControlGet, Word, Words:, Listbox1
	StringReplace, text, text, `n, \|/userReturns\|/, ALL
	GuiControlGet, ButtonCountCheck, AI:, ButtonCountCheck
	GuiControlGet, Save_File, AI:, AISave
	GuiControlGet, DopplerGet, AI:, WordKeeper
	if (FocTex == "RowText")
		Return % rowtext
	if (FocTex == "GetKeeper")
		Return % DopplerGet
	if (FocTex == "AISave")
		Return % Save_File
	if (FocTex == "ButtCount")
		Return % ButtonCountCheck
	if (FocTex == "Row")
		Return % row
	if (FocTex == "Focus")
		Return % InFocus
	if (FocTex == "Text")
		Return % text
	if (FocTex == "Word")
		Return % Word
	GuiControl, Words:, Listbox1, | 
	GuiControl, Words:, Listbox1, % FocTex
	Return
}

WinWonder()
{
	IfWinActive, AI
		Return % "True"
	IfWinNotActive, AI
		Return % "False"
	Return
}

WinProf()
{
	FileRead, contents, % Cache "\Profiles.Storage"
	if (ErrorLevel == 0)
	{
		Profiles:= StrSplit(contents, "[End-Splitter-Loop]")
		for index, profile in profiles
		{
			profilestrings:= StrSplit(profile, "&not@a#rea1*??sent3nc3")
			for index, profilepart in profilestrings
			{
				if (index == 1)
					profcheck:=% profilepart
				if (index == 2)
					datecheck:=% profilepart
			}
			if (profcheck != "")
				IfNotInString, updatedlist, % profcheck "`t" datecheck "|"
					updatedlist.= profcheck "`t" datecheck "|"
		}
	}
	Return % updatedlist
}

HashContents(contents)
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, \|/CR+LF\|/, `n, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, `n, ALL
	Return % contents
}

GetHistory()
{
	FileRead, contents, % Temp
	if (ErrorLevel == 1)
	{
		FileAppend, This is a new user., % Temp, UTF-8
		contents:=% "This is a new user."
	}
	StringReplace, contents, contents, `r`n,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, `n, (softReturn)\|/SoftReturn\|/, ALL
	StringReplace, contents, contents, \|/CR+LF\|/,(hardReturn)\|/CR+LF\|/, ALL
	StringReplace, contents, contents, \|/SoftReturn\|/, (softReturn)\|/SoftReturn\|/, ALL
	Return % contents
}

RawTextFix(string) ; a series of string replace commands to eliminate special characters and so on. 
{
	StringReplace, string, string, (*Inner thought[lmn]) (, , All
	StringReplace, string, string, {*What I'm doing[lmn]} {, , All
	StringReplace, string, string, Chris Says:  , , All
	StringReplace, string, string, (*Chris thinks[lmn]) ( , , All
	StringReplace, string, string, {*Chris is doing[lmn]} { , , All
	StringReplace, string, string, (*Luke thinks[lmn])  (, , All
	StringReplace, string, string, {*Luke is doing[lmn]} {, , All
	StringReplace, string, string, *[10], , All
	StringReplace, string, string, "[10], , All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, }[10], , All
	StringReplace, string, string, )[10], , All
	StringReplace, string, string, `n`r, , All
	StringReplace, string, string, `n, , All
	StringReplace, string, string, `r, , All
	var:= SubStr(string, 1, 1) ; for beginning of string 
	if (var == "*")
	{
		str:=StrLen(string)
		string:=SubStr(string, 2, str)
	}
	nv = " ; " <--- this is being done because of my edited language encoder for AHK.
	if (var == nv)
	{
		str:=StrLen(string)
		string:= SubStr(string, 2, str)
	}
	StringReplace, string, string, ., % A_Space, All
	StringReplace, string, string, |, % A_Space, All
	StringReplace, string, string, !, % A_Space, All
	StringReplace, string, string, ?, % A_Space, All
	StringReplace, string, string, ", % A_Space, All ; " <--- this is being done because of my edited language encoder for AHK.
	StringReplace, string, string, *, % A_Space, All
	StringReplace, string, string, `,, % A_Space, All
	StringReplace, string, string, % A_Space A_Space, % A_Space, All
	StringReplace, string, string, % A_Space, |, All
	StringReplace, string, string, `n, |, All
	Return % string
}

DesGet()
{
	FileRead, descriptions, % Cache "\descriptions.txt"
	if Not ErrorLevel
	{
		Loop, Parse, % descriptions, `n
		{
			if (A_LoopField == "")
				Continue
			IfNotInstring, list, % A_LoopField
				list:=% list A_LoopField "|"
		}
		descriptions:=% list
	}
	if (ErrorLevel == 1)
	{
		MsgBox, 262144, Fatal Error, % "the file does not exist in current directory:`n" Cache "\descriptions.txt`n please place your words in the above location`n FATAL ERROR 1 FILE DOES NOT EXIST"
		exitapp
	}
	Return % descriptions
}

AIGuiClose:
esc::
exitapp

Post Reply

Return to “Scripts and Functions (v1)”