; Sections.nsh
;
; Defines and macros for section control
;
; Include in your script using:
; !include "Sections.nsh"

;--------------------------------

!verbose push
!verbose 3
!ifndef SECTIONS_INCLUDED

!define SECTIONS_INCLUDED

  !ifndef _LOGICLIB_VERBOSITY
    !include "LogicLib.nsh"
  !endif

  ;--------------------------------

; Generic section defines

  !macro _IsSelected _a _b _d _t _f
    Push $0
    Push $1
    Push $2
    Push $3
    Push $4
    
    StrLen $2 `${_d}`
    
    ${If} ${_b} == 1

      ${For} $0 0 $2
        StrCpy $1 `${_d}` 1 $0
        ${If} $1 == ","
          StrCpy $0 `${_d}` $0
          ${Break}
        ${EndIf}
      ${Next}
      
    ${Else}

      StrCpy $4 0
      IntOp $0 ${_b} - 1

      ${For} $1 0 $2
        StrCpy $3 `${_d}` 1 $1
        ${If} $3 == ","
          IntOp $4 $4 + 1
          ${If} $4 == $0
            IntOp $3 $1 + 1
            StrCpy $4 `${_d}` "" $3
            ${Break}
          ${EndIf}
        ${EndIf}
      ${Next}

      StrLen $2 `$4`
      ${For} $3 0 $2
        StrCpy $1 `$4` 1 $3
        ${If} $1 == ","
          StrCpy $0 `$4` $3
          ${Break}
        ${EndIf}
      ${Next}

    ${EndIf}

    IntOp $0 $0 & `${_a}`
    
    Pop $4
    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 Else
    !define _s=${_s}
    !ifdef _s=true                                        ; If is true
      !insertmacro _${_o} `${_a}` `${_b}` `${_d}` "" ${${_Logic}ElseSection}
    !else                                                 ; If 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 And without a preceding If or Unless"
    !endif
    !ifndef ${_Logic}ElseSection
      !error "Cannot use And following an Else"
    !endif
    !define _s=${_s}
    !ifdef _s=true                                               ; If is true
      !insertmacro _${_o} `${_a}` `${_b}` `${_d}` "" ${${_Logic}ElseSection}
    !else                                                        ; If 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 Or without a preceding If or Unless"
    !endif
    !ifndef ${_Logic}ElseSection
      !error "Cannot use Or following an Else"
    !endif
    !define _label _${__LINE__}                                  ; Skip this test as we already
    Goto ${_label}                                               ; have a successful result
    ${${_Logic}ElseSection}:                                     ; Place the Else label
    !undef ${_Logic}ElseSection                                  ; and remove it
    !define ${_Logic}ElseSection _${__LINE__}                    ; Get a label for the next Else and perform the new If
    !define _s=${_s}
    !ifdef _s=true                                               ; If is true
      !insertmacro _${_o} `${_a}` `${_b}` `${_d}` "" ${${_Logic}ElseSection}
    !else                                                        ; If 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 Else without a preceding If or Unless"
    !endif
    !ifndef ${_Logic}ElseSection
      !error "Cannot use Else following an Else"
    !endif
    !ifndef ${_Logic}EndIfSection                                ; First Else for this If?
      !define ${_Logic}EndIfSection _${__LINE__}                 ; Get a label for the EndIf
    !endif
    Goto ${${_Logic}EndIfSection}                                ; Go to the EndIf
    ${${_Logic}ElseSection}:                                     ; Place the Else 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 Else
    !define ${_Logic}ElseSection _${__LINE__}                    ; Get a label for the next Else and perform the new If
    !define _s=${_s}
    !ifdef _s=true                                               ; If is true
      !insertmacro _${_o} `${_a}` `${_b}` `${_d}` "" ${${_Logic}ElseSection}
    !else                                                        ; If 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 End${_n} without a preceding If or Unless"
    !endif
    !ifdef ${_Logic}ElseSection
      ${${_Logic}ElseSection}:                                   ; Place the Else label
      !undef ${_Logic}ElseSection                                ; and remove it
    !endif
    !ifdef ${_Logic}EndIfSection
      ${${_Logic}EndIfSection}:                                  ; Place the EndIf
      !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 _Section _a _o _n
    !verbose push
    !verbose ${LOGICLIB_VERBOSITY}
    !insertmacro _PushLogic
    !define ${_Logic}Section `${_a}`                       ; Remember the left hand side of the comparison
    !define ${_Logic}OldFlags `${_o}`
    !define ${_Logic}NewFlags `${_n}`
    !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}
    !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}
    !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`

;--------------------------------

!endif
!verbose pop