LyX for Windows: update pdfview for Acrobat XI and fix longstanding bug

- to be able to support Adobe Reader/Acrobat XI I had to use new binaries for opening/closing PDFs. That way I found the solution for a long standing and super annoying PDF viewing bug (not 100% perfect but works for more than 95% of the cases, while formerly the view failed for all cases where LaTeX run more than once when updating a PDF view)
This commit is contained in:
Uwe Stöhr 2012-11-20 01:07:08 +01:00
parent 63295f9dc5
commit bd504c09de
2 changed files with 114 additions and 55 deletions

View File

@ -1,4 +1,7 @@
Changelog for LyX-205-4: Changelog for LyX-205-4:
- support to update the view as PDF if Adobe Reader XI is used
- fix longstanding bug that updating a PDF view failed for larger
LyX documents if Adobe Reader or Acrobat was used as PDF viewer
- fixed bug that EPS and PDF images were not displayed if LyX was installed this time without admin privileges - fixed bug that EPS and PDF images were not displayed if LyX was installed this time without admin privileges
but an older LyX version was once installed with admin privileges but an older LyX version was once installed with admin privileges
- correct the required disk space for the German thesaurus dictionaries - correct the required disk space for the German thesaurus dictionaries

View File

@ -1,15 +1,15 @@
/* /*
Windows PDF view helper Windows PDF view helper
Author: Joost Verburg Author: Joost Verburg and Uwe Stöhr
This will be installed as pdfview.exe. This will be installed as pdfview.exe.
The application will launch the default PDF viewer to display the PDF file, 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: The files pdfopen/pdfclose are part of this archive:
http://magic.aladdin.cs.cmu.edu/2005/07/15/pdfopen-and-pdfclose/ http://www.tex.ac.uk/tex-archive/systems/win32/w32tex/pdftex-w32.tar.xz
*/ */
@ -25,7 +25,7 @@ Icon "..\packaging\icons\lyx.ico"
SilentInstall silent SilentInstall silent
#-------------------------------- #--------------------------------
# Windows Vista settings # Windows Vista (and later) settings
RequestExecutionLevel user RequestExecutionLevel user
@ -35,7 +35,9 @@ RequestExecutionLevel user
!define FALSE 0 !define FALSE 0
!define TRUE 1 !define TRUE 1
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa364417%28v=vs.85%29.aspx
!define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010 !define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
# http://msdn.microsoft.com/en-us/library/windows/desktop/ms687032%28v=vs.85%29.aspx
!define WAIT_TIMEOUT 0x00000102 !define WAIT_TIMEOUT 0x00000102
#-------------------------------- #--------------------------------
@ -51,17 +53,12 @@ Var OriginalDir
Var PDFFile Var PDFFile
Var ViewerFileName Var ViewerFileName
Var Viewer Var Viewer
Var ViewerVersion
Var DDEName
Var ChangeNotification Var ChangeNotification
Var WaitReturn Var WaitReturn
Var LockedFile Var LockedFile
Var OriginalTimeHigh Var TimeDiff
Var OriginalTimeLow
Var CurrentTimeHigh
Var CurrentTimeLow
#-------------------------------- #--------------------------------
# Macros # Macros
@ -89,6 +86,76 @@ Var CurrentTimeLow
!macroend !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 viewing # PDF viewing
@ -130,55 +197,33 @@ Section "View PDF file"
${EndIf} ${EndIf}
${If} $Viewer == "AcroRd32.exe" ${If} $Viewer == "AcroRd32.exe"
${OrIf} $Viewer == "Acrobat.exe" ${OrIf} $Viewer == "Acrobat.exe"
# Using Adobe viewer
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"
${If} $ViewerVersion < 10
StrCpy $DDEName "AcroView"
${Else}
${If} $Viewer == "AcroRd32.exe"
StrCpy $DDEName "AcroViewR$ViewerVersion"
${ElseIf} $Viewer == "Acrobat.exe"
StrCpy $DDEName "AcroViewA$ViewerVersion"
${EndIf}
${EndIf}
# Close existing view # Close existing view
${If} ${FileExists} $PDFFile ${If} ${FileExists} $PDFFile
!insertmacro HideConsole '"$EXEDIR\pdfclose.exe" --reader "$ViewerFileName" --ddename "$DDEName" --file "$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 CopyFiles /SILENT $OriginalFile $PDFFile
# Open a new view # Open a new view
!insertmacro HideConsole '"$EXEDIR\pdfopen.exe" --reader "$ViewerFileName" --ddename "$DDEName" --back --file "$PDFFile"' !insertmacro HideConsole '"$EXEDIR\pdfopen.exe" --file "$PDFFile"'
# Monitor for updates of the original file # check if a file in LyX's temp folder has been changed
GetFileTime $OriginalFile $OriginalTimeHigh $OriginalTimeLow
!insertmacro SystemCall "kernel32::FindFirstChangeNotification(t '$OriginalDir', \ !insertmacro SystemCall "kernel32::FindFirstChangeNotification(t '$OriginalDir', \
i 1, i ${FILE_NOTIFY_CHANGE_LAST_WRITE}) i.s" i 1, i ${FILE_NOTIFY_CHANGE_LAST_WRITE}) i.s"
Pop $ChangeNotification Pop $ChangeNotification
${Do} ${Do}
# 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" !insertmacro SystemCall "kernel32::WaitForSingleObject(i $ChangeNotification, i 10000) i.s"
Pop $WaitReturn Pop $WaitReturn
# Check whether the lock is still active (if not, Adobe Reader is closed)
# Check whether the lock of the PDF file is still active (if not, Adobe Reader is closed)
FileOpen $LockedFile $PDFFile a FileOpen $LockedFile $PDFFile a
${If} $LockedFile != "" ${If} $LockedFile != ""
# Quit this application # Quit this application
FileClose $LockedFile FileClose $LockedFile
@ -187,29 +232,40 @@ Section "View PDF file"
Quit Quit
${EndIf} ${EndIf}
# if the folder is (for now) not changed anymore
${IfNot} $WaitReturn = ${WAIT_TIMEOUT} ${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"
# The LyX temporary directory has been updated # if the file is older than 1 second
# Check whether it's the PDF file that has been updated ${If} $TimeDiff < -1
# close the PDF
!insertmacro HideConsole '"$EXEDIR\pdfclose.exe" --file "$PDFFile"'
GetFileTime $OriginalFile $CurrentTimeHigh $CurrentTimeLow # The problem is now that LaTeX might need several runs and therefore the PDF can
# also be rewritten consecutively several times.
${If} $OriginalTimeHigh != $CurrentTimeHigh # If we would directly open the file we will get in troubles as the PDF can be
${OrIf} $OriginalTimeLow != $CurrentTimeLow # unreadable. We also don't know the time of a LaTeX run.
# PDF has been modified, update view # (As example take UserGuide.lyx, view it, then remove a letter in a section heading
!insertmacro HideConsole '"$EXEDIR\pdfclose.exe" --reader "$ViewerFileName" --ddename "$DDEName" --file "$PDFFile"' # and finally update the view.)
CopyFiles /SILENT $OriginalFile $PDFFile # We therefore loop until the PDF is no longer changed and wait some time in each loop.
!insertmacro HideConsole '"$EXEDIR\pdfopen.exe" --reader "$ViewerFileName" --ddename "$DDEName" --back --file "$PDFFile"' ${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
# Time of new file # open the new file
StrCpy $OriginalTimeHigh $CurrentTimeHigh !insertmacro HideConsole '"$EXEDIR\pdfopen.exe" --file "$PDFFile"'
StrCpy $OriginalTimeLow $CurrentTimeLow
${EndIf} ${EndIf}
#Monitor again #Monitor again
!insertmacro SystemCall "kernel32::FindNextChangeNotification(i $ChangeNotification)" !insertmacro SystemCall "kernel32::FindNextChangeNotification(i $ChangeNotification)"
${EndIf} ${EndIf} # end ifnot
${Loop} ${Loop}