
!verbose push
!verbose 3
!ifndef SECTIONFUNC_VERBOSITY
  !define SECTIONFUNC_VERBOSITY 3
!endif
!define _SECTIONFUNC_VERBOSITY ${SECTIONFUNC_VERBOSITY}
!undef SECTIONFUNC_VERBOSITY
!verbose ${_SECTIONFUNC_VERBOSITY}

!include StrFunc.nsh
!include Sections.nsh

!ifndef SECTIONFUNC

  !macro _IsSelected _a _b _d _t _f
    Push $0
    Push $1
    Push $2
    Push $3

    StrLen $2 `${_d}`

    ${If} ${_b} == 0

      ${For} $1 0 $2
        StrCpy $3 `${_d}` 1 $1
        ${If} $3 == ","
          StrCpy $0 `${_d}` $1
          ${Break}
        ${EndIf}
      ${Next}

    ${Else}

      StrCpy $0 0

      ${For} $1 0 $2
        StrCpy $3 `${_d}` 1 $1
        ${If} $3 == ","
          IntOp $0 $0 + 1
          ${If} $0 == ${_b}
            IntOp $1 $1 + 1
            StrCpy $0 `${_d}` "" $1
            ${Break}
          ${EndIf}
        ${EndIf}
      ${Next}

      StrLen $2 `$0`
      ${For} $1 0 $2
        StrCpy $3 `$0` 1 $1
        ${If} $3 == ","
          StrCpy $0 `$0` $1
          ${Break}
        ${EndIf}
      ${Next}

    ${EndIf}

    IntOp $0 $0 & `${_a}`

    Pop $3
    Pop $2
    Pop $1

    ${If} $0 == `${_a}`
      Pop $0
      Goto `${_t}`
    ${Else}
      Pop $0
      Goto `${_f}`
    ${EndIf}
  !macroend
  !define FlagIsSelected `${SF_SELECTED} IsSelected`
  !define FlagIsSubSection `${SF_SUBSEC} IsSelected`
  !define FlagIsSubSectionEnd `${SF_SUBSECEND} IsSelected`
  !define FlagIsSectionGroup `${SF_SECGRP} IsSelected`
  !define FlagIsSectionGroupEnd `${SF_SECGRPEND} IsSelected`
  !define FlagIsBold `${SF_BOLD} IsSelected`
  !define FlagIsReadOnly `${SF_RO} IsSelected`
  !define FlagIsExpanded `${SF_EXPAND} IsSelected`
  !define FlagIsPartiallySelected `${SF_PSELECTED} IsSelected`
  !define FlagIsOff `${SECTION_OFF} IsSelected`

  !macro _IfSection _s _a _o _b _d
    !verbose push
    !verbose ${LOGICLIB_VERBOSITY}
    !insertmacro _PushLogic
    !define ${_Logic}IfSection
    !define ${_Logic}ElseSection _${__LINE__}                   ; Get a label for the ElseSection
    !define _s=${_s}
    !ifdef _s=true                                              ; IfSection is true
      !insertmacro _${_o} `${_a}` `${_b}` `${_d}` "" ${${_Logic}ElseSection}
    !else                                                       ; IfSection condition is false
      !insertmacro _${_o} `${_a}` `${_b}` `${_d}` ${${_Logic}ElseSection} ""
    !endif
    !undef _s=${_s}
    !verbose pop
  !macroend
  !define IfSection `!insertmacro _IfSection true`
  !define UnlessSection `!insertmacro _IfSection false`

  !macro _AndSection _s _a _o _b _d
    !verbose push
    !verbose ${LOGICLIB_VERBOSITY}
    !ifndef _Logic | ${_Logic}IfSection
      !error "Cannot use AndSection without a preceding IfSection or UnlessSection"
    !endif
    !ifndef ${_Logic}ElseSection
      !error "Cannot use AndSection following an ElseSection"
    !endif
    !define _s=${_s}
    !ifdef _s=true                                              ; IfSection is true
      !insertmacro _${_o} `${_a}` `${_b}` `${_d}` "" ${${_Logic}ElseSection}
    !else                                                       ; IfSection condition is false
      !insertmacro _${_o} `${_a}` `${_b}` `${_d}` ${${_Logic}ElseSection} ""
    !endif
    !undef _s=${_s}
    !verbose pop
  !macroend
  !define AndIfSection     `!insertmacro _AndSection true`
  !define AndUnlessSection `!insertmacro _AndSection false`

  !macro _OrSection _s _a _o _b _d
    !verbose push
    !verbose ${LOGICLIB_VERBOSITY}
    !ifndef _Logic | ${_Logic}IfSection
      !error "Cannot use OrSection without a preceding IfSection or UnlessSection"
    !endif
    !ifndef ${_Logic}ElseSection
      !error "Cannot use OrSection following an ElseSection"
    !endif
    !define _label _${__LINE__}                                 ; Skip this test as we already
    Goto ${_label}                                              ; have a successful result
    ${${_Logic}ElseSection}:                                    ; Place the ElseSection label
    !undef ${_Logic}ElseSection                                 ; and remove it
    !define ${_Logic}ElseSection _${__LINE__}                   ; Get a label for the next ElseSection and perform the new IfSection
    !define _s=${_s}
    !ifdef _s=true                                              ; IfSection is true
      !insertmacro _${_o} `${_a}` `${_b}` `${_d}` "" ${${_Logic}ElseSection}
    !else                                                       ; IfSection condition is false
      !insertmacro _${_o} `${_a}` `${_b}` `${_d}` ${${_Logic}ElseSection} ""
    !endif
    !undef _s=${_s}
    ${_label}:
    !undef _label
    !verbose pop
  !macroend
  !define OrIfSection     `!insertmacro _OrSection true`
  !define OrUnlessSection `!insertmacro _OrSection false`

  !macro _ElseSection
    !verbose push
    !verbose ${LOGICLIB_VERBOSITY}
    !ifndef _Logic | ${_Logic}IfSection
      !error "Cannot use ElseSection without a preceding IfSection or UnlessSection"
    !endif
    !ifndef ${_Logic}ElseSection
      !error "Cannot use ElseSection following an ElseSection"
    !endif
    !ifndef ${_Logic}EndIfSection                                ; First ElseSection for this IfSection?
      !define ${_Logic}EndIfSection _${__LINE__}                 ; Get a label for the EndIfSection
    !endif
    Goto ${${_Logic}EndIfSection}                                ; Go to the EndIfSection
    ${${_Logic}ElseSection}:                                     ; Place the ElseSection label
    !undef ${_Logic}ElseSection                                  ; and remove it
    !verbose pop
  !macroend
  !define ElseSection `!insertmacro _ElseSection`

  !macro _ElseIfSection _s _a _o _b _d
    !verbose push
    !verbose ${LOGICLIB_VERBOSITY}
    ${ElseSection}                                               ; Perform the ElseSection
    !define ${_Logic}ElseSection _${__LINE__}                    ; Get a label for the next ElseSection and perform the new IfSection
    !define _s=${_s}
    !ifdef _s=true                                               ; IfSection is true
      !insertmacro _${_o} `${_a}` `${_b}` `${_d}` "" ${${_Logic}ElseSection}
    !else                                                        ; IfSection condition is false
      !insertmacro _${_o} `${_a}` `${_b}` `${_d}` ${${_Logic}ElseSection} ""
    !endif
    !undef _s=${_s}
    !verbose pop
  !macroend
  !define ElseIfSection     `!insertmacro _ElseIfSection true`
  !define ElseUnlessSection `!insertmacro _ElseIfSection false`

  !macro _EndIfSection _n
    !verbose push
    !verbose ${LOGICLIB_VERBOSITY}
    !ifndef _Logic | ${_Logic}IfSection
      !error "Cannot use EndSection${_n} without a preceding IfSection or UnlessSection"
    !endif
    !ifdef ${_Logic}ElseSection
      ${${_Logic}ElseSection}:                                   ; Place the ElseSection label
      !undef ${_Logic}ElseSection                                ; and remove it
    !endif
    !ifdef ${_Logic}EndIfSection
      ${${_Logic}EndIfSection}:                                  ; Place the EndIfSection
      !undef ${_Logic}EndIfSection                               ; and remove it
    !endif
    !undef ${_Logic}IfSection
    !insertmacro _PopLogic
    !verbose pop
  !macroend
  !define EndIfSection `!insertmacro _EndIfSection IfSection`
  !define EndUnlessSection `!insertmacro _EndIfSection UnlessSection`
  
  !macro _SectionGetValues _r _k _v
    Push $0
    Push $1
    Push $2
    Push $3
      
    !ifndef _SectionGetValue
      var /GLOBAL _OldFlags
      var /GLOBAL _NewFlags
      !define _SectionGetValue
    !endif

    ReadRegStr $0 `${_r}` `${_k}` `${_v}`

    SectionGetFlags 0 $1
    StrCpy $2 0
    ${Do}
      IntOp $2 $2 + 1
      SectionGetFlags $2 $3
      ${IfThen} ${Errors} ${|} ${ExitDo} ${|}
      ${IfThen} $3 != "" ${|} StrCpy $1 "$1,$3" ${|}
    ${Loop}

    StrCpy $_OldFlags $0
    StrCpy $_NewFlags "$1,0"

    Pop $3
    Pop $2
    Pop $1
    Pop $0
  !macroend
  !define SectionGetValues `!insertmacro _SectionGetValues`

  !macro _Section _a
    !verbose push
    !verbose ${LOGICLIB_VERBOSITY}
    !insertmacro _PushLogic
    !define ${_Logic}Section `${_a}`                             ; Remember the left hand side of the comparsion
    !define ${_Logic}OldFlags `$_OldFlags`
    !define ${_Logic}NewFlags `$_NewFlags`
    !define ${_Logic}SectionEnd _${__LINE__}                     ; Get a label for SectionEnd
    !insertmacro _IsSelected `${SF_SELECTED}` `${${_Logic}Section}` `${${_Logic}OldFlags}` "" ${${_Logic}SectionEnd}
    !verbose pop
  !macroend
  !define Section `!insertmacro _Section`

  !macro _Repair
    !verbose push
    !verbose ${LOGICLIB_VERBOSITY}
    !ifndef _Logic | ${_Logic}Section
      !error "Cannot use Repair without a preceding Section"
    !endif
    !define ${_Logic}Remove _${__LINE__}                         ; Get a label for the next Remove
    !insertmacro _IsSelected `${SF_SELECTED}` `${${_Logic}Section}` `${${_Logic}OldFlags}` "" ${${_Logic}Remove}
    !verbose pop
  !macroend
  !define Repair `!insertmacro _Repair`

  !macro _Remove
    !verbose push
    !verbose ${LOGICLIB_VERBOSITY}
    !ifndef _Logic | ${_Logic}Section
      !error "Cannot use Remove without a preceding Section"
    !endif
    !ifdef ${_Logic}Remove
      ${${_Logic}Remove}:                                        ; Place the Remove label
      !undef ${_Logic}Remove                                     ; and remove it
    !endif
    !insertmacro _IsSelected `${SF_SELECTED}` `${${_Logic}Section}` `${${_Logic}NewFlags}` ${${_Logic}SectionEnd} ""
    !verbose pop
  !macroend
  !define Remove `!insertmacro _Remove`

  !macro _SectionEnd
    !verbose push
    !verbose ${LOGICLIB_VERBOSITY}
    !ifndef _Logic | ${_Logic}Section
      !error "Cannot use SectionEnd without a preceding Section"
    !endif
    !ifdef ${_Logic}Remove
      ${${_Logic}Remove}:                                        ; Place the Remove label
      !undef ${_Logic}Remove                                     ; and remove it
    !endif
    !ifdef ${_Logic}SectionEnd
      ${${_Logic}SectionEnd}:                                    ; Place the SectionEnd
      !undef ${_Logic}SectionEnd                                 ; and remove it
    !endif
    !undef ${_Logic}NewFlags
    !undef ${_Logic}OldFlags
    !undef ${_Logic}Section
    !insertmacro _PopLogic
    !verbose pop
  !macroend
  !define SectionEnd `!insertmacro _SectionEnd`
  
  

  !insertmacro STRFUNC_DEFFUNC SectionResetFlags
  !define SectionResetFlags_List `RootKey|SubKey|ValueStr`
  !define SectionResetFlags_TypeList `Text|Text|Text`
  !macro `FUNCTION_STRING_UnSectionResetFlags`
    !undef UnSectionResetFlags
    !insertmacro FUNCTION_STRING_SectionResetFlags
  !macroend

  !insertmacro STRFUNC_DEFFUNC SectionWriteReg
  !define SectionWriteReg_List `RootKey|SubKey|ValueStr`
  !define SectionWriteReg_TypeList `Text|Text|Text`
  !macro `FUNCTION_STRING_UnSectionWriteReg`
    !undef UnSectionWriteReg
    !insertmacro FUNCTION_STRING_SectionWriteReg
  !macroend

  !insertmacro STRFUNC_DEFFUNC SectionReadReg
  !define SectionReadReg_List `RootKey|SubKey|ValueStr`
  !define SectionReadReg_TypeList `Text|Text|Text`
  !macro `FUNCTION_STRING_UnSectionReadReg`
    !undef UnSectionReadReg
    !insertmacro FUNCTION_STRING_SectionReadReg
  !macroend

  !macro FUNCTION_STRING_SectionResetFlags
    !insertmacro STRFUNC_FUNC `SectionResetFlags` `2004 - 2005 Tu Tong - Based on functions by Tu Tong`

      Exch $2
      Exch
      Exch $1
      Exch
      Exch 2
      Exch $0
      Exch 2
      Push $3
      Push $4
      Push $5
      Push $6

      ${Select} $0
        ${Case2} "HKCR" "HKEY_CLASSES_ROOT"
          ReadRegStr $0 HKCR `$1` `$2`
        ${Case2} "HKLM" "HKEY_LOCAL_MACHINE"
          ReadRegStr $0 HKLM `$1` `$2`
        ${Case2} "HKCU" "HKEY_CURRENT_USER"
          ReadRegStr $0 HKCU `$1` `$2`
        ${Case2} "HKU" "HKEY_USERS"
          ReadRegStr $0 HKU `$1` `$2`
        ${Case2} "HKCC" "HKEY_CURRENT_CONFIG"
          ReadRegStr $0 HKCC `$1` `$2`
        ${Case2} "HKDD" "HKEY_DYN_DATA"
          ReadRegStr $0 HKDD `$1` `$2`
        ${Case2} "HKPD" "HKEY_PERFORMANCE_DATA"
          ReadRegStr $0 HKPD `$1` `$2`
        ${Case2} "SHCTX" "SHELL_CONTEXT"
          ReadRegStr $0 SHCTX `$1` `$2`
      ${EndSelect}

      ${If} $0 != ""

        StrLen $5 `$0`
        ${For} $2 0 $5
          StrCpy $4 `$0` 1 $2
          ${If} $4 == ","
            IntOp $3 $3 + 1
          ${EndIf}
        ${Next}

        IntOp $3 $3 - 1
        StrCpy $4 "-1"
        ${Do}

          StrLen $5 `$0`
          ${For} $2 0 $5
            StrCpy $6 `$0` 1 $2
            ${If} $6 == ","
              StrCpy $1 `$0` $2
              IntOp $2 $2 + 1
              StrCpy $0 `$0` "" $2
              IntOp $4 $4 + 1
              ${Break}
            ${EndIf}
          ${Next}

          ${If} $4 < $3
          ${AndIf} $1 != ""
            SectionSetFlags $4 $1
          ${EndIf}

        ${LoopUntil} $4 >= $3

      ${EndIf}

      ClearErrors

      Pop $6
      Pop $5
      Pop $4
      Pop $3
      Pop $2
      Pop $1
      Pop $0

    ;------------------------
    ;End

    FunctionEnd

  !macroend

  !macro FUNCTION_STRING_SectionWriteReg
    !insertmacro STRFUNC_FUNC `SectionWriteReg` `2004 - 2005 Tu Tong - Based on functions by Tu Tong`

      Exch $2
      Exch
      Exch $1
      Exch
      Exch 2
      Exch $0
      Exch 2
      Push $3
      Push $4
      Push $5
      Push $6

      ClearErrors

      SectionGetFlags 0 $3
      StrCpy $4 0
      ${Do}
        IntOp $4 $4 + 1
        SectionGetFlags $4 $5
        ${IfThen} ${Errors} ${|} ${ExitDo} ${|}
        StrCpy $3 "$3,$5"
      ${Loop}

      StrCpy $3 "$3,0"

      ${Select} $0
        ${Case2} "HKCR" "HKEY_CLASSES_ROOT"
          WriteRegStr HKCR `$1` `$2` "$3"
        ${Case2} "HKLM" "HKEY_LOCAL_MACHINE"
          WriteRegStr HKLM `$1` `$2` "$3"
        ${Case2} "HKCU" "HKEY_CURRENT_USER"
          WriteRegStr HKCU `$1` `$2` "$3"
        ${Case2} "HKU" "HKEY_USERS"
          WriteRegStr HKU `$1` `$2` "$3"
        ${Case2} "HKCC" "HKEY_CURRENT_CONFIG"
          WriteRegStr HKCC `$1` `$2` "$3"
        ${Case2} "HKDD" "HKEY_DYN_DATA"
          WriteRegStr HKDD `$1` `$2` "$3"
        ${Case2} "HKPD" "HKEY_PERFORMANCE_DATA"
          WriteRegStr HKPD `$1` `$2` "$3"
        ${Case2} "SHCTX" "SHELL_CONTEXT"
          WriteRegStr SHCTX `$1` `$2` "$3"
      ${EndSelect}

      Pop $5
      Pop $4
      Pop $3
      Pop $2
      Pop $1
      Pop $0

    ;------------------------
    ;End

    FunctionEnd

  !macroend

  !macro FUNCTION_STRING_SectionReadReg
    !insertmacro STRFUNC_FUNC `SectionReadReg` `2004 - 2005 Tu Tong - Based on functions by Tu Tong`

      Exch $2
      Exch
      Exch $1
      Exch
      Exch 2
      Exch $0
      Exch 2
      Push $3

      ${Select} $0
        ${Case2} "HKCR" "HKEY_CLASSES_ROOT"
          ReadRegStr $0 HKCR `$1` `$2`
        ${Case2} "HKLM" "HKEY_LOCAL_MACHINE"
          ReadRegStr $0 HKLM `$1` `$2`
        ${Case2} "HKCU" "HKEY_CURRENT_USER"
          ReadRegStr $0 HKCU `$1` `$2`
        ${Case2} "HKU" "HKEY_USERS"
          ReadRegStr $0 HKU `$1` `$2`
        ${Case2} "HKCC" "HKEY_CURRENT_CONFIG"
          ReadRegStr $0 HKCC `$1` `$2`
        ${Case2} "HKDD" "HKEY_DYN_DATA"
          ReadRegStr $0 HKDD `$1` `$2`
        ${Case2} "HKPD" "HKEY_PERFORMANCE_DATA"
          ReadRegStr $0 HKPD `$1` `$2`
        ${Case2} "SHCTX" "SHELL_CONTEXT"
          ReadRegStr $0 SHCTX `$1` `$2`
      ${EndSelect}

      ClearErrors

      SectionGetFlags 0 $1
      StrCpy $2 0
      ${Do}
        IntOp $2 $2 + 1
        SectionGetFlags $2 $3
        ${IfThen} ${Errors} ${|} ${ExitDo} ${|}
        ${IfThen} $3 != "" ${|} StrCpy $1 "$1,$3" ${|}
      ${Loop}

      StrCpy $1 "$1,0"

      Pop $3
      Pop $2
      Exch
      Exch $1
      Exch
      Exch $0

    FunctionEnd

  !macroend
  
  
  !macro FUNCTION_STRING_SectionResetFlags_Call RootKey SubKey ValueStr
    !verbose push
    !verbose 4
    !echo `$ {SectionResetFlags} "${RootKey}" "${SubKey}" "${ValueStr}"`
    !verbose pop

    Push `${RootKey}`
    Push `${SubKey}`
    Push `${ValueStr}`
    Call SectionResetFlags
  !macroend
  !macro FUNCTION_STRING_UnSectionResetFlags_Call RootKey SubKey ValueStr
    !verbose push
    !verbose 4
    !echo `$ {UnSectionResetFlags} "${RootKey}" "${SubKey}" "${ValueStr}"`
    !verbose pop

    Push `${RootKey}`
    Push `${SubKey}`
    Push `${ValueStr}`
    Call un.SectionResetFlags
  !macroend

  !macro FUNCTION_STRING_SectionWriteReg_Call RootKey SubKey ValueStr
    !verbose push
    !verbose 4
    !echo `$ {SectionWriteReg} "${RootKey}" "${SubKey}" "${ValueStr}"`
    !verbose pop

    Push `${RootKey}`
    Push `${SubKey}`
    Push `${ValueStr}`
    Call SectionWriteReg
  !macroend
  !macro FUNCTION_STRING_UnSectionWriteReg_Call RootKey SubKey ValueStr
    !verbose push
    !verbose 4
    !echo `$ {UnSectionWriteReg} "${RootKey}" "${SubKey}" "${ValueStr}"`
    !verbose pop

    Push `${RootKey}`
    Push `${SubKey}`
    Push `${ValueStr}`
    Call un.SectionWriteReg
  !macroend

  !macro FUNCTION_STRING_SectionReadReg_Call ResultVar1 ResultVar2 RootKey SubKey ValueStr
    !verbose push
    !verbose 4
    !echo `$ {SectionReadReg} "${ResultVar1}" "${ResultVar2}" "${RootKey}" "${SubKey}" "${ValueStr}"`
    !verbose pop

    Push `${RootKey}`
    Push `${SubKey}`
    Push `${ValueStr}`
    Call SectionReadReg
    Pop `${ResultVar1}`
    Pop `${ResultVar2}`
  !macroend
  !macro FUNCTION_STRING_UnSectionReadReg_Call ResultVar1 ResultVar2 RootKey SubKey ValueStr
    !verbose push
    !verbose 4
    !echo `$ {UnSectionReadReg} "${ResultVar1}" "${ResultVar2}" "${RootKey}" "${SubKey}" "${ValueStr}"`
    !verbose pop

    Push `${RootKey}`
    Push `${SubKey}`
    Push `${ValueStr}`
    Call un.SectionReadReg
    Pop `${ResultVar1}`
    Pop `${ResultVar2}`
  !macroend

!endif
!verbose 3
!define SECTIONFUNC_VERBOSITY ${_SECTIONFUNC_VERBOSITY}
!undef _SECTIONFUNC_VERBOSITY
!verbose pop