- !verbose push
- !verbose 3
- !include LogicLib.nsh
- !include Sections.nsh
- !ifndef ___MEMENTO_NSH___
- !define ___MEMENTO_NSH___
- #####################################
- ### Memento ###
- #####################################
- /*
- Memento is a set of macros that allow installers to remember user selection
- across separate runs of the installer. Currently, it can remember the state
- of sections and mark new sections as bold. In the future, it'll integrate
- InstallOptions and maybe even the Modern UI.
- A usage example can be found in `Examples\Memento.nsi`.
- */
- #####################################
- ### Usage Instructions ###
- #####################################
- /*
- 1. Declare usage of Memento by including Memento.nsh at the top of the script.
- !include Memento.nsh
- 2. Define MEMENTO_REGISTRY_ROOT and MEMENTO_REGISTRY_KEY with the a registry key
- where sections' state should be saved.
- !define MEMENTO_REGISTRY_ROOT HKLM
- !define MEMENTO_REGISTRY_KEY \
- Software\Microsoft\Windows\CurrentVersion\Uninstall\MyProgram
- 3. Replace Section with ${MementoSection} and SectionEnd with ${MementoSectionEnd}
- for sections that whose state should be remembered by Memento.
- For sections that should be unselected by default, use ${MementoSection}'s
- brother - ${MementoUnselectedSection}.
- Sections that don't already have an identifier must be assigned one.
- Section identifiers must stay the same across different versions of the
- installer or their state will be forgotten.
- 4. Use ${MementoSectionDone} after the last ${MementoSection}.
- 5. Add a call to ${MementoSectionRestore} to .onInit to restore the state
- of all sections from the registry.
- Function .onInit
- ${MementoSectionRestore}
- FunctionEnd
- 6. Add a call to ${MementoSectionSave} to .onInstSuccess to save the state
- of all sections to the registry.
- Function .onInstSuccess
- ${MementoSectionSave}
- FunctionEnd
- 7. Tattoo the location of the chosen registry key on your arm.
- */
- #####################################
- ### User API ###
- #####################################
- ;
- ; ${MementoSection}
- ;
- ; Defines a section whose state is remembered by Memento.
- ;
- ; Usage is similar to Section.
- ;
- ; ${MementoSection} "name" "some_id"
- ;
- !define MementoSection "!insertmacro MementoSection"
- ;
- ; ${MementoSectionEnd}
- ;
- ; Ends a section previously opened using ${MementoSection}.
- ;
- ; Usage is similar to SectionEnd.
- ;
- ; ${MementoSection} "name" "some_id"
- ; # some code...
- ; ${MementoSectionEnd}
- ;
- ;
- ; ${MementoUnselectedSection}
- ;
- ; Defines a section whose state is remembered by Memento and is
- ; unselected by default.
- ;
- ; Usage is similar to Section with the /o switch.
- ;
- ; ${MementoUnselectedSection} "name" "some_id"
- ;
- !define MementoUnselectedSection "!insertmacro MementoUnselectedSection"
- ;
- ; ${MementoSectionEnd}
- ;
- ; Ends a section previously opened using ${MementoSection}.
- ;
- ; Usage is similar to SectionEnd.
- ;
- ; ${MementoSection} "name" "some_id"
- ; # some code...
- ; ${MementoSectionEnd}
- ;
- !define MementoSectionEnd "!insertmacro MementoSectionEnd"
- ;
- ; ${MementoSectionDone}
- ;
- ; Used after all ${MementoSection} have been set.
- ;
- ; ${MementoSection} "name1" "some_id1"
- ; # some code...
- ; ${MementoSectionEnd}
- ;
- ; ${MementoSection} "name2" "some_id2"
- ; # some code...
- ; ${MementoSectionEnd}
- ;
- ; ${MementoSection} "name3" "some_id3"
- ; # some code...
- ; ${MementoSectionEnd}
- ;
- ; ${MementoSectionDone}
- ;
- !define MementoSectionDone "!insertmacro MementoSectionDone"
- ;
- ; ${MementoSectionRestore}
- ;
- ; Restores the state of all Memento sections from the registry.
- ;
- ; Commonly used in .onInit.
- ;
- ; Function .onInit
- ;
- ; ${MementoSectionRestore}
- ;
- ; FunctionEnd
- ;
- !define MementoSectionRestore "!insertmacro MementoSectionRestore"
- ;
- ; ${MementoSectionSave}
- ;
- ; Saves the state of all Memento sections to the registry.
- ;
- ; Commonly used in .onInstSuccess.
- ;
- ; Function .onInstSuccess
- ;
- ; ${MementoSectionSave}
- ;
- ; FunctionEnd
- ;
- !define MementoSectionSave "!insertmacro MementoSectionSave"
- #####################################
- ### Internal Defines ###
- #####################################
- !define __MementoSectionIndex 1
- #####################################
- ### Internal Macros ###
- #####################################
- !macro __MementoCheckSettings
- !ifndef MEMENTO_REGISTRY_ROOT | MEMENTO_REGISTRY_KEY
- !error "MEMENTO_REGISTRY_ROOT and MEMENTO_REGISTRY_KEY must be defined before using any of Memento's macros"
- !endif
- !macroend
- !macro __MementoSection flags name id
- !insertmacro __MementoCheckSettings
- !ifndef __MementoSectionIndex
- !error "MementoSectionDone already used!"
- !endif
- !define __MementoSectionLastSectionId `${id}`
- !verbose pop
- Section ${flags} `${name}` `${id}`
- !verbose push
- !verbose 3
- !macroend
- #####################################
- ### User Macros ###
- #####################################
- !macro MementoSection name id
- !verbose push
- !verbose 3
- !insertmacro __MementoSection "" `${name}` `${id}`
- !verbose pop
- !macroend
- !macro MementoUnselectedSection name id
- !verbose push
- !verbose 3
- !insertmacro __MementoSection /o `${name}` `${id}`
- !define __MementoSectionUnselected
- !verbose pop
- !macroend
- !macro MementoSectionEnd
- SectionEnd
- !verbose push
- !verbose 3
- !insertmacro __MementoCheckSettings
- !ifndef __MementoSectionIndex
- !error "MementoSectionDone already used!"
- !endif
- !define /MATH __MementoSectionIndexNext \
- ${__MementoSectionIndex} + 1
- Function __MementoSectionMarkNew${__MementoSectionIndex}
- ClearErrors
- ReadRegDWORD $0 ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `MementoSection_${__MementoSectionLastSectionId}`
- ${If} ${Errors}
- !insertmacro SetSectionFlag `${${__MementoSectionLastSectionId}}` ${SF_BOLD}
- ${EndIf}
- GetFunctionAddress $0 __MementoSectionMarkNew${__MementoSectionIndexNext}
- Goto $0
- FunctionEnd
- Function __MementoSectionRestoreStatus${__MementoSectionIndex}
- ClearErrors
- ReadRegDWORD $0 ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `MementoSection_${__MementoSectionLastSectionId}`
- !ifndef __MementoSectionUnselected
- ${If} ${Errors}
- ${OrIf} $0 != 0
- !insertmacro SelectSection `${${__MementoSectionLastSectionId}}`
- ${Else}
- !insertmacro UnselectSection `${${__MementoSectionLastSectionId}}`
- ${EndIf}
- !else
- !undef __MementoSectionUnselected
- ${If} ${Errors}
- ${OrIf} $0 == 0
- !insertmacro UnselectSection `${${__MementoSectionLastSectionId}}`
- ${Else}
- !insertmacro SelectSection `${${__MementoSectionLastSectionId}}`
- ${EndIf}
- !endif
- GetFunctionAddress $0 __MementoSectionRestoreStatus${__MementoSectionIndexNext}
- Goto $0
- FunctionEnd
- Function __MementoSectionSaveStatus${__MementoSectionIndex}
- ${If} ${SectionIsSelected} `${${__MementoSectionLastSectionId}}`
- WriteRegDWORD ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `MementoSection_${__MementoSectionLastSectionId}` 1
- ${Else}
- WriteRegDWORD ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `MementoSection_${__MementoSectionLastSectionId}` 0
- ${EndIf}
- GetFunctionAddress $0 __MementoSectionSaveStatus${__MementoSectionIndexNext}
- Goto $0
- FunctionEnd
- !undef __MementoSectionIndex
- !define __MementoSectionIndex ${__MementoSectionIndexNext}
- !undef __MementoSectionIndexNext
- !undef __MementoSectionLastSectionId
- !verbose pop
- !macroend
- !macro MementoSectionDone
- !verbose push
- !verbose 3
- !insertmacro __MementoCheckSettings
- Function __MementoSectionMarkNew${__MementoSectionIndex}
- FunctionEnd
- Function __MementoSectionRestoreStatus${__MementoSectionIndex}
- FunctionEnd
- Function __MementoSectionSaveStatus${__MementoSectionIndex}
- FunctionEnd
- !undef __MementoSectionIndex
- !verbose pop
- !macroend
- !macro MementoSectionRestore
- !verbose push
- !verbose 3
- !insertmacro __MementoCheckSettings
- Push $0
- Push $1
- Push $2
- Push $3
- # check for first usage
- ClearErrors
- ReadRegStr $0 ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` MementoSectionUsed
- ${If} ${Errors}
- # use script defaults on first run
- Goto done
- ${EndIf}
- # mark new components in bold
- Call __MementoSectionMarkNew1
- # mark section groups in bold
- StrCpy $0 0
- StrCpy $1 ""
- StrCpy $2 ""
- StrCpy $3 ""
- loop:
- ClearErrors
- ${If} ${SectionIsBold} $0
- ${If} $1 != ""
- !insertmacro SetSectionFlag $1 ${SF_BOLD}
- ${EndIf}
- ${If} $2 != ""
- !insertmacro SetSectionFlag $2 ${SF_BOLD}
- ${EndIf}
- ${If} $3 != ""
- !insertmacro SetSectionFlag $3 ${SF_BOLD}
- ${EndIf}
- ${ElseIf} ${Errors}
- Goto loop_end
- ${EndIf}
- ${If} ${SectionIsSectionGroup} $0
- ${If} $1 == ""
- StrCpy $1 $0
- ${ElseIf} $2 == ""
- StrCpy $2 $0
- ${ElseIf} $3 == ""
- StrCpy $3 $0
- ${EndIf}
- ${EndIf}
- ${If} ${SectionIsSectionGroupEnd} $0
- ${If} $3 != ""
- StrCpy $3 ""
- ${ElseIf} $2 != ""
- StrCpy $2 ""
- ${ElseIf} $1 != ""
- StrCpy $1 ""
- ${EndIf}
- ${EndIf}
- IntOp $0 $0 + 1
- Goto loop
- loop_end:
- # restore sections' status
- Call __MementoSectionRestoreStatus1
- # all done
- done:
- Pop $3
- Pop $2
- Pop $1
- Pop $0
- !verbose pop
- !macroend
- !macro MementoSectionSave
- !verbose push
- !verbose 3
- !insertmacro __MementoCheckSettings
- Push $0
- WriteRegStr ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` MementoSectionUsed ""
- Call __MementoSectionSaveStatus1
- Pop $0
- !verbose pop
- !macroend
- !endif # ___MEMENTO_NSH___
- !verbose pop