]> git.lyx.org Git - features.git/blob - development/Win32/packaging/installer2/src/main.nsh
WinInstaller2: assure configure.py is run in the user dir, by Eugene
[features.git] / development / Win32 / packaging / installer2 / src / main.nsh
1 #-------------------------------------------------------------
2 # - - - - - - - - - - - - Preamble - - - - - - - - - - - - - -
3 #-------------------------------------------------------------
4
5   # Do a Cyclic Redundancy Check to make sure the installer
6   # was not corrupted by the download.
7   CRCCheck force
8   # Make the installer as small as possible
9   SetCompressor /SOLID lzma
10   # Make it a Unicode installer
11   Unicode true
12   # Enable support for high DPI resolution
13   ManifestDPIAware true
14
15   Name "LyX ${APP_VERSION}" # Name of the Program to be displayed during installation
16   BrandingText " " # Remove branding text ('Nullsoft Install System vX.XX')
17
18   # ===== Variables =====
19
20     Var LatexPath # Used to store path to "latex.exe"
21     Var StartMenuFolder # Used to store the start menu folder
22
23     # FIXME Variables needed due to "old" set of language strings, delete
24     Var LaTeXInstalled
25     Var LaTeXName
26     Var OldVersionNumber
27     Var AppPre
28     Var AppSuff
29     # R3
30
31     # FIXME Compile time constants needed due to "old" set of language strings, delete
32     !define APP_SERIES_KEY2 ${APP_VERSION}
33     !define APP_DIR_USERDATA "LyX${VERSION_MAJOR}.${VERSION_MINOR}"
34
35   # ========= Multiuser settings =========
36
37     !define MULTIUSER_MUI # Multiuser uses modern UI 2
38     !define MULTIUSER_EXECUTIONLEVEL Highest # Can install with any privileges (admin, user)
39     !if ${APP_ARCHITECTURE} = 64
40       !define MULTIUSER_USE_PROGRAMFILES64 # Install 64 bit program in "Program files" instead of "Program files (x86)"
41     !endif
42
43     !define MULTIUSER_INSTALLMODE_COMMANDLINE # Allow setting installmode in commandline (/AllUsers or /CurrentUser)
44
45     # Set default install mode based on a non empty registry entry (if exists in HKLM, then all users, if HKCU then current user)
46     !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY "SOFTWARE\LyX"
47     !define MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME "InstDir${VERSION_MAJOR}${VERSION_MINOR}"
48
49     !define MULTIUSER_INSTALLMODE_INSTDIR "LyX ${VERSION_MAJOR}.${VERSION_MINOR}" # Default install dir if not over-installing
50
51     # Retrieve default install location from following registry entry (HKCU/HKLM  is chosen automatically)
52     !define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY "SOFTWARE\LyX"
53     !define MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME "InstDir${VERSION_MAJOR}${VERSION_MINOR}"
54
55     !include MultiUser.nsh # Header file: Installer configuration for multi-user Windows environments
56     # When MULTIUSER_INSTALLMODE_COMMANDLINE is defined, MultiUser.nsh defines ${StrStr} and ${UnStrStr} functions
57
58   # ============= Modern UI 2 general settings ===============
59
60     #!include MUI2.nsh # included in MultiUser # Header file for creating modern looking installer
61     !define MUI_ABORTWARNING # Show a message box with a warning when the user wants to close the installer.
62     !define MUI_ICON "..\installer\icons\lyx.ico" # FIXME path # The icon for the installer.
63     !define MUI_UNICON "..\installer\icons\lyx.ico" # FIXME path # The icon for the uninstaller
64     !define MUI_HEADERIMAGE # Display an image on the header of the page.
65     !define MUI_HEADERIMAGE_BITMAP "..\installer\graphics\header.bmp" # FIXME path # Header image source
66     !define MUI_HEADERIMAGE_RIGHT # Display header image on the right and not left
67     !define MUI_WELCOMEFINISHPAGE_BITMAP "..\installer\graphics\wizard.bmp" # FIXME path # Source for image on welcome and finish page of the installer
68     !define MUI_UNWELCOMEFINISHPAGE_BITMAP "..\installer\graphics\wizard.bmp" # FIXME path # Source for image on welcome and finish page of the uninstaller
69
70   # ======== Pages definitions ==========
71
72     # Installer
73
74     !define MUI_WELCOMEPAGE_TEXT $(TEXT_WELCOME) # Use custom welcome text
75     !insertmacro MUI_PAGE_WELCOME # Welcome page
76
77     !insertmacro MUI_PAGE_LICENSE "..\installer\license.rtf" # FIXME path # License page
78
79     !define MUI_PAGE_CUSTOMFUNCTION_PRE PrepareShellCTX # Prepare shell context before the multiuser page is created, so that the installer searches for default install folder in the right context (x64/x32)
80     !insertmacro MULTIUSER_PAGE_INSTALLMODE # Multiuser page
81
82     !define MUI_PAGE_CUSTOMFUNCTION_LEAVE VerifyInstDir # Custom leave-function for directory page to verify installdir
83     !insertmacro MUI_PAGE_DIRECTORY # Directory page (where to install)
84
85     !define MUI_PAGE_CUSTOMFUNCTION_PRE DefaultDesktopFileAssoc # Custom pre-function for components page to search for already present dictionaries (in dictionaries.nsh)
86     !insertmacro MUI_PAGE_COMPONENTS # Components page (what to install)
87
88     # Default startmenu folder if registry contains no information from a previous installment, same as the default install dir
89     !define MUI_STARTMENUPAGE_DEFAULTFOLDER "${MULTIUSER_INSTALLMODE_INSTDIR}"
90     # Define registry entry to store the startmenu folder, also reads this entry in as default startmenu folder in case of over-installing
91     !define MUI_STARTMENUPAGE_REGISTRY_ROOT "SHCTX" # Context dependent on what the user chooses on multiuser page
92     !define MUI_STARTMENUPAGE_REGISTRY_KEY "SOFTWARE\LyX"
93     !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "SMDir${VERSION_MAJOR}${VERSION_MINOR}"
94     !define MUI_PAGE_CUSTOMFUNCTION_PRE PrepareShellCTX # Prepare shell context before the startmenu page is created, so that the installer searches for default startmenu folder in the right context
95     !define MUI_PAGE_CUSTOMFUNCTION_SHOW RetrieveSMState # Custom show-function for startmenu page to disable startmenu dir creation in case of over-installment where previously disabled
96     !insertmacro MUI_PAGE_STARTMENU startmenuPage $StartMenuFolder # Page to choose start menu folder entry, the folder is stored in VARIABLE
97
98     # Latexfolder page
99     !include "src\CustomPages\LaTeXFolder.nsdinc"
100     Page custom LatexFolder_Show LatexFolder_Leave
101
102     !insertmacro MUI_PAGE_INSTFILES # Progress page
103
104     !define MUI_FINISHPAGE_SHOWREADME # Showreadme-checkbox appears
105     !define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED # Showreadme-checkbox disabled by default
106     !define MUI_FINISHPAGE_SHOWREADME_FUNCTION StartLyX # Custom function for the showreadme-checkbox (start latex instead of show readme)
107     !define MUI_FINISHPAGE_SHOWREADME_TEXT $(FinishPageRun) # Custom text for the label on the showreadme-checkbox
108     !define MUI_FINISHPAGE_LINK $(TEXT_FINISH_WEBSITE) # Text for the link on the bottom of finish page
109     !define MUI_FINISHPAGE_LINK_LOCATION "https://www.lyx.org/" # Website opens by clicking on the link on finish page
110     !insertmacro MUI_PAGE_FINISH # Finish page
111
112     # Uninstaller
113
114     !insertmacro MUI_UNPAGE_WELCOME # Welcome page
115     !insertmacro MUI_UNPAGE_CONFIRM # Confirmation page
116
117     !define MUI_PAGE_CUSTOMFUNCTION_PRE un.ComponentsPre # Custom function for components page to prepare strings for the description of a section
118     !insertmacro MUI_UNPAGE_COMPONENTS # Components page
119
120     !insertmacro MUI_UNPAGE_INSTFILES # Progress page
121     !insertmacro MUI_UNPAGE_FINISH # Finish page
122
123   # ======= Other includes =======
124
125     !include "src\lang\TranslatedLanguages.nsh" # languages strings
126
127     #!include LogicLib.nsh # included in MUI2 # Allows using logic commands (such as ${If}..${Else}..${EndIf})
128     #!include LangFile.nsh # included in MUI2 # Header file to create language files that can be included with a single command.
129     !include x64.nsh # Header file to check if target system is 64 bit or not with ${RunningX64}, also defines ${DisableX64FSRedirection} and ${EnableX64FSRedirection}
130     !include NSISList.nsh # Header file to create and work with lists in NSIS (plugin)
131
132     #!include StrFunc.nsh # included in MultiUser # Provides some additional string functions
133     ${StrRep} # Define this function from StrFunc.nsh for further use
134     ${StrStrAdv} # Define this function from StrFunc.nsh for further use
135     ${UnStrStrAdv} # Define this function from StrFunc.nsh for further use
136     ${UnStrRep} # Define this function from StrFunc.nsh for further use
137
138   # ========= Installer Attributes ===========
139
140     VIProductVersion "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_REVISION}.${VERSION_BUILD}" # Must be X.X.X.X format
141     VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductName" "LyX"
142     VIAddVersionKey /LANG=${LANG_ENGLISH} "ProductVersion" "LyX ${APP_VERSION} installer"
143     VIAddVersionKey /LANG=${LANG_ENGLISH} "FileVersion" "${APP_VERSION}"
144     VIAddVersionKey /LANG=${LANG_ENGLISH} "FileDescription" "LyX - The Document Processor"
145     VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalCopyright" "LyX is Copyright © 1995 by Matthias Ettrich, 1995-${COPYRIGHT_YEAR} by the LyX Team"
146     VIAddVersionKey /LANG=${LANG_ENGLISH} "CompanyName" "LyX Team"
147     VIAddVersionKey /LANG=${LANG_ENGLISH} "LegalTrademarks" ""
148
149 #-------------------------------------------------------------
150 # - - - - - - - - - - Helper Functions - - - - - - - - - - - -
151 #-------------------------------------------------------------
152
153   # Forward declarations
154   
155   !macro SearchAllRegistry resultVar resultStateIdx resultRegIdx subKey searchFor startStateIdx startRegIdx
156     Push ${subKey}
157     Push ${searchFor}
158     Push ${startStateIdx}
159     Push ${startRegIdx}
160     Call SearchAllRegistry
161     Pop ${resultStateIdx}
162     Pop ${resultRegIdx}
163     Pop ${resultVar}
164   !macroend
165   
166   !define SearchAllRegistry "!insertmacro SearchAllRegistry"
167   
168   !macro SearchRegistry resultVar resultRegIdx subKey searchFor startRegIdx
169     Push ${subKey}
170     Push ${searchFor}
171     Push ${startRegIdx}
172     Call SearchRegistry
173     Pop ${resultRegIdx}
174     Pop ${resultVar}
175   !macroend
176   
177   !define SearchRegistry "!insertmacro SearchRegistry"
178   
179   # Functions
180   
181   Function SearchAllRegistry
182     Exch $9 # startRegIdx
183     Exch
184     Exch $8 # startStateIdx
185     Exch 2
186     Exch $7 # searchFor
187     Exch 3
188     Exch $6 # subKey
189     Push $5
190   
191     ${Do}
192       ${Select} $8
193         ${Case} 0
194           SetShellVarContext all
195           ${If} ${RunningX64}
196             SetRegView 64
197           ${Else}
198             IntOp $8 $8 + 1
199           ${EndIf}
200         ${Case} 1
201           SetShellVarContext all
202           ${If} ${RunningX64}
203             SetRegView 32
204           ${EndIf}
205         ${Case} 2
206           SetShellVarContext current
207           ${If} ${RunningX64}
208             SetRegView 64
209           ${Else}
210             IntOp $8 $8 + 1
211           ${EndIf}
212         ${Case} 3
213           SetShellVarContext current
214           ${If} ${RunningX64}
215             SetRegView 32
216           ${EndIf}
217       ${EndSelect}
218       ${SearchRegistry} $5 $9 $6 $7 $9
219       ${If} $5 != ""
220         ${Break}
221       ${EndIf}
222       IntOp $8 $8 + 1
223       StrCpy $9 0
224     ${LoopUntil} $8 >= 4
225   
226     Exch $5 # resultVar
227     Exch 4
228     Pop $7
229     Pop $6
230     Exch $9 # resultRegIdx
231     Exch
232     Exch $8 # resultStateIdx
233   FunctionEnd
234   
235   Function SearchRegistry
236     Exch $9 # startRegIdx
237     Exch
238     Exch $8 # searchFor
239     Exch 2
240     Exch $7 #subKey
241     Push $6
242     Push $5
243   
244     ${Do}
245       EnumRegKey $6 SHCTX $7 $9
246       ${StrStr} $5 $6 $8
247       IntOp $9 $9 + 1
248       ${If} $5 != ""
249         ${Break}
250       ${EndIf}
251     ${LoopUntil} $6 == ""
252   
253     Exch $5 # resultVar
254     Exch 4
255     Pop $8
256     Pop $6
257     Pop $7
258     Exch $9 # resultRegIdx
259   FunctionEnd
260   
261   !macro CreatePrepareShellCTXFun UnPrefix
262     Function ${UnPrefix}PrepareShellCTX
263       ${if} $MultiUser.InstallMode == "CurrentUser"
264         SetShellVarContext current
265       ${Else}
266         SetShellVarContext all
267       ${EndIf}
268       !if ${APP_ARCHITECTURE} <> 32
269         SetRegView ${APP_ARCHITECTURE}
270       !endif
271     FunctionEnd
272   !macroend
273   
274   !insertmacro CreatePrepareShellCTXFun ""
275   !insertmacro CreatePrepareShellCTXFun "un."
276
277 #-------------------------------------------------------------
278 # - - - - - - - - - - - - Sections - - - - - - - - - - - - - -
279 #-------------------------------------------------------------
280
281 # ============ Installer Page Functions ============
282
283 Function .onInit # Callback function, called at the very beginning, when user double clicks on the installer
284
285   !if ${APP_ARCHITECTURE} = 64 # If 64 bit installer
286     # Abort if not 64 bit Windows
287     ${IfNot} ${RunningX64}
288       MessageBox MB_OK|MB_ICONSTOP "Cannot install a 64 bit application on 32 bit Windows, please use the 32 bit installer" /SD IDOK
289       Quit
290     ${EndIf}
291   !EndIf
292
293   # Check Windows version
294   ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
295   ${if} $0 S<= "6.0" # Atleast Win7 is needed
296     MessageBox MB_OK|MB_ICONSTOP "LyX ${APP_VERSION} requires Windows 7 or newer." /SD IDOK
297     Quit
298   ${endif}
299
300   Call PrepareShellCTX # MULTIUSER_INIT should search in the right registry view
301   !insertmacro MULTIUSER_INIT # Verify multiuser privileges
302
303   # Check if the same version of LyX is installed anywhere (admin/user, x64/x32) on the computer
304   StrCpy $1 0
305   StrCpy $2 0
306   ${DoUntil} $1 >= 4
307     ${SearchAllRegistry} $0 $1 $2 "SOFTWARE\LyX" ${APP_VERSION_DOTLESS} $1 $2 # Helper Function from above
308     ${If} $0 == ${APP_VERSION_DOTLESS}
309       ReadRegStr $0 SHCTX "SOFTWARE\LYX\$0" ""
310       ${If} ${FileExists} "$0\Uninstall-LyX.exe"
311         ${IfCmd} MessageBox MB_YESNO|MB_DEFBUTTON2|MB_ICONEXCLAMATION "$(AlreadyInstalled)" /SD IDNO IDNO ${||} Quit ${|}
312       ${Else}
313         DeleteRegKey SHCTX "SOFTWARE\LYX\$0"
314       ${EndIf}
315     ${EndIf}
316   ${Loop} 
317
318   # Check if a newer version of the same LyX series is installed anywhere (admin/user, x64/x32) on the computer
319   StrCpy $1 0
320   StrCpy $2 0
321   ${DoUntil} $1 >= 4
322     ${SearchAllRegistry} $R9 $1 $2 "SOFTWARE\LyX" "${VERSION_MAJOR}${VERSION_MINOR}" $1 $2 # Helper Function from above
323     StrCpy $OldVersionNumber $R9 # FIXME remove
324     ${If} $R9 S> ${APP_VERSION_DOTLESS} # $R9 is used in $(NewerInstalled)
325       ReadRegStr $0 SHCTX "SOFTWARE\LYX\$0" ""
326       ${If} ${FileExists} "$0\Uninstall-LyX.exe"
327         MessageBox MB_OK|MB_ICONSTOP "$(NewerInstalled)" /SD IDOK
328         Quit
329       ${Else}
330         DeleteRegKey SHCTX "SOFTWARE\LYX\$0"
331       ${EndIf}
332     ${EndIf}
333   ${Loop}
334 FunctionEnd
335
336 Function CheckIfRunning # Check that LyX in $INSTDIR is not currently running, called from Function VerifyInstDir and Section -CheckSilent (if silentinstall)
337   ${If} ${RunningX64}
338     ${DisableX64FSRedirection} # We need the following process to be 64 bit on 64 bit system
339   ${EndIf}
340   nsExec::ExecToStack "powershell (Get-Process LyX).Path"
341   Pop $0 # Exit code
342   Pop $0 # Result string
343   ${If} ${RunningX64}
344     ${EnableX64FSRedirection} # Need to be anabled asap or installer might crash
345   ${EndIf}
346   ${StrStr} $0 $0 "$INSTDIR\bin\LyX.exe"
347   ${If} $0 != ""
348     MessageBox MB_OK|MB_ICONSTOP "$(UnInstallRunning)" /SD IDOK
349     Abort # Abort leaving the page (when called from the page callback) / Abort install (when called from the section)
350   ${EndIf}
351 FunctionEnd
352
353 Function VerifyInstDir # Custom Function, called when leaving directory page
354   # if the $INSTDIR does not contain "LyX" we must add a subfolder to avoid that LyX will e.g.
355   # be installed directly to "C:\Program Files" - the uninstaller will then delete the whole
356   # "C:\Program Files" directory
357   ${StrStr} $0 $INSTDIR LyX
358   ${If} $0 == ""
359     StrCpy $INSTDIR "$INSTDIR\${MULTIUSER_INSTALLMODE_INSTDIR}" # Append e.g. "LyX 2.3" to $INSTDIR
360     ${NSD_SetText} $mui.DirectoryPage.Directory $INSTDIR # Refresh Textbox
361     Abort # Abort leaving the page
362   ${EndIf}
363
364   Call CheckIfRunning
365 FunctionEnd
366
367 Function RetrieveSMState # Custom function, called after the Startmenu page has been created
368   ${IfNot} ${FileExists} "$INSTDIR\Uninstall-LyX.exe"
369     Return # Not over-installing
370   ${EndIf}
371
372   Call PrepareShellCTX # Helper function from above
373   ReadRegStr $0 SHCTX "SOFTWARE\LyX" "SMDir${VERSION_MAJOR}${VERSION_MINOR}"
374   ${If} $0 == ""
375     ${If} ${Silent}
376       StrCpy $StartMenuFolder ">$StartMenuFolder"
377     ${Else}
378       GetDlgItem $0 $mui.StartMenuPage 1005 # Get the HWND of the checkbox, MUI2 does not provide variable for that
379       SendMessage $0 ${BM_CLICK} 0 0 # NSIS delivers no other possibility here other than to send a click event to the checkbox
380     ${EndIf}
381   ${EndIf}
382 FunctionEnd
383
384 Function LatexFolder_Show # Custom Function, called before showing the LaTeXFolder page to create it
385   Call FindLatex # detect latex  
386   Pop $0 # Result string from FindLatex
387   # $0 should contain the path to latex.exe, it is used in the fnc_LaTeXFolder_Create
388   ${StrStr} $1 $0 "\latex.exe"
389   ${If} $1 != "" # If latex was actually found
390     ${StrRep} $0 $0 $1 ""
391     # $R9 is used in $(EnterLaTeXFolder) on the page
392     ${StrStr} $1 $0 "\miktex\bin"
393     ${If} $1 != ""
394       StrCpy $R9 "MiKTeX"
395     ${Else}
396       StrCpy $R9 "TeXLive"
397     ${EndIf}
398     StrCpy $LaTeXName $R9 # FIXME remove
399     StrCpy $1 $(EnterLaTeXFolder) # $1 is used on the page
400   ${Else}
401     StrCpy $1 $(EnterLaTeXFolderNone)
402   ${EndIf}
403   ${StrRep} $1 $1 "\r\n" "$\r$\n" # FIXME remove
404
405   Call fnc_LaTeXFolder_Show # In LaTeXFolder.nsdinc, defined by NSIS Dialog Designer
406 FunctionEnd
407
408 Function FindLatex # Searches latex.exe, called from pre and leave functions of latexfolder page
409   # Find "LaTeX Path" value in registry written by a previous installment of the same LyX series, prioritized, because could be user preference
410   Call PrepareShellCTX
411   ${If} ${RunningX64}
412     SetRegView 64
413   ${EndIf}
414   StrCpy $1 0
415   StrCpy $2 0
416   ${DoUntil} $2 > 1
417     ${SearchRegistry} $0 $1 "SOFTWARE\LyX" "${VERSION_MAJOR}${VERSION_MINOR}" $1
418     ${If} $0 != ""
419       ReadRegStr $0 SHCTX "SOFTWARE\LyX\$0" "LaTeX Path"
420       StrCpy $0 "$0\latex.exe"
421       ${If} ${FileExists} $0
422         Push $0
423         Return
424       ${EndIf}
425     ${ElseIf} ${RunningX64}
426       IntOp $2 $2 + 1
427       SetRegView 32
428     ${Else}
429       ${Break}
430     ${EndIf}
431   ${Loop}
432
433   nsExec::ExecToStack "where latex.exe" # Ask CMD to find "latex.exe" for us, works if latexpath is added to PATH
434   Pop $0 # Exit code: 0 = success, 1 = fail
435   ${If} $0 = 0
436     Return
437   ${EndIf}
438   Pop $0 # If search failed, this is garbage, otherwise path to latex
439
440   # Search the registry for TexLive
441   StrCpy $1 0
442   StrCpy $2 0
443   ${DoUntil} $1 >= 4
444     ${SearchAllRegistry} $0 $1 $2 "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" "TeXLive" $1 $2 # Helper Function from above
445     ReadRegStr $0 SHCTX "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$0" "UninstallString"
446     ${StrRep} $0 $0 '"' ""
447     ${StrRep} $0 $0 "tlpkg\installer\uninst.bat" "bin\win32\latex.exe" # TeXLive is not 64 bit yet
448     ${If} ${FileExists} $0
449       Push $0
450       Return
451     ${EndIf}
452   ${Loop}
453
454   # Search the registry for MiKTex  
455   StrCpy $1 0
456   StrCpy $2 0
457   ${DoUntil} $1 >= 4
458     ${SearchAllRegistry} $0 $1 $2 "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" "MiKTeX" $1 $2 # Helper Function from above
459     ReadRegStr $0 SHCTX "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$0" "InstallLocation"
460     StrCpy $0 "$0\miktex\bin\latex.exe"
461     ${If} ${FileExists} $0
462       Push $0
463       Return
464     ${EndIf}
465     ${If} ${RunningX64} # MiKTeX can also be x64
466       ${StrRep} $0 $0 "latex.exe" "x64\latex.exe"
467       ${If} ${FileExists} $0
468         Push $0
469         Return
470       ${EndIf}
471     ${EndIf}
472   ${Loop}
473
474   # No latex was found
475   Push "C:\"
476
477 FunctionEnd
478
479 Function LatexFolder_Leave # Custom function, called when trying to leave LatexFolder page to verify that "latex.exe" really exists in the given path
480   ${NSD_GetText} $hCtl_LaTeXFolder_DirRequest1_Txt $LatexPath
481   ${NSD_GetState} $hCtl_LaTeXFolder_CheckBox1 $0
482
483   ${If} $0 = ${BST_CHECKED}
484     StrCpy $LatexPath ""
485   ${ElseIfNot} ${FileExists} "$LatexPath\latex.exe"
486     MessageBox MB_OK $(InvalidLaTeXFolder)
487     Call FindLatex # Search for latex again
488     Pop $0 # Result string from FindLatex
489     ${StrStrAdv} $0 $0 "\latex.exe" ">" "<" "0" "0" "0" # Get everything before "\latex.exe"
490     ${NSD_SetText} $hCtl_LaTeXFolder_DirRequest1_Txt $0 # Refresh textbox
491     Abort # Abort leaving the page
492   ${EndIf}
493 FunctionEnd
494
495 # ========= Installer Sections =========
496
497 Section -CheckSilent # This section checks if it's a silent install and calls needed callback- and custom-pagefunctions, which are not called in this case
498   ${IfNot} ${Silent}
499     Return
500   ${EndIf}
501
502   # .onInit is called
503
504   Call CheckIfRunning
505
506   Call RetrieveSMState
507
508   Call FindLatex # Search for latex
509   Pop $0 # Result string from FindLatex
510   ${StrStrAdv} $0 $0 "\latex.exe" ">" "<" "0" "0" "0" # Get everything before "\latex.exe"
511   ${If} ${FileExists} "$0\latex.exe"
512     StrCpy $LatexPath $0
513   ${Else}
514     MessageBox MB_OK $(InvalidLaTeXFolder)
515     Quit
516   ${EndIf}
517
518   Call DefaultDesktopFileAssoc
519 SectionEnd
520
521 Section -OverInstallReg # If over-installing, we need to delete the registry keys written by the previous installment
522   Call PrepareShellCTX # Helper function from above
523   StrCpy $1 0
524   ${Do}
525     EnumRegKey $2 SHCTX "SOFTWARE\LyX" $1
526     ${StrStr} $3 $2 "${VERSION_MAJOR}${VERSION_MINOR}"
527     ReadRegStr $0 SHCTX "SOFTWARE\LyX\$3" ""
528     ${If} $0 == $INSTDIR
529       DeleteRegKey SHCTX "SOFTWARE\LyX\$3"
530       DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX$3"
531     ${EndIf}
532     IntOp $1 $1 + 1
533   ${LoopUntil} $2 == ""
534 SectionEnd
535
536 Section -ProgramFiles
537
538   # Install the core LyX files
539   
540   # Initializes the plug-ins dir ($PLUGINSDIR) if not already initialized.
541   # $PLUGINSDIR is automatically deleted when the installer exits.
542   InitPluginsDir
543   
544   # Binaries
545   SetOutPath "$INSTDIR\bin"
546   File "${FILES_LYX}\bin\LyX.exe"
547   File "${FILES_LYX}\bin\tex2lyx.exe"
548   # Visual C++ redistributable (if native build)
549   File "${FILES_DEPS}\bin\concrt140.dll"
550   File "${FILES_DEPS}\bin\msvcp140.dll"
551   File "${FILES_DEPS}\bin\vcamp140.dll"
552   File "${FILES_DEPS}\bin\vccorlib140.dll"
553   File "${FILES_DEPS}\bin\vcomp140.dll"
554   File "${FILES_DEPS}\bin\vcruntime140.dll"
555   !if ${APP_ARCHITECTURE} = 64
556     File "${FILES_DEPS}\bin\vcruntime140_1.dll"
557   !endif
558   # MinGW redistributable (if cross platform with MinGW)
559   #File "${FILES_DEPS}\bin\iconv.dll"
560   #File "${FILES_DEPS}\bin\libbz2-1.dll"
561   #File "${FILES_DEPS}\bin\libfreetype-6.dll"
562   #File "${FILES_DEPS}\bin\libgcc_s_sjlj-1.dll"
563   #File "${FILES_DEPS}\bin\libglib-2.0-0.dll"
564   #File "${FILES_DEPS}\bin\libharfbuzz-0.dll"
565   #File "${FILES_DEPS}\bin\libintl-8.dll"
566   #File "${FILES_DEPS}\bin\libjpeg-62.dll"
567   #File "${FILES_DEPS}\bin\libpcre-1.dll"
568   #File "${FILES_DEPS}\bin\libpcre2-16-0.dll"
569   #File "${FILES_DEPS}\bin\libpng16-16.dll"
570   #File "${FILES_DEPS}\bin\libstdc++-6.dll"
571   #File "${FILES_DEPS}\bin\libtiff-5.dll"
572   #File "${FILES_DEPS}\bin\libwinpthread-1.dll"
573   #File "${FILES_DEPS}\bin\libwebp-7.dll"
574   #File "${FILES_DEPS}\bin\libwebpdemux-2.dll"
575   #File "${FILES_DEPS}\bin\zlib1.dll"
576   # Netpbm
577   File "${FILES_DEPS}\bin\libnetpbm10.dll"
578   File "${FILES_DEPS}\bin\pnmcrop.exe"
579   # Rsvg
580   File "${FILES_DEPS}\bin\rsvg-convert.exe"
581   # Pdfview
582   File "${FILES_DEPS}\bin\pdfview.exe"
583   # Qt libraries
584   File "${FILES_QT}\bin\Qt5Concurrent.dll"
585   File "${FILES_QT}\bin\Qt5Core.dll"
586   File "${FILES_QT}\bin\Qt5Gui.dll"
587   File "${FILES_QT}\bin\Qt5Network.dll"
588   File "${FILES_QT}\bin\Qt5OpenGL.dll"
589   File "${FILES_QT}\bin\Qt5PrintSupport.dll"
590   File "${FILES_QT}\bin\Qt5Svg.dll"
591   File "${FILES_QT}\bin\Qt5Widgets.dll"
592   File "${FILES_QT}\bin\Qt5WinExtras.dll"
593
594   # Qt plugin DLLs
595   SetOutPath "$INSTDIR\bin\imageformats"
596   File "${FILES_QT}\bin\imageformats\qgif.dll"
597   File "${FILES_QT}\bin\imageformats\qico.dll"
598   File "${FILES_QT}\bin\imageformats\qjpeg.dll"
599   File "${FILES_QT}\bin\imageformats\qsvg.dll"
600   File "${FILES_QT}\bin\imageformats\qicns.dll"
601   File "${FILES_QT}\bin\imageformats\qtiff.dll"
602   File "${FILES_QT}\bin\imageformats\qwbmp.dll"
603   File "${FILES_QT}\bin\imageformats\qwebp.dll"
604
605   SetOutPath "$INSTDIR\bin\iconengines"
606   File "${FILES_QT}\bin\iconengines\qsvgicon.dll"
607
608   SetOutPath "$INSTDIR\bin\platforms"
609   File "${FILES_QT}\bin\platforms\qminimal.dll"
610   File "${FILES_QT}\bin\platforms\qwindows.dll"
611
612   SetOutPath "$INSTDIR\bin\styles"
613   File "${FILES_QT}\bin\styles\qwindowsvistastyle.dll"
614
615   # Resources
616   SetOutPath "$INSTDIR\Resources"
617   # recursively copy all files under Resources
618   File /r "${FILES_LYX}\Resources\"
619   File /r "${FILES_DEPS}\Resources\" # Already present files will be skiped
620
621   # Python
622   SetOutPath "$INSTDIR\Python"
623   # recursively copy all files under Python
624   File /r "${FILES_DEPS}\Python\"
625
626   # Components of ImageMagick
627   SetOutPath "$INSTDIR\imagemagick"
628   File /r "${FILES_DEPS}\imagemagick\"
629
630   # Components of Ghostscript
631   SetOutPath "$INSTDIR\ghostscript"
632   File /r "${FILES_DEPS}\ghostscript\"
633
634   # Install unoconv
635   SetOutPath "$INSTDIR\Python\Lib"
636   File "${FILES_DEPS}\bin\unoconv.py"
637   
638   WriteUninstaller "$INSTDIR\Uninstall-LyX.exe"
639 SectionEnd
640
641 Section -TexRessources # Section installs cls files from Ressources\tex and updates latex filebase
642   # First make sure that latex was found in LatexFolder_Leave function
643   ${If} $LatexPath == ""
644     Return
645   ${EndIf}
646
647   # Miktex or Texlive?
648   ${StrStr} $0 $LatexPath "\miktex\bin"
649   ${If} $0 == "" # TexLive
650     ${StrRep} $0 $LatexPath "\bin\win32" "\texmf-dist\tex\latex\lyx"
651     ${If} ${FileExists} "$0\broadway.cls"
652       Return
653     ${EndIf}
654     CopyFiles "$INSTDIR\Resources\tex\*.*" $0
655     ExecWait '$LatexPath\texhash' # Update package file list
656
657   ${Else} # Miktex
658     ${StrRep} $0 $LatexPath $0 "\tex\latex\lyx"
659     ${If} ${FileExists} "$0\broadway.cls"
660       Return
661     ${EndIf}
662     CopyFiles /SILENT "$INSTDIR\Resources\tex\*.*" $0 # First try to put into Miktex install dir
663
664     ${IfNot} ${FileExists} "$0\broadway.cls" # Check if copying succeeded
665       # Didn't suceed to put into install dir, put into users dir
666       nsExec::ExecToStack "$LatexPath\mpm.exe --version" # get the Miktex version
667       Pop $0 # Exit code
668       Pop $0 # Result
669       ${StrStrAdv} $0 $0 "MiKTeX Package Manager " ">" ">" "0" "0" "0" # $0 contains "2.9.7420 ......" now (everything after "MiKTeX Package Manager ")
670       ${StrStrAdv} $0 $0 "." ">" "<" "0" "1" "0" # $0 contains "2.9" now (everything before the second dot)
671       SetShellVarContext current
672       ${If} ${FileExists} "$APPDATA\MiKTeX\$0\tex\latex\lyx\broadway.cls" # UserInstall-dir can not be changed in Miktex currently, so this should work
673         Return
674       ${EndIf}
675       CopyFiles /SILENT "$INSTDIR\Resources\tex\*.*" "$APPDATA\MiKTeX\$0\tex\latex\lyx" # Put into user install dir
676     ${EndIf}
677
678     # Update package file list
679     nsExec::ExecToLog "$LatexPath\initexmf.exe --admin --update-fndb" # Try as admin
680     Pop $0 # Exit code
681     ${If} $0 <> 0 # Not successful
682       nsExec::ExecToLog "$LatexPath\initexmf.exe --update-fndb" # Do as user
683       Pop $0
684     ${EndIf}
685   ${EndIf}
686 SectionEnd
687
688 Section -CompilePython
689   # Compile all Python files to byte-code
690   # The user using the scripts may not have write access
691   FileOpen $R0 "$INSTDIR\compilepy.py" w
692   FileWrite $R0 "import compileall$\r$\n"
693   FileWrite $R0 "compileall.compile_dir('$INSTDIR\python\Lib')$\r$\n"
694   FileWrite $R0 "compileall.compile_dir('$INSTDIR\Resources')$\r$\n"
695   FileClose $R0
696   DetailPrint $(TEXT_CONFIGURE_PYTHON)
697   nsExec::ExecToLog '"$INSTDIR\python\python.exe" "$INSTDIR\compilepy.py"'
698   Pop $0 # Exit code
699   Delete "$INSTDIR\compilepy.py"
700 SectionEnd
701
702 Section -LyxrcDist
703   FileOpen $R0 "$INSTDIR\Resources\lyxrc.dist" a
704   FileSeek $R0 0 END
705   # set some general things
706   FileWrite $R0 '\screen_zoom 120$\r$\n'
707   FileWrite $R0 '\path_prefix "$LatexPath;$$LyXDir\bin;$$LyXDir\Python;$$LyXDir\Python\Lib;$$LyXDir\imagemagick;$$LyXDir\ghostscript'
708
709   # Do not overwrite $R0 in this Section!!!
710   # =======================================
711
712   # Find additional software and add their install locations to the path_prefix
713   # This list contains all software, which write the string value "InstallLocation" in their corresponding keys in "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
714   # To add additional software matching this requirement, just append it to the string after "${List.Append} editors "
715   ${List.Create} editors
716   ${List.Append} editors "jEdit,PSPad,WinShell,TeXnicCenter,WinEdt"
717   ${List.Count} $R1 editors
718   IntOp $R1 $R1 - 1
719   ${For} $R2 0 $R1
720     ${List.Get} $0 editors $R2
721     ${SearchAllRegistry} $0 $1 $1 "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" $0 0 0 # Helper Function from above
722     ReadRegStr $0 SHCTX "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$0" "InstallLocation"
723     ${If} $0 != ""
724       StrCpy $1 $0 "" -1 # Get the last char
725       ${If} $1 == "\" # If ends with "\"
726         StrCpy $0 $0 -1 # Remove "\"
727       ${EndIf}
728       FileWrite $R0 ";$0"
729     ${EndIf}
730   ${Next}
731   ${List.Destroy} editors
732
733   # Following Software does not create "InstallLocation"
734   # Vim  
735   ${SearchAllRegistry} $0 $1 $1 "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" "Vim" 0 0 # Helper Function from above
736   ReadRegStr $0 SHCTX "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$0" "DisplayIcon"
737   ${StrStrAdv} $0 $0 "\gvim.exe" ">" "<" "0" "0" "0" # get everything before "\gvim.exe"
738   ${If} $0 != ""
739     FileWrite $R0 ";$0"
740   ${EndIf}
741
742   # JabRef, Hard to locate, JabRef uses MSI installer, lets try to find it through the .bib extension
743   SetShellVarContext all
744   ${If} ${RunningX64}
745     SetRegView 64
746   ${EndIf}
747   ${For} $R1 0 1 # Try as admin and then as user
748     ReadRegStr $0 SHCTX "SOFTWARE\Classes\.bib" ""
749     ReadRegStr $0 SHCTX "Software\Classes\$0\shell\open\command" ""
750     ${StrRep} $0 $0 '"' "" # Remove quotes
751     ${StrStrAdv} $0 $0 "\JabRef.exe" ">" "<" "0" "0" "0" # Get everything before "\JabRef.exe"
752     ${If} ${FileExists} "$0\JabRef.exe"
753       FileWrite $R0 ";$0"
754       ${Break}
755     ${EndIf}
756     SetShellVarContext current # Retry as user
757   ${Next}
758
759   # Gnumeric
760   SetShellVarContext all
761   ${If} ${RunningX64}
762     SetRegView 64
763   ${EndIf}
764   ${For} $R1 0 1 # Try as admin and then as user
765     ReadRegStr $0 SHCTX "Software\Classes\Applications\gnumeric.exe\shell\Open\command" ""
766     ${StrRep} $0 $0 '"' "" # Remove quotes
767     ${StrStrAdv} $0 $0 "\gnumeric.exe" ">" "<" "0" "0" "0" # Get everything before "\gnumeric.exe"
768     ${If} $0 != ""
769       FileWrite $R0 ";$0"
770       ${Break}
771     ${EndIf}
772     SetShellVarContext current # Retry as user
773   ${Next}
774
775   # Pandoc, same as JabRef, can only attempt to ask cmd if added to PATH, the user can't disable that while installing pandoc though
776   nsExec::ExecToStack "where pandoc.exe"
777   Pop $1 # Exit code
778   Pop $0 # Return sring
779   ${If} $1 = 0
780     ${StrStrAdv} $0 $0 "\pandoc.exe" ">" "<" "0" "0" "0" # Get everything before "\pandoc.exe"
781     ${If} $0 != ""
782       FileWrite $R0 ";$0"
783     ${EndIf}
784   ${EndIf}
785
786   ${Map.Create} softwarePathsMap # Create a map (NSISList plugin) to temp store paths of 3rd party software
787
788   # LilyPond
789   ${SearchAllRegistry} $0 $1 $1 "SOFTWARE" "LilyPond" 0 0 # Helper Function from above
790   ReadRegStr $0 SHCTX "SOFTWARE\$0" "Install_Dir"
791   ${If} $0 != ""
792     FileWrite $R0 ";$0\usr\bin"
793     ${Map.Set} softwarePathsMap "LilyPond" "$0\usr\bin"
794   ${EndIf}
795
796   # Gimp
797   ${SearchAllRegistry} $2 $1 $1 "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" "GIMP" 0 0 # Helper Function from above
798   ReadRegStr $0 SHCTX "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$2" "InstallLocation"
799   ${If} $0 != ""
800     FileWrite $R0 ";$0bin" # Install Location ends with '\' for Gimp in Registry
801     ReadRegStr $0 SHCTX "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$2" "DisplayIcon"
802     ${StrStrAdv} $0 $0 ".exe" ">" "<" "0" "0" "0" # Get everything before the ".exe"
803     ${StrStrAdv} $0 $0 "\" "<" ">" "0" "0" "0" # Get everything after the last "\", $0 contains "gimp-10" now
804     ${Map.Set} softwarePathsMap "ImageEditor" $0
805   ${EndIf}
806
807   # Krita
808   ${SearchAllRegistry} $0 $1 $1 "SOFTWARE" "Krita" 0 0 # Helper Function from above
809   ReadRegStr $0 SHCTX "SOFTWARE\$0" "InstallLocation"
810   ${If} $0 != ""
811     FileWrite $R0 ";$0\bin"
812     ${Map.Set} softwarePathsMap "ImageEditor" "krita"
813   ${EndIf}
814
815   # Photoshop
816   SetShellVarContext all
817   ${If} ${RunningX64}
818     SetRegView 64
819   ${EndIf}
820   ${For} $R1 0 1 # Try as admin and then as user
821     ReadRegStr $0 SHCTX "Software\Classes\Applications\Photoshop.exe\shell\Open\command" ""
822     ${StrRep} $0 $0 '"' "" # Remove quotes
823     ${StrStrAdv} $0 $0 "\photoshop.exe" ">" "<" "0" "0" "0" # Get everything before "\photoshop.exe"
824     ${If} $0 != ""
825       FileWrite $R0 ";$0"
826       ${Break}
827     ${EndIf}
828     SetShellVarContext current # Retry as user
829   ${Next}
830
831   FileWrite $R0 '"$\r$\n'
832
833   ClearErrors
834   
835   # use pdfview for all types of PDF files
836   FileWrite $R0 '\format "pdf5" "pdf" "PDF (LuaTeX)" "u" "pdfview" "" "document,vector,menu=export" "application/pdf"$\r$\n\
837                 \format "pdf4" "pdf" "PDF (XeTeX)" "X" "pdfview" "" "document,vector,menu=export" "application/pdf"$\r$\n\
838                 \format "pdf3" "pdf" "PDF (dvipdfm)" "m" "pdfview" "" "document,vector,menu=export" "application/pdf"$\r$\n\
839                 \format "pdf2" "pdf" "PDF (pdflatex)" "F" "pdfview" "" "document,vector,menu=export" "application/pdf"$\r$\n\
840                 \format "pdf" "pdf" "PDF (ps2pdf)" "P" "pdfview" "" "document,vector,menu=export" "application/pdf"$\r$\n'
841
842   # If krita or gimp was found previously
843   ${Map.Get} $0 softwarePathsMap "ImageEditor"
844   ${If} $0 != "__NULL" # If "ImageEditor" is set in map    
845     FileWrite $R0 '\format "gif" "gif" "GIF" "" "auto" "$0" "" "image/gif"$\r$\n\
846                   \format "jpg" "jpg, jpeg" "JPEG" "" "auto" "$0" "" "image/jpeg"$\r$\n\
847                   \format "png" "png" "PNG" "" "auto" "$0" "" "image/x-png"$\r$\n'
848   ${EndIf}
849   
850   FileWrite $R0 '\converter "wmf" "eps" "magick -density 300 $$$$i $$$$o" ""$\r$\n\
851     \converter "emf" "eps" "magick -density 300 $$$$i $$$$o" ""$\r$\n'
852
853   # If LilyPond was found previously
854   ${Map.Get} $0 softwarePathsMap "LilyPond"
855   ${If} $0 != "__NULL" # If "LilyPond" is set in map
856     FileWrite $R0 '\format "lilypond-book" "lytex" "LilyPond book (LaTeX)" "" "" "auto" "document,menu=export" ""$\r$\n\
857                   \converter "lilypond-book" "pdflatex" "python \"$0\\lilypond-book.py\" --safe --pdf --latex-program=pdflatex --lily-output-dir=ly-pdf $$$$i" ""$\r$\n\
858                   \converter "lilypond-book" "xetex" "python \"$0\\lilypond-book.py\" --safe --pdf --latex-program=xelatex --lily-output-dir=ly-pdf $$$$i" ""$\r$\n\
859                   \converter "lilypond-book" "luatex" "python \"$0\\lilypond-book.py\" --safe --pdf --latex-program=lualatex --lily-output-dir=ly-pdf $$$$i" ""$\r$\n\
860                   \converter "lilypond-book" "latex" "python \"$0\\lilypond-book.py\" --safe --lily-output-dir=ly-eps $$$$i" ""$\r$\n'
861   ${EndIf}
862
863   ${Map.Destroy} softwarePathsMap
864
865   FileClose $R0
866   
867   ${If} ${Errors}
868     MessageBox MB_OK|MB_ICONEXCLAMATION "$(ModifyingConfigureFailed)" /SD IDOK
869     ClearErrors
870   ${EndIf}
871 SectionEnd
872
873 Section "$(SecFileAssocTitle)" SecFileAssoc # Registry information to assiciate ".lyx" extension with this LyX installation
874   Call PrepareShellCTX # Helper function from above
875
876   WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\App Paths\LyX.exe" "" "$INSTDIR\bin\LyX.exe" # Writes in both 64 and 32 bit registry
877   WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\App Paths\LyX.exe" "Version" ${APP_VERSION} # Writes in both 64 and 32 bit registry
878   
879   WriteRegStr SHCTX "Software\Classes\.lyx" "" "LyX.Document"
880   WriteRegStr SHCTX "Software\Classes\.lyx" "Content Type" "application/lyx"
881
882   WriteRegStr SHCTX "Software\Classes\LyX.Document" "" "LyX Document"
883   WriteRegStr SHCTX "Software\Classes\LyX.Document\DefaultIcon" "" "$INSTDIR\bin\LyX.exe,0"
884   WriteRegStr SHCTX "Software\Classes\LyX.Document\Shell\open\command" "" '"$INSTDIR\bin\LyX.exe" "%1"'
885
886   # we need to update also the automatically created entry about the lyx.exe
887   # otherwise .lyx-files will could be opened with an older LyX version
888   ReadRegStr $0 SHCTX "Software\Classes\Applications\LyX.exe\shell\open\command" ""
889   ${if} $0 != "" # if something was found
890     WriteRegStr SHCTX "Software\Classes\Applications\LyX.exe\shell\open\command" "" '"$INSTDIR\bin\LyX.exe" "%1"'
891   ${endif}
892
893   WriteRegStr SHCTX "SOFTWARE\LyX" "FileAssoc${VERSION_MAJOR}${VERSION_MINOR}" $INSTDIR # Save user preference for over-installing
894 SectionEnd
895
896 Section "$(SecDesktopTitle)" SecDesktop
897   SetOutPath "$INSTDIR\bin" # Need to set this so that the shortcut to lyx.exe is executed in the bin folder
898   CreateShortCut "$DESKTOP\LyX ${VERSION_MAJOR}.${VERSION_MINOR}.lnk" "$INSTDIR\bin\LyX.exe" "" "" "" "" "" "LyX - The Document Processor" # Last parameter is the comment of the shortcut
899   Call PrepareShellCTX
900   WriteRegStr SHCTX "SOFTWARE\LyX" "Desktop${VERSION_MAJOR}${VERSION_MINOR}" $INSTDIR # Save user preference for over-installing
901 SectionEnd
902
903 Section -StartMenuFolder # Creates starm menu shortcut and website links to lyx website and lyx wiki
904   Call PrepareShellCTX # Helper function from above, need to call be before the following macro, because the macro writes registry string (storing the default startmenu folder)
905   !insertmacro MUI_STARTMENU_WRITE_BEGIN startmenuPage # This macro also assures that the folder is not empty for us
906     SetOutPath "$INSTDIR\bin" # Need to set this so that the shortcut to lyx.exe is executed in the bin folder
907     CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
908     CreateShortCut "$SMPROGRAMS\$StartMenuFolder\LyX.lnk" "$INSTDIR\bin\LyX.exe" "" "" "" "" "" "LyX - The Document Processor" # Last parameter is the comment of the shortcut
909     SetOutPath $INSTDIR
910     CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall LyX.lnk" "$INSTDIR\Uninstall-LyX.exe"
911     WriteINIStr "$SMPROGRAMS\$StartMenuFolder\LyX Website.url" "InternetShortcut" "URL" "https://www.lyx.org/"
912     WriteINIStr "$SMPROGRAMS\$StartMenuFolder\LyX Wiki.url" "InternetShortcut" "URL" "https://wiki.lyx.org"
913   !insertmacro MUI_STARTMENU_WRITE_END
914 SectionEnd
915
916 !include "src\dictionaries.nsh"
917
918 Section -SoftwareRegistry # Registry information in "SOFTWARE" subkey
919   Call PrepareShellCTX # Helper function from above
920
921   ReadRegStr $0 SHCTX "SOFTWARE\LyX" "latestVersion"
922   ${If} $0 S< ${APP_VERSION_DOTLESS}
923     WriteRegStr SHCTX "SOFTWARE\LyX" "latestVersion" ${APP_VERSION_DOTLESS}
924   ${EndIf}
925   WriteRegStr SHCTX "SOFTWARE\LyX\${APP_VERSION_DOTLESS}" "" $INSTDIR
926   WriteRegStr SHCTX "SOFTWARE\LyX\${APP_VERSION_DOTLESS}" "LaTeX Path" $LatexPath
927   WriteRegStr SHCTX "SOFTWARE\LyX" "InstDir${VERSION_MAJOR}${VERSION_MINOR}" $INSTDIR # Remember install dir for the next over-installment of the same series
928 SectionEnd
929
930 Section -UninstallInfoRegistry # Registry information in "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" subkey
931   Call PrepareShellCTX # Helper function from above
932
933   ${If} $MultiUser.InstallMode == "AllUsers"
934     WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}" "DisplayName" "LyX ${APP_VERSION}"
935   ${Else}
936     WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}" "DisplayName" "LyX ${APP_VERSION} $(TEXT_INSTALL_CURRENTUSER)"
937   ${EndIf}
938
939   WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}" "UninstallString" '"$INSTDIR\Uninstall-LyX.exe"'
940   WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}" "DisplayVersion" "${APP_VERSION}"
941   WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}" "VersionMajor" "${VERSION_MAJOR}"
942   WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}" "VersionMinor" "${VERSION_MINOR}"
943   WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}" "DisplayIcon" "$INSTDIR\bin\LyX.exe"
944   WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}" "URLUpdateInfo" "https://www.lyx.org/"
945   WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}" "URLInfoAbout" "https://www.lyx.org/AboutLyX"
946   WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}" "Publisher" "LyX Team"
947   WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}" "HelpLink" "https://www.lyx.org/MailingLists"
948   WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}" "NoModify" 0x00000001
949   WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}" "NoRepair" 0x00000001
950   WriteRegStr SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}" "InstallLocation" "$INSTDIR"
951
952   ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2
953   IntFmt $0 "0x%08X" $0
954   WriteRegDWORD SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}" "EstimatedSize" $0
955 SectionEnd
956
957 Section -ConfigureScript # Runs the configure.py script
958   ${StrStr} $0 $LatexPath "\miktex\bin"
959   # R9 is used in $(TEXT_CONFIGURE_LYX)
960   ${If} $0 == "" # TexLive
961     StrCpy $R9 "TeXLive"
962   ${Else}
963     StrCpy $R9 "MiKTeX"
964   ${EndIf}
965   StrCpy $LaTeXInstalled $R9 # FIXME remove
966   DetailPrint $(TEXT_CONFIGURE_LYX) # Uses R9 to display the name of the installed latex distribution
967   
968   Call PrepareShellCTX
969   SetShellVarContext current # Otherwise $APPDATA would return C:\ProgrammData instead of C:\Users\username\AppData\Roaming
970   SetOutPath "$APPDATA\LyX${VERSION_MAJOR}.${VERSION_MINOR}" # Need to run configure from the user dir, because it creates .lst files and some folders.
971   nsExec::ExecToLog '"$INSTDIR\Python\python.exe" "$INSTDIR\Resources\configure.py"'
972   Pop $0 # Return value
973 SectionEnd
974
975 Function DefaultDesktopFileAssoc # Custom function, called before the components page, reads the states of SecDesktop and SecFileAssoc from registry (if overinstalling) and sets them
976   ${IfNot} ${FileExists} "$INSTDIR\Uninstall-LyX.exe"
977     Return # Not over-installing
978   ${EndIf}
979
980   Call PrepareShellCTX
981   ReadRegStr $0 SHCTX "SOFTWARE\LyX" "FileAssoc${VERSION_MAJOR}${VERSION_MINOR}"
982   ${If} $0 == ""
983     SectionSetFlags ${SecFileAssoc} 0 # 0 means unselected
984   ${EndIf}
985   ReadRegStr $0 SHCTX "SOFTWARE\LyX" "Desktop${VERSION_MAJOR}${VERSION_MINOR}"
986   ${If} $0 == ""
987     SectionSetFlags ${SecDesktop} 0 # 0 means unselected
988   ${EndIf}
989
990   Call CheckDictionaries # Also search for already installed dictionaries, in dictionaries.nsh
991 FunctionEnd
992
993 Function StartLyX
994   Exec "$INSTDIR\bin\LyX.exe"
995 FunctionEnd
996
997 # Installer Section Descriptions
998
999 !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
1000   !insertmacro MUI_DESCRIPTION_TEXT ${SecFileAssoc} "$(SecFileAssocDescription)"
1001   !insertmacro MUI_DESCRIPTION_TEXT ${SecDesktop} "$(SecDesktopDescription)"
1002   !insertmacro MUI_DESCRIPTION_TEXT ${SecDictionaries} "$(SecDictionariesDescription)" # In dictionaries.nsh
1003   !insertmacro MUI_DESCRIPTION_TEXT ${SecThesaurus} "$(SecThesaurusDescription)" # In dictionaries.nsh
1004 !insertmacro MUI_FUNCTION_DESCRIPTION_END
1005
1006 # ===== Uninstaller ======
1007
1008 Function un.onInit # Callback function, called when the uninstaller initializes
1009   # Check that LyX is not currently running
1010   ${If} ${RunningX64}
1011     ${DisableX64FSRedirection} # We need the following process to be 64 bit on 64 bit system
1012   ${EndIf}
1013   nsExec::ExecToStack "powershell (Get-Process LyX).Path"
1014   Pop $0 # Exit code
1015   Pop $0 # Result string
1016   ${If} ${RunningX64}
1017     ${EnableX64FSRedirection} # Need to be anabled asap or installer might crash
1018   ${EndIf}
1019   ${UnStrStr} $0 $0 "$INSTDIR\bin\LyX.exe"
1020   ${If} $0 != ""
1021     MessageBox MB_OK|MB_ICONSTOP "$(UnInstallRunning)" /SD IDOK
1022     Quit # Quit uninstaller
1023   ${EndIf}
1024
1025   Call un.PrepareShellCTX
1026   !insertmacro MULTIUSER_UNINIT
1027
1028   # Ascertain whether the user has sufficient privileges to uninstall.
1029   # abort when LyX was installed with admin permissions but the user doesn't have administrator privileges
1030   Call un.PrepareShellCTX # Helperfunction from above
1031   ReadRegStr $0 HKLM "SOFTWARE\LyX\${APP_VERSION_DOTLESS}" ""
1032   ${If} $0 == $INSTDIR
1033     ${If} $MultiUser.Privileges != "Admin"
1034     ${AndIf} $MultiUser.Privileges != "Power"
1035       MessageBox MB_OK|MB_ICONSTOP "$(UnNotAdminLabel)" /SD IDOK
1036       Abort
1037     ${Else}
1038       StrCpy $MultiUser.InstallMode "AllUsers"
1039     ${EndIf}
1040   ${Else}
1041     ReadRegStr $0 HKCU "SOFTWARE\LyX\${APP_VERSION_DOTLESS}" ""
1042     ${If} $0 == ""
1043       MessageBox MB_OK|MB_ICONEXCLAMATION "$(UnNotInRegistryLabel)" /SD IDOK
1044     ${Else}
1045       StrCpy $MultiUser.InstallMode "CurrentUser"
1046     ${EndIf}
1047   ${EndIf}
1048
1049   # question message if the user really wants to uninstall LyX
1050   ${IfCmd} MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "$(UnReallyRemoveLabel)" /SD IDYES IDNO ${||} Quit ${|}
1051 FunctionEnd
1052
1053 Function un.ComponentsPre # Callback Function, called before the components page is loaded
1054   # R9 and R8 are used in $(SecUnPreferencesDescription)
1055   SetShellVarContext current
1056   ${UnStrStrAdv} $R9 $PROFILE "\" "<" "<" "0" "0" "0" # Get everything before the last "\" of $PROFILE ("C:\Users\username") -> $R9: "C:\Users"
1057   StrCpy $AppPre $R9 # FIXME remove
1058   ${UnStrRep} $R8 $APPDATA "$PROFILE\" "" # "C:\Users\username\" gets replaced with "" in "C:\Users\username\AppData\Roaming" -> $R8: "Appdata\Roaming"
1059   StrCpy $AppSuff $R8 # FIXME remove
1060 FunctionEnd
1061
1062 Section "un.LyX" un.SecUnProgramFiles # Deletes files in $INSTDIR and registry entries
1063   SectionIn RO
1064   # LaTeX class files that were installed together with LyX
1065   # will not be uninstalled because other LyX versions will
1066   # need them and these few files don't harm to stay in LaTeX 
1067
1068   Call un.PrepareShellCTX # Helperfunction from above
1069
1070   # Subfolders and unistaller
1071   RMDir /r "$INSTDIR\bin"
1072   RMDir /r "$INSTDIR\Resources"
1073   RMDir /r "$INSTDIR\Python"
1074   RMDir /r "$INSTDIR\imagemagick"
1075   RMDir /r "$INSTDIR\ghostscript"
1076   Delete "$INSTDIR\Uninstall-LyX.exe"
1077   # Install directory
1078   SetOutPath $PLUGINSDIR
1079   RMDir $INSTDIR
1080
1081   # Startmenu
1082   !insertmacro MUI_STARTMENU_GETFOLDER startmenuPage $StartMenuFolder # Reads registry value written with macro MUI_STARTMENU_WRITE_BEGIN
1083   ShellLink::GetShortCutTarget "$SMPROGRAMS\$StartMenuFolder\LyX.lnk" # Check if the shortcut really is pointing to the current installation
1084   Pop $0
1085   ${IfNot} ${FileExists} $0 # If still exists, then belongs to another lyx installment, so don't delete
1086     RMDir /r "$SMPROGRAMS\$StartMenuFolder"
1087     DeleteRegValue SHCTX "SOFTWARE\LyX" "SMDir${VERSION_MAJOR}${VERSION_MINOR}"
1088   ${EndIf}
1089
1090   # Desktop icon
1091   ShellLink::GetShortCutTarget "$DESKTOP\LyX ${VERSION_MAJOR}.${VERSION_MINOR}.lnk"
1092   Pop $0
1093   ${UnStrStr} $0 $0 $INSTDIR
1094   ${If} $0 != ""
1095     Delete "$DESKTOP\LyX ${VERSION_MAJOR}.${VERSION_MINOR}.lnk"
1096   ${EndIf}
1097   ReadRegStr $0 SHCTX "SOFTWARE\LyX" "Desktop${VERSION_MAJOR}${VERSION_MINOR}"
1098   ${If} $0 == $INSTDIR
1099     DeleteRegValue SHCTX "SOFTWARE\LyX" "Desktop${VERSION_MAJOR}${VERSION_MINOR}"
1100   ${EndIf}
1101
1102   # File association
1103   ReadRegStr $0 SHCTX "Software\Classes\LyX.Document\DefaultIcon" ""
1104   ${UnStrStr} $0 $0 $INSTDIR
1105   ${If} $0 != ""
1106     DeleteRegKey SHCTX "Software\Classes\LyX.Document"
1107     DeleteRegKey SHCTX "Software\Classes\.lyx"
1108   ${EndIf}
1109   ReadRegStr $0 SHCTX "Software\Microsoft\Windows\CurrentVersion\App Paths\LyX.exe" ""
1110   ${UnStrStr} $0 $0 $INSTDIR
1111   ${If} $0 != ""
1112     DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\App Paths\LyX.exe" # Deletes key in both 64 and 32 bit registry
1113   ${EndIf}
1114   ReadRegStr $0 SHCTX "SOFTWARE\LyX" "FileAssoc${VERSION_MAJOR}${VERSION_MINOR}"
1115   ${If} $0 == $INSTDIR
1116     DeleteRegValue SHCTX "SOFTWARE\LyX" "FileAssoc${VERSION_MAJOR}${VERSION_MINOR}"
1117   ${EndIf}
1118   DeleteRegKey SHCTX "Software\Classes\Applications\LyX.exe"
1119
1120   # Uninstaller info registry
1121   DeleteRegKey SHCTX "Software\Microsoft\Windows\CurrentVersion\Uninstall\LyX${APP_VERSION_DOTLESS}"
1122
1123   # Software registry
1124   DeleteRegKey SHCTX "SOFTWARE\LyX\${APP_VERSION_DOTLESS}"
1125   DeleteRegValue SHCTX "SOFTWARE\LyX" "latestVersion"
1126   ReadRegStr $0 SHCTX "SOFTWARE\LyX" "InstDir${VERSION_MAJOR}${VERSION_MINOR}"
1127   ${If} $0 == $INSTDIR
1128     DeleteRegValue SHCTX "SOFTWARE\LyX" "InstDir${VERSION_MAJOR}${VERSION_MINOR}"
1129   ${EndIf}
1130   DeleteRegValue SHCTX "SOFTWARE\LyX" "latestVersion"
1131   # Now that "latestVersion" is gone we need to find if there is another (newest) LyX version installed and write it's verion to "latestVersion"
1132   # The keys in the registry are sorted alphabetically, so we dont need to compare, the latest found will be the newest version
1133   StrCpy $0 0
1134   StrCpy $1 ""
1135   ${Do}
1136     StrCpy $2 $1
1137     EnumRegKey $2 SHCTX "SOFTWARE\LyX" $0
1138     IntOp $0 $0 + 1
1139   ${LoopUntil} $1 == ""
1140   ${If} $2 != ""
1141     WriteRegStr SHCTX "SOFTWARE\LyX" "latestVersion" $2
1142   ${EndIf}
1143   DeleteRegKey /ifempty SHCTX "SOFTWARE\LyX"
1144 SectionEnd
1145
1146 Section /o "un.$(UnLyXPreferencesTitle)" un.SecUnPreferences # Deletes user preferences folders for all users (if admin) and registry entry made by LyX to HKCU
1147   Call un.PrepareShellCTX
1148   SetShellVarContext current
1149   # If installed as user, only delete folder and registry key of current user
1150   ${If} $MultiUser.InstallMode == "CurrentUser"
1151     RMDir /r "$APPDATA\LyX${VERSION_MAJOR}.${VERSION_MINOR}"
1152
1153   ${Else} # If installed as admin, things are a little more complicated
1154     ${UnStrStrAdv} $2 $PROFILE "\" "<" ">" "0" "0" "0" # Get everything after the last "\" of $PROFILE ("C:\Users\username") -> $2: "username"
1155     ${UnStrStrAdv} $3 $PROFILE "\" "<" "<" "0" "0" "0" # Get everything before the last "\" of $PROFILE ("C:\Users\username") -> $3: "C:\Users"
1156     ClearErrors
1157     FindFirst $1 $0 "$3\*" # Find any folder/file in "C:\Users"
1158     ${DoUntil} ${Errors} # Errors are set while FindFirst/FindNext if the search is completed (there are no more files)
1159       ${UnStrRep} $0 $APPDATA $2 $0 # Replace "username" in $APPDATA ("C:\Users\username\AppData\Roaming") with what was found
1160       ${If} ${FileExists} "$0\LyX${VERSION_MAJOR}.${VERSION_MINOR}\*" # Check if anything exists in the LyX userdir
1161         RMDir /r "$0\LyX${VERSION_MAJOR}.${VERSION_MINOR}"
1162       ${EndIf}
1163       FindNext $1 $0
1164     ${Loop}
1165     FindClose $1
1166   ${EndIf}
1167
1168   # Can only delete for current user, because Admin can't access registry of other users
1169   DeleteRegKey HKCU "Software\LyX\LyX${VERSION_MAJOR}.${VERSION_MINOR}"
1170   DeleteRegKey /ifempty HKCU "Software\LyX"
1171 SectionEnd
1172
1173 # Uninstaller Section Descriptions
1174
1175 !insertmacro MUI_UNFUNCTION_DESCRIPTION_BEGIN
1176   !insertmacro MUI_DESCRIPTION_TEXT ${un.SecUnProgramFiles} "$(SecUnProgramFilesDescription)"
1177   !insertmacro MUI_DESCRIPTION_TEXT ${un.SecUnPreferences} "$(SecUnPreferencesDescription)"
1178 !insertmacro MUI_UNFUNCTION_DESCRIPTION_END