/*
_____________________________________________________________________________

                       Text Functions Header v2.1
_____________________________________________________________________________

 2005 Shengalts Aleksander aka Instructor (Shengalts@mail.ru)

 See documentation for more information about the following functions.

 Usage in script:
 1. !include "TextFunc.nsh"
 2. !insertmacro TextFunction
 3. [Section|Function]
      ${TextFunction} "File" "..."  $var
    [SectionEnd|FunctionEnd]


 TextFunction=[LineFind|LineRead|FileReadFromEnd|LineSum|FileJoin|
               TextCompare|ConfigRead|ConfigWrite|FileRecode|TrimNewLines]

 un.TextFunction=[un.LineFind|un.LineRead|un.FileReadFromEnd|un.LineSum|
                  un.FileJoin|un.TextCompare|un.ConfigRead|un.ConfigWrite|
                  un.FileRecode|un.TrimNewLines]


_____________________________________________________________________________

                       Thanks to:
_____________________________________________________________________________

LineRead
	Afrow UK (Based on his idea of Function "ReadFileLine")
LineSum
	Afrow UK (Based on his idea of Function "LineCount")
FileJoin
	Afrow UK (Based on his idea of Function "JoinFiles")
ConfigRead
	vbgunz (His idea)
ConfigWrite
	vbgunz (His idea)
TrimNewLines
	sunjammer (Based on his Function "TrimNewLines")
*/


;_____________________________________________________________________________
;
;                                   Macros
;_____________________________________________________________________________
;
; Change log window verbosity (default: 3=no script)
;
; Example:
; !include "TextFunc.nsh"
; !insertmacro LineFind
; ${TEXTFUNC_VERBOSE} 4   # all verbosity
; !insertmacro LineSum
; ${TEXTFUNC_VERBOSE} 3   # no script

!verbose push
!verbose 3
!ifndef _TEXTFUNC_VERBOSE
	!define _TEXTFUNC_VERBOSE 3
!endif
!verbose ${_TEXTFUNC_VERBOSE}
!define TEXTFUNC_VERBOSE `!insertmacro TEXTFUNC_VERBOSE`
!define _TEXTFUNC_UN
!verbose pop

!macro TEXTFUNC_VERBOSE _VERBOSE
	!verbose push
	!verbose 3
	!undef _TEXTFUNC_VERBOSE
	!define _TEXTFUNC_VERBOSE ${_VERBOSE}
	!verbose 4
	!echo `"verbosity=${_VERBOSE}"`
	!verbose pop
!macroend


!macro LineFindCall _INPUT _OUTPUT _RANGE _FUNC
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push $0
	Push `${_INPUT}`
	Push `${_OUTPUT}`
	Push `${_RANGE}`
	GetFunctionAddress $0 `${_FUNC}`
	Push `$0`
	Call LineFind
	Pop $0
	!verbose pop
!macroend

!macro LineReadCall _FILE _NUMBER _RESULT
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push `${_FILE}`
	Push `${_NUMBER}`
	Call LineRead
	Pop ${_RESULT}
	!verbose pop
!macroend

!macro FileReadFromEndCall _FILE _FUNC
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push $0
	Push `${_FILE}`
	GetFunctionAddress $0 `${_FUNC}`
	Push `$0`
	Call FileReadFromEnd
	Pop $0
	!verbose pop
!macroend

!macro LineSumCall _FILE _RESULT
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push `${_FILE}`
	Call LineSum
	Pop ${_RESULT}
	!verbose pop
!macroend

!macro FileJoinCall _FILE1 _FILE2 _FILE3
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push `${_FILE1}`
	Push `${_FILE2}`
	Push `${_FILE3}`
	Call FileJoin
	!verbose pop
!macroend

!macro TextCompareCall _FILE1 _FILE2 _OPTION _FUNC
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push $0
	Push `${_FILE1}`
	Push `${_FILE2}`
	Push `${_OPTION}`
	GetFunctionAddress $0 `${_FUNC}`
	Push `$0`
	Call TextCompare
	Pop $0
	!verbose pop
!macroend

!macro ConfigReadCall _FILE _ENTRY _RESULT
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push `${_FILE}`
	Push `${_ENTRY}`
	Call ConfigRead
	Pop ${_RESULT}
	!verbose pop
!macroend

!macro ConfigWriteCall _FILE _ENTRY _VALUE _RESULT
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push `${_FILE}`
	Push `${_ENTRY}`
	Push `${_VALUE}`
	Call ConfigWrite
	Pop ${_RESULT}
	!verbose pop
!macroend

!macro FileRecodeCall _FILE _FORMAT
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push `${_FILE}`
	Push `${_FORMAT}`
	Call FileRecode
	!verbose pop
!macroend

!macro TrimNewLinesCall _FILE _RESULT
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push `${_FILE}`
	Call TrimNewLines
	Pop ${_RESULT}
	!verbose pop
!macroend

!macro LineFind
	!ifndef ${_TEXTFUNC_UN}LineFind
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!define ${_TEXTFUNC_UN}LineFind `!insertmacro ${_TEXTFUNC_UN}LineFindCall`

		Function ${_TEXTFUNC_UN}LineFind
			Exch $3
			Exch
			Exch $2
			Exch
			Exch 2
			Exch $1
			Exch 2
			Exch 3
			Exch $0
			Exch 3
			Push $4
			Push $5
			Push $6
			Push $7
			Push $8
			Push $9
			Push $R4
			Push $R5
			Push $R6
			Push $R7
			Push $R8
			Push $R9
			ClearErrors

			IfFileExists '$0' 0 error
			StrCmp $1 '/NUL' begin
			StrCpy $8 0
			IntOp $8 $8 - 1
			StrCpy $9 $1 1 $8
			StrCmp $9 \ +2
			StrCmp $9 '' +3 -3
			StrCpy $9 $1 $8
			IfFileExists '$9\*.*' 0 error

			begin:
			StrCpy $4 1
			StrCpy $5 -1
			StrCpy $6 0
			StrCpy $7 0
			StrCpy $R4 ''
			StrCpy $R6 ''
			StrCpy $R7 ''
			StrCpy $R8 0

			StrCpy $8 $2 1
			StrCmp $8 '{' 0 delspaces
			StrCpy $2 $2 '' 1
			StrCpy $8 $2 1 -1
			StrCmp $8 '}' 0 delspaces
			StrCpy $2 $2 -1
			StrCpy $R6 cut

			delspaces:
			StrCpy $8 $2 1
			StrCmp $8 ' ' 0 +3
			StrCpy $2 $2 '' 1
			goto -3
			StrCmp $2$7 '0' file
			StrCpy $4 ''
			StrCpy $5 ''
			StrCmp $2 '' writechk

			range:
			StrCpy $8 0
			StrCpy $9 $2 1 $8
			StrCmp $9 '' +5
			StrCmp $9 ' ' +4
			StrCmp $9 ':' +3
			IntOp $8 $8 + 1
			goto -5
			StrCpy $5 $2 $8
			IntOp $5 $5 + 0
			IntOp $8 $8 + 1
			StrCpy $2 $2 '' $8
			StrCmp $4 '' 0 +2
			StrCpy $4 $5
			StrCmp $9 ':' range

			IntCmp $4 0 0 +2
			IntCmp $5 -1 goto 0 growthcmp
			StrCmp $R7 '' 0 minus2plus
			StrCpy $R7 0
			FileOpen $8 $0 r
			FileRead $8 $9
			IfErrors +3
			IntOp $R7 $R7 + 1
			Goto -3
			FileClose $8

			minus2plus:
			IntCmp $4 0 +5 0 +5
			IntOp $4 $R7 + $4
			IntOp $4 $4 + 1
			IntCmp $4 0 +2 0 +2
			StrCpy $4 0
			IntCmp $5 -1 goto 0 growthcmp
			IntOp $5 $R7 + $5
			IntOp $5 $5 + 1
			growthcmp:
			IntCmp $4 $5 goto goto
			StrCpy $5 $4
			goto:
			goto $7

			file:
			StrCmp $1 '/NUL' +4
			GetTempFileName $R4
			Push $R4
			FileOpen $R4 $R4 w
			FileOpen $R5 $0 r
			IfErrors preerror

			loop:
			IntOp $R8 $R8 + 1
			FileRead $R5 $R9
			IfErrors handleclose

			cmp:
			StrCmp $2$4$5 '' writechk
			IntCmp $4 $R8 call 0 writechk
			StrCmp $5 -1 call
			IntCmp $5 $R8 call 0 call

			GetLabelAddress $7 cmp
			goto delspaces

			call:
			StrCpy $7 $R9
			Push $0
			Push $1
			Push $2
			Push $3
			Push $4
			Push $5
			Push $6
			Push $7
			Push $R4
			Push $R5
			Push $R6
			Push $R7
			Push $R8
			StrCpy $R6 '$4:$5'
			StrCmp $R7 '' +3
			IntOp $R7 $R8 - $R7
			IntOp $R7 $R7 - 1
			Call $3
			Pop $9
			Pop $R8
			Pop $R7
			Pop $R6
			Pop $R5
			Pop $R4
			Pop $7
			Pop $6
			Pop $5
			Pop $4
			Pop $3
			Pop $2
			Pop $1
			Pop $0
			IfErrors preerror
			StrCmp $9 'StopLineFind' 0 +3
			IntOp $6 $6 + 1
			goto handleclose
			StrCmp $1 '/NUL' loop
			StrCmp $9 'SkipWrite' 0 +3
			IntOp $6 $6 + 1
			goto loop
			StrCmp $7 $R9 write
			IntOp $6 $6 + 1
			goto write

			writechk:
			StrCmp $1 '/NUL' loop
			StrCmp $R6 cut 0 write
			IntOp $6 $6 + 1
			goto loop

			write:
			FileWrite $R4 $R9
			goto loop

			preerror:
			SetErrors

			handleclose:
			StrCmp $1 '/NUL' +3
			FileClose $R4
			Pop $R4
			FileClose $R5
			IfErrors error

			StrCmp $1 '/NUL' end
			StrCmp $1 '' 0 +2
			StrCpy $1 $0
			StrCmp $6 0 0 rename
			FileOpen $7 $0 r
			FileSeek $7 0 END $8
			FileClose $7
			FileOpen $7 $R4 r
			FileSeek $7 0 END $9
			FileClose $7
			IntCmp $8 $9 0 rename
			Delete $R4
			StrCmp $1 $0 end
			CopyFiles /SILENT $0 $1
			goto end

			rename:
			Delete '$EXEDIR\$1'
			Rename $R4 '$EXEDIR\$1'
			IfErrors 0 end
			Delete $1
			Rename $R4 $1
			IfErrors 0 end

			error:
			SetErrors

			end:
			Pop $R9
			Pop $R8
			Pop $R7
			Pop $R6
			Pop $R5
			Pop $R4
			Pop $9
			Pop $8
			Pop $7
			Pop $6
			Pop $5
			Pop $4
			Pop $3
			Pop $2
			Pop $1
			Pop $0
		FunctionEnd

		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN
		!verbose pop
	!endif
!macroend

!macro LineRead
	!ifndef ${_TEXTFUNC_UN}LineRead
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!define ${_TEXTFUNC_UN}LineRead `!insertmacro ${_TEXTFUNC_UN}LineReadCall`

		Function ${_TEXTFUNC_UN}LineRead
			Exch $1
			Exch
			Exch $0
			Exch
			Push $2
			Push $3
			Push $4
			ClearErrors

			IfFileExists $0 0 error
			IntOp $1 $1 + 0
			IntCmp $1 0 error 0 plus
			StrCpy $4 0
			FileOpen $2 $0 r
			IfErrors error
			FileRead $2 $3
			IfErrors +3
			IntOp $4 $4 + 1
			Goto -3
			FileClose $2
			IntOp $1 $4 + $1
			IntOp $1 $1 + 1
			IntCmp $1 0 error error

			plus:
			FileOpen $2 $0 r
			IfErrors error
			StrCpy $3 0
			IntOp $3 $3 + 1
			FileRead $2 $0
			IfErrors +4
			StrCmp $3 $1 0 -3
			FileClose $2
			goto end
			FileClose $2

			error:
			SetErrors
			StrCpy $0 ''

			end:
			Pop $4
			Pop $3
			Pop $2
			Pop $1
			Exch $0
		FunctionEnd

		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN
		!verbose pop
	!endif
!macroend

!macro FileReadFromEnd
	!ifndef ${_TEXTFUNC_UN}FileReadFromEnd
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!define ${_TEXTFUNC_UN}FileReadFromEnd `!insertmacro ${_TEXTFUNC_UN}FileReadFromEndCall`

		Function ${_TEXTFUNC_UN}FileReadFromEnd
			Exch $1
			Exch
			Exch $0
			Exch
			Push $7
			Push $8
			Push $9
			ClearErrors

			StrCpy $7 -1
			StrCpy $8 0
			IfFileExists $0 0 error
			FileOpen $0 $0 r
			IfErrors error
			FileRead $0 $9
			IfErrors +4
			Push $9
			IntOp $8 $8 + 1
			goto -4
			FileClose $0

			nextline:
			StrCmp $8 0 end
			Pop $9
			Push $1
			Push $7
			Push $8
			Call $1
			Pop $0
			Pop $8
			Pop $7
			Pop $1
			IntOp $7 $7 - 1
			IntOp $8 $8 - 1
			IfErrors error
			StrCmp $0 'StopFileReadFromEnd' clearstack nextline

			error:
			SetErrors

			clearstack:
			StrCmp $8 0 end
			Pop $9
			IntOp $8 $8 - 1
			goto clearstack

			end:
			Pop $9
			Pop $8
			Pop $7
			Pop $1
			Pop $0
		FunctionEnd

		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN
		!verbose pop
	!endif
!macroend

!macro LineSum
	!ifndef ${_TEXTFUNC_UN}LineSum
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!define ${_TEXTFUNC_UN}LineSum `!insertmacro ${_TEXTFUNC_UN}LineSumCall`

		Function ${_TEXTFUNC_UN}LineSum
			Exch $0
			Push $1
			Push $2
			ClearErrors

			IfFileExists $0 0 error
			StrCpy $2 0
			FileOpen $0 $0 r
			IfErrors error
			FileRead $0 $1
			IfErrors +3
			IntOp $2 $2 + 1
			Goto -3
			FileClose $0
			StrCpy $0 $2
			goto end

			error:
			SetErrors
			StrCpy $0 ''

			end:
			Pop $2
			Pop $1
			Exch $0
		FunctionEnd

		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN
		!verbose pop
	!endif
!macroend

!macro FileJoin
	!ifndef ${_TEXTFUNC_UN}FileJoin
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!define ${_TEXTFUNC_UN}FileJoin `!insertmacro ${_TEXTFUNC_UN}FileJoinCall`

		Function ${_TEXTFUNC_UN}FileJoin
			Exch $2
			Exch
			Exch $1
			Exch
			Exch 2
			Exch $0
			Exch 2
			Push $3
			Push $4
			Push $5
			ClearErrors

			IfFileExists $0 0 error
			IfFileExists $1 0 error
			StrCpy $3 0
			IntOp $3 $3 - 1
			StrCpy $4 $2 1 $3
			StrCmp $4 \ +2
			StrCmp $4 '' +3 -3
			StrCpy $4 $2 $3
			IfFileExists '$4\*.*' 0 error

			StrCmp $2 $0 0 +2
			StrCpy $2 ''
			StrCmp $2 '' 0 +3
			StrCpy $4 $0
			goto +3
			GetTempFileName $4
			CopyFiles /SILENT $0 $4
			FileOpen $3 $4 a
			IfErrors error
			FileSeek $3 -1 END
			FileRead $3 $5
			StrCmp $5 '$\r' +3
			StrCmp $5 '$\n' +2
			FileWrite $3 '$\r$\n'

			;FileWrite $3 '$\r$\n--Divider--$\r$\n'

			FileOpen $0 $1 r
			IfErrors error
			FileRead $0 $5
			IfErrors +3
			FileWrite $3 $5
			goto -3
			FileClose $0
			FileClose $3
			StrCmp $2 '' end
			Delete '$EXEDIR\$2'
			Rename $4 '$EXEDIR\$2'
			IfErrors 0 end
			Delete $2
			Rename $4 $2
			IfErrors 0 end

			error:
			SetErrors

			end:
			Pop $5
			Pop $4
			Pop $3
			Pop $2
			Pop $1
			Pop $0
		FunctionEnd

		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN
		!verbose pop
	!endif
!macroend

!macro TextCompare
	!ifndef ${_TEXTFUNC_UN}TextCompare
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!define ${_TEXTFUNC_UN}TextCompare `!insertmacro ${_TEXTFUNC_UN}TextCompareCall`

		Function ${_TEXTFUNC_UN}TextCompare
			Exch $3
			Exch
			Exch $2
			Exch
			Exch 2
			Exch $1
			Exch 2
			Exch 3
			Exch $0
			Exch 3
			Push $4
			Push $5
			Push $6
			Push $7
			Push $8
			Push $9
			ClearErrors

			IfFileExists $0 0 error
			IfFileExists $1 0 error
			StrCmp $2 'FastDiff' +5
			StrCmp $2 'FastEqual' +4
			StrCmp $2 'SlowDiff' +3
			StrCmp $2 'SlowEqual' +2
			goto error

			FileOpen $4 $0 r
			IfErrors error
			FileOpen $5 $1 r
			IfErrors error
			SetDetailsPrint textonly

			StrCpy $6 0
			StrCpy $8 0

			nextline:
			StrCmp $4 '' fast
			IntOp $8 $8 + 1
			FileRead $4 $9
			IfErrors 0 +4
			FileClose $4
			StrCpy $4 ''
			StrCmp $5 '' end
			StrCmp $2 'FastDiff' fast
			StrCmp $2 'FastEqual' fast slow

			fast:
			StrCmp $5 '' call
			IntOp $6 $6 + 1
			FileRead $5 $7
			IfErrors 0 +5
			FileClose $5
			StrCpy $5 ''
			StrCmp $4 '' end
			StrCmp $2 'FastDiff' call close
			StrCmp $2 'FastDiff' 0 +2
			StrCmp $7 $9 nextline call
			StrCmp $7 $9 call nextline

			slow:
			StrCmp $4 '' close
			StrCpy $6 ''
			DetailPrint '$8. $9'
			FileSeek $5 0

			slownext:
			FileRead $5 $7
			IfErrors 0 +2
			StrCmp $2 'SlowDiff' call nextline
			StrCmp $2 'SlowDiff' 0 +2
			StrCmp $7 $9 nextline slownext
			IntOp $6 $6 + 1
			StrCmp $7 $9 0 slownext

			call:
			Push $2
			Push $3
			Push $4
			Push $5
			Push $6
			Push $7
			Push $8
			Push $9
			Call $3
			Pop $0
			Pop $9
			Pop $8
			Pop $7
			Pop $6
			Pop $5
			Pop $4
			Pop $3
			Pop $2
			StrCmp $0 'StopTextCompare' 0 nextline

			close:
			FileClose $4
			FileClose $5
			goto end

			error:
			SetErrors

			end:
			SetDetailsPrint both
			Pop $9
			Pop $8
			Pop $7
			Pop $6
			Pop $5
			Pop $4
			Pop $3
			Pop $2
			Pop $1
			Pop $0
		FunctionEnd

		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN
		!verbose pop
	!endif
!macroend

!macro ConfigRead
	!ifndef ${_TEXTFUNC_UN}ConfigRead
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!define ${_TEXTFUNC_UN}ConfigRead `!insertmacro ${_TEXTFUNC_UN}ConfigReadCall`

		Function ${_TEXTFUNC_UN}ConfigRead
			Exch $1
			Exch
			Exch $0
			Exch
			Push $2
			Push $3
			Push $4
			ClearErrors

			FileOpen $2 $0 r
			IfErrors error
			StrLen $0 $1
			StrCmp $0 0 error

			readnext:
			FileRead $2 $3
			IfErrors empty
			StrCpy $4 $3 $0
			StrCmp $4 $1 0 readnext
			StrCpy $0 $3 '' $0
			StrCpy $4 $0 1 -1
			StrCmp $4 '$\r' +2
			StrCmp $4 '$\n' 0 close
			StrCpy $0 $0 -1
			goto -4

			error:
			SetErrors

			empty:
			StrCpy $0 ''

			close:
			FileClose $2

			Pop $4
			Pop $3
			Pop $2
			Pop $1
			Exch $0
		FunctionEnd

		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN
		!verbose pop
	!endif
!macroend

!macro ConfigWrite
	!ifndef ${_TEXTFUNC_UN}ConfigWrite
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!define ${_TEXTFUNC_UN}ConfigWrite `!insertmacro ${_TEXTFUNC_UN}ConfigWriteCall`

		Function ${_TEXTFUNC_UN}ConfigWrite
			Exch $2
			Exch
			Exch $1
			Exch
			Exch 2
			Exch $0
			Exch 2
			Push $3
			Push $4
			Push $5
			Push $6
			ClearErrors

			IfFileExists $0 0 error
			FileOpen $3 $0 a
			IfErrors error

			StrLen $0 $1
			StrCmp $0 0 0 readnext
			StrCpy $0 ''
			goto close

			readnext:
			FileRead $3 $4
			IfErrors add
			StrCpy $5 $4 $0
			StrCmp $5 $1 0 readnext

			StrCpy $5 0
			IntOp $5 $5 - 1
			StrCpy $6 $4 1 $5
			StrCmp $6 '$\r' -2
			StrCmp $6 '$\n' -3
			StrCpy $6 $4
			StrCmp $5 -1 +3
			IntOp $5 $5 + 1
			StrCpy $6 $4 $5

			StrCmp $2 '' change
			StrCmp $6 '$1$2' 0 change
			StrCpy $0 SAME
			goto close

			change:
			FileSeek $3 0 CUR $5
			StrLen $4 $4
			IntOp $4 $5 - $4
			FileSeek $3 0 END $6
			IntOp $6 $6 - $5

			System::Alloc $6
			Pop $0
			FileSeek $3 $5 SET
			System::Call 'kernel32::ReadFile(i r3, i r0, i $6, t.,)'
			FileSeek $3 $4 SET
			StrCmp $2 '' +2
			FileWrite $3 '$1$2$\r$\n'
			System::Call 'kernel32::WriteFile(i r3, i r0, i $6, t.,)'
			System::Call 'kernel32::SetEndOfFile(i r3)'
			System::Free $0
			StrCmp $2 '' +3
			StrCpy $0 CHANGED
			goto close
			StrCpy $0 DELETED
			goto close

			add:
			StrCmp $2 '' 0 +3
			StrCpy $0 SAME
			goto close
			FileSeek $3 -1 END
			FileRead $3 $4
			IfErrors +4
			StrCmp $4 '$\r' +3
			StrCmp $4 '$\n' +2
			FileWrite $3 '$\r$\n'
			FileWrite $3 '$1$2$\r$\n'
			StrCpy $0 ADDED

			close:
			FileClose $3
			goto end

			error:
			SetErrors
			StrCpy $0 ''

			end:
			Pop $6
			Pop $5
			Pop $4
			Pop $3
			Pop $2
			Pop $1
			Exch $0
		FunctionEnd

		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN
		!verbose pop
	!endif
!macroend

!macro FileRecode
	!ifndef ${_TEXTFUNC_UN}FileRecode
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!define ${_TEXTFUNC_UN}FileRecode `!insertmacro ${_TEXTFUNC_UN}FileRecodeCall`

		Function ${_TEXTFUNC_UN}FileRecode
			Exch $1
			Exch
			Exch $0
			Exch
			Push $2
			Push $3
			Push $4

			IfFileExists $0 0 error
			StrCmp $1 OemToChar +2
			StrCmp $1 CharToOem 0 error

			FileOpen $2 $0 a
			FileSeek $2 0 END $3
			System::Alloc $3
			Pop $4

			FileSeek $2 0 SET
			System::Call 'kernel32::ReadFile(i r2, i r4, i $3, t.,)'
			System::Call 'user32::$1Buff(i r4, i r4, i $3)'
			FileSeek $2 0 SET
			System::Call 'kernel32::WriteFile(i r2, i r4, i $3, t.,)'

			System::Free $4
			FileClose $2
			goto end

			error:
			SetErrors

			end:
			Pop $4
			Pop $3
			Pop $2
			Pop $1
			Pop $0
		FunctionEnd

		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN
		!verbose pop
	!endif
!macroend

!macro TrimNewLines
	!ifndef ${_TEXTFUNC_UN}TrimNewLines
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!define ${_TEXTFUNC_UN}TrimNewLines `!insertmacro ${_TEXTFUNC_UN}TrimNewLinesCall`

		Function ${_TEXTFUNC_UN}TrimNewLines
			Exch $0
			Push $1
			Push $2

			StrCpy $1 0
			IntOp $1 $1 - 1
			StrCpy $2 $0 1 $1
			StrCmp $2 '$\r' -2
			StrCmp $2 '$\n' -3
			StrCmp $1 -1 +3
			IntOp $1 $1 + 1
			StrCpy $0 $0 $1

			Pop $2
			Pop $1
			Exch $0
		FunctionEnd

		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN
		!verbose pop
	!endif
!macroend

!macro un.LineFindCall _INPUT _OUTPUT _RANGE _FUNC
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push $0
	Push `${_INPUT}`
	Push `${_OUTPUT}`
	Push `${_RANGE}`
	GetFunctionAddress $0 `${_FUNC}`
	Push `$0`
	Call un.LineFind
	Pop $0
	!verbose pop
!macroend

!macro un.LineReadCall _FILE _NUMBER _RESULT
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push `${_FILE}`
	Push `${_NUMBER}`
	Call un.LineRead
	Pop ${_RESULT}
	!verbose pop
!macroend

!macro un.FileReadFromEndCall _FILE _FUNC
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push $0
	Push `${_FILE}`
	GetFunctionAddress $0 `${_FUNC}`
	Push `$0`
	Call un.FileReadFromEnd
	Pop $0
	!verbose pop
!macroend

!macro un.LineSumCall _FILE _RESULT
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push `${_FILE}`
	Call un.LineSum
	Pop ${_RESULT}
	!verbose pop
!macroend

!macro un.FileJoinCall _FILE1 _FILE2 _FILE3
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push `${_FILE1}`
	Push `${_FILE2}`
	Push `${_FILE3}`
	Call un.FileJoin
	!verbose pop
!macroend

!macro un.TextCompareCall _FILE1 _FILE2 _OPTION _FUNC
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push $0
	Push `${_FILE1}`
	Push `${_FILE2}`
	Push `${_OPTION}`
	GetFunctionAddress $0 `${_FUNC}`
	Push `$0`
	Call un.TextCompare
	Pop $0
	!verbose pop
!macroend

!macro un.ConfigReadCall _FILE _ENTRY _RESULT
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push `${_FILE}`
	Push `${_ENTRY}`
	Call un.ConfigRead
	Pop ${_RESULT}
	!verbose pop
!macroend

!macro un.ConfigWriteCall _FILE _ENTRY _VALUE _RESULT
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push `${_FILE}`
	Push `${_ENTRY}`
	Push `${_VALUE}`
	Call un.ConfigWrite
	Pop ${_RESULT}
	!verbose pop
!macroend

!macro un.FileRecodeCall _FILE _FORMAT
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push `${_FILE}`
	Push `${_FORMAT}`
	Call un.FileRecode
	!verbose pop
!macroend

!macro un.TrimNewLinesCall _FILE _RESULT
	!verbose push
	!verbose ${_TEXTFUNC_VERBOSE}
	Push `${_FILE}`
	Call un.TrimNewLines
	Pop ${_RESULT}
	!verbose pop
!macroend

!macro un.LineFind
	!ifndef un.LineFind
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN `un.`

		!insertmacro LineFind

		!verbose pop
	!endif
!macroend

!macro un.LineRead
	!ifndef un.LineRead
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN `un.`

		!insertmacro LineRead

		!verbose pop
	!endif
!macroend

!macro un.FileReadFromEnd
	!ifndef un.FileReadFromEnd
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN `un.`

		!insertmacro FileReadFromEnd

		!verbose pop
	!endif
!macroend

!macro un.LineSum
	!ifndef un.LineSum
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN `un.`

		!insertmacro LineSum

		!verbose pop
	!endif
!macroend

!macro un.FileJoin
	!ifndef un.FileJoin
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN `un.`

		!insertmacro FileJoin

		!verbose pop
	!endif
!macroend

!macro un.TextCompare
	!ifndef un.TextCompare
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN `un.`

		!insertmacro TextCompare

		!verbose pop
	!endif
!macroend

!macro un.ConfigRead
	!ifndef un.ConfigRead
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN `un.`

		!insertmacro ConfigRead

		!verbose pop
	!endif
!macroend

!macro un.ConfigWrite
	!ifndef un.ConfigWrite
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN `un.`

		!insertmacro ConfigWrite

		!verbose pop
	!endif
!macroend

!macro un.FileRecode
	!ifndef un.FileRecode
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN `un.`

		!insertmacro FileRecode

		!verbose pop
	!endif
!macroend

!macro un.TrimNewLines
	!ifndef un.TrimNewLines
		!verbose push
		!verbose ${_TEXTFUNC_VERBOSE}
		!undef _TEXTFUNC_UN
		!define _TEXTFUNC_UN `un.`

		!insertmacro TrimNewLines

		!verbose pop
	!endif
!macroend
