summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/epspdf/epspdfrc.rb
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/scripts/epspdf/epspdfrc.rb')
-rwxr-xr-xMaster/texmf-dist/scripts/epspdf/epspdfrc.rb507
1 files changed, 507 insertions, 0 deletions
diff --git a/Master/texmf-dist/scripts/epspdf/epspdfrc.rb b/Master/texmf-dist/scripts/epspdf/epspdfrc.rb
new file mode 100755
index 00000000000..f75d65b5339
--- /dev/null
+++ b/Master/texmf-dist/scripts/epspdf/epspdfrc.rb
@@ -0,0 +1,507 @@
+# epspdf conversion utility, configuration module
+
+#####
+# Copyright (C) 2006, 2008 Siep Kroonenberg
+# n dot s dot kroonenberg at rug dot nl
+#
+# This program is free software, licensed under the GNU GPL, >=2.0.
+# This software comes with absolutely NO WARRANTY. Use at your own risk!
+#####
+
+# This version has been adapted for TeX Live. The adaptations only
+# concern Windows. If TL is set then pdftops and
+# ghostscript are set to the version included in TeXLive, settings are
+# stored in HKCU\software\epspdftl (rather than epspdf) and the logfile
+# is %USERPROFILE%\epspdftl.log, rather than epspdf.log.
+# A future version should offer a dynamic way of settingt his option.
+
+# Settings are stored in a settings hash, with some methods added
+# for less unwieldy notation.
+#
+# In phase 1, some programs (converters, viewers) are autodetected.
+# In phase 2, user preferences are read from the epspdf configuration.
+#
+# For unix/osx, configuration info is stored in $HOME/.epspdfrc.
+# For w32, configuration info is stored in HKCU\software\epspdf.
+#
+# The UIs for settings are not here; they are:
+# 1. the epspdf.rb command-line if epspdf.rb is run as
+# a stand-alone program, and
+# 2. a configuration screen in epspdftk.rb.
+
+require 'rbconfig'
+include Config
+
+# for notational convenience, we keep ARCH separate
+
+ARCH = case CONFIG['arch']
+when /win32|mingw/
+ 'w32'
+when /darwin/
+ 'osx'
+else
+ 'unix'
+end
+
+TL = ENV.has_key?('TLROOT')
+if ARCH == 'w32'
+ require 'dl/win32'
+ require 'win32/registry'
+ include Win32 # this lets us abbreviate Win32::Registry to Registry
+ ShortPName = Win32API.new(
+ 'kernel32', 'GetShortPathName', ['P','P','N'], 'N' )
+ TLROOT = ENV['TLROOT']
+end
+
+# for Windows, use short names within backquotes
+# to avoid quotes within backquotes
+
+def short_name( fn )
+ return fn if ARCH != 'w32'
+ fn.gsub!( /\\/, '/' )
+ buffer = ' ' * 260
+ length = ShortPName.call( fn, buffer, buffer.size )
+ return ( length > 0 ) ? buffer.slice(0..length-1) : fn
+end
+
+# system-dependent location of logfile
+
+LOGFILE = case ARCH
+when 'w32'
+ TL ? "#{ENV['USERPROFILE']}\\epspdftl.log" :
+ "#{ENV['USERPROFILE']}\\epspdf.log"
+else
+ "#{ENV['HOME']}//epspdf.log"
+end
+LOGFILE_OLD = LOGFILE + '.old'
+
+# system-dependent locations of saved settings
+
+RC_FILE = "#{ENV['HOME']}/.epspdfrc"
+REG_K = TL ? 'epspdftl' : 'epspdf'
+REG_KEY = TL ? 'SOFTWARE\\epspdftl' : 'SOFTWARE\\epspdf'
+
+# hash of saved settings from rc file or registry
+
+$rc_settings = {}
+
+# find open command for extension (w32 only)
+
+def open_with( ext )
+ ext = '' unless ext
+ answer = nil
+ if ARCH == 'w32'
+ begin # open cl = HKCR\ext safely
+ Registry::HKEY_CLASSES_ROOT.open(
+ (ext =~ /^\./ ? ext : '.'+ext) ) do |cl|
+ begin # read ftype safely
+ ftype = cl.read_s( nil )
+ begin # open cmd = HKCR\ftype\shell... safely
+ Registry::HKEY_CLASSES_ROOT.open(
+ ftype + '\\shell\\open\\command' ) do |cmd|
+ begin # read answer safely
+ answer = cmd.read_s( nil )
+ if answer =~ /^"([^"]+)".*/
+ answer = $1
+ elsif answer =~ /^([^ ]+) .*/
+ answer = $1
+ end
+ answer = nil unless answer and test( ?s, answer )
+ rescue # answer not read
+ end # read answer safely
+ end # HKCR\ftype\shell... do |cmd|
+ rescue # cmd not opened
+ end # open cmd = HKCR\ftype\shell... safely
+ rescue # ftype not read
+ end # read ftype safely
+ end # HKCR\ext do |cl|
+ rescue # cl not opened
+ end # open cl = HKCR\ext safely
+ end # w32
+ answer
+end
+
+# test whether a string is a valid program call
+# 'which' also works with explicit paths.
+# 'which' returns an error for non-executable files.
+
+def is_a_program( s )
+ case ARCH
+ when 'w32'
+ nil
+ else
+ ( system "which #{s} >/dev/null" ) ? 1 : nil
+ end
+end # is_a_program
+
+# Parse version info from a prog from the xpdf suite.
+# This is used as validity test.
+
+def xpdf_version( arg )
+ retval = nil
+ arg = short_name( arg ) if ARCH == 'w32'
+ version_output = `#{arg} -v 2>&1`
+ if version_output and not version_output.empty?
+ vo = version_output.split(/\r\n?|\n/)
+ vo.grep(/version/i) { |a|
+ a =~ /^\D*(\d+\.\w*)\b/
+ retval = $& # matched part; nil if no match
+ }
+ end
+ retval
+end
+
+class Setting
+ attr_reader :val, :type, :comment
+ attr_writer :val
+
+ def initialize( v, t, c )
+ @val = v
+ @type = t
+ @comment = c
+ end
+end
+
+PDF_TARGETS = [ 'default', 'printer', 'prepress', 'screen', 'ebook' ]
+PDF_VERSIONS = [ '1.2', '1.3', '1.4', 'default' ]
+
+$settings = {
+ # converters
+ 'gs_prog' => Setting.new( nil, 'auto', nil ),
+ 'gs_version' => Setting.new( nil, 'auto', nil ),
+ 'pdftops_prog' => Setting.new( nil, ARCH=='w32' ? 'config' : 'auto', nil ),
+ # viewers
+ 'pdf_viewers' => Setting.new( nil, ARCH=='unix' ? 'auto' : nil, nil ),
+ 'ps_viewers' => Setting.new( nil, ARCH=='unix' ? 'auto' : nil, nil ),
+ 'pdf_viewer' => Setting.new( nil, ARCH=='unix' ? 'config' : 'auto', nil ),
+ 'ps_viewer' => Setting.new( nil, ARCH=='unix' ? 'config' : 'auto', nil ),
+ # conversion options
+ 'ignore_pdftops' => Setting.new( '0', 'config',
+ 'Ignore pdftops even if available; 1=yes, empty or 0=no(default)' ),
+ 'pdf_target' => Setting.new( 'prepress', 'config',
+ 'Target: screen, ebook, print, prepress (default) or default' ),
+ 'pdf_version' => Setting.new( '1.4', 'config',
+ 'Pdf version: e.g 1.4 or 1.2 (fewer features, more compatibility)' +
+ ' or unspecified' ),
+ 'pdf_custom' => Setting.new( '', 'config',
+ 'additional options for [e]ps to pdf conversion' ),
+ 'ps_options' => Setting.new( '-level2', 'config',
+ 'options for pdftops; default -level2' ),
+ 'bb_spread' => Setting.new( '1', 'config',
+ 'margin to be added to computed boundingbox; default 1' )
+}
+
+class << $settings
+
+ # create shortcut methods $settings.x and $settings.x=
+ # for reading and writing hash elements.
+
+ $settings.each_key { |k|
+ eval "def #{k} ; self[\'#{k}\'].val ; end"
+ eval "def #{k}=(v) ; self[\'#{k}\'].val=v ; end"
+ }
+
+ # use_pdftops is a boolean counterpart and inverse
+ # of the stored string attribute ignore_pdftops
+
+ def use_pdftops
+ case self['ignore_pdftops'].val
+ when /t(rue)?|y(es)?|1/i
+ false
+ when /f(alse)?|n(o)?|0/i
+ true
+ when 1
+ false
+ when 0
+ true
+ else
+ true
+ end
+ end
+
+ # we want use_pdftops = nil = default = true but
+ # we also want use_pdftops = nil <=> use_pdftops = false
+ # we give the second one priority.
+
+ def use_pdftops=( x )
+ self['ignore_pdftops'].val = case x
+ when /t(rue)?|y(es)?|1/i
+ '0'
+ when /f(alse)?|n(o)?|0/i
+ '1'
+ when 1
+ '0'
+ when 0
+ '1'
+ when false
+ '1'
+ when nil # try to avoid this assignment
+ '1'
+ when true
+ '0'
+ else
+ '1'
+ end
+ end
+
+ def accept_pdf_viewer( s )
+ if ARCH == 'unix'
+ if is_a_program( s )
+ self.pdf_viewer = s
+ self.pdf_viewers.unshift( s ) unless self.pdf_viewers.index( s )
+ return 1
+ else
+ return nil
+ end
+ else
+ return nil
+ end
+ end # accept_pdf_viewer
+
+ def accept_ps_viewer( s )
+ if ARCH == 'unix'
+ if is_a_program( s )
+ self.ps_viewer = s
+ self.pdf_viewer = s unless \
+ self.pdf_viewer and not self.pdf_viewer.empty?
+ self.ps_viewers.unshift( s ) unless self.ps_viewers.index( s )
+ self.pdf_viewers.push( s ) unless self.pdf_viewers.index( s )
+ return 1
+ else
+ return nil
+ end
+ else
+ return nil
+ end
+ end # accept_ps_viewer
+
+ # previously-configured settings into hash $rc_settings
+ # here no validity testing.
+ # we accept empty settings.
+
+ def read_settings
+ if ARCH == 'w32'
+ [Registry::HKEY_LOCAL_MACHINE,
+ Registry::HKEY_CURRENT_USER].each { |hk|
+ begin # open REG_KEY safely
+ hk.open( REG_KEY ) do |ep|
+ ep.each_value do |key, type, val|
+ $rc_settings[ key ] = val \
+ if $settings[ key ] and $settings[ key ].type == 'config'
+ end # do |key, type, val|
+ end # do |ep|
+ rescue
+ end # open REG_KEY safely
+ } # each |hk|
+ else
+ if test( ?s, RC_FILE )
+ lines = File.read( RC_FILE ).split( /\r\n?|\n/ )
+ lines.each do |l|
+ l = l.sub( /#.*$/, '' ) # remove trailing comments
+ if l =~ /^\s*(\S+)\s*=\s*(\S(.*\S)?)\s*$/
+ key, val = $1, $2
+ $rc_settings[ key ] = val \
+ if $settings[ key ] and $settings[ key ].type == 'config'
+ elsif l =~ /^\s*(\S+)\s*=\s*$/
+ key, val = $1, ''
+ $rc_settings[ key ] = '' \
+ if $settings[ key ] and $settings[ key ].type == 'config'
+ end # if l =~
+ end # do |l|
+ end # if ?s
+ end # if ARCH
+ end # def
+
+ def write_settings
+ if ARCH == 'w32'
+ begin
+ Registry::HKEY_CURRENT_USER.create(
+ 'SOFTWARE', desired = Registry::KEY_ALL_ACCESS) do |reg|
+ reg.create( REG_K, desired = Registry::KEY_ALL_ACCESS ) do |rk|
+ $settings.each do |k, s|
+ key = String.new( k )
+ st = Setting.new( s.val, s.type, s.comment )
+ # this copying looks kind of silly,
+ # but prevents a 'modifying frozen object' error.
+ if st.type == 'config'
+ vl = st.val ? st.val : ''
+ rk.write_s( key, vl )
+ end
+ end # do each
+ end # do |rk|
+ end # do |reg|
+ rescue => er # no real error handling for now
+ puts $!
+ puts er.backtrace.join( $/ )
+ puts 'Settings will be lost at next run'
+ end
+ else
+ File.open( RC_FILE, 'w' ) do |f|
+ f.write( "# This file will be overwritten by epspdf_tk[.rb]" \
+ + $/ )
+ $settings.each do |key, st|
+ if st.type == 'config'
+ f.write( $/ )
+ f.write( '# ' + st.comment + $/ ) if st.comment
+ # STDERR.puts "write setting for " + key
+ # STDERR.flush
+ f.write( key + " = " + ( st.val ? st.val : '' ) + $/ )
+ end
+ end # do |key, st|
+ end # do |f|
+ end # if
+ end # def
+
+ def get_settings
+
+ # phase 1: autodetect
+ # w32: gs_prog, gs_version, pdf_viewer, ps_viewer
+ # gs: search registry settings; the highest version wins.
+ # viewers: check file type registry entry for valid open commands
+ # w32/TL: gs_prog, gs_version, pdf_viewer, ps_viewer
+ # gs: from TL
+ # viewers: check file type registry entry for valid open commands
+
+ # unix: gs_prog, gs_version, pdftops_prog, pdf_viewers, ps_viewers
+ # osx: gs_prog, gs_version, pdftops_prog
+ # viewers: use Preview; don't check anything
+ # unix/osx are done together, except that for osx
+ # the viewers code is skipped.
+
+ case ARCH
+ when 'w32'
+ if !TL then # else use built-in texlive versions
+ # check registry for latest valid version of Ghostscript
+ # tentative values; HKLM and HKCU may provide different values
+ try_gs_version = nil
+ try_gs_prog = nil
+ [Registry::HKEY_LOCAL_MACHINE,
+ Registry::HKEY_CURRENT_USER].each { |hk|
+ puts hk.to_s if $DEBUG
+ hk.open('SOFTWARE') { |sof|
+ puts sof.to_s if $DEBUG
+ sof.each_key { |key, wtime|
+ puts key.to_s if $DEBUG
+ if key =~ /ghostscript/i
+ gh = hk.open('SOFTWARE\\' + key)
+ gh.each_key { |skey, wtime|
+ if skey =~ /^\d+\.\d+$/ # version number
+ if skey.to_f > try_gs_version.to_f
+ this_gs = hk.open('SOFTWARE\\' + key + '\\' + skey)
+ this_gs_prog = this_gs['GS_DLL'].sub(
+ /([\\\/])([^\\\/]+)$/, '\1gswin32c.exe')
+ if test(?e,this_gs_prog)
+ try_gs_version = skey
+ try_gs_prog = this_gs_prog
+ end # if ?e (exist)
+ end # skey.to_f > try_gs_version.to_f
+ end # if skey =~ /^\d+\.\d+$/
+ } # gh.each_key
+ end # if key =~ /ghostscript/i
+ } # sof.each_key
+ } # hk.open |sof|
+ } # [HKCU, HKLM].each
+ self.gs_version = try_gs_version
+ self.gs_prog = try_gs_prog
+ end
+
+ # viewers
+ self.pdf_viewer = open_with( 'pdf' )
+ self.ps_viewer = open_with( 'ps' )
+
+ when /unix|osx/
+ # gs
+ answer = `gs --version`
+ if answer and not answer.empty?
+ self.gs_prog = 'gs'
+ self.gs_version = answer.chomp
+ else
+ self.gs_prog = nil
+ self.gs_version = nil
+ end
+
+ # pdftops
+ self.pdftops_prog = xpdf_version( 'pdftops' ) ? 'pdftops' : nil
+
+ # viewers
+ vw = %w{ gpdf xpdf acroread evince ggv gv kghostview }
+ vw.delete_if { |x| not is_a_program( x ) }
+ vw = nil if vw.empty?
+ self.pdf_viewers = vw
+ self.pdf_viewer = vw ? vw[0] : nil
+ if vw
+ vw2 = vw.dup # copy the elements rather than the array ref
+ [ 'gpdf', 'xpdf', 'acroread' ].each { |pg|
+ vw2.delete( pg ) if vw2.index( pg )
+ }
+ vw2 = nil if vw2.empty?
+ self.ps_viewers = vw2
+ self.ps_viewer = vw2 ? vw2[ 0 ] : nil
+ end # if vw
+ end # case
+
+ # built-in defaults already set during initialization of $settings
+
+ # phase 2: pre-existing configuration
+ # w32: pdftops_prog
+ # unix (not osx): pdf_viewers
+
+ read_settings
+
+ case ARCH
+ when 'w32'
+ $rc_settings[ 'pdftops_prog' ] = (
+ TL ? (TLROOT.gsub( /\//, '\\' ) + '\\bin\\win32\\pdftops.exe') :
+ "z:\\aps\\staff\\ber\\miktex\\xpdf\\pdftops.exe" ) unless
+ ( $rc_settings[ 'pdftops_prog' ] and
+ ! $rc_settings[ 'pdftops_prog' ].empty? )
+ ptop = $rc_settings[ 'pdftops_prog' ]
+ if xpdf_version( ptop ) then
+ self.pdftops_prog = ptop
+ end
+ if TL
+ self.gs_prog = TLROOT.gsub( /\//, '\\' ) +
+ '\\tlpkg\\tlgs\\bin\\gswin32c.exe'
+ self.gs_version =
+ ( `#{short_name( self.gs_prog )} --version` ).chomp
+ end
+ when 'unix'
+ if v = $rc_settings[ 'pdf_viewer' ] and is_a_program( v )
+ self.pdf_viewer = v
+ self.pdf_viewers.unshift( v ) unless self.pdf_viewers.index( v )
+ end # if
+ if v = $rc_settings[ 'ps_viewer' ] and is_a_program( v )
+ self.ps_viewer = v
+ self.ps_viewers.unshift( v ) unless self.ps_viewers.index( v )
+ end # if
+ if self.ps_viewers and not self.pdf_viewers
+ self.pdf_viewers = self.ps_viewers.dup
+ self.pdf_viewer = self.ps_viewer
+ end # if
+ end # case ARCH
+
+ # no validity checks for pdf- and ps output options.
+ # reminder: self.s shortcut for self['s'].val
+ [ 'pdf_target', 'pdf_version', 'pdf_custom', 'ps_options' ].each { |p|
+ self[ p ].val = $rc_settings[ p ] if $rc_settings[ p ]
+ }
+ if $rc_settings.has_key?( 'ignore_pdftops' )
+ $settings.ignore_pdftops = case $rc_settings[ 'ignore_pdftops' ]
+ when /1|yes|true|y|t/i
+ '1'
+ when /0|no|false|n|f/i
+ '0'
+ end
+ else
+ $settings.ignore_pdftops = '0'
+ end
+
+ self.bb_spread = $rc_settings[ 'bb_spread' ] if
+ $rc_settings.has_key?( 'bb_spread' ) and
+ $rc_settings[ 'bb_spread' ] =~ /^[+-]?[\d]+$/
+
+ end # get_settings
+
+end # class << $settings
+
+$settings.get_settings