]> git.lyx.org Git - lyx.git/blob - development/Win32/pdfview/pdfview.nsi
installer: a comment format fix
[lyx.git] / development / Win32 / pdfview / pdfview.nsi
1 /*
2
3 Windows PDF view helper
4 Author: Joost Verburg and Uwe Stöhr
5
6 This will be installed as pdfview.exe.
7
8 The application will launch the default PDF viewer to display the PDF file,
9 but works around the file locking problems of Adobe Reader and Acrobat.
10
11 The files pdfopen/pdfclose are part of this archive:
12 http://www.tex.ac.uk/tex-archive/systems/win32/w32tex/pdftex-w32.tar.xz
13
14 */
15
16 !include LogicLib.nsh
17 !include FileFunc.nsh
18
19 #--------------------------------
20 # Settings
21
22 Caption "PDF Viewer"
23 OutFile pdfview.exe
24 Icon "..\packaging\icons\lyx.ico"
25 SilentInstall silent
26
27 #--------------------------------
28 # Windows Vista (and later) settings
29
30 RequestExecutionLevel user
31
32 #--------------------------------
33 # Constants
34
35 !define FALSE 0
36 !define TRUE 1
37
38 # see http://msdn.microsoft.com/en-us/library/windows/desktop/aa364417%28v=vs.85%29.aspx
39 !define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
40 # see http://msdn.microsoft.com/en-us/library/windows/desktop/ms687032%28v=vs.85%29.aspx
41 !define WAIT_TIMEOUT 0x00000102
42
43 #--------------------------------
44 # Variables
45
46 Var Character
47 Var RunAppReturn
48
49 Var OriginalFile
50 Var OriginalFileName
51 Var OriginalDir
52
53 Var PDFFile
54 Var ViewerFileName
55 Var Viewer
56
57 Var ChangeNotification
58 Var WaitReturn
59 Var LockedFile
60
61 Var TimeDiff
62
63 #--------------------------------
64 # Macros
65
66 !macro SystemCall STACK
67
68   # Call a Windows API function
69
70   Push `${STACK}`
71   CallInstDLL "$EXEDIR\System.dll" Call
72
73 !macroend
74
75 !macro HideConsole COMMAND_LINE
76
77   # Run an application and hide console output
78
79   Push `${COMMAND_LINE}`
80   CallInstDLL "$EXEDIR\Console.dll" Exec
81   Pop $RunAppReturn
82   
83   ${If} $RunAppReturn == "error"
84     MessageBox MB_OK|MB_ICONSTOP "Error opening PDF file $PDFFile."
85   ${EndIf}
86
87 !macroend
88
89 # all following macros and functions are from
90 # http://nsis.sourceforge.net/FileTimeDiff
91 !define GetFileTimeS "!insertmacro _GetFileTimeS"
92
93 !macro _GetFileTimeS _Time_ _File_
94
95    Push "${_File_}"
96    Call GetFileTimeS
97    Pop ${_Time_}
98    
99 !macroend
100
101 Function GetFileTimeS
102         
103    Exch $0  # File / hi
104    Push $1  # lo
105  
106    ClearErrors
107    GetFileTime "$0" $0 $1
108    IfErrors err
109    System::Call '*(i r1, i r0) i .r0'
110    System::Call '*$0(l .r0)'
111    System::Int64Op $0 / 10000000  # Conversion From '100 ns' to '1 sec' unit
112    Goto end
113  
114    err:
115       Push ""
116       SetErrors
117       Goto +3
118    end:
119    System::Free $0
120    Exch 2
121    Pop $0
122    Pop $1
123    
124 FunctionEnd
125
126 !define FileTimeDiff "!insertmacro _FileTimeDiff"
127
128 !macro _FileTimeDiff _RetVal_ _FileA_ _FileB_
129
130    Push "${_FileB_}"
131    Push "${_FileA_}"
132    Call FileTimeDiff
133    Pop ${_RetVal_}
134    
135 !macroend
136
137 Function FileTimeDiff 
138    Exch $0  # FileA
139    Exch 
140    Exch $1  # FileB
141  
142    ${GetFileTimeS} $0 "$0"
143    IfErrors err
144    ${GetFileTimeS} $1 "$1"
145    IfErrors err
146    System::Int64Op $0 - $1
147    Goto end
148  
149    err:
150       Push ""
151       SetErrors
152    end:
153    Exch 2
154    Pop $0
155    Pop $1
156    
157 FunctionEnd
158
159 #--------------------------------
160 # PDF viewing
161
162 Section "View PDF file"
163
164   InitPluginsDir # Temporary directory for PDF file
165
166   # Command line parameters
167   ${GetParameters} $OriginalFile
168
169   # Trim quotes
170   StrCpy $Character $OriginalFile 1
171   ${If} $Character == '"'
172     StrCpy $OriginalFile $OriginalFile "" 1
173   ${EndIf}
174   StrCpy $Character $OriginalFile 1 -1
175   ${If} $Character == '"'
176     StrCpy $OriginalFile $OriginalFile -1
177   ${EndIf}
178
179   GetFullPathName $OriginalFile $OriginalFile
180   ${GetFileName} $OriginalFile $OriginalFileName
181   ${GetParent} $OriginalFile $OriginalDir # tmpbuf
182   ${GetParent} $OriginalDir $OriginalDir # tmpdir
183
184   SetOutPath $TEMP # The LyX tmpbuf should not be locked
185
186   StrCpy $PDFFile $PLUGINSDIR\$OriginalFileName
187
188   # Check whether the file will be opened with Adobe Reader or Adobe Acrobat
189   !insertmacro SystemCall "shell32::FindExecutable(t '$OriginalFile', t '', t .s)"
190   Pop $ViewerFileName
191   ${GetFileName} $ViewerFileName $Viewer
192
193   ${If} $Viewer == ""
194     MessageBox MB_OK|MB_ICONEXCLAMATION "No PDF viewer is installed. \
195         Please install a PDF viewer such as Adobe Reader."
196     Quit        
197   ${EndIf}
198
199   ${If} $Viewer == "AcroRd32.exe"
200   ${OrIf} $Viewer == "Acrobat.exe"
201   
202     # get the version of Acrobat - currenly not necessary
203     #GetDLLVersion $ViewerFileName $R0 $R1
204     #IntOp $R2 $R0 >> 16
205     #IntOp $R2 $R2 & 0x0000FFFF ; $R2 now contains major version
206     #IntOp $R3 $R0 & 0x0000FFFF ; $R3 now contains minor version
207     #IntOp $R4 $R1 >> 16
208     #IntOp $R4 $R4 & 0x0000FFFF ; $R4 now contains release
209     #IntOp $R5 $R1 & 0x0000FFFF ; $R5 now contains build
210     #StrCpy $ViewerVersion "$R2"
211     
212     # Close existing view
213     ${If} ${FileExists} $PDFFile
214       !insertmacro HideConsole '"$EXEDIR\pdfclose.exe" --file "$PDFFile"'
215     ${EndIf}
216     
217     # Copy PDF to temporary file to allow LyX to overwrite the original
218     CopyFiles /SILENT $OriginalFile $PDFFile
219     
220     # Open a new view
221     !insertmacro HideConsole '"$EXEDIR\pdfopen.exe" --file "$PDFFile"'
222         
223     # check if a file in LyX's temp folder has been changed
224     !insertmacro SystemCall "kernel32::FindFirstChangeNotification(t '$OriginalDir', \
225       i 1, i ${FILE_NOTIFY_CHANGE_LAST_WRITE}) i.s"
226     Pop $ChangeNotification
227     
228     ${Do}
229     
230       # wait until the folder is not changed anymore, if so a "0" is returned
231       # otherwise a "258" (0x00000102) is returned
232       !insertmacro SystemCall "kernel32::WaitForSingleObject(i $ChangeNotification, i 10000) i.s"
233       Pop $WaitReturn
234       
235       # Check whether the lock of the PDF file is still active (if not, Adobe Reader is closed)
236       FileOpen $LockedFile $PDFFile a
237       ${If} $LockedFile != ""
238         # Quit this application
239         FileClose $LockedFile
240         Delete $PDFFile
241         !insertmacro SystemCall "kernel32::FindCloseChangeNotification(i $ChangeNotification)"
242         Quit
243       ${EndIf}
244       
245       # if the folder is (for now) not changed anymore
246       ${IfNot} $WaitReturn = ${WAIT_TIMEOUT}
247       
248         # check if the PDF-file in our temp directory is older than the one
249         # in LyX's temp folder because then it has been changed by LaTeX
250         ${FileTimeDiff} $TimeDiff "$PDFFile" "$OriginalFile"
251         
252         # if the file is older than 1 second
253         ${If} $TimeDiff < -1
254           # close the PDF
255           !insertmacro HideConsole '"$EXEDIR\pdfclose.exe" --file "$PDFFile"'
256           
257           # The problem is now that LaTeX might need several runs and therefore the PDF can
258           # also be rewritten consecutively several times.
259           # If we would directly open the file we will get in troubles as the PDF can be
260           # unreadable. We also don't know the time of a LaTeX run.
261           # (As example take UserGuide.lyx, view it, then remove a letter in a section heading
262           # and finally update the view.)
263           # We therefore loop until the PDF is no longer changed and wait some time in each loop.
264           ${Do}
265            CopyFiles /SILENT $OriginalFile $PDFFile
266            # wait 1.666 seconds (is empirically enough time that the PDF can be changed)
267            Sleep 1666
268            ${FileTimeDiff} $TimeDiff "$PDFFile" "$OriginalFile"
269           ${LoopUntil} $TimeDiff = 0
270           
271           # open the new file
272           !insertmacro HideConsole '"$EXEDIR\pdfopen.exe" --file "$PDFFile"'
273         ${EndIf}
274         
275         #Monitor again
276         !insertmacro SystemCall "kernel32::FindNextChangeNotification(i $ChangeNotification)"
277         
278       ${EndIf} # end ifnot
279     
280     ${Loop}
281     
282   ${Else}
283   
284     # Another PDF viewer like GSView is used
285     # No need for special actions, just forward to ShellExecute
286     ExecShell open $OriginalFile
287     
288   ${EndIf}
289     
290 SectionEnd