X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=development%2FWin32%2Fpdfview%2Fpdfview.nsi;h=aab892f44ca668dbcf7f45ca14cfc24cb4f011f3;hb=367bf556574142388309f40142cddcf0c5676f06;hp=f00457be526ac6b218c0cdb9661ad63a50f01e64;hpb=f5e613ac51279f81e223ad3d454d79cb557ec582;p=lyx.git diff --git a/development/Win32/pdfview/pdfview.nsi b/development/Win32/pdfview/pdfview.nsi index f00457be52..aab892f44c 100644 --- a/development/Win32/pdfview/pdfview.nsi +++ b/development/Win32/pdfview/pdfview.nsi @@ -1,60 +1,72 @@ /* Windows PDF view helper -Author: Joost Verburg +Author: Joost Verburg and Uwe Stöhr This will be installed as pdfview.exe. The application will launch the default PDF viewer to display the PDF file, -but works around the file locking problems of Adobe Reader. +but works around the file locking problems of Adobe Reader and Acrobat. -Source code of pdfopen/pdfclose is available at: -http://magic.aladdin.cs.cmu.edu/2005/07/15/pdfopen-and-pdfclose/ +The files pdfopen/pdfclose are part of this archive: +http://www.tex.ac.uk/tex-archive/systems/win32/w32tex/pdftex-w32.tar.xz */ -!include "LogicLib.nsh" -!include "FileFunc.nsh" -!insertmacro GetParameters -!insertmacro GetFileName +!include LogicLib.nsh +!include FileFunc.nsh #-------------------------------- -#Settings +# Settings Caption "PDF Viewer" OutFile pdfview.exe -Icon "..\packaging\icons\lyx_32x32.ico" +Icon "..\packaging\icons\lyx.ico" SilentInstall silent #-------------------------------- -#Windows Vista settings +# Windows Vista (and later) settings RequestExecutionLevel user #-------------------------------- -#Constants +# Constants !define FALSE 0 !define TRUE 1 +# see http://msdn.microsoft.com/en-us/library/windows/desktop/aa364417%28v=vs.85%29.aspx +!define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010 +# see http://msdn.microsoft.com/en-us/library/windows/desktop/ms687032%28v=vs.85%29.aspx +!define WAIT_TIMEOUT 0x00000102 + #-------------------------------- -#Variables +# Variables + +Var Character +Var RunAppReturn -Var Dummy Var OriginalFile Var OriginalFileName +Var OriginalDir + Var PDFFile +Var ViewerFileName Var Viewer -Var OriginalTimeHigh -Var OriginalTimeLow -Var CurrentTimeHigh -Var CurrentTimeLow + +Var ChangeNotification +Var WaitReturn +Var LockedFile + +Var TimeDiff #-------------------------------- -#Macros +# Macros !macro SystemCall STACK + # Call a Windows API function + Push `${STACK}` CallInstDLL "$EXEDIR\System.dll" Call @@ -62,118 +74,217 @@ Var CurrentTimeLow !macro HideConsole COMMAND_LINE + # Run an application and hide console output + Push `${COMMAND_LINE}` CallInstDLL "$EXEDIR\Console.dll" Exec - Pop $Dummy + Pop $RunAppReturn - ${if} $Dummy == "error" - MessageBox MB_OK|MB_ICONSTOP "Error opening PDF file $R0." - ${endif} + ${If} $RunAppReturn == "error" + MessageBox MB_OK|MB_ICONSTOP "Error opening PDF file $PDFFile." + ${EndIf} + +!macroend + +# all following macros and functions are from +# http://nsis.sourceforge.net/FileTimeDiff +!define GetFileTimeS "!insertmacro _GetFileTimeS" + +!macro _GetFileTimeS _Time_ _File_ + + Push "${_File_}" + Call GetFileTimeS + Pop ${_Time_} + +!macroend +Function GetFileTimeS + + Exch $0 # File / hi + Push $1 # lo + + ClearErrors + GetFileTime "$0" $0 $1 + IfErrors err + System::Call '*(i r1, i r0) i .r0' + System::Call '*$0(l .r0)' + System::Int64Op $0 / 10000000 # Conversion From '100 ns' to '1 sec' unit + Goto end + + err: + Push "" + SetErrors + Goto +3 + end: + System::Free $0 + Exch 2 + Pop $0 + Pop $1 + +FunctionEnd + +!define FileTimeDiff "!insertmacro _FileTimeDiff" + +!macro _FileTimeDiff _RetVal_ _FileA_ _FileB_ + + Push "${_FileB_}" + Push "${_FileA_}" + Call FileTimeDiff + Pop ${_RetVal_} + !macroend +Function FileTimeDiff + Exch $0 # FileA + Exch + Exch $1 # FileB + + ${GetFileTimeS} $0 "$0" + IfErrors err + ${GetFileTimeS} $1 "$1" + IfErrors err + System::Int64Op $0 - $1 + Goto end + + err: + Push "" + SetErrors + end: + Exch 2 + Pop $0 + Pop $1 + +FunctionEnd + #-------------------------------- -#PDF vieweing +# PDF viewing Section "View PDF file" - InitPluginsDir #Temporary directory for PDF file + InitPluginsDir # Temporary directory for PDF file - #Command line parameters - Call GetParameters - Pop $OriginalFile + # Command line parameters + ${GetParameters} $OriginalFile - #Trim quotes - StrCpy $Dummy $OriginalFile 1 - ${if} $Dummy == '"' + # Trim quotes + StrCpy $Character $OriginalFile 1 + ${If} $Character == '"' StrCpy $OriginalFile $OriginalFile "" 1 - ${endif} - StrCpy $Dummy $OriginalFile 1 -1 - ${if} $Dummy == '"' + ${EndIf} + StrCpy $Character $OriginalFile 1 -1 + ${If} $Character == '"' StrCpy $OriginalFile $OriginalFile -1 - ${endif} + ${EndIf} GetFullPathName $OriginalFile $OriginalFile - Push $OriginalFile - Call GetFileName - Pop $OriginalFileName + ${GetFileName} $OriginalFile $OriginalFileName + ${GetParent} $OriginalFile $OriginalDir # tmpbuf + ${GetParent} $OriginalDir $OriginalDir # tmpdir - SetOutPath $TEMP #The LyX tmpbuf should not be locked + SetOutPath $TEMP # The LyX tmpbuf should not be locked StrCpy $PDFFile $PLUGINSDIR\$OriginalFileName - #Check whether the file will be opened with Adobe Reader or Adobe Acrobat - Push $OriginalFile - !insertmacro SystemCall "shell32::FindExecutable(t s, t '', t .s)" - Call GetFileName - Pop $Viewer + # Check whether the file will be opened with Adobe Reader or Adobe Acrobat + !insertmacro SystemCall "shell32::FindExecutable(t '$OriginalFile', t '', t .s)" + Pop $ViewerFileName + ${GetFileName} $ViewerFileName $Viewer - ${if} $Viewer == "" + ${If} $Viewer == "" MessageBox MB_OK|MB_ICONEXCLAMATION "No PDF viewer is installed. \ Please install a PDF viewer such as Adobe Reader." Quit - ${endif} + ${EndIf} - ${if} $Viewer == "AcroRd32.exe" - ${orif} $Viewer == "Acrobat.exe" - - #Using Adobe viewer + ${If} $Viewer == "AcroRd32.exe" + ${OrIf} $Viewer == "Acrobat.exe" + + # get the version of Acrobat - currenly not necessary + #GetDLLVersion $ViewerFileName $R0 $R1 + #IntOp $R2 $R0 >> 16 + #IntOp $R2 $R2 & 0x0000FFFF ; $R2 now contains major version + #IntOp $R3 $R0 & 0x0000FFFF ; $R3 now contains minor version + #IntOp $R4 $R1 >> 16 + #IntOp $R4 $R4 & 0x0000FFFF ; $R4 now contains release + #IntOp $R5 $R1 & 0x0000FFFF ; $R5 now contains build + #StrCpy $ViewerVersion "$R2" - #Close existing view - ${if} ${fileexists} $PDFFile + # Close existing view + ${If} ${FileExists} $PDFFile !insertmacro HideConsole '"$EXEDIR\pdfclose.exe" --file "$PDFFile"' - ${endif} + ${EndIf} - #Copy PDF to temporary file to allow LyX to overwrite the original + # Copy PDF to temporary file to allow LyX to overwrite the original CopyFiles /SILENT $OriginalFile $PDFFile - #Open a new view - !insertmacro HideConsole '"$EXEDIR\pdfopen.exe" --back --file "$PDFFile"' - - #Monitor for updates of the original file - - GetFileTime $OriginalFile $OriginalTimeHigh $OriginalTimeLow + # Open a new view + !insertmacro HideConsole '"$EXEDIR\pdfopen.exe" --file "$PDFFile"' + + # check if a file in LyX's temp folder has been changed + !insertmacro SystemCall "kernel32::FindFirstChangeNotification(t '$OriginalDir', \ + i 1, i ${FILE_NOTIFY_CHANGE_LAST_WRITE}) i.s" + Pop $ChangeNotification - ${do} + ${Do} - Sleep 500 - - FileOpen $Dummy $PDFFile a + # wait until the folder is not changed anymore, if so a "0" is returned + # otherwise a "258" (0x00000102) is returned + !insertmacro SystemCall "kernel32::WaitForSingleObject(i $ChangeNotification, i 10000) i.s" + Pop $WaitReturn - ${if} $Dummy != "" - #File no longer locked, reader closed - FileClose $Dummy + # Check whether the lock of the PDF file is still active (if not, Adobe Reader is closed) + FileOpen $LockedFile $PDFFile a + ${If} $LockedFile != "" + # Quit this application + FileClose $LockedFile Delete $PDFFile + !insertmacro SystemCall "kernel32::FindCloseChangeNotification(i $ChangeNotification)" Quit - ${endif} + ${EndIf} - ${if} ${fileexists} $OriginalFile - - GetFileTime $OriginalFile $CurrentTimeHigh $CurrentTimeLow + # if the folder is (for now) not changed anymore + ${IfNot} $WaitReturn = ${WAIT_TIMEOUT} + + # check if the PDF-file in our temp directory is older than the one + # in LyX's temp folder because then it has been changed by LaTeX + ${FileTimeDiff} $TimeDiff "$PDFFile" "$OriginalFile" - ${if} $OriginalTimeHigh != $CurrentTimeHigh - ${orif} $OriginalTimeLow != $CurrentTimeLow - - #Original has been modified, update! - - StrCpy $OriginalTimeHigh $CurrentTimeHigh - StrCpy $OriginalTimeLow $CurrentTimeLow + # if the file is older than 1 second + ${If} $TimeDiff < -1 + # close the PDF !insertmacro HideConsole '"$EXEDIR\pdfclose.exe" --file "$PDFFile"' - CopyFiles /SILENT $OriginalFile $PDFFile - !insertmacro HideConsole '"$EXEDIR\pdfopen.exe" --back --file "$PDFFile"' - ${endif} + # The problem is now that LaTeX might need several runs and therefore the PDF can + # also be rewritten consecutively several times. + # If we would directly open the file we will get in troubles as the PDF can be + # unreadable. We also don't know the time of a LaTeX run. + # (As example take UserGuide.lyx, view it, then remove a letter in a section heading + # and finally update the view.) + # We therefore loop until the PDF is no longer changed and wait some time in each loop. + ${Do} + CopyFiles /SILENT $OriginalFile $PDFFile + # wait 1.666 seconds (is empirically enough time that the PDF can be changed) + Sleep 1666 + ${FileTimeDiff} $TimeDiff "$PDFFile" "$OriginalFile" + ${LoopUntil} $TimeDiff = 0 + + # open the new file + !insertmacro HideConsole '"$EXEDIR\pdfopen.exe" --file "$PDFFile"' + ${EndIf} + + #Monitor again + !insertmacro SystemCall "kernel32::FindNextChangeNotification(i $ChangeNotification)" - ${endif} + ${EndIf} # end ifnot - ${loop} + ${Loop} - ${else} + ${Else} - #Another PDF viewer like GSView is used - #No need for special actions, just forward to ShellExecute + # Another PDF viewer like GSView is used + # No need for special actions, just forward to ShellExecute ExecShell open $OriginalFile - ${endif} + ${EndIf} SectionEnd