3 Windows PDF view helper
4 Author: Joost Verburg and Uwe Stöhr
6 This will be installed as pdfview.exe.
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.
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
19 #--------------------------------
24 Icon "..\packaging\icons\lyx.ico"
27 #--------------------------------
28 # Windows Vista (and later) settings
30 RequestExecutionLevel user
32 #--------------------------------
38 # http://msdn.microsoft.com/en-us/library/windows/desktop/aa364417%28v=vs.85%29.aspx
39 !define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
40 # http://msdn.microsoft.com/en-us/library/windows/desktop/ms687032%28v=vs.85%29.aspx
41 !define WAIT_TIMEOUT 0x00000102
43 #--------------------------------
57 Var ChangeNotification
63 #--------------------------------
66 !macro SystemCall STACK
68 # Call a Windows API function
71 CallInstDLL "$EXEDIR\System.dll" Call
75 !macro HideConsole COMMAND_LINE
77 # Run an application and hide console output
79 Push `${COMMAND_LINE}`
80 CallInstDLL "$EXEDIR\Console.dll" Exec
83 ${If} $RunAppReturn == "error"
84 MessageBox MB_OK|MB_ICONSTOP "Error opening PDF file $PDFFile."
89 # all following macros and functions are from
90 # http://nsis.sourceforge.net/FileTimeDiff
91 !define GetFileTimeS "!insertmacro _GetFileTimeS"
93 !macro _GetFileTimeS _Time_ _File_
101 Function GetFileTimeS
107 GetFileTime "$0" $0 $1
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
126 !define FileTimeDiff "!insertmacro _FileTimeDiff"
128 !macro _FileTimeDiff _RetVal_ _FileA_ _FileB_
137 Function FileTimeDiff
142 ${GetFileTimeS} $0 "$0"
144 ${GetFileTimeS} $1 "$1"
146 System::Int64Op $0 - $1
159 #--------------------------------
162 Section "View PDF file"
164 InitPluginsDir # Temporary directory for PDF file
166 # Command line parameters
167 ${GetParameters} $OriginalFile
170 StrCpy $Character $OriginalFile 1
171 ${If} $Character == '"'
172 StrCpy $OriginalFile $OriginalFile "" 1
174 StrCpy $Character $OriginalFile 1 -1
175 ${If} $Character == '"'
176 StrCpy $OriginalFile $OriginalFile -1
179 GetFullPathName $OriginalFile $OriginalFile
180 ${GetFileName} $OriginalFile $OriginalFileName
181 ${GetParent} $OriginalFile $OriginalDir # tmpbuf
182 ${GetParent} $OriginalDir $OriginalDir # tmpdir
184 SetOutPath $TEMP # The LyX tmpbuf should not be locked
186 StrCpy $PDFFile $PLUGINSDIR\$OriginalFileName
188 # Check whether the file will be opened with Adobe Reader or Adobe Acrobat
189 !insertmacro SystemCall "shell32::FindExecutable(t '$OriginalFile', t '', t .s)"
191 ${GetFileName} $ViewerFileName $Viewer
194 MessageBox MB_OK|MB_ICONEXCLAMATION "No PDF viewer is installed. \
195 Please install a PDF viewer such as Adobe Reader."
199 ${If} $Viewer == "AcroRd32.exe"
200 ${OrIf} $Viewer == "Acrobat.exe"
202 # Close existing view
203 ${If} ${FileExists} $PDFFile
204 !insertmacro HideConsole '"$EXEDIR\pdfclose.exe" --file "$PDFFile"'
207 # Copy PDF to temporary file to allow LyX to overwrite the original
208 CopyFiles /SILENT $OriginalFile $PDFFile
211 !insertmacro HideConsole '"$EXEDIR\pdfopen.exe" --file "$PDFFile"'
213 # check if a file in LyX's temp folder has been changed
214 !insertmacro SystemCall "kernel32::FindFirstChangeNotification(t '$OriginalDir', \
215 i 1, i ${FILE_NOTIFY_CHANGE_LAST_WRITE}) i.s"
216 Pop $ChangeNotification
220 # wait until the folder is not changed anymore, if so a "0" is returned
221 # otherwise a "258" (0x00000102) is returned
222 !insertmacro SystemCall "kernel32::WaitForSingleObject(i $ChangeNotification, i 10000) i.s"
225 # Check whether the lock of the PDF file is still active (if not, Adobe Reader is closed)
226 FileOpen $LockedFile $PDFFile a
227 ${If} $LockedFile != ""
228 # Quit this application
229 FileClose $LockedFile
231 !insertmacro SystemCall "kernel32::FindCloseChangeNotification(i $ChangeNotification)"
235 # if the folder is (for now) not changed anymore
236 ${IfNot} $WaitReturn = ${WAIT_TIMEOUT}
238 # check if the PDF-file in our temp directory is older than the one
239 # in LyX's temp folder because then it has been changed by LaTeX
240 ${FileTimeDiff} $TimeDiff "$PDFFile" "$OriginalFile"
242 # if the file is older than 1 second
245 !insertmacro HideConsole '"$EXEDIR\pdfclose.exe" --file "$PDFFile"'
247 # The problem is now that LaTeX might need several runs and therefore the PDF can
248 # also be rewritten consecutively several times.
249 # If we would directly open the file we will get in troubles as the PDF can be
250 # unreadable. We also don't know the time of a LaTeX run.
251 # (As example take UserGuide.lyx, view it, then remove a letter in a section heading
252 # and finally update the view.)
253 # We therefore loop until the PDF is no longer changed and wait some time in each loop.
255 CopyFiles /SILENT $OriginalFile $PDFFile
256 # wait 1.666 seconds (is empirically enough time that the PDF can be changed)
258 ${FileTimeDiff} $TimeDiff "$PDFFile" "$OriginalFile"
259 ${LoopUntil} $TimeDiff = 0
262 !insertmacro HideConsole '"$EXEDIR\pdfopen.exe" --file "$PDFFile"'
266 !insertmacro SystemCall "kernel32::FindNextChangeNotification(i $ChangeNotification)"
274 # Another PDF viewer like GSView is used
275 # No need for special actions, just forward to ShellExecute
276 ExecShell open $OriginalFile