/*
  This file is part of YUMI

  It is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 2 of the License, or
  any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with it. If not, see <https://www.gnu.org/licenses/>.

  Copyright https://www.pendrivelinux.com (See YUMI-Copying.txt and YUMI-Readme.txt for more information, Credits, and Licensing)
*/

; -------- Configuration and Text File Manipulation Stuff! --------

!include "TextFunc.nsh" ; TextFunc.nsh required for the following DeleteInstall function
Function DeleteInstalled  ; Deletes Select Entry from Installed.txt          
	StrLen $0 "$DistroName"
	StrCpy $1 "$R9" $0
	StrCmp $1 "$DistroName" 0 End
	StrCpy $R9 ""
	End:
	Push $0
FunctionEnd   

Function DeleteEmptyLine ; Deletes empty lines    
	StrLen $0 "$\r$\n"
	StrCpy $1 "$R9" $0
	StrCmp $1 "$\r$\n" 0 End
	StrCpy $R9 ""
	End:
	Push $0
FunctionEnd

!macro DriveList String File
  Push "${String}"
  Push "${File}"
  Call DriveList
!macroend  
!define DriveList "!insertmacro DriveList"

Function InstalledList ; Creates a list of installed distros in the YUMI folder on the USB drive (So we can uninstall the distros later)
 ${If} ${FileExists} "$BootDir\YUMI\$DistroPath\$JustISO" ; If the file exists, add a removal entry. 
 ${OrIf} ${FileExists} "$BootDir\YUMI\$DistroPath\$JustISOName.vhdx"
   Exch $R0 ;file to write to
   Exch
   Exch $1 ;text to write
   ${If} ${FileExists} "$BootDir\YUMI\Installed.txt" 
    FileOpen $R0 '$BootDir\YUMI\Installed.txt' a 
    FileSeek $R0 0 END
	FileWrite $R0 '$\r$\n$1' ; add subsequent entry on a new line
   ${Else}
    FileOpen $R0 '$BootDir\YUMI\Installed.txt' a 
    FileSeek $R0 0 END
    FileWrite $R0 '$1'  ; add first entry without a new line
   ${EndIf}
    FileClose $R0
    Pop $1
    Pop $R0
 ${EndIf}
FunctionEnd

!macro InstalledList String File
  Push "${String}"
  Push "${File}"
  Call InstalledList
!macroend  
!define InstalledList "!insertmacro InstalledList"

Function Trim ; Remove leading and trailing whitespace from string - orgiginal function by Iceman_K  http://nsis.sourceforge.net/Remove_leading_and_trailing_whitespaces_from_a_string edited for use with YUMI
	Exch $R1 ; Original string
	Push $R2
Loop:
	StrCpy $R2 "$R1" 1
	StrCmp "$R2" " " TrimLeft
	StrCmp "$R2" "$\r" TrimLeft
	StrCmp "$R2" "$\n" TrimLeft
	StrCmp "$R2" "$\t" TrimLeft
	GoTo Loop2
TrimLeft:	
	StrCpy $R1 "$R1" "" 1
	Goto Loop
Loop2:
	StrCpy $R2 "$R1" 1 -1
	StrCmp "$R2" " " TrimRight
	StrCmp "$R2" "$\r" TrimRight
	StrCmp "$R2" "$\n" TrimRight
	StrCmp "$R2" "$\t" TrimRight
	GoTo Done
TrimRight:	
	StrCpy $R1 "$R1" -1
	Goto Loop2
Done:
	Pop $R2
	Exch $R1
FunctionEnd
!macro Trim TrimmedString OriginalString
  Push "${OriginalString}"
  Call Trim
  Pop "${TrimmedString}"
!macroend
!define Trim "!insertmacro Trim" 

Function RemovalList ; Lists the distros installed on the select drive.
 ${NSD_SetText} $LinuxDistroSelection "Step 2: Select a Distro from the list to remove"  
 ${If} ${FileExists} "$BootDir\YUMI\Installed.txt" ; Are there distributions on the select drive? 
 ClearErrors
 FileOpen $0 $BootDir\YUMI\Installed.txt r
  loop:
   FileRead $0 $1
    IfErrors done
    StrCpy $DistroName $1
	${Trim} "$DistroName" "$DistroName" ; Remove spaces, newlines, and carriage return
    ${NSD_CB_AddString} $Distro "$DistroName" ; Add DistroName to the listbox of removable distros ; was ${NSD_LB_AddString} $Distro "$DistroName" ; Enable for DropBox
   Goto loop
  done:  
 FileClose $0
 ${Else}
     ;Call SetISOFileName
 ${EndIf}
FunctionEnd

;!include "TextFunc.nsh" ; TextFunc.nsh required for the following

!define StrRep "!insertmacro StrRep"
!macro StrRep ResultVar String SubString RepString
  Push "${String}"
  Push "${SubString}"
  Push "${RepString}"
  Call StrRep
  Pop "${ResultVar}"
!macroend  
 
Function StrRep ;http://nsis.sourceforge.net/mediawiki/index.php?title=StrRep&direction=next&oldid=4565
/*After this point:
  ------------------------------------------
  $R0 = RepString (input)
  $R1 = SubString (input)
  $R2 = String (input)
  $R3 = RepStrLen (temp)
  $R4 = SubStrLen (temp)
  $R5 = StrLen (temp)
  $R6 = StartCharPos (temp)
  $R7 = TempStrL (temp)
  $R8 = TempStrR (temp)*/
 
  ;Get input from user
  Exch $R0
  Exch
  Exch $R1
  Exch
  Exch 2
  Exch $R2
  Push $R3
  Push $R4
  Push $R5
  Push $R6
  Push $R7
  Push $R8
 
  ;Return "String" if "SubString" is ""
  ${IfThen} $R1 == "" ${|} Goto Done ${|}
 
  ;Get "RepString", "String" and "SubString" length
  StrLen $R3 $R0
  StrLen $R4 $R1
  StrLen $R5 $R2
  ;Start "StartCharPos" counter
  StrCpy $R6 0
 
  ;Loop until "SubString" is found or "String" reaches its end
  ${Do}
    ;Remove everything before and after the searched part ("TempStrL")
    StrCpy $R7 $R2 $R4 $R6
 
    ;Compare "TempStrL" with "SubString"
    ${If} $R7 == $R1
      ;Split "String" to replace the string wanted
      StrCpy $R7 $R2 $R6 ;TempStrL
 
      ;Calc: "StartCharPos" + "SubStrLen" = EndCharPos
      IntOp $R8 $R6 + $R4
 
      StrCpy $R8 $R2 "" $R8 ;TempStrR
 
      ;Insert the new string between the two separated parts of "String"
      StrCpy $R2 $R7$R0$R8
      ;Now calculate the new "StrLen" and "StartCharPos"
      StrLen $R5 $R2
      IntOp $R6 $R6 + $R3
      ${Continue}
    ${EndIf}
 
    ;If not "SubString", this could be "String" end
    ${IfThen} $R6 >= $R5 ${|} ${ExitDo} ${|}
    ;If not, continue the loop
    IntOp $R6 $R6 + 1
  ${Loop}
 
  Done:
 
  ;Return output to user
  StrCpy $R0 $R2
 
/*After this point:
  ------------------------------------------
  $R0 = ResultVar (output)*/
 
  Pop $R8
  Pop $R7
  Pop $R6
  Pop $R5
  Pop $R4
  Pop $R3
  Pop $R2
  Pop $R1
  Exch $R0
FunctionEnd 

; Persistent File Creation Progress
Function ddProgress
 ${Do}
 Sleep 1
 ReadEnvStr $COMSPEC COMSPEC
 nsExec::Exec '"$COMSPEC" /C "copy" $PLUGINSDIR\ddlog.txt $PLUGINSDIR\ddlog2.txt'
 Push "$PLUGINSDIR\ddlog2.txt"
 Call LineCount
 Pop $R0
 
 Push $R0 ;line number to read from
 Push "$PLUGINSDIR\ddlog2.txt" ;text file to read
 Call ReadFileLine
 Pop $0 ;output string (read from file.txt)
 StrCpy $PERCENT "$0"
 GetDlgItem $2 $1 1030
 SendMessage $2 ${WM_SETTEXT} 0 "STR:$PERCENT"  
 ${LoopUntil} $R0 >= "$Casper"
FunctionEnd

Function cli_percent
 ${Do}
 Sleep 2
 Push 1 ;$R0 ;line number to read from
 Push "$PLUGINSDIR\ventoy-$Ventoy_Version\cli_percent.txt" ;text file to read
 Call ReadFileLine
 Pop $0 ;output string (read from file.txt)
 StrCpy $PERCENT "$0"
 GetDlgItem $2 $1 1030
 SendMessage $2 ${WM_SETTEXT} 0 "STR:$PERCENT"  
 ${LoopUntil} $0 >= "100"
 Delete "$PLUGINSDIR\ventoy-$Ventoy_Version\cli_percent.txt"
 Banner::destroy
FunctionEnd

Function LineCount ; https://nsis.sourceforge.net/Get_number_of_lines_in_text_file
Exch $R0
Push $R1
Push $R2
 FileOpen $R0 $R0 r
loop:
 ClearErrors
 FileRead $R0 $R1
 IfErrors +3
 IntOp $R2 $R2 + 1
Goto loop
 FileClose $R0
 StrCpy $R0 $R2
Pop $R2
Pop $R1
Exch $R0
FunctionEnd

Function ReadFileLine ; https://nsis.sourceforge.net/Read_from_text_file_line_number
Exch $0 ;file
Exch
Exch $1 ;line number
Push $2
Push $3
 
 FileOpen $2 $0 r
 StrCpy $3 0
 
Loop:
 IntOp $3 $3 + 1
  ClearErrors
  FileRead $2 $0
  IfErrors +2
  StrCmp $3 $1 0 loop
  FileClose $2
 
Pop $3
Pop $2
Pop $1
Exch $0
FunctionEnd

/* ; Other String Stuff
!define CharStrip "!insertmacro CharStrip"
!macro CharStrip Char InStr OutVar
 Push '${InStr}'
 Push '${Char}'
  Call CharStrip
 Pop '${OutVar}'
!macroend */

/* Function CharStrip ; https://nsis.sourceforge.io/CharStrip_%26_StrStrip:_Remove_character_or_string_from_another_string
Exch $R0 #char
Exch
Exch $R1 #in string
Push $R2
Push $R3
Push $R4
 StrCpy $R2 -1
 IntOp $R2 $R2 + 1
 StrCpy $R3 $R1 1 $R2
 StrCmp $R3 "" +8
 StrCmp $R3 $R0 0 -3
  StrCpy $R3 $R1 $R2
  IntOp $R2 $R2 + 1
  StrCpy $R4 $R1 "" $R2
  StrCpy $R1 $R3$R4
  IntOp $R2 $R2 - 2
  Goto -9
  StrCpy $R0 $R1
Pop $R4
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd */

/* !define StrStrAdv "!insertmacro StrStrAdv"
!macro StrStrAdv ResultVar String SubString SearchDirection \
       StrInclusionDirection IncludeSubString Loops CaseSensitive
  Push '${String}'
  Push '${SubString}'
  Push '${SearchDirection}'
  Push '${StrInclusionDirection}'
  Push '${IncludeSubString}'
  Push '${Loops}'
  Push '${CaseSensitive}'
  Call StrStrAdv
  Pop '${ResultVar}'
!macroend
 */
/*Function StrStrAdv ; https://nsis.sourceforge.io/StrStrAdv
/*After this point:
  ------------------------------------------
  $0 = String (input)
  $1 = SubString (input)
  $2 = SearchDirection (input)
  $3 = StrInclusionDirection (input)
  $4 = IncludeSubString (input)
  $5 = Loops (input)
  $6 = CaseSensitive (input)
  $7 = StringLength (temp)
  $8 = StrToSearchLength (temp)
  $9 = CurrentLoop (temp)
  $R0 = EndCharPos (temp)
  $R1 = StartCharPos (temp)
  $R2 = ResultVar (output)
  $R3 = Temp (temp)*/
 
/*  ;Get input from user
 
  Exch $6
  Exch
  Exch $5
  Exch
  Exch 2
  Exch $4
  Exch 2
  Exch 3
  Exch $3
  Exch 3
  Exch 4
  Exch $2
  Exch 4
  Exch 5
  Exch $1
  Exch 5
  Exch 6
  Exch $0
  Exch 6
  Push $7
  Push $8
  Push $9
  Push $R3
  Push $R2
  Push $R1
  Push $R0
 
  ; Clean $R0-$R3 variables
  StrCpy $R0 ""
  StrCpy $R1 ""
  StrCpy $R2 ""
  StrCpy $R3 ""
 
  ; Verify if we have the correct values on the variables
  ${If} $0 == ''
    SetErrors ;AdvStrStr_StrToSearch not found
    Goto AdvStrStr_End
  ${EndIf}
 
  ${If} $1 == ''
    SetErrors ;No text to search
    Goto AdvStrStr_End
  ${EndIf}
 
  ${If} $2 != <
    StrCpy $2 >
  ${EndIf}
 
  ${If} $3 != <
    StrCpy $3 >
  ${EndIf}
 
  ${If} $4 <> 0
    StrCpy $4 1
  ${EndIf}
 
  ${If} $5 <= 0
    StrCpy $5 0
  ${EndIf}
 
  ${If} $6 <> 1
    StrCpy $6 0
  ${EndIf}
 
  ; Find "AdvStrStr_String" length
  StrLen $7 $0
 
  ; Then find "AdvStrStr_SubString" length
  StrLen $8 $1
 
  ; Now set up basic variables
 
  ${If} $2 == <
    IntOp $R1 $7 - $8
    StrCpy $R2 $7
  ${Else}
    StrCpy $R1 0
    StrCpy $R2 $8
  ${EndIf}
 
  StrCpy $9 0 ; First loop
 
  ;Let's begin the search
 
  ${Do}
    ; Step 1: If the starting or ending numbers are negative
    ;         or more than AdvStrStr_StringLen, we return
    ;         error
 
    ${If} $R1 < 0
      StrCpy $R1 ''
      StrCpy $R2 ''
      StrCpy $R3 ''
      SetErrors ;AdvStrStr_SubString not found
      Goto AdvStrStr_End
    ${ElseIf} $R2 > $7
      StrCpy $R1 ''
      StrCpy $R2 ''
      StrCpy $R3 ''
      SetErrors ;AdvStrStr_SubString not found
      Goto AdvStrStr_End
    ${EndIf}
 
    ; Step 2: Start the search depending on
    ;         AdvStrStr_SearchDirection. Chop down not needed
    ;         characters.
 
    ${If} $R1 <> 0
      StrCpy $R3 $0 '' $R1
    ${EndIf}
 
    ${If} $R2 <> $7
      ${If} $R1 = 0
        StrCpy $R3 $0 $8
      ${Else}
        StrCpy $R3 $R3 $8
      ${EndIf}
    ${EndIf}
 
    ; Step 3: Make sure that's the string we want
 
    ; Case-Sensitive Support <- Use "AdvStrStr_Temp"
    ; variable because it won't be used anymore
 
    ${If} $6 == 1
      System::Call 'kernel32::lstrcmpA(ts, ts) i.s' '$R3' '$1'
      Pop $R3
      ${If} $R3 = 0
        StrCpy $R3 1 ; Continue
      ${Else}
        StrCpy $R3 0 ; Break
      ${EndIf}
    ${Else}
      ${If} $R3 == $1
        StrCpy $R3 1 ; Continue
      ${Else}
        StrCpy $R3 0 ; Break
      ${EndIf}
    ${EndIf}
 
    ; After the comparasion, confirm that it is the
    ; value we want.
 
    ${If} $R3 = 1
 
      ;We found it, return except if the user has set up to
      ;search for another one:
      ${If} $9 >= $5
 
        ;Now, let's see if the user wants
        ;AdvStrStr_SubString to appear:
        ${If} $4 == 0
          ;Return depends on AdvStrStr_StrInclusionDirection
          ${If} $3 == <
            ; RTL
            StrCpy $R0 $0 $R1
          ${Else}
            ; LTR
            StrCpy $R0 $0 '' $R2
          ${EndIf}
          ${Break}
        ${Else}
          ;Return depends on AdvStrStr_StrInclusionDirection
          ${If} $3 == <
            ; RTL
            StrCpy $R0 $0 $R2
          ${Else}
            ; LTR
            StrCpy $R0 $0 '' $R1
          ${EndIf}
          ${Break}
        ${EndIf}
      ${Else}
        ;If the user wants to have more loops, let's do it so!
        IntOp $9 $9 + 1
 
        ${If} $2 == <
          IntOp $R1 $R1 - 1
          IntOp $R2 $R2 - 1
        ${Else}
          IntOp $R1 $R1 + 1
          IntOp $R2 $R2 + 1
        ${EndIf}
      ${EndIf}
    ${Else}
      ; Step 4: We didn't find it, so do steps 1 thru 3 again
 
      ${If} $2 == <
        IntOp $R1 $R1 - 1
        IntOp $R2 $R2 - 1
      ${Else}
        IntOp $R1 $R1 + 1
        IntOp $R2 $R2 + 1
      ${EndIf}
    ${EndIf}
  ${Loop}
 
  AdvStrStr_End:
 
  ;Add 1 to AdvStrStr_EndCharPos to be supportable
  ;by "StrCpy"
 
  IntOp $R2 $R2 - 1
 
  ;Return output to user
 
  Exch $R0
  Exch
  Pop $R1
  Exch
  Pop $R2
  Exch
  Pop $R3
  Exch
  Pop $9
  Exch
  Pop $8
  Exch
  Pop $7
  Exch
  Pop $6
  Exch
  Pop $5
  Exch
  Pop $4
  Exch
  Pop $3
  Exch
  Pop $2
  Exch
  Pop $1
  Exch
  Pop $0
 
FunctionEnd */