#include <GuiSlider.au3>
#include <GuiScrollBars.au3>
#include <GDIPlus.au3>
#include <WinAPI.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <ProgressConstants.au3>
#include <WindowsConstants.au3>
#include <ScrollBarConstants.au3>
#include <StructureConstants.au3>
#include <String.au3>
#include <Array.au3>

;#AutoIt3Wrapper_Run_Before=""%autoitdir%\aapp.exe" "%in%""


Opt("MustDeclareVars", 1)
Opt("GUICloseOnESC", 0)
Opt("GUIOnEventMode", 1)


;0: splitten
;1: Strings
;2: Compiler
;3: geteilte Zeilen
;4: Global Const
;5: StringCalls


Global $oDictGlobalConst = ObjCreate('Scripting.Dictionary')
If Not IsObj($oDictGlobalConst) Then
	MsgBox(0, "ERROR", "creating scripting.dictionary object failed")
	Exit
EndIf
$oDictGlobalConst.CompareMode = 1

Global $oSCParam = ObjCreate('Scripting.Dictionary'), $oSCIsFunc = ObjCreate('Scripting.Dictionary'), $oSCIsVar = ObjCreate('Scripting.Dictionary')
$oSCParam.CompareMode = 1
$oSCIsFunc.CompareMode = 1
$oSCIsVar.CompareMode = 1

Global $aScriptQuotes, $aScriptCompiler, $aScriptConst, $aScriptStringCall
Global $bDisableFunc = False, $bDisableVar = False, $bIgnoreDisable = False

Global $iErrorCnt
Global $bInclude = True
Global $bUseBetaIncludes = False
Global $bReplaceCostants = True
Global $bRemoveConstants = True
Global $bRemoveFunctions = True
Global $bRenameFunctions = True
Global $bRenameVariables = True
Global $bInsertIncludes = True
Global $bExecCallFunc = False
Global $bExecCallVar = False
Global $bConvert0ToNot = False
Global $bOptimize = True
Global $bStop = False
Global $bVista = False
If @OSVersion = "WIN_VISTA" Or @OSVersion = "WIN_7" Then $bVista = True
Global $aIncludesDir, $aSCException[1][3], $sSCPattern, $sSCExtraPattern

Global $hGui, $hInputFile, $hOutputFile, $hButtonStart, $hButtonExit, $hCB_Save, $hButtonInput, $hButtonOutput, $hCB_Includes, $hCB_Beta
Global $hCB_RemoveFunc, $hCB_ReplaceConst, $hCB_RemoveConst, $hCB_RenameFuncs, $hCB_RenameVars, $hCB_Optimize, $hCB_OptimizeCalc
Global $hCB_OptimizeMerg, $hCB_OptimizeCase, $hCB_OptimizeHexa, $hCB_OptimizeAssi, $hSlider, $hStatusProgress, $hEntireProgress, $hStatusGui
Global $aStatusText[1000000][3], $aStatusTextAll[1000000][3], $iStatusOffsetX = 0, $iStatusOffsetY = 0, $iStatusOffsetW = 480
Global $iStatusDetail = 1, $hStatusGuiGraphic, $hStatusBitmap, $hStatusGraphic, $hStatusBrush[6], $hStatusFormat, $hStatusFamily, $hStatusFont
Global $iStatusTimer, $iStatusUpdateTime = 50, $hCB_Ignore, $hCB_LogFile, $hCB_OptimizeLine, $hCB_ExecuteFunc, $hCB_ExecuteVar, $hCB_0ToNot
Global $iStatusStep, $iStatusStepCnt, $iStatusStepMax, $iStatusStepUpdate
Global $bCmdLine = False, $bExitNoError = True, $bExitOnError = False, $bHideGui = False

_CreateGui()

_StatusAdd("#1#Another Autoit PreProcessor")
_StatusAdd("#4#by Eukalyptus")
_StatusAdd()
_StatusAdd("#3#rightclick on checkboxes to get some infos")
_StatusDrawBmp(0)
_CmdLine($CmdLine)

While 1
	Sleep(1000)
WEnd



;===========================================================================================================================
; Optimize
;===========================================================================================================================

Func _OptimizeCode(ByRef $sScript)
	Local $iTimer = TimerInit(), $iCnt
	_StatusAdd()
	_StatusAdd("#1#Optimize code")
	_StatusStepSet(6)
	If GUICtrlRead($hCB_OptimizeCalc) = 1 Then _OptimizeCalc($sScript)
	_StatusStep()
	If GUICtrlRead($hCB_OptimizeLine) = 1 Then
		$iCnt = 0
		_StatusAdd("#4#combine #2#& _ #4#-splited lines", 1, 1)
		_OptimizeLine($sScript, $iCnt)
		For $i = 0 To UBound($aScriptConst) - 1
			_OptimizeLine($aScriptConst[$i], $iCnt)
		Next
		_StatusAdd("#3#" & $iCnt & " #4#lines combined", 1, 2)
	EndIf
	_StatusStep()
	If GUICtrlRead($hCB_OptimizeMerg) = 1 Then
		$iCnt = 0
		_StatusAdd("#4#merging strings", 1, 1)
		_OptimizeMerg($sScript, $iCnt)
		For $i = 0 To UBound($aScriptConst) - 1
			_OptimizeMerg($aScriptConst[$i], $iCnt)
		Next
		_StatusAdd("#3#" & $iCnt & " #4# strings merged", 1, 2)
	EndIf
	_StatusStep()
	If GUICtrlRead($hCB_OptimizeCase) = 1 Then _OptimizeCase($sScript)
	_StatusStep()
	If GUICtrlRead($hCB_OptimizeHexa) = 1 Then _OptimizeHexa($sScript)
	_StatusStep()
	If GUICtrlRead($hCB_OptimizeAssi) = 1 Then _OptimizeAssi($sScript)
	_StatusStep()
	_StatusAdd("#1#Done... Time: #4#" & Round(TimerDiff($iTimer) / 1000, 3), 0, 1)
	Return True
EndFunc   ;==>_OptimizeCode


Func _OptimizeMerg(ByRef $sScript, ByRef $iCnt)
	Local $aLine, $sExecuted, $aIndex, $sStr1, $sStr2, $sQuote1, $sQuote2, $sQNot1, $sQNot2, $iNewIndex = UBound($aScriptQuotes) - 1
	While StringRegExp($sScript, Chr(1) & "\#\d+\#\h*&\h*" & Chr(1) & "\#\d+\#") ; solange es "string" & "string" gibt
		$aLine = _RegExSeparate($sScript, Chr(6), Chr(1) & "\#\d+\#\h*&\h*" & Chr(1) & "\#\d+\#")
		For $i = 0 To UBound($aLine) - 1
			$aIndex = StringRegExp($aLine[$i], Chr(1) & "\#(\d+)\#", 3)
			Switch UBound($aIndex)
				Case 2
					$sStr1 = $aScriptQuotes[$aIndex[0]]
					$sQuote1 = StringLeft($sStr1, 1)
					Switch $sQuote1
						Case "'"
							$sQNot1 = '"'
						Case Else
							$sQNot1 = "'"
					EndSwitch
					$sStr1 = StringTrimRight(StringTrimLeft($sStr1, 1), 1)
					$sStr2 = $aScriptQuotes[$aIndex[1]]
					$sQuote2 = StringLeft($sStr2, 1)
					Switch $sQuote2
						Case "'"
							$sQNot2 = '"'
						Case Else
							$sQNot2 = "'"
					EndSwitch
					$sStr2 = StringTrimRight(StringTrimLeft($sStr2, 1), 1)
					If Not $sStr1 Or Not $sStr2 Or ($sQuote1 <> $sQuote2 And (StringInStr($sStr1, $sQNot1) Or StringInStr($sStr2, $sQNot2))) Then ContinueCase ;Wenn einer der Strings leer ist, dann nicht mergen, weil das dann Absicht ist -> siehe RichEdit UDF: "MemoryFuncCall" & ""
					$sExecuted = Execute($sQuote1 & $sStr1 & $sQuote1 & "&" & $sQuote2 & $sStr2 & $sQuote2)
					If @error Or Not $sExecuted Then ContinueCase
					_StatusAdd("#2#" & $sQuote1 & $sStr1 & $sQuote1 & " #4#& #2#" & $sQuote2 & $sStr2 & $sQuote2 & " #4#merged to #2#" & $sQuote1 & $sExecuted & $sQuote1, 3, 2)
					$iNewIndex += 1
					ReDim $aScriptQuotes[$iNewIndex + 1]
					$aLine[$i] = Chr(1) & "#" & $iNewIndex & "#"
					$aScriptQuotes[$iNewIndex] = $sQuote1 & $sExecuted & $sQuote1
					$iCnt += 1
				Case Else
					$sStr1 = $aLine[$i]
					_RegExMerge($sStr1, Chr(1), $aScriptQuotes)
					$aLine[$i] = StringReplace($aLine[$i], "&", Chr(19), 1) ; damit das beim nächsten Durchlauf nicht mehr verwendet wird
					_StatusAdd("#3#" & $sStr1 & " & " & $sStr2 & " #4#can´t be merged", 3, 2)
					ContinueLoop
			EndSwitch
		Next
		_RegExMerge($sScript, Chr(6), $aLine)
	WEnd
	$sScript = StringReplace($sScript, Chr(19), "&")
EndFunc   ;==>_OptimizeMerg


Func _OptimizeLine(ByRef $sScript, ByRef $iCnt)
	Local $aLine, $sLine, $aSplit, $aTemp
	$aLine = _RegExSeparate($sScript, Chr(6), "(?m)^.*" & Chr(3) & ".*")
	If IsArray($aLine) Then
		For $i = 0 To UBound($aLine) - 1
			$sLine = $aLine[$i]
			_RegExMerge($sLine, Chr(4), $aScriptConst)
			_RegExMerge($sLine, Chr(1), $aScriptQuotes)
			$aSplit = StringSplit($sLine, Chr(3))
			$aTemp = StringSplit($aLine[$i], Chr(3))
			If $aSplit[0] <> $aTemp[0] Then ContinueLoop
			$sLine = $aSplit[1]
			For $j = 2 To $aSplit[0]
				If StringLen($sLine & $aSplit[$j]) < 4096 Then
					$sLine &= $aSplit[$j]
					$aSplit[$j - 1] = False
				Else
					$sLine = $aSplit[$j - 1]
					$aSplit[$j - 1] = True
					_StatusAdd("#3#can´t combine line - would exceed 4096 chars", 3, 2)
				EndIf
			Next
			$aLine[$i] = ""
			For $j = 1 To $aTemp[0]
				$aLine[$i] &= $aTemp[$j]
				Switch $aSplit[$j]
					Case True
						If $j < $aTemp[0] Then $aLine[$i] &= Chr(3)
					Case Else
						$iCnt += 1
				EndSwitch
			Next
		Next
		_RegExMerge($sScript, Chr(6), $aLine)
	EndIf
EndFunc   ;==>_OptimizeLine


Func _OptimizeAssi(ByRef $sScript)
	_StatusAdd("#4#optimize assignment operators", 1, 1)
	Local $aExp, $iCnt = 0, $sTemp, $aTemp
	$sTemp = $sScript
	$aExp = _RegExSeparate($sScript, Chr(6), '(?m)^h*(\$\w+)(?:\h*=\h*\1\h*[\+\-\*/&].*)')
	If IsArray($aExp) Then
		$aTemp = StringRegExp($sTemp, '(?m)^h*(\$\w+)(\h*=\h*\1\h*[\+\-\*/&].*)', 3)
		For $i = 0 To UBound($aExp) - 1
			$aExp[$i] &= $aTemp[$i * 2 + 1]
			$sTemp = StringRegExpReplace($aExp[$i], "\h*(=\h*)(\$\w+\h*)([\+\-\*/&])", "$3$1")
			Switch @error
				Case 0
					If @extended <> 2 Then ContinueCase
					$iCnt += 1
					_StatusAdd("#2#" & $aExp[$i] & " #4#changed to #2#" & $sTemp, 3, 2)
					$aExp[$i] = $sTemp
				Case Else
			EndSwitch
		Next
		_RegExMerge($sScript, Chr(6), $aExp)
	EndIf
	_StatusAdd("#3#" & $iCnt & " #4#assignment operators changed", 1, 2)
EndFunc   ;==>_OptimizeAssi


Func _OptimizeHexa(ByRef $sScript)
	_StatusAdd("#4#convert dec to hex", 1, 1)
	Local $aDec, $iCnt = 0, $sPar, $sExp, $sTemp
	$aDec = _RegExSeparate($sScript, Chr(6), "(?<![\.\$\#\wx-])(?:[\(=]\h*-\h*)?\d+(?![\.\w\#x])") ; da bin ich mir nicht ganz sicher!!!
	If IsArray($aDec) Then
		For $i = 0 To UBound($aDec) - 1
			$sPar = ""
			$sExp = StringStripWS($aDec[$i], 8)
			Switch StringLeft($sExp, 1)
				Case "("
					$sExp = StringTrimLeft($sExp, 1)
					$sPar = "("
				Case "="
					$sExp = StringTrimLeft($sExp, 1)
					$sPar = "="
			EndSwitch
			Switch StringLeft($sExp, 1)
				Case "-"
					If Not StringIsDigit(StringTrimLeft($sExp, 1)) Then ContinueLoop
				Case Else
					If Not StringIsDigit($sExp) Then ContinueLoop
			EndSwitch
			$sTemp = $sExp
			$sExp = Hex($sExp)
			Switch @error
				Case False
					$iCnt += 1
					_StatusAdd("#2#" & $sTemp & " #4#converted to #2#0x" & $sExp, 3, 2)
					$aDec[$i] = $sPar & "0x" & $sExp
				Case Else
			EndSwitch
		Next
		_RegExMerge($sScript, Chr(6), $aDec)
	EndIf
	_StatusAdd("#3#" & $iCnt & " #4#dec converted to hex", 1, 2)
EndFunc   ;==>_OptimizeHexa


Func _OptimizeCase(ByRef $sScript)
	_StatusAdd("#4#optimize if/case statements", 1, 1)
	Local $aLine, $iCnt = 0, $sExp, $aIndex, $iTemp = 0
	$aLine = _RegExSeparate($sScript, Chr(6), "(?im)^\h*(if\h+.*[^\$\w]then|case\h+.*|elseif\h+.*[^\$\w]then)")
	If IsArray($aLine) Then
		For $i = 0 To UBound($aLine) - 1
			$sExp = $aLine[$i]
			$sExp = StringRegExpReplace($sExp, "(?i)(\$\w+)(\h*=\h*True)", "$1 ")
			If Not @error Then $iCnt += @extended
			$aIndex = StringRegExp($sExp, Chr(1) & "\#(\d+)\#", 3)
			If IsArray($aIndex) Then
				For $j = 0 To UBound($aIndex) - 1
					Switch $aScriptQuotes[$aIndex[$j]]
						Case "''", '""'
							$sExp = StringRegExpReplace($sExp, "(?i)(\$\w+)(\h*=\h*" & Chr(1) & "\#" & $aIndex[$j] & "\#)", " NOT $1 ")
							If Not @error Then $iCnt += @extended
					EndSwitch
				Next
			EndIf
			$sExp = StringRegExpReplace($sExp, "(?i)(\$\w+)(\h*=\h*false)", " NOT $1 ")
			If Not @error Then $iCnt += @extended
			If $bConvert0ToNot = 1 Then
				$sExp = StringRegExpReplace($sExp, "(?i)(\$\w+)(\h*=\h*0[^x\.\d])", " NOT $1 ")
				If Not @error Then $iCnt += @extended
			EndIf
			If $iTemp <> $iCnt Then
				_StatusAdd("#2#" & $aLine[$i] & " #4#changed to #2#" & $sExp, 3, 2)
				$iTemp = $iCnt
			EndIf
			$aLine[$i] = $sExp
		Next
		_RegExMerge($sScript, Chr(6), $aLine)
	EndIf
	$aLine = _RegExSeparate($sScript, Chr(6), "(?im)^\h*if\h+.*[^\$\w]then\s*\n\s*.*?\n\s*endif")
	If IsArray($aLine) Then
		For $i = 0 To UBound($aLine) - 1
			$sExp = $aLine[$i]
			Switch StringRegExp($sExp, "(?im)^\h*if.*\n\h*if")
				Case True ; Zeile ist selbst ein IF-Statement
					ContinueLoop ; die zusammenfügen mach ich erst später
				Case Else ; Zeile ist sonswas
					$aLine[$i] = StringRegExpReplace($aLine[$i], "(?im)^(\h*if\h+.*[^\$\w]then)\s*\n\s*(.*?)\n\s*endif", "$1 $2")
					If Not @error Then $iCnt += @extended
					If $iTemp <> $iCnt Then
						_StatusAdd("#2#" & StringRegExpReplace($sExp, "\n", "#3#@LF#2#") & " #4#combined to single line #2#" & $aLine[$i], 3, 2)
						$iTemp = $iCnt
					EndIf
			EndSwitch
		Next
		_RegExMerge($sScript, Chr(6), $aLine)
	EndIf
	_StatusAdd("#3#" & $iCnt & " #4#changes on if/case statements", 1, 2)
EndFunc   ;==>_OptimizeCase


Func _OptimizeCalc(ByRef $sScript)
	Local $aCalc, $iCnt = 0, $iResult
	_StatusAdd("#4#calculate simple expressions", 1, 1)
	While StringRegExp($sScript, "(?i)\b((?:BitOr|BitAnd|BitXor|BitNot|A?Sin|A?Cos|A?Tan|Abs|Ceiling|Exp|Floor|Log|Mod|Round|Sqrt)\h*\([x\.\,[:xdigit:]]*\))")
		$aCalc = _RegExSeparate($sScript, Chr(6), "(?i)\b((?:BitOr|BitAnd|BitXor|BitNot|A?Sin|A?Cos|A?Tan|Abs|Ceiling|Exp|Floor|Log|Mod|Round|Sqrt)\h*\([x\.\,[:xdigit:]]*\))")
		If Not IsArray($aCalc) Then Return False
		For $i = 0 To UBound($aCalc) - 1
			$iResult = Execute($aCalc[$i])
			Switch @error
				Case True
					_StatusAdd("#5#Error calculating #4#" & $aCalc[$i], 3, 2)
				Case Else
					$iCnt += 1
					_StatusAdd("#2#" & $aCalc[$i] & " #4#calculated to #2# " & $iResult, 3, 2)
					$aCalc[$i] = $iResult
			EndSwitch
		Next
		_RegExMerge($sScript, Chr(6), $aCalc)
	WEnd
	_StatusAdd("#3#" & $iCnt & " #4# expressions calculated", 1, 2)
	Return True
EndFunc   ;==>_OptimizeCalc

;===========================================================================================================================
; END Optimize
;===========================================================================================================================



;===========================================================================================================================
; Rename Variables
;===========================================================================================================================

Func _RenameVariables(ByRef $sScript)
	Local $iTimer = TimerInit(), $aVarAll, $iCnt = 0, $aTemp, $aVar[1][2], $sVar, $sName, $iOffset = 0, $aStep
	Local $oDictionary = ObjCreate('Scripting.Dictionary'), $oDictNames = ObjCreate('Scripting.Dictionary')
	$oDictNames.CompareMode = 1
	$oDictionary.CompareMode = 1
	$bDisableVar = False
	_StatusAdd()
	_StatusAdd("#1#Rename variables")
	$aVarAll = _RegExSeparate($sScript, Chr(6), "\$\w+")
	If Not IsArray($aVarAll) Then
		_StatusAdd("#3#0 #4#variables found", 1, 1)
		Return True
	EndIf
	For $i = 0 To UBound($aVarAll) - 1
		If Not $oDictionary.Exists($aVarAll[$i]) Then $oDictionary.Add($aVarAll[$i], $aVarAll[$i]); Variables unique
	Next
	For $i = 0 To UBound($aScriptConst) - 1
		If Not $aScriptConst[$i] Then ContinueLoop
		$aTemp = StringRegExp($aScriptConst[$i], "\$\w+", 3)
		If IsArray($aTemp) Then
			For $j = 0 To UBound($aTemp) - 1
				If Not $oDictionary.Exists($aTemp[$j]) Then $oDictionary.Add($aTemp[$j], $aTemp[$j]) ; Variables unique const hinzufügen
			Next
		EndIf
	Next
	$aStep = StringRegExp($sScript, Chr(5) & "\#", 3)
	$aTemp = $oDictionary.Keys()
	_StatusAdd("#3#" & UBound($aTemp) & " #4#variables found", 1, 1)
	_StatusStepSet(UBound($aStep) * 2 + UBound($aTemp))
	ReDim $aVar[UBound($aTemp) + 1][2]
	$aVar[0][0] = UBound($aTemp)
	For $i = 1 To $aVar[0][0]
		$aVar[$i][0] = $aTemp[$i - 1]
		$aVar[$i][1] = True
		Switch $aVar[$i][0]
			Case "$cmdline" ; gibt es noch weitere Variablen, die man nicht umbenennen darf?
				$aVar[$i][1] = False
		EndSwitch
		$sVar &= ";" & $aTemp[$i - 1] & ";"
		$oDictNames.Add($aVar[$i][0], $i) ; hier sind alle namen, die beim umbenennen nicht verwendet werden dürfen
	Next
	_VarCheckBadStringCall($sScript, $aVar, $sVar, $oDictNames)
	_VarCheckInNormalString($sScript, $aVar, $sVar, $oDictNames)
	If Not $bDisableVar Then
		For $i = 1 To $aVar[0][0]
			_StatusStep()
			Switch $aVar[$i][1]
				Case True ; kann umbenannt werden
					$iCnt += 1
					$sName = _CntToName($i + $iOffset)
					While $oDictNames.Exists("$" & $sName)
						$iOffset += 1
						$sName = _CntToName($i + $iOffset)
					WEnd
					$oDictNames.Remove($aVar[$i][0])
					$oDictNames.Add("$" & $sName, 0)
					$oDictionary.Item($aVar[$i][0]) = "$" & $sName
					_StatusAdd("#2#" & $aVar[$i][0] & " #4#renamed to #2#$" & $sName, 2, 2)
				Case Else
					_StatusAdd("#3#" & $aVar[$i][0] & " #4#can´t be renamed", 3, 2)
			EndSwitch
		Next
		For $i = 0 To UBound($aVarAll) - 1
			$aVarAll[$i] = $oDictionary.Item($aVarAll[$i]) ; Variable erhält neuen Namen
		Next
		For $i = 0 To UBound($aScriptConst) - 1
			If Not $aScriptConst[$i] Then ContinueLoop
			$aTemp = _RegExSeparate($aScriptConst[$i], Chr(7), "\$\w+")
			If IsArray($aTemp) Then
				For $j = 0 To UBound($aTemp) - 1
					If $oDictionary.Exists($aTemp[$j]) Then $aTemp[$j] = $oDictionary.Item($aTemp[$j])
				Next
				_RegExMerge($aScriptConst[$i], Chr(7), $aTemp)
			EndIf
		Next
		_VarRenameInStringCall($sScript, $oDictionary)
		_RenameVariablesInComp($sScript, $oDictionary)
	EndIf
	_RegExMerge($sScript, Chr(6), $aVarAll)
	If $iCnt <> $aVar[0][0] Then _StatusAdd("#3#" & $aVar[0][0] - $iCnt & " #4# variables #5#not #4#renamed", 1, 1)
	_StatusAdd("#3#" & $iCnt & " #4# variables renamed", 1, 1)
	_StatusAdd("#1#Done... Time: #4#" & Round(TimerDiff($iTimer) / 1000, 3), 0, 1)
	Return True
EndFunc   ;==>_RenameVariables


Func _VarCheckInNormalString($sScript, ByRef $aVar, $sVar, $oDictNames)
	If Not IsArray($aScriptQuotes) Then Return
	Local $aTemp, $iIndex
	Local $oDictionary = ObjCreate('Scripting.Dictionary')
	$oDictionary.CompareMode = 1
	For $i = 1 To $aScriptStringCall[0][0]
		$aTemp = StringRegExp($aScriptStringCall[$i][1], Chr(1) & "\#(\d+)\#", 3)
		If Not IsArray($aTemp) Then ContinueLoop
		For $j = 0 To UBound($aTemp) - 1
			If Not $oDictionary.Exists($aTemp[$j]) Then $oDictionary.Add($aTemp[$j], 0)
		Next
	Next
	For $i = 0 To UBound($aScriptQuotes) - 1
		If $oDictionary.Exists(String($i)) Then ContinueLoop; String ist StringCall
		$aTemp = StringRegExp($aScriptQuotes[$i], "\$\w+", 3)
		If IsArray($aTemp) Then
			For $j = 0 To UBound($aTemp) - 1
				If $oDictNames.Exists($aTemp[$j]) Then
					$iIndex = $oDictNames.Item($aTemp[$j])
					$aVar[$iIndex][1] = False
					_StatusAdd("#2#" & $aVar[$iIndex][0] & " #3#can´t be renamed, found in string #4#" & $aScriptQuotes[$i], 2, 1)
					ContinueLoop
				EndIf
				If StringInStr($sVar, $aTemp[$j]) Then
					For $k = 1 To $aVar[0][0]
						If $aVar[$k][1] And StringInStr($aVar[$k][0], $aTemp[$j]) Then
							$aVar[$k][1] = False
							_StatusAdd("#2#" & $aVar[$k][0] & " #3#can´t be renamed, found in string #4#" & $aScriptQuotes[$i], 2, 1)
						EndIf
					Next
				EndIf
			Next
		EndIf
	Next
EndFunc   ;==>_VarCheckInNormalString


Func _RenameVariablesInComp($sScript, $oDictionary)
	If Not StringInStr($sScript, Chr(2)) Then Return
	Local $aComp, $aVar
	$aComp = StringRegExp($sScript, Chr(2) & "\#(\d+)\#", 3)
	If IsArray($aComp) Then
		For $i = 0 To UBound($aComp) - 1
			If Not StringInStr($aScriptCompiler[$aComp[$i]], "#forceref") Then ContinueLoop
			$aVar = StringRegExp($aScriptCompiler[$aComp[$i]], "\$\w+", 3)
			If IsArray($aVar) Then
				For $j = 0 To UBound($aVar) - 1
					If $oDictionary.Exists($aVar[$j]) Then $aScriptCompiler[$aComp[$i]] = StringReplace($aScriptCompiler[$aComp[$i]], $aVar[$j], $oDictionary.Item($aVar[$j]))
				Next
			EndIf
		Next
	EndIf
EndFunc   ;==>_RenameVariablesInComp


Func _VarRenameInStringCall(ByRef $sScript, $oDictionary)
	If Not StringInStr($sScript, Chr(5)) Then Return ; Script enthält keine Stringcalls
	Local $aLine, $aStringCall, $aIndex, $sTemp, $sName, $aString, $sPre
	$aLine = _RegExSeparate($sScript, Chr(7), Chr(5) & "\#\d+\#.*")
	If Not IsArray($aLine) Then Return False
	For $i = 0 To UBound($aLine) - 1
		_StatusStep()
		$aIndex = StringRegExp($aLine[$i], Chr(5) & "\#(\d+)\#", 3)
		For $j = 0 To UBound($aIndex) - 1
			If $aScriptStringCall[$aIndex[$j]][5] And $aScriptStringCall[$aIndex[$j]][3] = 1 Then ; Stringcall = Var und reiner String
				$sTemp = StringStripWS(Execute($aScriptStringCall[$aIndex[$j]][2]), 8)
				If @error Or Not $sTemp Then ContinueLoop
				$sPre = ""
				If StringLeft($sTemp, 1) = "$" Then
					$sTemp = StringTrimLeft($sTemp, 1)
					$sPre = "$"
				EndIf
				Switch $oDictionary.Exists("$" & $sTemp)
					Case True
						$aStringCall = _RegExSeparate($aLine[$i], Chr(8), Chr(5) & "\#" & $aIndex[$j] & "\#.*" & Chr(5) & "\\\#" & $aIndex[$j] & "\#")
						$sName = $oDictionary.Item("$" & $sTemp)
						If StringLeft($sName, 1) = "$" Then $sName = StringTrimLeft($sName, 1)
						If $sName = $sTemp Then
							_RegExMerge($aLine[$i], Chr(8), $aStringCall)
							ContinueLoop
						EndIf
						$sName = "'" & $sPre & $sName & "'"
						$aString = StringRegExp($aStringCall[0], Chr(1) & "\#([0-9]+)\#", 1)
						If Not IsArray($aString) Then
							_RegExMerge($aLine[$i], Chr(8), $aStringCall)
							ContinueCase
						EndIf
						$aScriptQuotes[$aString[0]] = $sName
						_StatusAdd("#4#renamed #2#" & $sTemp & " #4# in stringcall #3#" & $aScriptStringCall[$aIndex[$j]][0] & "...#2#" & $aScriptStringCall[$aIndex[$j]][2] & " #4#to #2#" & $sName, 3, 2)
						$aScriptStringCall[$aIndex[$j]][1] = $sName
						_RegExMerge($aLine[$i], Chr(8), $aStringCall)
					Case Else
						;_StatusAdd("#5#ERROR renaming #2#" & $sTemp & " #4# in stringcall #3#" & $aScriptStringCall[$aIndex[$j]][0] & "...#5#" & $aScriptStringCall[$aIndex[$j]][2], 0, 2, 1)
				EndSwitch
			EndIf
		Next
	Next
	_RegExMerge($sScript, Chr(7), $aLine)
EndFunc   ;==>_VarRenameInStringCall


Func _VarCheckBadStringCall($sScript, ByRef $aVar, $sVar, ByRef $oDictionary)
	If Not StringInStr($sScript, Chr(5)) Then Return ; Script enthält keine Stringcalls
	Local $aIndex, $sTemp, $aString
	$aIndex = StringRegExp($sScript, Chr(5) & "\#([0-9]+)\#", 3)
	If IsArray($aIndex) Then
		For $i = 0 To UBound($aIndex) - 1
			_StatusStep()
			If Not $aScriptStringCall[$aIndex[$i]][5] Then ContinueLoop ; Stringcall hat nichts mit Variablen zu tun
			Switch $aScriptStringCall[$aIndex[$i]][0]
				Case "Assign"
					If $aScriptStringCall[$aIndex[$i]][3] = 1 Then
						$sTemp = StringStripWS(Execute($aScriptStringCall[$aIndex[$i]][2]), 8)
						If $sTemp And Not $oDictionary.Exists("$" & $sTemp) Then ; Variablenname, die nicht existieren, jedoch mit Assign erstellt werden dürfen nicht zum umbenennen verwendet werden
							$oDictionary.Add("$" & $sTemp, 0)
							_StatusAdd("#2#a variable is created by stringcall #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#2#" & $aScriptStringCall[$aIndex[$i]][2], 3, 1)
						EndIf
					EndIf
			EndSwitch
			Switch $aScriptStringCall[$aIndex[$i]][3]
				Case 2 ;beginnt mit String
					$aString = StringRegExp($aScriptStringCall[$aIndex[$i]][2], '["][^"]*["]|' & "['][^']*[']", 1)
					If IsArray($aString) Then
						$sTemp = StringStripWS(Execute($aString[0]), 8)
						If @error Or Not $sTemp Then ContinueLoop
						If StringLeft($sTemp, 1) = "$" Then $sTemp = StringTrimLeft($sTemp, 1)
						If Not StringInStr($sVar, ";$" & $sTemp) Then ContinueLoop
						For $j = 1 To $aVar[0][0]
							If $aVar[$j][1] And StringInStr(";" & $aVar[$j][0], ";$" & $sTemp) Then
								$aVar[$j][1] = False
								_StatusAdd("#2#" & $aVar[$j][0] & " #3#can´t be renamed, used by stringcall #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#2#" & $aScriptStringCall[$aIndex[$i]][2], 2, 1)
							EndIf
						Next
					EndIf
				Case 3 ; TeilString
					$aString = StringRegExp($aScriptStringCall[$aIndex[$i]][2], '["][^"]*["]|' & "['][^']*[']", 3)
					If IsArray($aString) Then
						$sTemp = _GetLongest($aString)
						$sTemp = StringStripWS(Execute($sTemp), 8)
						If @error Or Not $sTemp Then ContinueLoop
						If StringLeft($sTemp, 1) = "$" Then $sTemp = StringTrimLeft($sTemp, 1)
						For $j = 1 To $aVar[0][0]
							If $aVar[$j][1] And StringInStr($aVar[$j][0], $sTemp) Then
								$aVar[$j][1] = False
								_StatusAdd("#2#" & $aVar[$j][0] & " #3#can´t be renamed, #5#maybe #3#used by stringcall #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#2#" & $aScriptStringCall[$aIndex[$i]][2], 2, 1)
							EndIf
						Next
					EndIf
				Case 4 ;Kein String
					If $bExecCallVar = 4 And $aScriptStringCall[$aIndex[$i]][0] = "Execute" Then ContinueLoop
					_StatusAdd("#5#bad stringcall found: #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#3#" & $aScriptStringCall[$aIndex[$i]][1] & " #4# is not clear and could be any variable", 0, 2)
					Switch $bIgnoreDisable
						Case 4
							$bDisableVar = True
							_StatusAdd("#5#no variable will be renamed", 0, 3, 1)
							Return
						Case Else
							_StatusAdd("#5#ignore bad stringcall - continue renaming variables", 0, 3, 1)
					EndSwitch
				Case Else
			EndSwitch
		Next
		For $i = 0 To UBound($aIndex) - 1
			If Not $aScriptStringCall[$aIndex[$i]][5] Then ContinueLoop ; Stringcall hat nichts mit Variablen zu tun
			$sTemp = StringStripWS(Execute($aScriptStringCall[$aIndex[$i]][2]), 8)
			If @error Or Not $sTemp Then ContinueLoop
			For $j = 1 To $aVar[0][0] ; Deepscan
				If $aVar[$j][1] And $sTemp <> $aVar[$j][0] And StringInStr($sTemp, $aVar[$j][0]) Then
					$aVar[$j][1] = False
					_StatusAdd("#2#" & $aVar[$j][0] & " #3#can´t be renamed, found by #5#deepscan #3#in stringcall #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#2#" & $aScriptStringCall[$aIndex[$i]][2], 2, 2)
				EndIf
			Next
		Next
	EndIf
EndFunc   ;==>_VarCheckBadStringCall

;===========================================================================================================================
; END Rename Variables
;===========================================================================================================================



;===========================================================================================================================
; Rename Functions
;===========================================================================================================================

Func _RenameFunctions(ByRef $sScript)
	Local $iTimer = TimerInit(), $iCnt = 0, $aTemp, $aFunc[1][3], $sTemp, $sFunc, $iOffset = 0, $sName, $aFuncCall, $sFull, $aStep
	Local $oDictionary = ObjCreate('Scripting.Dictionary'), $oDictNames = ObjCreate('Scripting.Dictionary')
	$oDictNames.CompareMode = 1
	$oDictionary.CompareMode = 1
	$bDisableFunc = False
	_StatusAdd()
	_StatusAdd("#1#Rename functions")
	$sFull = $sScript
	$aTemp = _RegExSeparate($sScript, Chr(6), "(?mis)^\h*func\h+\w+\h*\(.*?^\h*endfunc")
	_StatusAdd("#3#" & UBound($aTemp) & " #4#functions found", 1, 1)
	$aStep = StringRegExp($sFull, Chr(5) & "\#", 3)
	_StatusStepSet(UBound($aStep) * 2 + UBound($aTemp))
	If Not IsArray($aTemp) Then Return True
	ReDim $aFunc[UBound($aTemp) + 1][3]
	$aFunc[0][0] = UBound($aTemp)
	For $i = 1 To $aFunc[0][0]
		$sTemp = StringRegExp($aTemp[$i - 1], "(?i)func\h+(\w+)", 1)
		$aFunc[$i][0] = $sTemp[0]
		$aFunc[$i][1] = $aTemp[$i - 1]
		$aFunc[$i][2] = True
		$sFunc &= ";" & $sTemp[0] & ";"
		$oDictionary.Add($aFunc[$i][0], $aFunc[$i][0])
		$oDictNames.Add($aFunc[$i][0], $i)
	Next
	_FuncCheckBadStringCall($sFull, $aFunc, $sFunc)
	_FuncCheckInNormalString($sScript, $aFunc, $sFunc, $oDictNames)
	If Not $bDisableFunc Then
		For $i = 1 To $aFunc[0][0]
			_StatusStep()
			Switch $aFunc[$i][2]
				Case True ; kann umbenannt werden
					$iCnt += 1
					$sName = _CntToName($i + $iOffset)
					While $oDictNames.Exists("_" & $sName)
						$iOffset += 1
						$sName = _CntToName($i + $iOffset)
					WEnd
					$aTemp[$i - 1] = StringReplace($aTemp[$i - 1], $aFunc[$i][0], "_" & $sName, 1) ; Bennene Funktion selber um
					If @error Or @extended <> 1 Then Return False
					$oDictNames.Remove($aFunc[$i][0])
					$oDictNames.Add("_" & $sName, 0)
					$oDictionary.Item($aFunc[$i][0]) = "_" & $sName
					_StatusAdd("#2#" & $aFunc[$i][0] & " #4#renamed to #2#_" & $sName, 2, 2)
				Case Else
					_StatusAdd("#3#" & $aFunc[$i][0] & " #4#can´t be renamed", 3, 2)
			EndSwitch
		Next
	EndIf
	_RegExMerge($sScript, Chr(6), $aTemp)
	If @error Then Return False
	If Not $bDisableFunc Then
		$aFuncCall = _RegExSeparate($sScript, Chr(6), "(?i)(?<!\$)(\w+)(?!\w)") ; Alle Funktionsaufrufe im Script
		If IsArray($aFuncCall) Then
			For $i = 0 To UBound($aFuncCall) - 1
				If $oDictionary.Exists($aFuncCall[$i]) Then $aFuncCall[$i] = $oDictionary.Item($aFuncCall[$i])
			Next
		EndIf
		_RegExMerge($sScript, Chr(6), $aFuncCall)
		If @error Then Return False
		_FuncRenameInStringCall($sScript, $oDictionary)
	EndIf
	If $iCnt <> $aFunc[0][0] Then _StatusAdd("#3#" & $aFunc[0][0] - $iCnt & " #4# functions #5#not #4#renamed", 1, 1)
	_StatusAdd("#3#" & $iCnt & " #4# functions renamed", 1, 1)
	_StatusAdd("#1#Done... Time: #4#" & Round(TimerDiff($iTimer) / 1000, 3), 0, 1)
	Return True
EndFunc   ;==>_RenameFunctions


Func _FuncCheckInNormalString($sScript, ByRef $aFunc, $sFunc, $oDictNames)
	If Not IsArray($aScriptQuotes) Then Return
	Local $aTemp, $iIndex
	Local $oDictionary = ObjCreate('Scripting.Dictionary')
	$oDictionary.CompareMode = 1
	For $i = 1 To $aScriptStringCall[0][0]
		$aTemp = StringRegExp($aScriptStringCall[$i][1], Chr(1) & "\#(\d+)\#", 3)
		If Not IsArray($aTemp) Then ContinueLoop
		For $j = 0 To UBound($aTemp) - 1
			If Not $oDictionary.Exists($aTemp[$j]) Then $oDictionary.Add($aTemp[$j], 0)
		Next
	Next
	For $i = 0 To UBound($aScriptQuotes) - 1
		If $oDictionary.Exists(String($i)) Or Not StringInStr($aScriptQuotes[$i], "(") Then ContinueLoop; String ist StringCall
		$aTemp = StringRegExp($aScriptQuotes[$i], "(\w+)\h*\(", 3)
		If IsArray($aTemp) Then
			For $j = 0 To UBound($aTemp) - 1
				If $oDictNames.Exists($aTemp[$j]) Then
					$iIndex = $oDictNames.Item($aTemp[$j])
					$aFunc[$iIndex][2] = False
					_StatusAdd("#2#" & $aFunc[$iIndex][0] & " #3#can´t be renamed, found in string #4#" & $aScriptQuotes[$i], 2, 1)
					ContinueLoop
				EndIf
				If StringLen($aTemp[$j]) > 3 And StringInStr($sFunc, $aTemp[$j]) Then
					For $k = 1 To $aFunc[0][0]
						If $aFunc[$k][1] And StringInStr($aFunc[$k][0], $aTemp[$j]) Then
							$aFunc[$k][2] = False
							_StatusAdd("#2#" & $aFunc[$k][0] & " #3#can´t be renamed, found in string #4#" & $aScriptQuotes[$i], 2, 1)
						EndIf
					Next
				EndIf
			Next
		EndIf
	Next
EndFunc   ;==>_FuncCheckInNormalString


Func _FuncRenameInStringCall(ByRef $sScript, $oDictionary)
	Local $aLine, $aStringCall, $aIndex, $sTemp, $sName, $aString
	For $i = 0 To UBound($aScriptCompiler) - 1
		If Not StringInStr(";" & $aScriptCompiler[$i], ";#OnAutoItStartRegister") Then ContinueLoop
		$aIndex = StringRegExp($aScriptCompiler[$i], Chr(1) & "\#(\d+)\#", 1)
		$sTemp = StringStripWS(Execute($aScriptQuotes[$aIndex[0]]), 8)
		If Not $sTemp Then ContinueLoop
		For $j In $oDictionary.Keys()
			If $sTemp = $j Then
				$sName = $oDictionary.Item($sTemp)
				If $sName = $sTemp Then ContinueLoop
				$sName = '"' & $sName & '"'
				_StatusAdd("#4#renamed #2#" & $sTemp & " #4# in stringcall #3#OnAutoItStartRegister...#2#" & $aScriptQuotes[$aIndex[0]] & " #4#to #2#" & $sName, 3, 2)
				$aScriptQuotes[$aIndex[0]] = $sName
				ContinueLoop
			EndIf
		Next
	Next
	If Not StringInStr($sScript, Chr(5)) Then Return ; Script enthält keine Stringcalls
	$aLine = _RegExSeparate($sScript, Chr(7), Chr(5) & "\#\d+\#.*")
	If Not IsArray($aLine) Then Return False
	For $i = 0 To UBound($aLine) - 1
		_StatusStep()
		$aIndex = StringRegExp($aLine[$i], Chr(5) & "\#(\d+)\#", 3)
		For $j = 0 To UBound($aIndex) - 1
			If $aScriptStringCall[$aIndex[0]][4] And $aScriptStringCall[$aIndex[0]][3] = 1 Then ; Stringcall = Func und reiner String
				$sTemp = StringStripWS(Execute($aScriptStringCall[$aIndex[$j]][2]), 8)
				If @error Or Not $sTemp Or StringInStr($sTemp, "$") Then ContinueLoop
				Switch $oDictionary.Exists($sTemp)
					Case True
						$aStringCall = _RegExSeparate($aLine[$i], Chr(8), Chr(5) & "\#" & $aIndex[$j] & "\#.*" & Chr(5) & "\\\#" & $aIndex[$j] & "\#")
						$sName = $oDictionary.Item($sTemp)
						If $sName = $sTemp Then
							_RegExMerge($aLine[$i], Chr(8), $aStringCall)
							ContinueLoop
						EndIf
						$sName = "'" & $sName & "'"
						$aString = StringRegExp($aStringCall[0], Chr(1) & "\#([0-9]+)\#", 1)
						If Not IsArray($aString) Then
							_RegExMerge($aLine[$i], Chr(8), $aStringCall)
							ContinueCase
						EndIf
						$aScriptQuotes[$aString[0]] = $sName
						_StatusAdd("#4#renamed #2#" & $sTemp & " #4# in stringcall #3#" & $aScriptStringCall[$aIndex[$j]][0] & "...#2#" & $aScriptStringCall[$aIndex[$j]][2] & " #4#to #2#" & $sName, 3, 2)
						$aScriptStringCall[$aIndex[$j]][1] = $sName
						_RegExMerge($aLine[$i], Chr(8), $aStringCall)
					Case Else
						;_StatusAdd("#5#ERROR renaming #2#" & $sTemp & " #4# in stringcall #3#" & $aScriptStringCall[$aIndex[$j]][0] & "...#5#" & $aScriptStringCall[$aIndex[$j]][2], 0, 2, 1)
				EndSwitch
			EndIf
		Next
	Next
	_RegExMerge($sScript, Chr(7), $aLine)
EndFunc   ;==>_FuncRenameInStringCall


Func _FuncCheckBadStringCall($sScript, ByRef $aFunc, $sFunc)
	If Not StringInStr($sScript, Chr(5)) Then Return ; Script enthält keine Stringcalls
	Local $aIndex, $sTemp, $aString
	$aIndex = StringRegExp($sScript, Chr(5) & "\#([0-9]+)\#", 3)
	If IsArray($aIndex) Then
		For $i = 0 To UBound($aIndex) - 1
			_StatusStep()
			If Not $aScriptStringCall[$aIndex[$i]][4] Then ContinueLoop ; Stringcall hat nichts mit Functions zu tun
			Switch $aScriptStringCall[$aIndex[$i]][3]
				Case 2 ;beginnt mit String
					$aString = StringRegExp($aScriptStringCall[$aIndex[$i]][2], '["][^"]*["]|' & "['][^']*[']", 1)
					If IsArray($aString) Then
						$sTemp = StringStripWS(Execute($aString[0]), 8)
						If @error Or Not $sTemp Or Not StringInStr($sFunc, ";" & $sTemp) Then ContinueLoop
						For $j = 1 To $aFunc[0][0]
							If $aFunc[$j][2] And StringInStr(";" & $aFunc[$j][0], ";" & $sTemp) Then
								$aFunc[$j][2] = False
								_StatusAdd("#2#" & $aFunc[$j][0] & " #3#can´t be renamed, used by stringcall #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#2#" & $aScriptStringCall[$aIndex[$i]][2], 2, 1)
							EndIf
						Next
					EndIf
				Case 3 ; TeilString
					$aString = StringRegExp($aScriptStringCall[$aIndex[$i]][2], '["][^"]*["]|' & "['][^']*[']", 3)
					If IsArray($aString) Then
						$sTemp = _GetLongest($aString)
						$sTemp = StringStripWS(Execute($sTemp), 8)
						If @error Or Not $sTemp Then ContinueLoop
						For $j = 1 To $aFunc[0][0]
							If $aFunc[$j][2] And StringInStr($aFunc[$j][0], $sTemp) Then
								$aFunc[$j][2] = False
								_StatusAdd("#2#" & $aFunc[$j][0] & " #3#can´t be renamed, #5#maybe #3#used by stringcall #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#2#" & $aScriptStringCall[$aIndex[$i]][2], 2, 1)
							EndIf
						Next
					EndIf
				Case 4 ;Kein String
					If $bExecCallFunc = 4 And $aScriptStringCall[$aIndex[$i]][0] = "Execute" Then ContinueLoop
					_StatusAdd("#5#bad stringcall found: #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#3#" & $aScriptStringCall[$aIndex[$i]][1] & " #4# is not clear and could be any function", 0, 2)
					Switch $bIgnoreDisable
						Case 4
							$bDisableFunc = True
							_StatusAdd("#5#no function will be renamed", 0, 3, 1)
							Return
						Case Else
							_StatusAdd("#5#ignore bad stringcall - continue renaming functions", 0, 3, 1)
					EndSwitch
				Case Else
			EndSwitch
		Next
		For $i = 0 To UBound($aIndex) - 1
			If Not $aScriptStringCall[$aIndex[$i]][4] Then ContinueLoop ; Stringcall hat nichts mit Functions zu tun
			$sTemp = StringStripWS(Execute($aScriptStringCall[$aIndex[$i]][2]), 8)
			If @error Or Not $sTemp Then ContinueLoop
			For $j = 1 To $aFunc[0][0] ; Deepscan
				If $aFunc[$j][2] And $sTemp <> $aFunc[$j][0] And StringInStr($sTemp, $aFunc[$j][0]) Then
					$aFunc[$j][2] = False
					_StatusAdd("#2#" & $aFunc[$j][0] & " #3#can´t be renamed, found by #5#deepscan #3#in stringcall #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#2#" & $aScriptStringCall[$aIndex[$i]][2], 2, 2)
				EndIf
			Next
		Next
	EndIf
EndFunc   ;==>_FuncCheckBadStringCall

;===========================================================================================================================
; END Rename Functions
;===========================================================================================================================



;===========================================================================================================================
; Remove unused global Constants
;===========================================================================================================================

Func _RemoveUnusedGlobalConst(ByRef $sScript)
	Local $iTimer = TimerInit(), $iCnt = 0, $aConst[1][2], $aTemp
	Local $oDictionary = ObjCreate('Scripting.Dictionary')
	$oDictionary.CompareMode = 1
	$bDisableVar = False
	_StatusAdd()
	_StatusAdd("#1#Remove unused global const")
	$iCnt = $oDictGlobalConst.Count()
	_StatusAdd("#3#" & $iCnt & " #4#global constants found", 1, 1)
	If $iCnt = 0 Then Return True
	ReDim $aConst[UBound($aScriptConst)][2]
	$aTemp = StringRegExp($sScript, Chr(5), 3)
	_StatusStepSet(UBound($aTemp) + UBound($aConst) * 2)
	$aTemp = StringRegExp($sScript, "\$\w+", 3)
	If IsArray($aTemp) Then
		For $i = 0 To UBound($aTemp) - 1
			If Not $oDictionary.Exists($aTemp[$i]) Then $oDictionary.Add($aTemp[$i], 0)
		Next
	EndIf
	$aTemp = $oDictGlobalConst.Keys()
	If @error Or Not IsArray($aTemp) Then Return False
	For $i = 0 To UBound($aTemp) - 1
		_StatusStep()
		$aConst[$i][0] = $aTemp[$i]
		$oDictionary.Item($aTemp[$i]) = $i
		Switch $oDictionary.Exists($aTemp[$i])
			Case True
				$aConst[$i][1] = True
				_StatusAdd("#2#" & $aConst[$i][0] & " #4#is used", 2, 2)
			Case Else
				Switch StringInStr($aConst[$i][0], "[")
					Case True
						$aConst[$i][1] = True ; Arrays nie löschen
						_StatusAdd("#2#" & $aConst[$i][0] & " #4#is used (it´s an array)", 3, 2)
					Case Else
						$aConst[$i][1] = False
				EndSwitch
		EndSwitch
	Next
	If StringInStr($sScript, Chr(5)) Then _IsGlobalConstUsedByString($sScript, $aConst)
	_ConstUsedByNormalString($sScript, $aConst, $oDictionary)
	$iCnt = 0
	For $i = 0 To UBound($aConst) - 1
		_StatusStep()
		Switch $aConst[$i][1]
			Case False
				If Not $bDisableVar Then
					$iCnt += 1
					$aScriptConst[$i] = ""
					_StatusAdd("#3#" & $aConst[$i][0] & " #4#removed", 3, 2)
				EndIf
			Case Else
				ContinueLoop
		EndSwitch
	Next
	_StatusAdd("#3#" & $iCnt & " #4# unused global constants removed", 1, 1)
	_StatusAdd("#1#Done... Time: #4#" & Round(TimerDiff($iTimer) / 1000, 3), 0, 1)
	_StatusDrawBmp($aStatusText[0][0])
	Return True
EndFunc   ;==>_RemoveUnusedGlobalConst


Func _ConstUsedByNormalString($sScript, ByRef $aConst, $oDictNames)
	If Not IsArray($aScriptQuotes) Then Return
	Local $aTemp, $iIndex, $sConst
	Local $oDictionary = ObjCreate('Scripting.Dictionary')
	$oDictionary.CompareMode = 1
	For $i = 0 To UBound($aConst) - 1
		$sConst &= ";" & $aConst[$i][0] & ";"
	Next
	For $i = 1 To $aScriptStringCall[0][0]
		$aTemp = StringRegExp($aScriptStringCall[$i][1], Chr(1) & "\#(\d+)\#", 3)
		If Not IsArray($aTemp) Then ContinueLoop
		For $j = 0 To UBound($aTemp) - 1
			If Not $oDictionary.Exists($aTemp[$j]) Then $oDictionary.Add($aTemp[$j], 0)
		Next
	Next
	For $i = 0 To UBound($aScriptQuotes) - 1
		If $oDictionary.Exists(String($i)) Then ContinueLoop; String ist StringCall
		$aTemp = StringRegExp($aScriptQuotes[$i], "\$\w+", 3)
		If IsArray($aTemp) Then
			For $j = 0 To UBound($aTemp) - 1
				If $oDictNames.Exists($aTemp[$j]) Then
					$iIndex = $oDictNames.Item($aTemp[$j])
					If $iIndex Then
						$aConst[$iIndex][1] = True
						_StatusAdd("#2#" & $aConst[$iIndex][0] & " #3#found in string #4#" & $aScriptQuotes[$i], 2, 1)
						ContinueLoop
					EndIf
				EndIf
				If StringInStr($sConst, $aTemp[$j]) Then
					For $k = 0 To UBound($aConst[0][0]) - 1
						If Not $aConst[$k][1] And StringInStr($aConst[$k][0], $aTemp[$j]) Then
							$aConst[$k][1] = True
							_StatusAdd("#2#" & $aConst[$k][0] & " #3#found in string #4#" & $aScriptQuotes[$i], 2, 1)
						EndIf
					Next
				EndIf
			Next
		EndIf
	Next
EndFunc   ;==>_ConstUsedByNormalString


Func _IsGlobalConstUsedByString($sScript, ByRef $aConst)
	Local $aIndex, $iIndex, $sConst = "", $sTemp, $aString
	Local $oDictIndex = ObjCreate('Scripting.Dictionary')
	$oDictIndex.CompareMode = 1
	For $i = 0 To UBound($aConst) - 1
		If Not $aConst[$i][1] Then
			$sTemp = StringTrimLeft($aConst[$i][0], 1)
			$oDictIndex.Add($aConst[$i][0], $i)
			$oDictIndex.Add($sTemp, $i)
			$sConst &= ";" & $aConst[$i][0] & ";" & $sTemp & ";"
		EndIf
	Next
	$aIndex = StringRegExp($sScript, Chr(5) & "\#([0-9]+)\#", 3)
	If IsArray($aIndex) Then
		For $i = 0 To UBound($aIndex) - 1
			If Not $aScriptStringCall[$aIndex[$i]][5] Or $aScriptStringCall[$aIndex[$i]][3] <> 1 Then ContinueLoop ; Stringcall hat nichts mit Var zu tun
			$sTemp = StringStripWS(Execute($aScriptStringCall[$aIndex[$i]][2]), 8)
			If @error Or Not $sTemp Then ContinueLoop
			If StringLeft($sTemp, 1) = "$" Then $sTemp = StringTrimLeft($sTemp, 1)
			If $oDictIndex.Exists("$" & $sTemp) Then
				$iIndex = $oDictIndex.Item("$" & $sTemp)
				If Not $aConst[$iIndex][1] Then
					$aConst[$iIndex][1] = True
					_StatusAdd("#2#" & $aConst[$iIndex][0] & " #3#used by stringcall #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#2#" & $aScriptStringCall[$aIndex[$i]][2], 2, 1)
				EndIf
			EndIf
		Next
		For $i = 0 To UBound($aIndex) - 1
			_StatusStep()
			If Not $aScriptStringCall[$aIndex[$i]][5] Then ContinueLoop ; Stringcall hat nichts mit Var zu tun
			Switch $aScriptStringCall[$aIndex[$i]][3]
				Case 2 ;beginnt mit String
					$aString = StringRegExp($aScriptStringCall[$aIndex[$i]][2], '["][^"]*["]|' & "['][^']*[']", 3)
					If IsArray($aString) Then
						$sTemp = StringStripWS(Execute($aString[0]), 8)
						If StringLeft($sTemp, 1) = "$" Then $sTemp = StringTrimLeft($sTemp, 1)
						If Not @error And $sTemp <> "" And StringInStr($sConst, ";$" & $sTemp) Then
							For $j = 0 To UBound($aConst) - 1
								If Not $aConst[$j][1] And StringInStr(";" & $aConst[$j][0], ";$" & $sTemp) Then
									$aConst[$j][1] = True
									_StatusAdd("#2#" & $aConst[$j][0] & " #3#found in stringcall #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#2#" & $aScriptStringCall[$aIndex[$i]][2], 2, 1)
								EndIf
							Next
						EndIf
					EndIf
					If UBound($aString) > 1 Then ContinueCase
				Case 3 ; TeilString
					$aString = StringRegExp($aScriptStringCall[$aIndex[$i]][2], '["][^"]*["]|' & "['][^']*[']", 3)
					If IsArray($aString) Then
						_SortByLen($aString)
						For $k = 0 To UBound($aString) - 1
							If Not $aString[$k] Then ContinueLoop
							$sTemp = $aString[$k]
							$sTemp = StringStripWS(Execute($sTemp), 8)
							If @error Or Not $sTemp Then ContinueLoop
							If StringLeft($sTemp, 1) = "$" Then $sTemp = StringTrimLeft($sTemp, 1)
							If Not StringInStr($sConst, $sTemp) Then ContinueLoop
							For $j = 0 To UBound($aConst) - 1
								If Not $aConst[$j][1] And StringInStr($aConst[$j][0], $sTemp) Then
									$aConst[$j][1] = True
									_StatusAdd("#2#" & $aConst[$j][0] & " #5#maybe #3#used by stringcall #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#2#" & $aScriptStringCall[$aIndex[$i]][2], 2, 1)
								EndIf
							Next
						Next
					EndIf
				Case 4 ;Kein String
					If $bExecCallVar = 4 And $aScriptStringCall[$aIndex[$i]][0] = "Execute" Then ContinueLoop
					_StatusAdd("#5#bad stringcall found: #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#3#" & $aScriptStringCall[$aIndex[$i]][1] & " #4# is not clear and could be any constant", 0, 2)
					Switch $bIgnoreDisable
						Case 4
							$bDisableVar = True
							_StatusAdd("#5#no constant will be removed", 0, 3, 1)
							Return
						Case Else
							_StatusAdd("#5#ignore bad stringcall - continue removing unused global constants", 0, 3, 1)
					EndSwitch
				Case Else
			EndSwitch
		Next
		For $i = 0 To UBound($aIndex) - 1
			If Not $aScriptStringCall[$aIndex[$i]][5] Then ContinueLoop ; Stringcall hat nichts mit Var zu tun
			For $j = 0 To UBound($aConst) - 1 ; Deepscan
				If Not $aConst[$j][1] And StringInStr($aScriptStringCall[$aIndex[$i]][2], StringTrimLeft($aConst[$j][0], 1)) Then
					$aConst[$j][1] = True
					_StatusAdd("#2#" & $aConst[$j][0] & " #3#found via #5#deepscan #3#in stringcall #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#2#" & $aScriptStringCall[$aIndex[$i]][2], 2, 1)
				EndIf
			Next
		Next
	EndIf
EndFunc   ;==>_IsGlobalConstUsedByString

;===========================================================================================================================
; END Remove unused global Constants
;===========================================================================================================================



;===========================================================================================================================
; Replace Constants
;===========================================================================================================================

Func _ReplaceConstants(ByRef $sScript)
	Local $iTimer = TimerInit(), $iCnt, $aTemp, $sName, $sValue, $sTemp, $aFunc, $sFuncParams
	Local $oDictIndex = ObjCreate('Scripting.Dictionary')
	$oDictIndex.CompareMode = 1
	_StatusAdd()
	_StatusAdd("#1#Replace constants by their value")
	$iCnt = $oDictGlobalConst.Count()
	_StatusAdd("#3#" & $iCnt & " #4#global constants found", 1, 1)
	If $iCnt = 0 Then Return True
	$aTemp = $oDictGlobalConst.Keys()
	If @error Or Not IsArray($aTemp) Then Return False
	For $i = 0 To UBound($aTemp) - 1 ;ersetzte const in anderen constvalues
		$sValue = $oDictGlobalConst.Item($aTemp[$i])
		If _StringReplaceConstbyValue($sValue) Then
			$oDictGlobalConst.Item($aTemp[$i]) = $sValue
			$aScriptConst[$i] = "GLOBAL CONST " & $aTemp[$i] & " = " & $sValue
		EndIf
	Next
	$aFunc = _RegExSeparate($sScript, Chr(6), "(?mis)^\h*func\h+\w+\h*\(.*?^\h*endfunc")
	_StatusStepSet(UBound($aFunc) + 1)
	_StatusAdd("#4#replace const in #2#mainscript", 2, 2)
	_StatusStep()
	$iCnt = 0
	_ReplaceConstantsByValue($sScript, $iCnt)
	If IsArray($aFunc) Then
		For $i = 0 To UBound($aFunc) - 1
			_StatusStep()
			$sName = StringRegExp($aFunc[$i], "(?i)func\h+(\w+)\h*\(", 1)
			$sFuncParams = StringRegExp($aFunc[$i], "\((.*?)\)", 1)
			_StatusAdd("#4#replace const in function #2#" & $sName[0], 2, 2)
			_ReplaceConstantsByValue($aFunc[$i], $iCnt, $sName[0], $sFuncParams[0])
		Next
	EndIf
	_RegExMerge($sScript, Chr(6), $aFunc)
	_StatusAdd("#3#" & $iCnt & " #4# global constants replaced", 1, 1)
	_StatusAdd("#1#Done... Time: #4#" & Round(TimerDiff($iTimer) / 1000, 3), 0, 1)
	_StatusDrawBmp($aStatusText[0][0])
	Return True
EndFunc   ;==>_ReplaceConstants


Func _ReplaceConstantsByValue(ByRef $sScript, ByRef $iCnt, $sFuncName = "mainscript", $sFuncParams = "")
	Local $aLocal, $sTemp, $aVar
	Local $oDictLocal = ObjCreate('Scripting.Dictionary'), $oDictIndex = ObjCreate('Scripting.Dictionary')
	$oDictLocal.CompareMode = 1
	$oDictIndex.CompareMode = 1
	$aLocal = StringRegExp($sScript, "(?im)^\h*local.*", 3) ; Lokale Variablen und Constanten dürfen nicht ersetzt werden
	If IsArray($aLocal) Then
		For $i = 0 To UBound($aLocal) - 1
			$sTemp = StringRegExpReplace($aLocal[$i], "\[(?:[^[]]*|(?R))*\]|\((?:[^()]*|(?R))*\)", "") ;entfernt Klammern
			$aVar = StringRegExp($sTemp, "\$\w+", 3)
			If IsArray($aVar) Then
				For $j = 0 To UBound($aVar) - 1
					If Not $oDictLocal.Exists($aVar[$j]) Then $oDictLocal.Add($aVar[$j], $j)
				Next
			EndIf
		Next
	EndIf
	If $sFuncParams Then ;Funktions-Parameter dürfen nicht ersetzt werden
		$aVar = StringRegExp($sFuncParams, "\$\w+", 3)
		If IsArray($aVar) Then
			For $i = 0 To UBound($aVar) - 1
				If Not $oDictLocal.Exists($aVar[$i]) Then $oDictLocal.Add($aVar[$i], $i)
			Next
		EndIf
	EndIf
	$aVar = _RegExSeparate($sScript, Chr(7), "\$\w+(?=[^\w\[])") ; Alle Variablen des Scripts, ohne Arrays
	If IsArray($aVar) Then
		For $i = 0 To UBound($aVar) - 1
			If $oDictGlobalConst.Exists($aVar[$i]) Then
				Switch $oDictLocal.Exists($aVar[$i])
					Case True
						If Not $oDictIndex.Exists($aVar[$i]) Then _StatusAdd("#3#" & $aVar[$i] & " #4#is defined as local in #2#" & $sFuncName & " #4# so can´t be replaced by global const #3#" & $aVar[$i], 3, 3)
						ContinueLoop
					Case Else
						$sTemp = $aVar[$i]
						$aVar[$i] = $oDictGlobalConst.Item($aVar[$i])
						$iCnt += 1
						If Not $oDictIndex.Exists($aVar[$i]) Then _StatusAdd("#2#" & $sTemp & " #4#replaced by it´s value #2#" & $aVar[$i], 2, 3)
				EndSwitch
				If Not $oDictIndex.Exists($aVar[$i]) Then $oDictIndex.Add($aVar[$i], 0)
			EndIf
		Next
	EndIf
	_RegExMerge($sScript, Chr(7), $aVar)
EndFunc   ;==>_ReplaceConstantsByValue

;===========================================================================================================================
; END Replace Constants
;===========================================================================================================================



;===========================================================================================================================
; Remove unused functions
;===========================================================================================================================

Func _RemoveUnusedFunctions(ByRef $sScript)
	Local $iTimer = TimerInit(), $aTemp, $aFunc[1][3], $sFunc, $sTemp, $iCnt = 0, $aIndex
	Local $oDictIndex = ObjCreate('Scripting.Dictionary')
	$oDictIndex.CompareMode = 1
	_StatusAdd()
	_StatusAdd("#1#Remove unused functions")
	$aTemp = _RegExSeparate($sScript, Chr(6), "(?mis)^\h*func\h+\w+\h*\(.*?^\h*endfunc")
	_StatusAdd("#3#" & UBound($aTemp) & " #4#functions found", 1, 1)
	If Not IsArray($aTemp) Then Return True
	_StatusStepSet(UBound($aTemp))
	ReDim $aFunc[UBound($aTemp) + 1][3]
	$aFunc[0][0] = UBound($aTemp)
	For $i = 1 To $aFunc[0][0]
		$sTemp = StringRegExp($aTemp[$i - 1], "(?i)func\h+(\w+)", 1)
		$aFunc[$i][0] = $sTemp[0]
		$aFunc[$i][1] = $aTemp[$i - 1]
		$aFunc[$i][2] = False
		$sFunc &= ";" & $sTemp[0] & ";"
		If Not $oDictIndex.Exists($sTemp[0]) Then $oDictIndex.Add($sTemp[0], $i)
	Next
	For $i = 0 To UBound($aScriptCompiler) - 1
		If Not StringInStr(";" & $aScriptCompiler[$i], ";#OnAutoItStartRegister") Then ContinueLoop
		$aIndex = StringRegExp($aScriptCompiler[$i], Chr(1) & "\#(\d+)\#", 1)
		$sTemp = StringStripWS(Execute($aScriptQuotes[$aIndex[0]]), 8)
		If Not $sTemp Then ContinueLoop
		For $j = 1 To $aFunc[0][0]
			If $sTemp = $aFunc[$j][0] Then
				$aFunc[$j][2] = True
				_StatusAdd("#2#" & $aFunc[$j][0] & " #3#used by stringcall #4#OnAutoItStartRegister...#2#" & $aScriptQuotes[$aIndex[0]], 2, 1)
				_FindUsedFunctions($aFunc[$j][1], $aFunc, $sFunc, $oDictIndex)
				ContinueLoop
			EndIf
		Next
	Next
	_FindUsedFunctions($sScript, $aFunc, $sFunc, $oDictIndex)
	If Not $bDisableFunc Then
		For $i = 1 To $aFunc[0][0]
			If Not $aFunc[$i][2] Then
				_StatusStep()
				$aTemp[$i - 1] = ""
				$iCnt += 1
				_StatusAdd("#3#" & $aFunc[$i][0] & " is not used", 3, 2)
			EndIf
		Next
	EndIf
	_RegExMerge($sScript, Chr(6), $aTemp)
	If @error Then Return False
	_StatusAdd("#3#" & $aFunc[0][0] - $iCnt & " #4# used functions found", 1, 1)
	_StatusAdd("#3#" & $iCnt & " #4# unused functions removed", 1, 1)
	_StatusAdd("#1#Done... Time: #4#" & Round(TimerDiff($iTimer) / 1000, 3), 0, 1)
	_StatusDrawBmp($aStatusText[0][0])
	Return True
EndFunc   ;==>_RemoveUnusedFunctions


Func _FindUsedFunctions($sScript, ByRef $aFunc, $sFunc, $oDictIndex, $iStatusLevel = 0)
	_StatusStep()
	If $bDisableFunc Then Return
	Local $aFuncCall, $iIndex, $aIndex, $sTemp, $aString, $aSort
	$aFuncCall = StringRegExp($sScript, "(?<![\w\$@])([a-zA-Z_]\w*)(?:\W)", 3)
	For $i = 0 To UBound($aFuncCall) - 1
		If Not $oDictIndex.Exists($aFuncCall[$i]) Then ContinueLoop
		$iIndex = $oDictIndex.Item($aFuncCall[$i])
		If Not $aFunc[$iIndex][2] Then
			$aFunc[$iIndex][2] = True
			_StatusAdd("#2#" & $aFunc[$iIndex][0] & " #4#is used", 2, 1 + $iStatusLevel)
			_FindUsedFunctions($aFunc[$iIndex][1], $aFunc, $sFunc, $oDictIndex, $iStatusLevel + 1)
		EndIf
	Next
	If StringInStr($sScript, Chr(5)) Then ; Script enthält Stringcalls
		$aIndex = StringRegExp($sScript, Chr(5) & "\#([0-9]+)\#", 3)
		If IsArray($aIndex) Then
			For $i = 0 To UBound($aIndex) - 1 ; Zuerst Alle NurStrings durchsuchen
				If Not $aScriptStringCall[$aIndex[$i]][4] Or $aScriptStringCall[$aIndex[$i]][3] <> 1 Then ContinueLoop ; Stringcall hat nichts mit Func zu tun
				$sTemp = StringStripWS(Execute($aScriptStringCall[$aIndex[$i]][2]), 8)
				If @error Or Not $sTemp Then ContinueLoop
				If $oDictIndex.Exists($sTemp) Then
					$iIndex = $oDictIndex.Item($sTemp)
					If Not $aFunc[$iIndex][2] Then
						$aFunc[$iIndex][2] = True
						_StatusAdd("#2#" & $aFunc[$iIndex][0] & " #3#used by stringcall #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#2#" & $aScriptStringCall[$aIndex[$i]][2], 2, 1 + $iStatusLevel)
						_FindUsedFunctions($aFunc[$iIndex][1], $aFunc, $sFunc, $oDictIndex, $iStatusLevel + 1)
					EndIf
				EndIf
			Next
			For $i = 0 To UBound($aIndex) - 1
				If Not $aScriptStringCall[$aIndex[$i]][4] Then ContinueLoop ; Stringcall hat nichts mit Func zu tun
				Switch $aScriptStringCall[$aIndex[$i]][3]
					Case 2 ;beginnt mit String
						$aString = StringRegExp($aScriptStringCall[$aIndex[$i]][2], '["][^"]*["]|' & "['][^']*[']", 3)
						If IsArray($aString) Then
							$sTemp = StringStripWS(Execute($aString[0]), 8)
							If Not @error And $sTemp <> "" And StringInStr($sFunc, ";" & $sTemp) Then
								For $j = 1 To $aFunc[0][0]
									If Not $aFunc[$j][2] And StringInStr(";" & $aFunc[$j][0], ";" & $sTemp) Then
										$aFunc[$j][2] = True
										_StatusAdd("#2#" & $aFunc[$j][0] & " #3#found in stringcall #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#2#" & $aScriptStringCall[$aIndex[$i]][2], 2, 1 + $iStatusLevel)
										_FindUsedFunctions($aFunc[$j][1], $aFunc, $sFunc, $oDictIndex, $iStatusLevel + 1)
									EndIf
								Next
							EndIf
						EndIf
						If UBound($aString) > 1 Then ContinueCase ; String enthält mehrere Teilstrings
					Case 3 ; TeilString
						$aString = StringRegExp($aScriptStringCall[$aIndex[$i]][2], '["][^"]*["]|' & "['][^']*[']", 3)
						If IsArray($aString) Then
							_SortByLen($aString)
							For $k = 0 To UBound($aString) - 1
								If Not $aString[$k] Then ContinueLoop
								$sTemp = $aString[$k]
								$sTemp = StringStripWS(Execute($sTemp), 8)
								If @error Or Not $sTemp Or Not StringInStr($sFunc, $sTemp) Then ContinueLoop
								For $j = 1 To $aFunc[0][0]
									If Not $aFunc[$j][2] And StringInStr($aFunc[$j][0], $sTemp) Then
										$aFunc[$j][2] = True
										_StatusAdd("#2#" & $aFunc[$j][0] & " #5#maybe #3#used by stringcall #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#2#" & $aScriptStringCall[$aIndex[$i]][2], 2, 1 + $iStatusLevel)
										_FindUsedFunctions($aFunc[$j][1], $aFunc, $sFunc, $oDictIndex, $iStatusLevel + 1)
									EndIf
								Next
							Next
						EndIf
					Case 4 ;Kein String
						If $bExecCallFunc = 4 And $aScriptStringCall[$aIndex[$i]][0] = "Execute" Then ContinueLoop
						_StatusAdd("#5#bad stringcall found: #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#3#" & $aScriptStringCall[$aIndex[$i]][1] & " #4# is not clear and could be any function", 0, 2)
						Switch $bIgnoreDisable
							Case 4
								$bDisableFunc = True
								_StatusAdd("#5#no function will be removed", 0, 3, 1)
								Return
							Case Else
								_StatusAdd("#5#ignore bad stringcall - continue removing unused functions", 0, 3, 1)
						EndSwitch
					Case Else
				EndSwitch
			Next
			For $i = 0 To UBound($aIndex) - 1
				If Not $aScriptStringCall[$aIndex[$i]][4] Then ContinueLoop ; Stringcall hat nichts mit Func zu tun
				For $j = 1 To $aFunc[0][0] ; Deepscan
					If Not $aFunc[$j][2] And StringInStr($aScriptStringCall[$aIndex[$i]][2], $aFunc[$j][0]) Then
						$aFunc[$j][2] = True
						_StatusAdd("#2#" & $aFunc[$j][0] & " #3#found via #5#deepscan #3#in stringcall #4#" & $aScriptStringCall[$aIndex[$i]][0] & "...#2#" & $aScriptStringCall[$aIndex[$i]][2], 2, 1 + $iStatusLevel)
						_FindUsedFunctions($aFunc[$j][1], $aFunc, $sFunc, $oDictIndex, $iStatusLevel + 1)
					EndIf
				Next
			Next
		EndIf
	EndIf
EndFunc   ;==>_FindUsedFunctions


Func _SortByLen(ByRef $aArray)
	Local $aSort[UBound($aArray)][2]
	For $i = 0 To UBound($aSort) - 1
		$aSort[$i][0] = $aArray[$i]
		$aSort[$i][1] = StringLen($aArray[$i])
	Next
	_ArraySort($aSort, 1, 0, 0, 1)
	For $i = 0 To UBound($aSort) - 1
		Switch $aSort[$i][1]
			Case 0 To 3
				$aArray[$i] = "" ; nur stringlängen größer als 1 (excl quotes)
			Case Else
				$aArray[$i] = $aSort[$i][0]
		EndSwitch
	Next
EndFunc   ;==>_SortByLen


Func _GetLongest($aArray)
	Local $iLen, $sReturn, $iMax = 0
	For $i = 0 To UBound($aArray) - 1
		$iLen = StringLen($aArray[$i])
		If $iLen > $iMax Then
			$iMax = $iLen
			$sReturn = $aArray[$i]
		EndIf
	Next
	Return $sReturn
EndFunc   ;==>_GetLongest

;===========================================================================================================================
; END Remove unused functions
;===========================================================================================================================



;===========================================================================================================================
; Prepare/Finish Script (excludiere Quotes, Compileranweisungen, und Const bekommen alle eine eigene Zeile
;===========================================================================================================================

Func _PrepareScript(ByRef $sScript)
	Local $iTimer = TimerInit(), $aConst, $sTemp, $sScope, $sName, $sValue, $aSplit
	_StatusAdd()
	_StatusAdd("#1#Prepare Script")
	_StatusStepSet(5)
	$bDisableFunc = False
	$bDisableVar = False
	$aScriptQuotes = _RegExSeparate($sScript, Chr(1), '["][^"]*["]|' & "['][^']*[']");Alle Quotes in ein Array und durch Chr(1)#Index# ersetzen -> $aScriptQuotes
	If @error Then Return False
	_StatusStep()
	_StatusAdd("#3#" & UBound($aScriptQuotes) & " #4#quotes excluded", 1, 1)
	$sScript = StringRegExpReplace($sScript, "(?i)\s*#include-once.*", "") ;#include-once entfernen
	$aScriptCompiler = _RegExSeparate($sScript, Chr(2), "(?<![" & Chr(1) & "\d])\#.+");Alle Compileranweisungen in ein Array und durch Chr(2)#Index# ersetzen -> $aScriptCompiler
	If @error Then Return False
	_StatusStep()
	_StatusAdd("#3#" & UBound($aScriptCompiler) & " #4#compiler directives excluded", 1, 1)
	$sScript = StringRegExpReplace($sScript, '\b\s*_\s*\n\s*', " " & Chr(3)) ; geteilte Zeilen zusammenfügen
	_StatusAdd("#3#" & @extended & " #4#splited lines joined", 1, 1)
	;Alle Global/Local/Dim/Static? Const bekommen eine eigene Zeile
	$aConst = _RegExSeparate($sScript, Chr(4), "(?i)((?:global|local|dim|static)(?:\h+const\h+)(?:.*))")
	_StatusStep()
	If @error Then Return False
	_StatusAdd("#3#" & UBound($aConst) & " #4#constant declaration lines found", 1, 1)
	For $i = 0 To UBound($aConst) - 1
		$aConst[$i] = StringRegExpReplace($aConst[$i], "[\r\n]", "")
		$sScope = StringUpper(StringRegExpReplace($aConst[$i], "(?i).*?(global|local|dim|static).*", "$1"))
		Switch StringRegExp($aConst[$i], "=.*=")
			Case True ;es gibt mehrere = ; d.h. es werden mehrere const in einer Zeile deklariert
				$aSplit = StringSplit($aConst[$i], "=")
				$aConst[$i] = StringStripWS($aSplit[$aSplit[0]], 3) ; value der letzten const
				For $j = $aSplit[0] - 1 To 2 Step -1
					$sName = StringRegExpReplace($aSplit[$j], ".*(\$\w+)", "$1", 1); const name
					$aSplit[$j] = StringReplace($aSplit[$j], $sName, "")
					$sName = StringStripWS($sName, 8)
					$sValue = StringRegExp($aSplit[$j], "(.*),", 3)
					$sValue = StringStripWS($sValue[0], 3);value der const des NÄCHSTEN! Durchlaufs
					$aConst[$i] = $sValue & @CRLF & $sScope & " CONST " & $sName & " = " & $aConst[$i]
				Next
				$sName = StringStripWS(StringRegExpReplace($aSplit[$j], ".*(\$\w+)", "$1", 1), 8); const name
				$aConst[$i] = $sScope & " CONST " & $sName & " = " & $aConst[$i]
			Case Else ;es gibt nur eine const in dieser Zeile
				$sName = StringStripWS(StringRegExpReplace($aConst[$i], ".*?(\$[^=]+).*", "$1", 1), 8)
				$sValue = StringStripWS(StringRegExpReplace($aConst[$i], ".*?=\h*(.*)", "$1", 1), 3)
				$aConst[$i] = $sScope & " CONST " & $sName & " = " & $sValue & @CRLF
		EndSwitch
	Next
	_RegExMerge($sScript, Chr(4), $aConst)
	$aScriptConst = _RegExSeparate($sScript, Chr(4), "(?i)(global\h+const\h+.*)")
	_StatusAdd("#3#" & UBound($aScriptConst) & " #4#global constants found", 1, 2)
	For $i In $oDictGlobalConst.Keys()
		$oDictGlobalConst.Remove($i)
	Next
	If IsArray($aScriptConst) Then
		For $i = 0 To UBound($aScriptConst) - 1
			$sName = StringRegExp($aScriptConst[$i], "(?i)global\h+const\h+((?:\$\w+)\h*(?:.*?))\h*=", 1)
			$sName = StringStripWS($sName[0], 8)
			$sValue = StringRegExpReplace(StringRegExpReplace($aScriptConst[$i], "(?i).*=\h*", ""), "[\r\n]", "")
			If Not $oDictGlobalConst.Exists($sName) Then $oDictGlobalConst.Add($sName, $sValue)
		Next
	EndIf
	_StatusStep()
	_CreateNewPattern()
	_GetExtraStringCallFuncs($sScript)
	_GetStringCalls($sScript)
	_StatusStep()
	_StatusAdd("#1#Done... Time: #4#" & Round(TimerDiff($iTimer) / 1000, 3), 0, 1)
	_StatusDrawBmp($aStatusText[0][0])
	Return True
EndFunc   ;==>_PrepareScript


Func _GetExtraStringCallFuncs($sScript)
	Local $aFunc, $aCallFunc, $aLine, $aTemp, $aIndex, $aExp, $iIndex, $sParam, $sFunc, $sCall, $sPattern = "|", $aException[4][3], $iCnt = 0, $sTemp
	$aException[0][0] = 3
	$iCnt = 3
	$aException[1][0] = "__IEInternalErrorHandlerDeRegister"
	$aException[1][1] = "ObjEvent"
	$aException[1][2] = "$sIEUserErrorHandler"
	$aException[2][0] = "_SQLite_GetTable2d"
	$aException[2][1] = "Call"
	$aException[2][2] = "$sCallBack"
	$aException[3][0] = "__WordInternalErrorHandlerDeRegister"
	$aException[3][1] = "ObjEvent"
	$aException[3][2] = "$sWordUserErrorHandler"
	Local $oDictionary = ObjCreate('Scripting.Dictionary')
	$oDictionary.CompareMode = 1
	$aFunc = StringRegExp($sScript, "(?mis)^\h*func\h+\w+\h*\(.*?^\h*endfunc", 3)
	If Not IsArray($aFunc) Then Return
	_StatusAdd("#4#looking for extra stringcall functions...", 1, 1)
	For $i = 0 To UBound($aFunc) - 1
		$aCallFunc = _RegExSeparate($aFunc[$i], Chr(6), "(?mi)(?<=[^\w\$\.]|^)(" & $sSCPattern & ")(?!\w)")
		If Not IsArray($aCallFunc) Then ContinueLoop
		$aLine = StringRegExp($aFunc[$i], Chr(6) & ".*", 3); Von Funktion bis Zeilenende
		For $j = 0 To UBound($aLine) - 1
			$aIndex = StringRegExp($aLine[$j], Chr(6) & "\#(\d+)\#", 3)
			For $k = 0 To UBound($aIndex) - 1 ;Somit werden auch SCF erkannt, welche inerhalb einer SCF sind
				$aTemp = StringRegExp($aLine[$j], Chr(6) & "\#" & $aIndex[$k] & "\#(.*)", 1);FuncStart bis Zeilenende
				$aExp = StringRegExp($aTemp[0], "\((?:[^()]*|(?R))*\)", 1);Ausdruck der gesammten Klammer
				$aExp[0] = StringRegExpReplace(StringTrimRight(StringTrimLeft($aExp[0], 1), 1), "\((?:[^()]*|(?R))*\)", "") ;entferne optionale Klammern
				$aTemp = StringRegExp($oSCParam.Item($aCallFunc[$aIndex[$k]]), ";(\d+);", 1)
				$iIndex = $aTemp[0]
				$aTemp = StringRegExp($aExp[0], "[^,]+", 3) ; Einzelne Parameter
				If $iIndex > UBound($aTemp) Then ContinueLoop ;Stringcall ist leer
				If $aCallFunc[$aIndex[$k]] = "ObjEvent" Then
					$sTemp = $aTemp[0]
					_RegExMerge($sTemp, Chr(1), $aScriptQuotes) ;füge Strings ein
					If Not StringInStr($sTemp, "AutoIt.Error") Then ContinueLoop ; ObjEvent nur, wenn "AutoIt.Error" erster Parameter!?
				EndIf
				$sParam = StringStripWS($aTemp[$iIndex - 1], 8)
				If StringRegExp($sParam, "[^\$\w]") Then ContinueLoop ; Parameter ist keine variable
				$aTemp = StringRegExp($aFunc[$i], "(?i)func\h+(\w+)", 1)
				$sFunc = $aTemp[0]
				If $oDictionary.Exists($sFunc & "," & $sParam) Then ContinueLoop ; Kombination Func-Param wurde schon registriert
				$oDictionary.Add($sFunc & "," & $sParam, 0)
				$aTemp = StringRegExp($aFunc[$i], "(?i)func\h+\w+\h*\((.*)\)", 1) ; Parameter der Funktion
				If Not StringInStr($aTemp[0], $sParam) Then ContinueLoop ; Parameter gibt es nicht als Funktionsparameter
				$aTemp = StringRegExp($aTemp[0], "(?i)(.*)\h*\" & $sParam, 1)
				StringRegExpReplace($aTemp[0], ",", ""); Liefert Position des Parameters
				If @error Then ContinueLoop
				$iIndex = @extended + 1
				$sCall = $aCallFunc[$aIndex[$k]]
				$sPattern &= $sFunc & "|"
				Switch $oSCParam.Exists($sFunc)
					Case False
						$oSCParam.Add($sFunc, ";" & $iIndex & ";") ;Parameter Cnt
					Case Else ; Es existiert schon ein Eintrag - hinzufügen
						$aTemp = $oSCParam.Item($sFunc)
						$oSCParam.Item($sFunc) = $aTemp & ";" & $iIndex & ";"
				EndSwitch
				If $oSCIsFunc.Exists($sCall) And Not $oSCIsFunc.Exists($sFunc) Then $oSCIsFunc.Add($sFunc, 0) ;Stringcall = Function
				If $oSCIsVar.Exists($sCall) And Not $oSCIsVar.Exists($sFunc) Then $oSCIsVar.Add($sFunc, 0)
				$iCnt += 1
				ReDim $aException[$iCnt + 1][3]
				$aException[$iCnt][0] = $sFunc
				$aException[$iCnt][1] = $sCall
				$aException[$iCnt][2] = $sParam
				Select
					Case $oSCIsFunc.Exists($sCall) And $oSCIsVar.Exists($sCall)
						_StatusAdd("#2#" & $sFunc & "#4#/#3#" & $sParam & " #4#registered as a function and variable strincall", 2, 2)
					Case $oSCIsFunc.Exists($sCall)
						_StatusAdd("#2#" & $sFunc & "#4#/#3#" & $sParam & " #4#registered as a function strincall", 2, 2)
					Case $oSCIsVar.Exists($sCall)
						_StatusAdd("#2#" & $sFunc & "#4#/#3#" & $sParam & " #4#registered as a variable strincall", 2, 2)
				EndSelect
			Next
		Next
	Next
	$sPattern = StringTrimRight($sPattern, 1)
	$sSCExtraPattern = $sPattern
	$aException[0][0] = $iCnt
	$aSCException = $aException
EndFunc   ;==>_GetExtraStringCallFuncs


Func _GetStringCalls(ByRef $sScript)
	Local $aStringCall[1][7], $aCallFunc, $aExp, $sExp, $aPar, $aLine, $iCnt = 0, $aSplit, $iIndex, $aIndex, $aTemp, $sTemp, $sLine
	$aStringCall[0][0] = 0
	$aScriptStringCall = $aStringCall
	$aCallFunc = _RegExSeparate($sScript, Chr(6), "(?mi)(?<=[^\w\$\.]|^)(" & $sSCPattern & $sSCExtraPattern & ")(?!\w)")
	If Not IsArray($aCallFunc) Then Return
	$sScript = StringRegExpReplace($sScript, "(?i)(\n\h*func\h*)" & Chr(6), "$1" & Chr(19)) ; Functionen aus UDFs dürfen nicht dazu
	ReDim $aStringCall[UBound($aCallFunc) + 1][7]
	$aLine = _RegExSeparate($sScript, Chr(7), Chr(6) & ".*"); Von Funktion bis Zeilenende
	For $i = 0 To UBound($aLine) - 1
		$aIndex = StringRegExp($aLine[$i], Chr(6) & "\#(\d+)\#", 3)
		For $j = 0 To UBound($aIndex) - 1
			$sLine = $aLine[$i]
			$aTemp = _RegExSeparate($aLine[$i], Chr(18), Chr(6) & "\#" & $aIndex[$j] & "\#.*"); FuncStart bis Zeilenende     !!!!!!!!!!!!Warum ist .* nich eingeklammert?
			$aExp = _RegExSeparate($aTemp[0], Chr(8), "\((?:[^()]*|(?R))*\)") ; liefert den gesammten Ausdruck der Klammer
			$aExp[0] = StringTrimRight(StringTrimLeft($aExp[0], 1), 1)
			$aPar = _RegExSeparate($aExp[0], Chr(17), "\((?:[^()]*|(?R))*\)") ; entferne optionale Klammern (BitAnd usw...)
			$iIndex = $oSCParam.Item($aCallFunc[$aIndex[$j]])
			$aSplit = StringSplit($aExp[0], ",")
			If $aCallFunc[$aIndex[$j]] = "ObjEvent" Then
				$sTemp = $aSplit[1]
				_RegExMerge($sTemp, Chr(1), $aScriptQuotes) ;füge Strings ein
				If Not StringInStr($sTemp, "AutoIt.Error") Then
					$aLine[$i] = $sLine
					ContinueLoop ; ObjEvent nur, wenn "AutoIt.Error" erster Parameter!?
				EndIf
			EndIf
			$sExp = ""
			For $k = 1 To $aSplit[0]
				Switch StringInStr($iIndex, ";" & $k & ";")
					Case True
						$iCnt += 1
						If $iCnt + 1 > UBound($aStringCall) Then ReDim $aStringCall[$iCnt + 1][7]
						$aStringCall[$iCnt][0] = $aCallFunc[$aIndex[$j]]
						$aStringCall[$iCnt][1] = $aSplit[$k]
						If StringInStr($aStringCall[$iCnt][1], Chr(6)) Then _RegExMerge($aStringCall[$iCnt][1], Chr(6), $aCallFunc)
						If StringInStr($aStringCall[$iCnt][1], Chr(17)) Then _RegExMerge($aStringCall[$iCnt][1], Chr(17), $aPar)
						$sExp &= Chr(5) & "#" & $iCnt & "#" & $aSplit[$k] & Chr(5) & "\#" & $iCnt & "#"
					Case Else
						$sExp &= $aSplit[$k]
				EndSwitch
				If $k < $aSplit[0] Then $sExp &= ","
			Next
			$aExp[0] = $sExp
			_RegExMerge($aExp[0], Chr(17), $aPar) ; Klammern wieder einfügen (z.b. BitAnd...)
			$aExp[0] = "(" & $aExp[0] & ")"
			_RegExMerge($aTemp[0], Chr(8), $aExp) ; Klammer wieder einfügen (die gesammte Klammer der Funktion)
			_RegExMerge($aLine[$i], Chr(18), $aTemp)
		Next
	Next
	$aStringCall[0][0] = $iCnt
	_RegExMerge($sScript, Chr(7), $aLine) ; Füge Zeile wieder in das Script ein
	$sScript = StringReplace($sScript, Chr(19), Chr(6))
	_RegExMerge($sScript, Chr(6), $aCallFunc)
	_StatusAdd("#3#" & $iCnt & " #4#stringcalls found", 1, 1)
	_ExecuteStringCall($aStringCall)
	_StringCallExceptions($sScript, $aStringCall)
	$aScriptStringCall = $aStringCall
	;_ArrayDisplay($aScriptStringCall)
EndFunc   ;==>_GetStringCalls


Func _CreateNewPattern()
	Local $sStringCall = "GUISetOnEvent|2|True|False" & @LF & _
			"GUICtrlSetOnEvent|2|True|False" & @LF & _
			"GUIRegisterMsg|2|True|False" & @LF & _
			"HotKeySet|2|True|False" & @LF & _
			"Execute|1|True|True" & @LF & _
			"Eval|1|False|True" & @LF & _
			"Assign|1|False|True" & @LF & _
			"IsDeclared|1|False|True" & @LF & _
			"Call|1|True|False" & @LF & _
			"TraySetOnEvent|2|True|False" & @LF & _
			"TrayItemSetOnEvent|2|True|False" & @LF & _
			"DllCallbackRegister|1|True|False" & @LF & _
			"AdlibRegister|1|True|False" & @LF & _
			"AdlibUnRegister|1|True|False" & @LF & _
			"GUICtrlRegisterListViewSort|2|True|False" & @LF & _
			"OnAutoItExitRegister|1|True|False" & @LF & _
			"OnAutoItExitUnRegister|1|True|False" & @LF & _
			"ObjEvent|2|True|False" & @LF & _
			"_SQLite_Exec|3|True|False"
	Local $iCnt = 0, $aSplit, $aTemp = StringSplit($sStringCall, @LF)
	For $i In $oSCParam.Keys()
		$oSCParam.Remove($i)
	Next
	For $i In $oSCIsFunc.Keys()
		$oSCIsFunc.Remove($i)
	Next
	For $i In $oSCIsVar.Keys()
		$oSCIsVar.Remove($i)
	Next
	$sSCPattern = ""
	For $i = 1 To $aTemp[0]
		$aSplit = StringSplit($aTemp[$i], "|", 2)
		If UBound($aSplit) <> 4 Then ContinueLoop
		$sSCPattern &= $aSplit[0]
		If $i < $aTemp[0] Then $sSCPattern &= "|"
		$oSCParam.Add($aSplit[0], ";" & $aSplit[1] & ";") ;Parameter Cnt
		If $aSplit[2] = "True" Then $oSCIsFunc.Add($aSplit[0], 0) ;Stringcall = Function
		If $aSplit[3] = "True" Then $oSCIsVar.Add($aSplit[0], 0) ;StringCall = Variable
	Next
	$sSCExtraPattern = ""
EndFunc   ;==>_CreateNewPattern






Func _StringCallExceptions($sScript, ByRef $aStringCall)
	Local $aFunc, $sReverse = _StringReverse($sScript), $sFunc
	For $i = 1 To $aStringCall[0][0]
		For $j = 1 To $aSCException[0][0]
			If StringStripWS($aStringCall[$i][0], 8) = $aSCException[$j][1] And StringStripWS($aStringCall[$i][1], 8) = $aSCException[$j][2] Then
				$aFunc = StringRegExp($sReverse, "(?is)\#" & _StringReverse($i) & "\#" & Chr(5) & ".*?(\w+)\h+cnuf\h*\n", 1)
				If IsArray($aFunc) Then
					$sFunc = _StringReverse($aFunc[0])
					If $sFunc = $aSCException[$j][0] Then $aStringCall[$i][3] = 0
				EndIf
			EndIf
		Next
	Next
EndFunc   ;==>_StringCallExceptions


Func _ExecuteStringCall(ByRef $aStringCall)
	Local $sTemp, $sExecuted, $aSplit, $bFirst, $sString, $bIsString, $aIndex, $iLen
	For $i = 1 To $aStringCall[0][0]
		$aStringCall[$i][3] = 9
		$bFirst = False
		$bIsString = False
		If $oSCIsFunc.Exists($aStringCall[$i][0]) Then $aStringCall[$i][4] = True
		If $oSCIsVar.Exists($aStringCall[$i][0]) Then $aStringCall[$i][5] = True
		$aStringCall[$i][2] = $aStringCall[$i][1]
		_StringReplaceConstbyValue($aStringCall[$i][2]) ;ersetzte Const durch value
		_RegExMerge($aStringCall[$i][2], Chr(1), $aScriptQuotes) ;füge Strings ein
		Switch $aStringCall[$i][2]
			Case "", "''", '""'
				$aStringCall[$i][3] = 0
				ContinueLoop
		EndSwitch
		Select
			Case StringInStr($aStringCall[$i][1], "replace");stringreplace und stringregexpreplace
				$aStringCall[$i][3] = 4
			Case Not StringInStr($aStringCall[$i][1], Chr(1)) ;überhaupt kein string
				$aStringCall[$i][3] = 4
				$sTemp = StringStripWS($aStringCall[$i][1], 8)
				Select
					Case $sTemp = '0' Or $sTemp = ""
						$aStringCall[$i][3] = 0
					Case $aStringCall[$i][0] = "Execute" And StringRegExp($sTemp, "[\+\-\*/]")
						$aStringCall[$i][3] = 0
				EndSelect
			Case Not StringRegExp($aStringCall[$i][1], "[^" & Chr(1) & "\#\d\h]") ; besteht nur einem String
				$aStringCall[$i][3] = 1
			Case StringRegExp($aStringCall[$i][1], "(?m)^" & Chr(1) & "\#\d+\#") ; beginnt mit einem String
				$aStringCall[$i][3] = 2
			Case StringInStr($aStringCall[$i][1], Chr(1)) ; enthält zumindest einen String
				$aStringCall[$i][3] = 3
		EndSelect
		Switch $aStringCall[$i][3]
			Case 3 ; Teilstring
				$aIndex = StringRegExp($aStringCall[$i][1], Chr(1) & "\#(\d+)\#", 3)
				If IsArray($aIndex) Then
					$iLen = 0
					For $j = 0 To UBound($aIndex) - 1
						$sTemp = StringLen($aScriptQuotes[$aIndex[$j]])
						If $sTemp > $iLen Then $iLen = $sTemp
					Next
					If $iLen < 5 Then $aStringCall[$i][3] = 4
				EndIf
		EndSwitch
	Next
EndFunc   ;==>_ExecuteStringCall


Func _FinishScript(ByRef $sScript)
	Local $iTimer = TimerInit()
	_StatusAdd()
	_StatusAdd("#1#Finish Script")
	_StatusStepSet(5)
	$sScript = StringRegExpReplace($sScript, Chr(5) & "\\?\#\d+\#", "")
	_StatusStep()
	_RegExMerge($sScript, Chr(4), $aScriptConst)
	If @error Then Return False
	_StatusAdd("#3#" & @extended & " #4#global constants included", 1, 1)
	_StatusStep()
	$sScript = StringReplace($sScript, Chr(3), "_" & @CRLF)
	If @error Then Return False
	_StatusAdd("#3#" & @extended & " #4#linesplits restored", 1, 1)
	_StatusStep()
	_RegExMerge($sScript, Chr(2), $aScriptCompiler)
	If @error Then Return False
	_StatusAdd("#3#" & @extended & " #4#compiler directives included", 1, 1)
	_StatusStep()
	_RegExMerge($sScript, Chr(1), $aScriptQuotes)
	If @error Then Return False
	_StatusAdd("#3#" & @extended & " #4#quotes included", 1, 1)
	_StatusStep()
	_StatusAdd("#1#Done... Time: #4#" & Round(TimerDiff($iTimer) / 1000, 3), 0, 1)
	_StatusDrawBmp($aStatusText[0][0])
	Return True
EndFunc   ;==>_FinishScript

;===========================================================================================================================
; END Prepare/Finish Script (excludiere Quotes, Compileranweisungen, und Const bekommen alle eine eigene Zeile
;===========================================================================================================================



;===========================================================================================================================
; Insert Includes
;===========================================================================================================================

Func _InsertIncludes($sScriptFile, ByRef $sScript)
	Local $iTimer = TimerInit()
	$aIncludesDir = _GetIncludesDir($sScriptFile)
	_StatusAdd()
	_StatusAdd("#1#Create full script")
	$bUseBetaIncludes = GUICtrlRead($hCB_Beta)
	$bInclude = GUICtrlRead($hCB_Includes)
	_InsertIncludeFile($sScriptFile, $sScript) ; Rekursives Einfügen
	_StatusAdd("#1#Done... Time: #4#" & Round(TimerDiff($iTimer) / 1000, 3), 0, 1)
	_StatusDrawBmp($aStatusText[0][0])
EndFunc   ;==>_InsertIncludes


Func _InsertIncludeFile($sIncludeFile, ByRef $sScript, $sIncluded = '', $iStatusLevel = 1)
	Local $aScript, $sFile, $aTemp, $aInclude
	$sFile = FileRead($sIncludeFile)
	If @error Then Return SetError(1, 0, $sIncluded)
	_RemoveComments($sFile)
	If StringInStr($sFile, "#include-once") And StringInStr($sIncluded, $sIncludeFile) Then ; wurde bereits eingefügt
		_StatusAdd("#3#> " & StringTrimLeft($sIncludeFile, StringInStr($sIncludeFile, "\", 0, -1)) & " #4#already included (include-once)", 2, $iStatusLevel)
		Return SetError(1, 0, $sIncluded)
	EndIf
	$aInclude = StringRegExp(@CRLF & $sFile, "(?i)(?:[\r\n]\h*)(\#include\h+.+)", 3)
	$aTemp = StringRegExpReplace(@CRLF & $sFile, "(?i)[\r\n]\h*\#include\h+.+", Chr(6))
	$aScript = StringSplit($aTemp, Chr(6))
	$sIncluded &= $sIncludeFile & ";"
	_StatusAdd("#3#>#2#" & StringTrimLeft($sIncludeFile, StringInStr($sIncludeFile, "\", 0, -1)) & "#4# (" & $sIncludeFile & ")", 1, $iStatusLevel)
	If $iStatusLevel = 1 And $bInclude = 1 Then
		_StatusAdd("#4#Insert Includes", 0, 1)
		_StatusStepSet($aScript[0] - 1)
	EndIf
	If Not IsArray($aScript) Or Not IsArray($aInclude) Or UBound($aInclude) <> $aScript[0] - 1 Then
		$sScript &= $sFile
		Return SetError(1, 0, $sIncluded)
	EndIf
	For $i = 1 To $aScript[0] - 1
		If $iStatusLevel = 1 Then _StatusStep()
		$sScript &= $aScript[$i]
		Switch $bInclude
			Case 1
				$sIncluded = _InsertIncludeFile(_GetIncludeFile($aInclude[$i - 1], $sIncludeFile), $sScript, $sIncluded, $iStatusLevel + 1)
			Case Else
				$sScript &= $aInclude[$i - 1]
		EndSwitch
	Next
	$sScript &= $aScript[$aScript[0]]
	Return $sIncluded
EndFunc   ;==>_InsertIncludeFile


Func _RemoveComments(ByRef $sScript)
	$sScript = StringRegExpReplace($sScript, '(?x)(?:\r?\n?\s*;.*)|' & '((?>"[^"]*")+|' & "(?>'[^']*')+)", "\1") ;entferne ;-Komments
	$sScript = StringRegExpReplace($sScript, '(?i)(?:[\r\n]\s*)(\#ce|\#comments-end)(.*)', '$1') ;manche #ce haben noch Text dahinter
	$sScript = StringRegExpReplace($sScript, '(?x)(?:\r?\n?\s*;.*)|(?s)\r?\n?\s*\#c(?>s|omments-start)(?>(?>"[^"]*")+|' & "(?>'[^']*')+|.)*?\#c(?>e|omments-end)(?-s)|" & '((?>"[^"]*")+|' & "(?>'[^']*')+)", "\1")
EndFunc   ;==>_RemoveComments


Func _GetIncludeFile($sLine, $sLastFile)
	Local $Temp, $sFilename, $sCurrentDir = StringLeft($sLastFile, StringInStr($sLastFile, "\", 0, -1))
	$Temp = StringRegExpReplace($sLine, "(?i)(.*#include\h+)([\<'" & '"].+[\>"' & "'])(.*)", "\2")
	$sFilename = StringStripWS(StringTrimRight(StringTrimLeft($Temp, 1), 1), 3)
	$Temp = StringLeft($Temp, 1)
	Switch $Temp
		Case "'", '"' ; Script, User, Standart
			If FileExists($sCurrentDir & $sFilename) Then Return $sCurrentDir & $sFilename
			For $i = 3 To $aIncludesDir[0]
				If FileExists($aIncludesDir[$i] & "\" & $sFilename) Then Return $aIncludesDir[$i] & "\" & $sFilename
			Next
			If FileExists($aIncludesDir[2] & "\" & $sFilename) Then Return $aIncludesDir[2] & "\" & $sFilename
		Case Else ; Standart, User, Script
			If FileExists($aIncludesDir[2] & "\" & $sFilename) Then Return $aIncludesDir[2] & "\" & $sFilename
			For $i = 3 To $aIncludesDir[0]
				If FileExists($aIncludesDir[$i] & "\" & $sFilename) Then Return $aIncludesDir[$i] & "\" & $sFilename
			Next
			If FileExists($sCurrentDir & $sFilename) Then Return $sCurrentDir & $sFilename
	EndSwitch
	Return $aIncludesDir[1] & "\" & $sFilename
EndFunc   ;==>_GetIncludeFile


Func _GetIncludesDir($sFilename)
	Local $aReturn[3], $Temp, $iCnt = 3
	$aReturn[0] = 2
	$aReturn[1] = StringLeft($sFilename, StringInStr($sFilename, "\", 0, -1) - 1)
	Switch $bUseBetaIncludes
		Case 1
			$aReturn[2] = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\AutoIt v3\AutoIt", 'betaInstallDir')
			If @error Or $aReturn[2] = "" Then $aReturn[2] = RegRead('HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\AutoIt v3\AutoIt', 'betaInstallDir')
			If $aReturn[2] = "" Then
				_StatusAdd("#5#ERROR no beta found - continue using standard includes", 0, 1, 1)
				$bUseBetaIncludes = False
				ContinueCase
			EndIf
		Case Else
			$aReturn[2] = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\AutoIt v3\AutoIt", "InstallDir")
			If @error Or $aReturn[2] = "" Then $aReturn[2] = RegRead('HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\AutoIt v3\AutoIt', 'InstallDir')
	EndSwitch
	If $aReturn[2] <> "" Then $aReturn[2] &= "\include"
	$Temp = RegRead("HKEY_CURRENT_USER\Software\AutoIt v3\AutoIt", "Include")
	If @error Or StringStripWS($Temp, 8) = "" Then Return $aReturn
	Switch StringInStr($Temp, ";")
		Case False
			ReDim $aReturn[4]
			$aReturn[0] = 3
			$aReturn[3] = $Temp
		Case Else
			$Temp = StringSplit($Temp, ";")
			If @error Or Not IsArray($Temp) Then Return $aReturn
			For $i = 1 To $Temp[0]
				ReDim $aReturn[$iCnt + 1]
				$aReturn[$iCnt] = $Temp[$i]
				$aReturn[0] = $iCnt
				$iCnt += 1
			Next
	EndSwitch
	Return $aReturn
EndFunc   ;==>_GetIncludesDir

;===========================================================================================================================
; END Insert Includes
;===========================================================================================================================



;===========================================================================================================================
; Generell
;===========================================================================================================================

Func _CntToName($iCnt)
	Local $sRet = "", $iS = Floor(Log($iCnt) / Log(36)), $iC
	For $i = 0 To $iS
		$iC = Mod(Floor($iCnt / (36 ^ $i)), 36)
		Switch $iC
			Case 0 To 9
				$sRet = Chr($iC + 48) & $sRet
			Case Else
				$sRet = Chr($iC + 55) & $sRet
		EndSwitch
	Next
	Return $sRet
EndFunc   ;==>_CntToName


Func _StringReplaceConstbyValue(ByRef $sString)
	Local $aConst
	$aConst = _RegExSeparate($sString, Chr(8), "\$\w+")
	If @error Or Not IsArray($aConst) Or Not $aConst[0] Then Return False
	For $i = 0 To UBound($aConst) - 1
		If $oDictGlobalConst.Exists($aConst[$i]) Then $aConst[$i] = $oDictGlobalConst.Item($aConst[$i])
	Next
	_RegExMerge($sString, Chr(8), $aConst)
	Return True
EndFunc   ;==>_StringReplaceConstbyValue


Func _RegExSeparate(ByRef $sString, $sSep, $sPatternSep, $sPatternSplit = "")
	If Not $sPatternSplit Then $sPatternSplit = $sPatternSep
	Local $aReturn[1] = [0], $aSplit, $sTemp
	$aReturn = StringRegExp($sString, $sPatternSep, 3)
	If Not IsArray($aReturn) Then Return SetError(0, 0, $aReturn)
	$sTemp = StringRegExpReplace($sString, $sPatternSplit, Chr(0))
	If @extended <> UBound($aReturn) Then Return SetError(1, 0, $aReturn)
	$aSplit = StringSplit($sTemp, Chr(0))
	If $aSplit[0] - 1 <> UBound($aReturn) Then Return SetError(1, 0, $aReturn)
	$sTemp = ""
	For $i = 1 To $aSplit[0] - 1
		$sTemp &= $aSplit[$i] & $sSep & "#" & $i - 1 & "#"
	Next
	$sTemp &= $aSplit[$aSplit[0]]
	$sString = $sTemp
	Return $aReturn
EndFunc   ;==>_RegExSeparate


Func _RegExMerge(ByRef $sString, $sSep, $aInsert)
	Local $aIndex, $sTemp, $aSplit, $iMax = UBound($aInsert) - 1, $iDim = UBound($aInsert, 0)
	$aIndex = StringRegExp($sString, $sSep & "\#([0-9]+)\#", 3)
	If Not IsArray($aIndex) Then Return True
	$sTemp = StringRegExpReplace($sString, $sSep & "\#[0-9]+\#", $sSep)
	$aSplit = StringSplit($sTemp, $sSep)
	If $aSplit[0] - 1 <> UBound($aIndex) Then Return False ; Hier noch nicht überprüfen, ob $aSplit[0]-1 <> Ubound($aInsert), da ein Element an mehreren Stellen vorkommen kann
	$sTemp = ""
	For $i = 1 To $aSplit[0] - 1
		If $aIndex[$i - 1] > $iMax Then Return False
		Switch $iDim
			Case 1
				$sTemp &= $aSplit[$i] & $aInsert[$aIndex[$i - 1]]
			Case 2
				$sTemp &= $aSplit[$i] & $aInsert[$aIndex[$i - 1]][1]
		EndSwitch
	Next
	$sTemp &= $aSplit[$aSplit[0]]
	$sString = $sTemp
	Return SetError(0, $aSplit[0] - 1, True)
EndFunc   ;==>_RegExMerge


Func _SaveScript($sFilename, $sScript)
	Local $iTimer = TimerInit()
	_StatusAdd()
	_StatusAdd("#1#Save file")
	_StatusAdd("#2#" & $sFilename, 0, 1)
	$sScript = StringRegExpReplace($sScript, "(?m)^\h+", "")
	$sScript = StringRegExpReplace($sScript, "\v+\v", @CRLF)
	;$sScript = StringRegExpReplace($sScript, '\r[^\n]|[^\r]\n', @CRLF)
	Local $hFile = FileOpen($sFilename, 2)
	FileWrite($hFile, $sScript)
	FileClose($hFile)
	_StatusAdd("#1#Done... Time: #4#" & Round(TimerDiff($iTimer) / 1000, 3), 0, 1)
	_StatusDrawBmp($aStatusText[0][0])
EndFunc   ;==>_SaveScript

;===========================================================================================================================
; END Generell
;===========================================================================================================================



;===========================================================================================================================
; Gui Functions
;===========================================================================================================================

Func _CreateGui()
	$hGui = GUICreate("Another AutoIt PreProcessor", 800, 570)
	GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit")
	GUISetOnEvent($GUI_EVENT_SECONDARYDOWN, "_Info")
	$hInputFile = GUICtrlCreateInput("", 10, 10, 415, 20)
	GUICtrlSetData($hInputFile, IniRead(@ScriptDir & "\AAPP.ini", "files", "input", ""))
	$hOutputFile = GUICtrlCreateInput("", 10, 40, 415, 20)
	GUICtrlSetData($hOutputFile, IniRead(@ScriptDir & "\AAPP.ini", "files", "output", ""))
	$hButtonStart = GUICtrlCreateButton("start processing", 530, 500, 250, 30)
	GUICtrlSetOnEvent(-1, "_Process")
	$hButtonExit = GUICtrlCreateButton("exit", 680, 540, 100, 20)
	GUICtrlSetOnEvent(-1, "_Exit")
	$hCB_Save = GUICtrlCreateCheckbox("save options on exit", 530, 540, 150, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "options", "save", 4))
	$hButtonInput = GUICtrlCreateButton("source", 430, 10, 80, 20)
	GUICtrlSetOnEvent(-1, "_Button")
	$hButtonOutput = GUICtrlCreateButton("destination", 430, 40, 80, 20)
	GUICtrlSetOnEvent(-1, "_Button")
	$hCB_Includes = GUICtrlCreateCheckbox("insert includes", 540, 20, 100, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "options", "incl", 1))
	$hCB_Beta = GUICtrlCreateCheckbox("use beta includes", 660, 20, 100, 20)
	Switch FileExists(RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\AutoIt v3\AutoIt", 'betaInstallDir') & "\include")
		Case False
			If FileExists(RegRead('HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\AutoIt v3\AutoIt', 'betaInstallDir') & "\include") Then ContinueCase
			GUICtrlSetState(-1, $GUI_DISABLE)
		Case Else
			GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "options", "beta", 4))
	EndSwitch
	$hCB_RemoveFunc = GUICtrlCreateCheckbox("remove unused functions", 540, 45, 200, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "options", "remf", 1))
	$hCB_ReplaceConst = GUICtrlCreateCheckbox("replace constants by their values", 540, 70, 200, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "options", "repc", 1))
	$hCB_RemoveConst = GUICtrlCreateCheckbox("remove unused constants", 540, 95, 200, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "options", "remc", 1))
	$hCB_RenameFuncs = GUICtrlCreateCheckbox("rename functions", 540, 120, 200, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "options", "renf", 1))
	$hCB_RenameVars = GUICtrlCreateCheckbox("rename variables / constants", 540, 145, 200, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "options", "renv", 1))
	$hCB_ExecuteFunc = GUICtrlCreateCheckbox("Execute is used to call functions", 560, 170, 200, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "options", "exef", 1))
	$hCB_ExecuteVar = GUICtrlCreateCheckbox("Execute is used to call variables", 560, 195, 200, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "options", "exev", 1))
	$hCB_Ignore = GUICtrlCreateCheckbox("ignore bad stringcalls", 560, 220, 200, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "options", "igno", 0))
	$hCB_Optimize = GUICtrlCreateCheckbox("optimize code", 540, 255, 200, 20)
	GUICtrlSetOnEvent(-1, "_Button")
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "options", "opti", 1))
	$hCB_OptimizeCalc = GUICtrlCreateCheckbox("calculate expressions", 560, 280, 200, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "optimize", "calc", 1))
	$hCB_OptimizeLine = GUICtrlCreateCheckbox('combine "_" splited lines', 560, 305, 250, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "optimize", "line", 1))
	$hCB_OptimizeMerg = GUICtrlCreateCheckbox("merge strings", 560, 330, 200, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "optimize", "merg", 1))
	$hCB_OptimizeCase = GUICtrlCreateCheckbox("optimize if / case statements", 560, 355, 200, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "optimize", "case", 1))

	$hCB_0ToNot = GUICtrlCreateCheckbox("change $var = 0 to Not $var", 580, 380, 200, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "optimize", "0not", 0))

	$hCB_OptimizeHexa = GUICtrlCreateCheckbox("convert dec to hex", 560, 405, 200, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "optimize", "hexa", 1))
	$hCB_OptimizeAssi = GUICtrlCreateCheckbox("optimize assignment operators", 560, 430, 250, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "optimize", "assi", 1))
	Switch GUICtrlRead($hCB_Optimize)
		Case 4
			GUICtrlSetState($hCB_OptimizeAssi, $GUI_DISABLE)
			GUICtrlSetState($hCB_OptimizeCalc, $GUI_DISABLE)
			GUICtrlSetState($hCB_OptimizeCase, $GUI_DISABLE)
			GUICtrlSetState($hCB_OptimizeHexa, $GUI_DISABLE)
			GUICtrlSetState($hCB_OptimizeLine, $GUI_DISABLE)
			GUICtrlSetState($hCB_OptimizeMerg, $GUI_DISABLE)
			GUICtrlSetState($hCB_0ToNot, $GUI_DISABLE)
	EndSwitch
	GUICtrlCreateLabel("status detail level", 185, 475, 150, 15, $SS_CENTER)
	$hSlider = GUICtrlCreateSlider(185, 493, 150, 25)
	GUICtrlSetOnEvent(-1, "_Button")
	_GUICtrlSlider_SetRange($hSlider, 0, 3)
	_GUICtrlSlider_SetPos($hSlider, IniRead(@ScriptDir & "\AAPP.ini", "options", "slid", 1))
	$hStatusProgress = GUICtrlCreateProgress(10, 525, 500, 15, $PBS_SMOOTH)
	$hEntireProgress = GUICtrlCreateProgress(10, 545, 500, 15, $PBS_SMOOTH)
	$hCB_LogFile = GUICtrlCreateCheckbox("create logfile", 10, 500, 100, 20)
	GUICtrlSetState(-1, IniRead(@ScriptDir & "\AAPP.ini", "options", "logf", 1))
	$hStatusGui = GUICreate("StatusGDIp", 500, 400, 10, 70, $WS_POPUP, BitOR(0, $WS_EX_MDICHILD), $hGui)
	GUISetBkColor(0xE0E0E0, $hStatusGui)
	_GUIScrollBars_Init($hStatusGui)
	_GUIScrollBars_ShowScrollBar($hStatusGui, $SB_HORZ, False)
	_GUIScrollBars_ShowScrollBar($hStatusGui, $SB_VERT, False)
	GUISetState(@SW_HIDE, $hStatusGui)
	GUISwitch($hGui)
	GUISetState(@SW_HIDE, $hGui)
	$aStatusText[0][0] = 0
	_GDIPlus_Startup()
	$hStatusGuiGraphic = _GDIPlus_GraphicsCreateFromHWND($hStatusGui)
	$hStatusBitmap = _GDIPlus_BitmapCreateFromGraphics(500, 400, $hStatusGuiGraphic)
	$hStatusGraphic = _GDIPlus_ImageGetGraphicsContext($hStatusBitmap)
	$hStatusBrush[0] = 0xFFE0E0E0
	$hStatusBrush[1] = _GDIPlus_BrushCreateSolid(0xFF008A19)
	$hStatusBrush[2] = _GDIPlus_BrushCreateSolid(0xFF007FCA)
	$hStatusBrush[3] = _GDIPlus_BrushCreateSolid(0xFFEA6419)
	$hStatusBrush[4] = _GDIPlus_BrushCreateSolid(0xFF4B4B64)
	$hStatusBrush[5] = _GDIPlus_BrushCreateSolid(0xFFFA1919)
	$hStatusFormat = _GDIPlus_StringFormatCreate()
	$hStatusFamily = _GDIPlus_FontFamilyCreate("Arial")
	$hStatusFont = _GDIPlus_FontCreate($hStatusFamily, 9, 1)
	$iStatusTimer = TimerInit()
	_StatusChangeDetail(GUICtrlRead($hSlider))
EndFunc   ;==>_CreateGui


Func _CmdLine($aCmd)
	If Not $aCmd[0] Then
		GUIRegisterMsg($WM_PAINT, "_WM_PAINT")
		GUIRegisterMsg($WM_VSCROLL, "_WM_VSCROLL")
		GUIRegisterMsg($WM_HSCROLL, "_WM_HSCROLL")
		GUIRegisterMsg($WM_MOUSEWHEEL, "_WM_MOUSEWHEEL")
		GUISetState(@SW_SHOW, $hStatusGui)
		GUISwitch($hGui)
		GUISetState(@SW_SHOW, $hGui)
		Return
	EndIf
	$bCmdLine = True
	Local $bSwitch, $sInputFile = "", $sOutputFile = "", $sPre, $sCmd, $hCtrl
	GUICtrlSetData($hInputFile, "")
	GUICtrlSetData($hOutputFile, "")
	GUICtrlSetState($hCB_Includes, $GUI_CHECKED)
	GUICtrlSetState($hCB_RemoveFunc, $GUI_CHECKED)
	GUICtrlSetState($hCB_ReplaceConst, $GUI_CHECKED)
	GUICtrlSetState($hCB_RemoveConst, $GUI_CHECKED)
	GUICtrlSetState($hCB_RenameFuncs, $GUI_CHECKED)
	GUICtrlSetState($hCB_RenameVars, $GUI_CHECKED)
	GUICtrlSetState($hCB_ExecuteFunc, $GUI_CHECKED)
	GUICtrlSetState($hCB_ExecuteVar, $GUI_CHECKED)
	GUICtrlSetState($hCB_Beta, $GUI_CHECKED)
	GUICtrlSetState($hCB_Ignore, $GUI_UNCHECKED)
	GUICtrlSetState($hCB_LogFile, $GUI_CHECKED)
	GUICtrlSetState($hCB_Save, $GUI_UNCHECKED)
	GUICtrlSetState($hCB_Optimize, $GUI_CHECKED)
	GUICtrlSetState($hCB_OptimizeAssi, $GUI_CHECKED)
	GUICtrlSetState($hCB_OptimizeCalc, $GUI_CHECKED)
	GUICtrlSetState($hCB_OptimizeCase, $GUI_CHECKED)
	GUICtrlSetState($hCB_0ToNot, $GUI_UNCHECKED)
	GUICtrlSetState($hCB_OptimizeHexa, $GUI_CHECKED)
	GUICtrlSetState($hCB_OptimizeLine, $GUI_CHECKED)
	GUICtrlSetState($hCB_OptimizeMerg, $GUI_CHECKED)
	GUICtrlSetState($hButtonStart, $GUI_DISABLE)
	GUICtrlSetOnEvent($hButtonStart, "")
	_GUICtrlSlider_SetPos($hSlider, 1)
	For $i = 1 To $aCmd[0]
		$sPre = StringLeft($aCmd[$i], 1)
		$sCmd = StringTrimLeft($aCmd[$i], 1)
		Switch $sPre
			Case "+"
				$bSwitch = True
			Case "-"
				$bSwitch = False
			Case Else
				Switch $sInputFile
					Case ""
						$sInputFile = $aCmd[$i]
						GUICtrlSetData($hInputFile, $aCmd[$i])
					Case Else
						$sOutputFile = $aCmd[$i]
						GUICtrlSetData($hOutputFile, $aCmd[$i])
				EndSwitch
				ContinueLoop
		EndSwitch
		$hCtrl = 0
		Switch $sCmd
			Case "include" ; Include
				$hCtrl = $hCB_Includes
			Case "remfunc" ; Remove Func
				$hCtrl = $hCB_RemoveFunc
			Case "repconst" ; Replace Const
				$hCtrl = $hCB_ReplaceConst
			Case "remconst" ; Remove Const
				$hCtrl = $hCB_RemoveConst
			Case "renfunc" ; Rename Func
				$hCtrl = $hCB_RenameFuncs
			Case "renvar" ; Rename Var
				$hCtrl = $hCB_RenameVars
			Case "execfunc" ; Deepscan = False
				$hCtrl = $hCB_ExecuteFunc
			Case "execvar" ; Deepscan = False
				$hCtrl = $hCB_ExecuteVar
			Case "ignorebad" ; Ignore Bad StringCall = False
				$hCtrl = $hCB_Ignore
			Case "optcalc" ; Calc Exp
				$hCtrl = $hCB_OptimizeCalc
			Case "optcombine" ; Combine Lines
				$hCtrl = $hCB_OptimizeLine
			Case "optmerge" ; Merge Strings
				$hCtrl = $hCB_OptimizeMerg
			Case "optifcase" ; If / Case
				$hCtrl = $hCB_OptimizeCase
			Case "optdec2hex" ; Dec to Hex
				$hCtrl = $hCB_OptimizeHexa
			Case "optassignment" ; Assignment operators
				$hCtrl = $hCB_OptimizeAssi
			Case "logfile" ; Create Logfile
				$hCtrl = $hCB_LogFile
			Case "exitnoerror" ; Exit after processing (if no errors) = True
				$bExitNoError = $bSwitch
			Case "exitonerror" ; Exit after processing if errors = False
				$bExitOnError = $bSwitch
			Case "hidegui"
				$bHideGui = $bSwitch
		EndSwitch
		If Not $hCtrl Then ContinueLoop
		Switch $bSwitch
			Case True
				GUICtrlSetState($hCtrl, $GUI_CHECKED)
			Case Else
				GUICtrlSetState($hCtrl, $GUI_UNCHECKED)
		EndSwitch
	Next
	If Not $bHideGui Then
		GUIRegisterMsg($WM_PAINT, "_WM_PAINT")
		GUIRegisterMsg($WM_VSCROLL, "_WM_VSCROLL")
		GUIRegisterMsg($WM_HSCROLL, "_WM_HSCROLL")
		GUIRegisterMsg($WM_MOUSEWHEEL, "_WM_MOUSEWHEEL")
		GUISetState(@SW_SHOW, $hStatusGui)
		GUISwitch($hGui)
		GUISetState(@SW_SHOW, $hGui)
	EndIf
	If _Process() Then ; es gab Errors
		If $bHideGui And Not $bExitOnError Then
			GUIRegisterMsg($WM_PAINT, "_WM_PAINT")
			GUIRegisterMsg($WM_VSCROLL, "_WM_VSCROLL")
			GUIRegisterMsg($WM_HSCROLL, "_WM_HSCROLL")
			GUIRegisterMsg($WM_MOUSEWHEEL, "_WM_MOUSEWHEEL")
			GUISetState(@SW_SHOW, $hStatusGui)
			GUISwitch($hGui)
			GUISetState(@SW_SHOW, $hGui)
		EndIf
		If Not $bExitOnError Then Return
	EndIf
	If $bHideGui And Not $bExitNoError Then
		GUIRegisterMsg($WM_PAINT, "_WM_PAINT")
		GUIRegisterMsg($WM_VSCROLL, "_WM_VSCROLL")
		GUIRegisterMsg($WM_HSCROLL, "_WM_HSCROLL")
		GUIRegisterMsg($WM_MOUSEWHEEL, "_WM_MOUSEWHEEL")
		GUISetState(@SW_SHOW, $hStatusGui)
		GUISwitch($hGui)
		GUISetState(@SW_SHOW, $hGui)
	EndIf
	If Not $bExitNoError Then Return
	_Exit()
EndFunc   ;==>_CmdLine


Func _Process()
	$iErrorCnt = 0
	$iStatusDetail = GUICtrlRead($hSlider)
	$bIgnoreDisable = GUICtrlRead($hCB_Ignore)
	$bExecCallFunc = GUICtrlRead($hCB_ExecuteFunc)
	$bExecCallVar = GUICtrlRead($hCB_ExecuteVar)
	$bReplaceCostants = GUICtrlRead($hCB_ReplaceConst)
	$bRemoveConstants = GUICtrlRead($hCB_RemoveConst)
	$bRemoveFunctions = GUICtrlRead($hCB_RemoveFunc)
	$bRenameFunctions = GUICtrlRead($hCB_RenameFuncs)
	$bRenameVariables = GUICtrlRead($hCB_RenameVars)
	$bInsertIncludes = GUICtrlRead($hCB_Includes)
	$bOptimize = GUICtrlRead($hCB_Optimize)
	Local $sFilename = GUICtrlRead($hInputFile), $sTemp
	Local $sOutputFile = GUICtrlRead($hOutputFile)
	Switch $bCmdLine
		Case False
			If $sFilename = "" Then
				MsgBox(0, "Error", "No inputfile")
				Return
			EndIf
			If Not FileExists($sFilename) Then
				MsgBox(0, "Error", "Inputfile" & @LF & $sFilename & @LF & "dose not exist!")
				Return
			EndIf
			FileSetAttrib($sFilename, "-R")
			If $sOutputFile = "" Then
				$sOutputFile = StringTrimRight($sFilename, 4) & "_PreProcessed.au3"
				GUICtrlSetData($hOutputFile, $sOutputFile)
			EndIf
			FileSetAttrib($sOutputFile, "-R")
			If FileExists($sOutputFile) Then
				If MsgBox(4, "Overwrite", "Outputfile" & @LF & $sOutputFile & @LF & "already exists" & @LF & @LF & "Overwrite?") <> 6 Then Return
			EndIf
			If $sOutputFile = $sFilename Then
				If MsgBox(4, "Overwrite", "Outputfile" & @LF & $sOutputFile & @LF & " is identical to inputfile " & @LF & @LF & "Overwrite original file?") <> 6 Then Return
				Local $sBackUpDir = StringLeft($sFilename, StringInStr($sFilename, "\", 0, -1)) & "AAPP_Backup"
				If Not FileExists($sBackUpDir) And Not DirCreate($sBackUpDir) Then
					_StatusAdd("#5#Error creating backup directory", 0, 0, 1)
					Return 1
				EndIf
				$sTemp = StringTrimLeft($sFilename, StringInStr($sFilename, "\", 0, -1))
				$sTemp = StringLeft($sTemp, StringInStr($sTemp, ".", 0, -1) - 1)
				If Not FileCopy($sFilename, $sBackUpDir & "\" & $sTemp & "_" & @YEAR & "-" & @MON & "-" & @MDAY & "_" & @HOUR & "-" & @MIN & "-" & @SEC & ".au3", 1) Then
					_StatusAdd("#5#Error creating backup", 0, 0, 1)
					Return 1
				EndIf
			EndIf
		Case Else
			If $sOutputFile = "" Then
				$sOutputFile = $sFilename
				GUICtrlSetData($hOutputFile, $sOutputFile)
			EndIf
			FileSetAttrib($sFilename, "-R")
			FileSetAttrib($sOutputFile, "-R")
			If $sOutputFile = $sFilename Then
				Local $sBackUpDir = StringLeft($sFilename, StringInStr($sFilename, "\", 0, -1)) & "AAPP_Backup"
				If Not FileExists($sBackUpDir) And Not DirCreate($sBackUpDir) Then
					_StatusAdd("#5#ERROR creating backup directory - stop processing", 0, 1, 1)
					ConsoleWrite(@LF & "!Error creating backup directory" & @LF)
					Return 1
				EndIf
				$sTemp = StringTrimLeft($sFilename, StringInStr($sFilename, "\", 0, -1))
				$sTemp = StringLeft($sTemp, StringInStr($sTemp, ".", 0, -1) - 1)
				If Not FileCopy($sFilename, $sBackUpDir & "\" & $sTemp & "_" & @YEAR & "-" & @MON & "-" & @MDAY & "_" & @HOUR & "-" & @MIN & "-" & @SEC & ".au3", 1) Then
					_StatusAdd("#5#ERROR creating backup - stop processing", 0, 1, 1)
					ConsoleWrite(@LF & "!Error creating backup file" & @LF)
					Return 1
				EndIf
			EndIf
	EndSwitch
	$bStop = False
	If Not $bCmdLine Then
		HotKeySet("{esc}", "_StopProcess")
		_StatusReset("#4#Press#5# ESC#4# to stop processing...")
	EndIf
	Opt("GUIOnEventMode", 0)
	Local $iTimer = TimerInit(), $sScript = "", $iStep = 4, $iCnt = 0
	If $bRemoveFunctions = 1 Then $iStep += 1
	If $bReplaceCostants = 1 Then $iStep += 1
	If $bRemoveConstants = 1 Then $iStep += 1
	If $bRenameVariables = 1 Then $iStep += 1
	If $bRenameFunctions = 1 Then $iStep += 1
	If $bOptimize = 1 Then $iStep += 1
	If Not $bStop Then
		_EntireStep($iStep, $iCnt)
		_InsertIncludes($sFilename, $sScript)
	EndIf
	If Not $bStop Then
		_EntireStep($iStep, $iCnt)
		If Not _PrepareScript($sScript) Then _StatusAdd("#5#ERROR", 0, 2, 1)
	EndIf
	If Not $bStop And $bRemoveFunctions = 1 Then
		_EntireStep($iStep, $iCnt)
		If Not _RemoveUnusedFunctions($sScript) Then _StatusAdd("#5#ERROR", 0, 2, 1)
	EndIf
	If Not $bStop And $bReplaceCostants = 1 Then
		_EntireStep($iStep, $iCnt)
		If Not _ReplaceConstants($sScript) Then _StatusAdd("#5#ERROR", 0, 2, 1)
	EndIf
	If Not $bStop And $bRemoveConstants = 1 Then
		_EntireStep($iStep, $iCnt)
		If Not _RemoveUnusedGlobalConst($sScript) Then _StatusAdd("#5#ERROR", 0, 2, 1)
	EndIf
	If Not $bStop And $bRenameFunctions = 1 Then
		_EntireStep($iStep, $iCnt)
		If Not _RenameFunctions($sScript) Then _StatusAdd("#5#ERROR", 0, 2, 1)
	EndIf
	If Not $bStop And $bRenameVariables = 1 Then
		_EntireStep($iStep, $iCnt)
		If Not _RenameVariables($sScript) Then _StatusAdd("#5#ERROR", 0, 2, 1)
	EndIf
	If Not $bStop And $bOptimize = 1 Then
		_EntireStep($iStep, $iCnt)
		If Not _OptimizeCode($sScript) Then _StatusAdd("#5#ERROR", 0, 2, 1)
	EndIf
	If Not $bStop Then
		_EntireStep($iStep, $iCnt)
		If Not _FinishScript($sScript) Then _StatusAdd("#5#ERROR", 0, 2, 1)
		_EntireStep($iStep, $iCnt)
	EndIf
	If Not $bStop Then _SaveScript($sOutputFile, $sScript)
	GUICtrlSetData($hStatusProgress, 0)
	GUICtrlSetData($hEntireProgress, 0)
	$bStop = False
	HotKeySet("{esc}")
	_StatusAdd()
	_StatusAdd("#1#...Finished... Time:#3# " & Round(TimerDiff($iTimer) / 1000) & "#1# seconds")
	Switch $iErrorCnt
		Case 0
			_StatusAdd("#3#" & $iErrorCnt & " #1#Errors occurred")
		Case Else
			_StatusAdd("#4#" & $iErrorCnt & " #5#Errors occurred")
	EndSwitch
	If GUICtrlRead($hCB_LogFile) = 1 Then _CreateLogFile(StringLeft($sOutputFile, StringInStr($sOutputFile, ".", 0, -1)) & "rtf", $aStatusTextAll)
	_StatusDrawBmp($aStatusText[0][0])
	Opt("GUIOnEventMode", 1)
	If $bCmdLine Then
		Switch $iErrorCnt
			Case 0
				ConsoleWrite(@LF & "+Another AutoIt Preprocessor detected " & $iErrorCnt & " errors in " & $sFilename & @LF & @LF)
			Case Else
				ConsoleWrite(@LF & "!Another AutoIt Preprocessor detected " & $iErrorCnt & " errors in " & $sFilename & @LF & @LF)
		EndSwitch
	EndIf
	Return $iErrorCnt
EndFunc   ;==>_Process


Func _Info()
	Local $aInfo = GUIGetCursorInfo($hGui)
	Switch $aInfo[4]
		Case $hCB_Includes
			_StatusReset("#5#INFO #2#insert Includes")
			_StatusAdd("#4#insert all includes")
		Case $hCB_Beta
			_StatusReset("#5#INFO #2#use beta includes")
			_StatusAdd("#4#insert includes from the beta install dir")
		Case $hCB_RemoveFunc
			_StatusReset("#5#INFO #2#remove unused functions")
			_StatusAdd("#4#first the preprocessor is looking for all function calls in the mainscript")
			_StatusAdd("#4#if a function call is found, this function is marked as #3#used #4#")
			_StatusAdd("#4#and searched through for another function calls recursively")
			_StatusAdd("#4#at the end all unused functions wil be removed")
		Case $hCB_ReplaceConst
			_StatusReset("#5#INFO #2#replace constants by their values")
			_StatusAdd("#4#first the preprocessor collects all global constants and their values")
			_StatusAdd("#4#next all global constants will be replaced by value in the script")
			_StatusAdd("#4#but function parameters or local declared variables / constants will be ignored:")
			_StatusAdd()
			_StatusAdd("#2#Global Const #3#$Const1 = '1', $Const2 = '2', $Const3 = '3'")
			_StatusAdd()
			_StatusAdd("#2#Func #4#_TestFunc(#3#$Const1#4#)")
			_StatusAdd("#2#Local #3#$Const2")
			_StatusAdd("#3#$Const2 = $Const3 #4# <- $Const3 will be replaced by #3#'3'")
			_StatusAdd("#2#EndFunc")
		Case $hCB_RemoveConst
			_StatusReset("#5#INFO #2#remove unused constants")
			_StatusAdd("#4#all global constants that are no longer needed")
			_StatusAdd("#4#because they aren´t used anyway or now replaced by their values")
			_StatusAdd("#4#will be removed")
		Case $hCB_RenameFuncs
			_StatusReset("#5#INFO #2#rename functions")
			_StatusAdd("#4#function names will be replaced by very short names")
			_StatusAdd("#4#starting from#2#_1#4#to#2#_Z#4#, then#2#_11#4#to#2#_ZZ#4#and so on")
			_StatusAdd("#4#function can be renamed if stringcalls are valid strings: #2#GuiCtrlSetOnEvent(-1,'Func')")
			_StatusAdd("#4#but not if Stringcalls contains variables: #2#HotKeySet('{ESC}','Func'#3#& $Str#2#)")
		Case $hCB_RenameVars
			_StatusReset("#5#INFO #2#rename variables / constants")
			_StatusAdd("#4#variable and constant names will be replaced by very short names")
			_StatusAdd("#4#starting from#3#$1#4#to#3#$Z#4#, then#3#$11#4#to#3#$ZZ#4#and so on")
			_StatusAdd("#4#vars and consts can be renamed if stringcalls are valid strings: #2#Eval('Var')")
			_StatusAdd("#4#but not if Stringcalls contains variables: #2#IsDesigned('Var'#3#& $Str#2#)")
		Case $hCB_ExecuteFunc
			_StatusReset("#5#INFO #2#Execute is used to call functions")
			_StatusAdd("#4#If the preprocessor gives an error on an Execute-Statement")
			_StatusAdd("#4#and you are shure that Execute is not used to call a function by string")
			_StatusAdd("#4#you can disable this option to ignore Execute-Statements for functions")
			_StatusAdd()
			_StatusAdd("#3#$Str1 = #4#'String1'")
			_StatusAdd("#3#$Str2 = #4#'String2'")
			_StatusAdd("#2#Execute(#3#$Str1 & $Str2#2#) #4#<- Execute is used to merge strings")
			_StatusAdd("#4#you can disable this option")
			_StatusAdd()
			_StatusAdd("#3#$Str = #4#'_Function()'")
			_StatusAdd("#2#Execute(#3#$Str#2#) #4#<- Execute is calling a function")
			_StatusAdd("#4#this option must be enabled")
		Case $hCB_ExecuteVar
			_StatusReset("#5#INFO #2#Execute is used to call variables")
			_StatusAdd("#4#If the preprocessor gives an error on an Execute-Statement")
			_StatusAdd("#4#and you are shure that Execute is not used to call a variable/constant by string")
			_StatusAdd("#4#you can disable this option to ignore Execute-Statements for variables/constants")
			_StatusAdd()
			_StatusAdd("#3#$Str1 = #4#'String1'")
			_StatusAdd("#3#$Str2 = #4#'String2'")
			_StatusAdd("#2#Execute(#3#$Str1 & $Str2#2#) #4#<- Execute is used to merge strings")
			_StatusAdd("#4#you can disable this option")
			_StatusAdd()
			_StatusAdd("#3#$Var = 1")
			_StatusAdd("#3#$Str = #4#'$Var + 1'")
			_StatusAdd("#2#Execute(#3#$Str#2#) #4#<- Execute is calling a variable")
			_StatusAdd("#4#this option must be enabled")
		Case $hCB_Ignore
			_StatusReset("#5#INFO #2#ignore bad stringcalls")
			_StatusAdd("#4#if a stringcall is found that contains no string but only a variable: #2#HotKeySet#4#('{ESC}',#3#$func#4#)")
			_StatusAdd("#4#then the preprocessor gives an error, because the variable could contain the name of ANY function, variable or constant")
			_StatusAdd("#4#and no function / variable / constant will be removed or renamed")
			_StatusAdd()
			_StatusAdd("#4#but you can ignore these errors and continue processing")
			_StatusAdd()
			_StatusAdd("#5#attention! #4#in most cases the preprocessed script will not work correctly")
		Case $hCB_OptimizeCalc
			_StatusReset("#5#INFO #2#calculate expressions")
			_StatusAdd("#4#simple math expressions like #2#Sqrt(10) #4#or #2#BitOr(1,2)")
			_StatusAdd("#4#will be calculated and replaced by the result")
		Case $hCB_OptimizeLine
			_StatusReset("#5#INFO #2#combine #3#'_' #4#- splitted lines")
			_StatusAdd("#4#you can split lines of your script by an underscore")
			_StatusAdd()
			_StatusAdd("#3#$Str=#4#'String1' #3#& _")
			_StatusAdd("#4#'String2'")
			_StatusAdd()
			_StatusAdd("#4#these lines will be combined to one single line if the resulting linelength doesn´t exceed 4095 characters")
			_StatusAdd()
			_StatusAdd("#3#$Str=#4#'String1' #3#& #4#'String2'")
		Case $hCB_OptimizeMerg
			_StatusReset("#5#INFO #2#merge strings")
			_StatusAdd("#4#strings that are combined by #3#& #4# will be merged")
			_StatusAdd("#4#if neither of the strings contains an opposite quote")
			_StatusAdd()
			_StatusAdd("#2#'String1' #3#& #2#" & '"String2"' & " #4#will be merged: #2#'String1String2'")
			_StatusAdd("#2#'Stri" & '"' & "ng1' #3#& #2#" & '"St' & "'" & 'ring2"' & " #4#can´t be merged")
		Case $hCB_OptimizeCase
			_StatusReset("#5#INFO #2#optimize if / case statements")
			_StatusAdd("#4#first step is to change things like:")
			_StatusAdd("#2#If #3#$Var = #2#True #4#to #2#If #3#$Var")
			_StatusAdd("#2#If #3#$Var = 0 #4#to #2#If NOT #3#$Var")
			_StatusAdd("#2#If #3#$Var = #2#False #4#to #2#If NOT #3#$Var")
			_StatusAdd("#2#If #3#$Var = '' #4#to #2#If NOT #3#$Var")
			_StatusAdd()
			_StatusAdd("#4#the second step combines If statements that could be written in one line")
			_StatusAdd("#2#If #3#$Var > 1 #2#Then")
			_StatusAdd("#2#ConsoleWrite()")
			_StatusAdd("#2#EndIf")
			_StatusAdd()
			_StatusAdd("#2#If #3#$Var > 1 #2#Then ConsoleWrite()")
		Case $hCB_0ToNot
			_StatusReset("#5#INFO #2#change #3#$var = 0 #2#to #3#NOT $var")
			_StatusAdd("#4#this can only be done if $var is NOT a string!")
			_StatusAdd()
			_StatusAdd("#3#$var = #2#IniRead#4#('test.ini', 'section', 'key', 1)")
			_StatusAdd("#2#If #3#$var = 0 #2#Then... #4# can´t be changed to #2#If NOT #3#$var #2#Then...")
		Case $hCB_OptimizeHexa
			_StatusReset("#5#INFO #2#convert DEC to HEX")
			_StatusAdd("#4#all decimal numbers are converted to hexadecimal")
		Case $hCB_OptimizeAssi
			_StatusReset("#5#INFO #2#optimize assignment operators")
			_StatusAdd("#4#change operators #2#+ - * / & #4# like this")
			_StatusAdd("#3#$Var = $Var + 1 #4#To #3#$Var += 1")
	EndSwitch
	_StatusDrawBmp($aStatusText[0][0])
EndFunc   ;==>_Info


Func _Button()
	If $bCmdLine Then Return
	Local $Temp
	Switch @GUI_CtrlId
		Case $hButtonInput
			$Temp = FileOpenDialog("select source script", "", "(*.au3)")
			If FileExists($Temp) Then
				GUICtrlSetData($hInputFile, $Temp)
				GUICtrlSetData($hOutputFile, StringTrimRight($Temp, 4) & "_PreProcessed.au3")
			EndIf
		Case $hButtonOutput
			$Temp = FileOpenDialog("select destination file", "", "(*.au3)")
			If FileExists($Temp) Then GUICtrlSetData($hOutputFile, $Temp)
		Case $hSlider
			_StatusChangeDetail(GUICtrlRead($hSlider))
		Case $hCB_Optimize
			Switch GUICtrlRead($hCB_Optimize)
				Case 4
					GUICtrlSetState($hCB_OptimizeAssi, $GUI_DISABLE)
					GUICtrlSetState($hCB_OptimizeCalc, $GUI_DISABLE)
					GUICtrlSetState($hCB_OptimizeCase, $GUI_DISABLE)
					GUICtrlSetState($hCB_OptimizeHexa, $GUI_DISABLE)
					GUICtrlSetState($hCB_OptimizeLine, $GUI_DISABLE)
					GUICtrlSetState($hCB_OptimizeMerg, $GUI_DISABLE)
					GUICtrlSetState($hCB_0ToNot, $GUI_DISABLE)
				Case Else
					GUICtrlSetState($hCB_OptimizeAssi, $GUI_ENABLE)
					GUICtrlSetState($hCB_OptimizeCalc, $GUI_ENABLE)
					GUICtrlSetState($hCB_OptimizeCase, $GUI_ENABLE)
					GUICtrlSetState($hCB_OptimizeHexa, $GUI_ENABLE)
					GUICtrlSetState($hCB_OptimizeLine, $GUI_ENABLE)
					GUICtrlSetState($hCB_OptimizeMerg, $GUI_ENABLE)
					GUICtrlSetState($hCB_0ToNot, $GUI_ENABLE)
			EndSwitch
	EndSwitch
EndFunc   ;==>_Button


Func _Exit()
	_GDIPlus_FontDispose($hStatusFont)
	_GDIPlus_FontFamilyDispose($hStatusFamily)
	_GDIPlus_StringFormatDispose($hStatusFormat)
	For $i = 1 To 5
		_GDIPlus_BrushDispose($hStatusBrush[$i])
	Next
	_GDIPlus_GraphicsDispose($hStatusGraphic)
	_GDIPlus_Shutdown()
	If Not $bCmdLine Then
		Switch GUICtrlRead($hCB_Save)
			Case 1
				IniWrite(@ScriptDir & "\AAPP.ini", "options", "save", 1)
				IniWrite(@ScriptDir & "\AAPP.ini", "options", "incl", GUICtrlRead($hCB_Includes))
				IniWrite(@ScriptDir & "\AAPP.ini", "options", "beta", GUICtrlRead($hCB_Beta))
				IniWrite(@ScriptDir & "\AAPP.ini", "optimize", "0not", GUICtrlRead($hCB_0ToNot))
				IniWrite(@ScriptDir & "\AAPP.ini", "options", "remf", GUICtrlRead($hCB_RemoveFunc))
				IniWrite(@ScriptDir & "\AAPP.ini", "options", "repc", GUICtrlRead($hCB_ReplaceConst))
				IniWrite(@ScriptDir & "\AAPP.ini", "options", "remc", GUICtrlRead($hCB_RemoveConst))
				IniWrite(@ScriptDir & "\AAPP.ini", "options", "renf", GUICtrlRead($hCB_RenameFuncs))
				IniWrite(@ScriptDir & "\AAPP.ini", "options", "renv", GUICtrlRead($hCB_RenameVars))
				IniWrite(@ScriptDir & "\AAPP.ini", "options", "igno", GUICtrlRead($hCB_Ignore))
				IniWrite(@ScriptDir & "\AAPP.ini", "options", "exef", GUICtrlRead($hCB_ExecuteFunc))
				IniWrite(@ScriptDir & "\AAPP.ini", "options", "exev", GUICtrlRead($hCB_ExecuteVar))
				IniWrite(@ScriptDir & "\AAPP.ini", "options", "opti", GUICtrlRead($hCB_Optimize))
				IniWrite(@ScriptDir & "\AAPP.ini", "options", "slid", GUICtrlRead($hSlider))
				IniWrite(@ScriptDir & "\AAPP.ini", "options", "logf", GUICtrlRead($hCB_LogFile))
				IniWrite(@ScriptDir & "\AAPP.ini", "optimize", "calc", GUICtrlRead($hCB_OptimizeCalc))
				IniWrite(@ScriptDir & "\AAPP.ini", "optimize", "merg", GUICtrlRead($hCB_OptimizeMerg))
				IniWrite(@ScriptDir & "\AAPP.ini", "optimize", "case", GUICtrlRead($hCB_OptimizeCase))
				IniWrite(@ScriptDir & "\AAPP.ini", "optimize", "hexa", GUICtrlRead($hCB_OptimizeHexa))
				IniWrite(@ScriptDir & "\AAPP.ini", "optimize", "assi", GUICtrlRead($hCB_OptimizeAssi))
				IniWrite(@ScriptDir & "\AAPP.ini", "optimize", "line", GUICtrlRead($hCB_OptimizeLine))
			Case 4
				IniWrite(@ScriptDir & "\AAPP.ini", "options", "save", 4)
		EndSwitch
		IniWrite(@ScriptDir & "\AAPP.ini", "files", "input", GUICtrlRead($hInputFile))
		IniWrite(@ScriptDir & "\AAPP.ini", "files", "output", GUICtrlRead($hOutputFile))
	EndIf
	GUIDelete($hStatusGui)
	GUIDelete($hGui)
	Exit
EndFunc   ;==>_Exit

;===========================================================================================================================
; END Gui Functions
;===========================================================================================================================



;===========================================================================================================================
; Status
;===========================================================================================================================

Func _StopProcess()
	_StatusAdd()
	_StatusAdd()
	_StatusAdd("#5#...Please wait, stop processing...")
	$iStatusDetail = 0
	$bStop = True
EndFunc   ;==>_StopProcess


Func _EntireStep($iStep, ByRef $iCnt)
	$iCnt += 1
	Local $iPercent = $iCnt * 100 / $iStep
	If $bVista Then
		If $iPercent + 1 > 100 Then $iPercent = 99
		GUICtrlSetData($hEntireProgress, $iPercent + 1)
	EndIf
	GUICtrlSetData($hEntireProgress, $iPercent)
EndFunc   ;==>_EntireStep


Func _StatusReset($sStatus = "")
	Local $aNew[1000000][3]
	$aNew[0][0] = 0
	$aStatusText = $aNew
	$aStatusTextAll = $aNew
	If $sStatus Then
		$aStatusText[0][0] = 1
		$aStatusText[1][0] = $sStatus
	EndIf
	_StatusDrawBmp(0)
EndFunc   ;==>_StatusReset


Func _StatusStep()
	If $iStatusDetail < 1 Then Return
	$iStatusStep += 1
	$iStatusStepCnt += 1
	If $iStatusStepCnt < $iStatusStepUpdate And $iStatusStep < $iStatusStepMax Then Return
	$iStatusStepCnt = 0
	Local $iPercent = Round(($iStatusStep * 100) / $iStatusStepMax)
	If $bVista Then
		Switch $iPercent
			Case 100
				GUICtrlSetData($hStatusProgress, 100)
			Case Else
				GUICtrlSetData($hStatusProgress, $iPercent + 1)
		EndSwitch
	EndIf
	GUICtrlSetData($hStatusProgress, $iPercent)
EndFunc   ;==>_StatusStep


Func _StatusStepSet($iMax)
	If $iMax > 0 Then
		$iStatusStepMax = $iMax
		$iStatusStep = 0
		$iStatusStepCnt = 0
		$iStatusStepUpdate = Floor($iMax / 100)
		GUICtrlSetData($hStatusProgress, 0)
	EndIf
EndFunc   ;==>_StatusStepSet


Func _StatusChangeDetail($iDetail)
	If $iDetail = $iStatusDetail Then Return
	Switch $iDetail
		Case 0, 1
			$iStatusUpdateTime = 50
		Case 2
			$iStatusUpdateTime = 250
		Case Else
			$iStatusUpdateTime = 500
	EndSwitch
	Local $aNew[1000000][3], $iCnt = 0
	$aStatusText = $aNew
	For $i = 1 To $aStatusTextAll[0][0]
		If $aStatusTextAll[$i][2] > $iDetail Then ContinueLoop
		$iCnt += 1
		$aStatusText[$iCnt][0] = $aStatusTextAll[$i][0]
		$aStatusText[$iCnt][1] = $aStatusTextAll[$i][1]
	Next
	$aStatusText[0][0] = $iCnt
	$iStatusDetail = $iDetail
	_StatusDrawBmp(0)
EndFunc   ;==>_StatusChangeDetail


Func _StatusAdd($sText = "", $iDetail = 0, $iTab = 0, $iError = 0)
	If StringInStr($sText, Chr(1)) Then _RegExMerge($sText, Chr(1), $aScriptQuotes)
	If $iError Then $iErrorCnt += 1
	$aStatusTextAll[0][0] += 1
	$aStatusTextAll[$aStatusTextAll[0][0]][0] = $sText
	$aStatusTextAll[$aStatusTextAll[0][0]][1] = $iTab * 30
	$aStatusTextAll[$aStatusTextAll[0][0]][2] = $iDetail
	If $iError Then ConsoleWrite(@LF & "!" & StringRegExpReplace($sText, "\#\d+\#", ""))
	If $iDetail > $iStatusDetail Then Return
	$aStatusText[0][0] += 1
	$aStatusText[$aStatusText[0][0]][0] = $sText
	$aStatusText[$aStatusText[0][0]][1] = $iTab * 30
	If TimerDiff($iStatusTimer) > $iStatusUpdateTime Or $iDetail = 0 Then
		$iStatusTimer = TimerInit()
		_StatusDrawBmp($aStatusText[0][0])
	EndIf
EndFunc   ;==>_StatusAdd


Func _StatusDrawBmp($iOffset, $bSetScroll = True)
	If $bHideGui Then Return
	If $iOffset > $aStatusText[0][0] - 24 Then $iOffset = $aStatusText[0][0] - 24
	If $iOffset < 0 Then $iOffset = 0
	$iStatusOffsetY = $iOffset
	Local $tLayout, $aInfo, $tSCROLLINFO = DllStructCreate($tagSCROLLINFO), $aSplit, $iXoff, $iColor, $iXMax = $iStatusOffsetW, $sTemp
	_GDIPlus_GraphicsClear($hStatusGraphic, $hStatusBrush[0])
	For $i = 1 To 25
		$iColor = 4
		$iXoff = $aStatusText[$i + $iOffset][1]
		$sTemp = $aStatusText[$i + $iOffset][0]
		If StringLen($sTemp) > 200 Then $sTemp = StringLeft($aStatusText[$i + $iOffset][0], 98) & "|...|" & StringRight($aStatusText[$i + $iOffset][0], 98)
		$aSplit = StringRegExp($sTemp, "(?m)\#(\d{1})\#(.*?)(?=\#\d{1}\#|$)", 3)
		For $j = 0 To UBound($aSplit) - 1
			Switch $aSplit[$j]
				Case "", " "
					ContinueLoop
				Case "1", "2", "3", "4", "5"
					$iColor = Int($aSplit[$j])
					If @error Or Not $iColor Then $iColor = 4
				Case Else
					$tLayout = _GDIPlus_RectFCreate(10 + $iStatusOffsetX + $iXoff, $i * 15 - 5, 0, 0)
					$aInfo = _GDIPlus_GraphicsMeasureString($hStatusGraphic, $aSplit[$j], $hStatusFont, $tLayout, $hStatusFormat)
					$iXoff += Ceiling(DllStructGetData($aInfo[0], "Width"))
					If $iStatusOffsetX + $iXoff > $iXMax Then $iXMax = $iStatusOffsetX + $iXoff
					_GDIPlus_GraphicsDrawStringEx($hStatusGraphic, $aSplit[$j], $hStatusFont, $aInfo[0], $hStatusFormat, $hStatusBrush[$iColor])
			EndSwitch
		Next
	Next
	If $iXMax > $iStatusOffsetW Then _StatusSetHScroll($iXMax)
	If $bSetScroll Then
		DllStructSetData($tSCROLLINFO, "fMask", BitOR($SIF_RANGE, $SIF_PAGE))
		DllStructSetData($tSCROLLINFO, "nMin", 0)
		DllStructSetData($tSCROLLINFO, "nMax", $aStatusText[0][0])
		DllStructSetData($tSCROLLINFO, "nPage", 20)
		_GUIScrollBars_SetScrollInfo($hStatusGui, $SB_VERT, $tSCROLLINFO)
		_GUIScrollBars_SetScrollInfoPos($hStatusGui, $SB_VERT, $iOffset)
	EndIf
	_WinAPI_RedrawWindow($hStatusGui, 0, 0, $RDW_INTERNALPAINT)
EndFunc   ;==>_StatusDrawBmp


Func _CreateLogFile($sFilename, $aText)
	Local $sFileHeader = "{\rtf1\ansi\ansicpg1252\deff0\deflang3079{\fonttbl{\f0\fswiss\fcharset0 Arial;}}" & @CRLF & _
			"{\colortbl ;\red0\green138\blue25;\red0\green127\blue202;\red234\green100\blue25;\red75\green75\blue100;\red250\green25\blue25;}" & @CRLF & _
			"{\*\generator Msftedit 5.41.15.1515;}\viewkind4\uc1\pard\cf4\b\f0\fs20\par" & @CRLF
	Local $aColor[6] = ["\cf0", "\cf1", "\cf2", "\cf3", "\cf4", "\cf5"]
	Local $sFileEnd = @CRLF & "}", $hFile, $iColor, $sTab, $sLine, $aSplit
	$hFile = FileOpen($sFilename, 2)
	FileWrite($hFile, $sFileHeader)
	For $i = 1 To $aText[0][0]
		$iColor = 4
		$sLine = ""
		For $j = 1 To $aText[$i][1] / 30
			$sLine &= @TAB
		Next
		$aSplit = StringRegExp(StringReplace($aText[$i][0], "\", "\\"), "(?m)\#(\d{1})\#(.*?)(?=\#\d{1}\#|$)", 3)
		For $j = 0 To UBound($aSplit) - 1
			Switch $aSplit[$j]
				Case ""
					ContinueLoop
				Case "1", "2", "3", "4", "5"
					$iColor = Int($aSplit[$j])
					If @error Or Not $iColor Then $iColor = 4
				Case Else
					$sLine &= " " & $aColor[$iColor] & " " & $aSplit[$j]
			EndSwitch
		Next
		FileWrite($hFile, $sLine & "\par" & @CRLF)
	Next
	FileWrite($hFile, "}")
	FileClose($hFile)
EndFunc   ;==>_CreateLogFile


Func _StatusSetHScroll($iXMax)
	$iStatusOffsetW = $iXMax
	If $iStatusOffsetW <= 480 Then
		$iStatusOffsetX = 0
		$iStatusOffsetW = 480
		_GUIScrollBars_ShowScrollBar($hStatusGui, $SB_HORZ, False)
		Return
	EndIf
	Local $tSCROLLINFO = DllStructCreate($tagSCROLLINFO)
	_GUIScrollBars_ShowScrollBar($hStatusGui, $SB_HORZ, True)
	DllStructSetData($tSCROLLINFO, "fMask", BitOR($SIF_RANGE, $SIF_PAGE))
	DllStructSetData($tSCROLLINFO, "nMin", 0)
	DllStructSetData($tSCROLLINFO, "nMax", $iStatusOffsetW)
	DllStructSetData($tSCROLLINFO, "nPage", 20)
	_GUIScrollBars_SetScrollInfo($hStatusGui, $SB_HORZ, $tSCROLLINFO)
EndFunc   ;==>_StatusSetHScroll


Func _WM_PAINT($hWnd, $Msg, $wParam, $lParam)
	_GDIPlus_GraphicsDrawImage($hStatusGuiGraphic, $hStatusBitmap, 0, 0)
	Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_PAINT


Func _WM_HSCROLL($hWnd, $Msg, $wParam, $lParam)
	#forceref $Msg, $lParam
	If $lParam Then Return $GUI_RUNDEFMSG
	Local $nScrollCode = BitAND($wParam, 0x0000FFFF)
	Local $Min, $Max, $Page, $Pos, $TrackPos, $xPos
	Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_HORZ)
	$Min = DllStructGetData($tSCROLLINFO, "nMin")
	$Max = DllStructGetData($tSCROLLINFO, "nMax")
	$Page = DllStructGetData($tSCROLLINFO, "nPage")
	$xPos = DllStructGetData($tSCROLLINFO, "nPos")
	$Pos = $xPos
	$TrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")
	#forceref $Min, $Max
	Switch $nScrollCode
		Case $SB_LINELEFT ; user clicked left arrow
			DllStructSetData($tSCROLLINFO, "nPos", $Pos - 1)
		Case $SB_LINERIGHT ; user clicked right arrow
			DllStructSetData($tSCROLLINFO, "nPos", $Pos + 1)
		Case $SB_PAGELEFT ; user clicked the scroll bar shaft left of the scroll box
			DllStructSetData($tSCROLLINFO, "nPos", $Pos - $Page)
		Case $SB_PAGERIGHT ; user clicked the scroll bar shaft right of the scroll box
			DllStructSetData($tSCROLLINFO, "nPos", $Pos + $Page)
		Case $SB_THUMBTRACK ; user dragged the scroll box
			DllStructSetData($tSCROLLINFO, "nPos", $TrackPos)
	EndSwitch
	DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS)
	_GUIScrollBars_SetScrollInfo($hWnd, $SB_HORZ, $tSCROLLINFO)
	_GUIScrollBars_GetScrollInfo($hWnd, $SB_HORZ, $tSCROLLINFO)
	$Pos = DllStructGetData($tSCROLLINFO, "nPos")
	If ($Pos <> $xPos) Then $xPos = $Pos
	$iStatusOffsetX = -$xPos
	_StatusDrawBmp($iStatusOffsetY, False)
	Sleep(10)
	Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_HSCROLL


Func _WM_VSCROLL($hWnd, $Msg, $wParam, $lParam)
	#forceref $Msg, $wParam, $lParam
	If $lParam Then Return $GUI_RUNDEFMSG
	Local $nScrollCode = BitAND($wParam, 0x0000FFFF)
	Local $Min, $Max, $Page, $Pos, $TrackPos, $yPos
	Local $tSCROLLINFO = _GUIScrollBars_GetScrollInfoEx($hWnd, $SB_VERT)
	$Min = DllStructGetData($tSCROLLINFO, "nMin")
	$Max = DllStructGetData($tSCROLLINFO, "nMax")
	$Page = DllStructGetData($tSCROLLINFO, "nPage")
	$yPos = DllStructGetData($tSCROLLINFO, "nPos")
	$Pos = $yPos
	$TrackPos = DllStructGetData($tSCROLLINFO, "nTrackPos")
	Switch $nScrollCode
		Case $SB_TOP ; user clicked the HOME keyboard key
			DllStructSetData($tSCROLLINFO, "nPos", $Min)
		Case $SB_BOTTOM ; user clicked the END keyboard key
			DllStructSetData($tSCROLLINFO, "nPos", $Max)
		Case $SB_LINEUP ; user clicked the top arrow
			DllStructSetData($tSCROLLINFO, "nPos", $Pos - 1)
		Case $SB_LINEDOWN ; user clicked the bottom arrow
			DllStructSetData($tSCROLLINFO, "nPos", $Pos + 1)
		Case $SB_PAGEUP ; user clicked the scroll bar shaft above the scroll box
			DllStructSetData($tSCROLLINFO, "nPos", $Pos - $Page)
		Case $SB_PAGEDOWN ; user clicked the scroll bar shaft below the scroll box
			DllStructSetData($tSCROLLINFO, "nPos", $Pos + $Page)
		Case $SB_THUMBTRACK ; user dragged the scroll box
			DllStructSetData($tSCROLLINFO, "nPos", $TrackPos)
	EndSwitch
	DllStructSetData($tSCROLLINFO, "fMask", $SIF_POS)
	_GUIScrollBars_SetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO)
	_GUIScrollBars_GetScrollInfo($hWnd, $SB_VERT, $tSCROLLINFO)
	$Pos = DllStructGetData($tSCROLLINFO, "nPos")
	If ($Pos <> $yPos) Then $yPos = $Pos
	_StatusDrawBmp($yPos, False)
	Sleep(10)
	Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_VSCROLL


Func _WM_MOUSEWHEEL($hWnd, $Msg, $wParam, $lParam)
	If $hWnd <> $hStatusGui Then Return $GUI_RUNDEFMSG
	Local $bDown = 1
	If BitShift($wParam, 16) > 0 Then $bDown = 0
	Switch $bDown
		Case 1
			_SendMessage($hWnd, $WM_VSCROLL, $SB_PAGEDOWN, 0)
		Case Else
			_SendMessage($hWnd, $WM_VSCROLL, $SB_PAGEUP, 0)
	EndSwitch
	Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_MOUSEWHEEL

;===========================================================================================================================
; END Status
;===========================================================================================================================