/* FIXME: Taken from nsis 2.28. Remove when bumping version requirement. */ !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. Add a call to ${MementoSectionRestore} to .onInit to restore the state of all sections from the registry. Function .onInit ${MementoSectionRestore} FunctionEnd 5. Add a call to ${MementoSectionSave} to .onInstSuccess to save the state of all sections to the registry. Function .onInstSuccess ${MementoSectionSave} FunctionEnd 6. 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