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