diff options
-rw-r--r-- | Master/texmf-dist/scripts/epspdf/epspdf.help | 123 | ||||
-rw-r--r-- | Master/texmf-dist/scripts/epspdf/epspdf.icns | bin | 0 -> 80465 bytes | |||
-rw-r--r-- | Master/texmf-dist/scripts/epspdf/epspdf.ico | bin | 0 -> 57022 bytes | |||
-rwxr-xr-x | Master/texmf-dist/scripts/epspdf/epspdf.rb | 168 | ||||
-rwxr-xr-x | Master/texmf-dist/scripts/epspdf/epspdfrc.rb | 217 | ||||
-rwxr-xr-x | Master/texmf-dist/scripts/epspdf/epspdftk | 2 | ||||
-rwxr-xr-x | Master/texmf-dist/scripts/epspdf/epspdftk.rb | 1036 | ||||
-rwxr-xr-x | Master/texmf-dist/scripts/epspdf/epspdftk.tcl | 848 |
8 files changed, 1107 insertions, 1287 deletions
diff --git a/Master/texmf-dist/scripts/epspdf/epspdf.help b/Master/texmf-dist/scripts/epspdf/epspdf.help index 6a5687aed69..4a43acbcd3d 100644 --- a/Master/texmf-dist/scripts/epspdf/epspdf.help +++ b/Master/texmf-dist/scripts/epspdf/epspdf.help @@ -1,7 +1,7 @@ Epspdf and epsdftk ****************** -This manual is for epspdf, version 0.4.3. +This manual is for epspdf, version 0.5. Copyright (C) 2006, 2008, 2009, 2010 Siep Kroonenberg. @@ -32,12 +32,7 @@ in the box in the upper part of the screen. The View button at the bottom of the screen calls an appropriate external viewer. -Windows: Epspdftk simply tries to use the default Open command. A -second button, labeled View with..., lets the user select a different -program to view the file. - -For OS X the viewer is also the default program, but there is no View -with... button. +Windows and OS X: Epspdftk simply tries to use the default Open command. Under Linux the PostScript- and pdf viewers are configurable; see *note The configuration screen::. @@ -62,10 +57,9 @@ selecting all pages. When converting to eps you are restricted to a single page. For general PostScript files, there is no quick way to determine the -number of pages, so the program won't check beforehand whether you -picked an existing page. If you picked a non-existent page, the program -will abort. If you don't like that, convert the entire document to pdf -first - which will be done behind the scenes anyhow. +number of pages, so the program may not check beforehand whether you +picked an existing page. If you don't like that, convert the entire +document to pdf first - which will be done behind the scenes anyhow. Specifying options such as grayscaling or page selection may require several roundtrips between PostScript or eps and pdf. @@ -93,8 +87,7 @@ manually. For Windows and Mac OS X, there is no such configuration option. Epspdf will use the program associated with the file type, which can be -configured outside epspdf. Under Windows, you can use the "View -with..." button instead. +configured outside epspdf. 1.5.2 Options for converting to pdf ----------------------------------- @@ -115,7 +108,7 @@ Ps2pdf.htm. For conversion the other way you may opt not to use pdftops even if it is available. In this case, the conversion will be done by Ghostscript. Characters may be converted to drawn shapes or little bitmaps so this -is not recommended. +is not recommended if the file uses fonts. Under Windows, this is also the place to point the program to the location of pdftops.exe. @@ -123,9 +116,8 @@ location of pdftops.exe. 1.5.4 Hires BoundingBox ----------------------- -Uncheck the option "Use hires boundingbox if possible" if otherwise the -computed boundingbox is slightly too tight, resulting in some clipping. -It has two effects: +Uncheck the option "Use hires boundingbox if possible" if your +conversions come out slightly clipped. It has two effects: * When converting to pdf, it uses the standard rather than the hires boundingbox for page dimensions @@ -136,9 +128,8 @@ It has two effects: 2 Command-line usage ******************** -epspdf.rb, the library for epspdftk.rb, does double duty as command-line -version of epspdftk.rb. It shares configuration settings with -epspdftk.rb. +epspdf.rb is the backend of epspdftk, but it can also be used +standalone. It shares configuration settings with epspdftk.tcl. It is strongly recommended to invoke epspdf.rb via a wrapper script epspdf or epspdf.bat on the search path, e.g. @@ -160,7 +151,7 @@ Basic usage: Typing `epspdf --help' gives you the following summary: $ epspdf --help - Epspdf version 0.4.3 + Epspdf version 0.5 Copyright (C) 2006, 2008, 2009, 2010 Siep Kroonenberg Convert between [e]ps and pdf formats Usage: epspdf.rb [options] infile [outfile] @@ -178,7 +169,6 @@ Typing `epspdf --help' gives you the following summary: -T, --target=TARGET Target use of pdf; one of default, printer, prepress, screen, ebook -N, --pdfversion=PDFVERSION Pdf version to be generated - -V, --version=PDFVERSION Deprecated; use `-N' or `--pdfversion'. -I Ignore pdftops even if available (default: use if available) -U Use pdftops if available @@ -192,8 +182,9 @@ Typing `epspdf --help' gives you the following summary: -i, --info Info: display detected filetype -s Save (some) settings -d Debug: don't remove temp files + --gui[=ACTION] Do not use; reserved for GUI - -v Prints version info + -v, --version Prints version info -h, --help Show this message 3 Notes on PostScript and pdf @@ -384,39 +375,87 @@ Things to try: If Ghostscript has to do the conversion from pdf to ps then text will not remain text, but will be replaced by drawn shapes or bitmaps. Try -to get hold of the xpdf suite, which includes pdftops, especially if -your files contain serious amount of text. +to get hold of the xpdf suite, which includes pdftops. + +5.4 Epspdftk quit unexpectedly (Mac OS X applet) +================================================ + +This sometimes happens to me when I start epspdftk from the AppleScript +applet. Unfortunately, I have no idea where this comes from. + +Try the "Reopen" button in the popup dialog. If this repeatedly fails, +install the regular Unix edition instead and run it from the +command-line. -5.4 Resources for troubleshooting +5.5 Resources for troubleshooting ================================= -Logfile. Epspdf and epspdftk maintain a log file epspdf.log in your -home directory or, in case of Windows, your profile directory. This -profile directory may be `c:\Documents and Settings\YOUR USER NAME'. -Otherwise, open a DOS box and type `echo %USERPROFILE%', which will -produce this information. +Logfile. The GUI has a button for viewing log output. This same output +is also written to a file `epspdf.log'. For Linux/Unix/Mac OS X this is +in a subdirectory .epspdf of your home directory; for Windows it is in +a subdirectory epspdf of `%APPDATA%'. This APPDATA directory may be +`c:\Documents and Settings\YOUR USER NAME\Application Data' or +`c:\Users\YOUR USER NAME\AppData\Roaming'. Otherwise, open a command +prompt and type `echo %APPDATA%', which will produce this information. -This logfile lists all Ghostscript- and pdftops program calls plus -error information. "EPCallError" is probably a program error. -'EPSystemError" is more likely caused by a faulty file, but may be a -program error as well. +The logfile lists all epspdf calls and all Ghostscript- and pdftops +calls plus error information. "EPCallError" is probably a program +error. 'EPSystemError" is more likely caused by a faulty file, but may +be a program error as well. -Temporary files. The temporary files may give clues as well. They will -be deleted at the end of the session (for the command-line version, -give a -d parameter to keep the temporary files). Check the logfile as -to which temporary files have been created. +Temporary files. The temporary files may give clues as well. Uncheck +the button "Remove temp files", or for the command-line version, give a +-d parameter to keep the temporary files. Check the log(file) as to +which temporary files have been created. Ghostscript- and pdftops documentation. For Ghostscript, the most important files are Ps2pdf.htm and Use.htm. For pdftops, type `pdftops -h'. For Unix, there is also a man page, and for Windows there is a file pdftops.txt in the distribution zip. -6 Changes in version 0.4 -************************ +6 Change history +**************** + +6.1 Version 0.5 +=============== + +The GUI has been rewritten in Tcl/Tk, removing the dependence on the +Ruby/Tk interface library. + +The Windows installer now installs a small Ruby subset and the standard +epspdf distribution, but with epspdftk.tcl replaced with a starpack: a +single executable containing `epspdftk.tcl' and a Tcl/Tk runtime. See +`http://wiki.tcl.tk/52'. + +Epspdf now uses its own subdirectory for both the logfile and the +configuration file. For Linux/Unix/Mac OS X this is `$HOME/.epspdf', +for Windows it is `%APPDATA%\epspdf'. On all supported platforms, +settings are stored in the file `config' in this directory. Under +Windows, the registry is no longer used for this. + +A button has been added to view log output. + +There is a second new button "Remove temp files", which is normally +checked, causing temporary files to be deleted after each conversion. +Unchecking this button may be useful for troubleshooting. In previous +versions, temporary files were deleted at the end of the entire +epspdftk session but that has become less practical now that the GUI and +epspdf itself have become two separate programs. + +The "Open with..." option for Windows has been dropped for technical +reasons. + +The "-version" option now prints the version string instead of setting +the desired pdf version. + +The "-info" option now also prints the number of pages for pdf files. + +6.2 Version 0.4 +=============== Hi-res boundingboxes are now supported. By default, conversion from eps to pdf now uses the hires boundingbox as "page" to determine the page -dmensions of the pdf file. Other conversions preserve or generate a +dimensions of the pdf file. Other conversions preserve or generate a hires boundingbox. Under Windows, the new version looks for an installed TeX and will use diff --git a/Master/texmf-dist/scripts/epspdf/epspdf.icns b/Master/texmf-dist/scripts/epspdf/epspdf.icns Binary files differnew file mode 100644 index 00000000000..183cf660ab4 --- /dev/null +++ b/Master/texmf-dist/scripts/epspdf/epspdf.icns diff --git a/Master/texmf-dist/scripts/epspdf/epspdf.ico b/Master/texmf-dist/scripts/epspdf/epspdf.ico Binary files differnew file mode 100644 index 00000000000..adab1a8d565 --- /dev/null +++ b/Master/texmf-dist/scripts/epspdf/epspdf.ico diff --git a/Master/texmf-dist/scripts/epspdf/epspdf.rb b/Master/texmf-dist/scripts/epspdf/epspdf.rb index 6c67f7eae3f..ccb3effb33f 100755 --- a/Master/texmf-dist/scripts/epspdf/epspdf.rb +++ b/Master/texmf-dist/scripts/epspdf/epspdf.rb @@ -27,17 +27,15 @@ ########################################### -# some initialization in case this file is used as main program +# some initialization -if __FILE__ == $0 +# add directory of this source to loadpath +$:.unshift( File.dirname( __FILE__ ) ) - # add directory of this source to loadpath - $:.unshift( File.dirname( __FILE__ ) ) +# turn on warnings +#$VERBOSE = 1 - # turn on warnings - #$VERBOSE = 1 - -end # if main program +$from_gui = nil ########################################### @@ -51,6 +49,9 @@ class EPCallError < StandardError; end # Can't get a valid boundingbox for an eps file class EPBBError < StandardError; end +# copying failed +class EPCopyError < StandardError; end + # system call failed class EPSystemError < StandardError; end @@ -136,13 +137,17 @@ def sliceFile( source, dest, len, offs, mode=$W ) s.binmode if ARCH == 'w32' s.seek( offs, IO::SEEK_SET ) if s.pos == offs - File.open( dest, mode ) do |d| - d.binmode if ARCH == 'w32' - tocopy = len - while tocopy>0 and s.read( [ tocopy, 16384 ].min, buffer ) - tocopy = tocopy - d.write( buffer ) - end # while - end # |d| (automatic closing) + begin + File.open( dest, mode ) do |d| + d.binmode if ARCH == 'w32' + tocopy = len + while tocopy>0 and s.read( [ tocopy, 16384 ].min, buffer ) + tocopy = tocopy - d.write( buffer ) + end # while + end # do + rescue + fail EPCopyError, "Failure to copy to #{dest}" + end end # if s.seek end # |s| (automatic closing) # return value true if anything has been copied @@ -168,6 +173,8 @@ def write_log( s ) File.open( LOGFILE, 'a' ) { |f| f.print( "#{$$} #{Time.now.strftime('%Y/%m/%d %H:%M:%S')} #{s}\n" ) } + puts( s ) if $from_gui + end ########################################### @@ -490,16 +497,26 @@ class PsPdf else @path = file @type = identify( file ) + @npages = pdf_pages if @type == 'pdf' # should we do this? + @npages = 1 if @type =~ /^eps/ end end # initialize + def file_info + if @npages and @type !~ /^eps/ + return "File type of #{@path} is #{@type} with #{@npages} pages" + else + return "File type of #{@path} is #{@type}" + end + end + ################## # debug string for EPCallError def buginfo( params = nil ) b = "Source was: " + @path + $/ - b = b + hash_prn( params ) if params + b = b + param_hash_prn( params ) if params b end @@ -756,6 +773,7 @@ class PsPdf retVal.hrbb = @hrbb.copy if @hrbb retVal.atfront = true retVal.hr_atfront = true + retVal.npages = 1 return retVal end # eps_clean @@ -928,6 +946,7 @@ class PsPdf # end fix for incorrect DSC header produced by some versions of pdftops retVal.atfront = 1 retVal.find_bb_simple + retVal.npages = 1 return retVal end # pdf_to_eps @@ -977,6 +996,7 @@ class PsPdf write_log cmd # if $DEBUG fail EPSystemError, cmd unless \ system( cmd ) and test( ?s, retVal.path ) + retVal.npages = @npages return retVal end # pdf_to_ps @@ -987,8 +1007,6 @@ class PsPdf def any_to_any( params={} ) - # $stderr.puts( hash_prn( params ) ) - type = params[ 'type' ] page = params[ 'page' ] bbox = params[ 'bbox' ] @@ -1017,7 +1035,8 @@ class PsPdf pp = pp.eps_clean if pp.type == 'epsPreview' pp = pp.eps_clean if pp.type == 'eps' and \ not ( pp.bb and pp.atfront ) # => not yet `cleaned' - pp.pdf_pages if pp.type == 'pdf' and not pp.npages + #pp.pdf_pages if pp.type == 'pdf' and not pp.npages + # now also done in initialize case pp.type when 'eps' @@ -1026,19 +1045,29 @@ class PsPdf # roundtrip guarantees bb.non_negative, necessary for fix_bb. # pdf_to_ps( sep ) improves chances of grayscaling. - pp = pp.eps_to_pdf.pdf_to_eps( 'sep' => gray ) \ - if gRAY or ( bbox and not pp.bb.non_negative ) - case type when 'eps' + pp = pp.eps_to_pdf.pdf_to_eps( 'sep' => gray ) \ + if gRAY or ( bbox and not pp.bb.non_negative ) pp = pp.eps_to_pdf( 'gray' => gray ).pdf_to_eps if gray pp = pp.fix_bb if bbox return pp when 'pdf' + pp = pp.eps_to_pdf.pdf_to_eps( 'sep' => gray ) \ + if gRAY or ( bbox and not pp.bb.non_negative ) pp = pp.fix_bb if bbox return pp.eps_to_pdf( 'gray' => gray ) + when 'ps' + if gRAY + pp = pp.eps_to_pdf.pdf_to_ps( 'sep' => gray ) + pp = pp.ps_to_pdf( 'gray' => gray ).pdf_to_ps + else + pp = pp.eps_to_pdf( 'gray' => gray ).pdf_to_ps + end + return pp + end # case type when 'pdf' @@ -1117,19 +1146,54 @@ class PsPdf end # case pp.type + #raise EPCallError fail "Unsupported conversion" + # this shouldn't happen anymore end # any_to_any end # class PsPdf ################################# -# main program when not called from GUI - -if __FILE__ == $0 +# main program require 'optparse' +def gui( action ) + case action + when 'config_w' then + puts "pdftops_prog=#{$settings.pdftops_prog}" if ARCH=='w32' + puts "pdf_viewer=#{$settings.pdf_viewer}" if ARCH=='unix' + puts "ps_viewer=#{$settings.ps_viewer}" if ARCH=='unix' + puts "defaultDir=#{$settings.defaultDir}" + puts "ignore_pdftops=#{$settings.ignore_pdftops}" + puts "pdf_target=#{$settings.pdf_target}" + puts "pdf_version=#{$settings.pdf_version}" + puts "pdf_custom=#{$settings.pdf_custom}" + puts "ps_options=#{$settings.ps_options}" + puts "ignore_hires_bb=#{$settings.ignore_hires_bb}" + puts "bb_spread=#{$settings.bb_spread}" + exit + when 'config_r' then + while line = gets + (varname, val) = line.split('=', 2) + varname.strip! if varname + val.strip! if val + if $settings.has_key?( varname ) + val = nil if val == '' + $settings[varname].val = val + # puts( "\"#{val}\" assigned to #{varname}" ) + end + end # while + $settings.write_settings + exit + when nil then + $from_gui = true + else + abort( "Action should be omitted or 'config_w' or 'config_r'" ) + end # case +end + # create a pause to examine temp files def abortt( msg ) if $DEBUG @@ -1139,8 +1203,6 @@ def abortt( msg ) fail end -begin # outer rescue block - save_settings = false opts = OptionParser.new do |opts| @@ -1208,11 +1270,6 @@ opts = OptionParser.new do |opts| $settings.pdf_version = opt end - #opts.on( "--version" ) do |opt| - # puts EPVERSION - # exit - #end - opts.on( "-I", "Ignore pdftops even if available", "(default: use if available)" ) do |opt| @@ -1253,6 +1310,10 @@ opts = OptionParser.new do |opts| $DEBUG = 1 end + opts.on( "--gui[=ACTION]", "Do not use; reserved for GUI" ) do |opt| + gui( opt ) + end + opts.separator "" opts.on( "-v", "Prints version info" ) do |opt| @@ -1276,8 +1337,10 @@ if ARGV.length == 1 and ARGV[0] == '--version' exit end -# parse options destructively +# save original command-line for later reporting +cmdline = "#{$0} #{ARGV.join( sep=' ' )}" +# parse options destructively begin opts.parse!( ARGV ) rescue OptionParser::ParseError => e @@ -1285,6 +1348,9 @@ rescue OptionParser::ParseError => e exit( -1 ) end +# log cmdline AFTER we found out whether we run from gui +write_log( cmdline ) + $options.page = 1 if $options.bbox and not $options.page $settings.write_settings if save_settings @@ -1297,7 +1363,8 @@ if ARGV.length < 1 exit end elsif $options.info - puts "File type of #{ARGV[0]} is #{PsPdf.new( 'file' => ARGV[0] ).type}" + p = PsPdf.new( 'file' => ARGV[0] ) + puts( p.file_info ) exit elsif ARGV.length > 1 and File.expand_path( ARGV[0] ) == File.expand_path( ARGV[1] ) @@ -1354,43 +1421,46 @@ end # case outfile abort "Unknown or unsupported output file extension" \ unless $options.type -abort "Output format not supported without xpdf utilities" \ - if outfile == 'ps' and not $settings.pstopdf_prog +#abort "Output format not supported without xpdf utilities" \ +# if outfile == 'ps' and not $settings.pstopdf_prog pp = PsPdf.new( 'file' => infile ) begin # inner rescue block pp = pp.any_to_any( $options ) + write_log( pp.file_info ) if $from_gui + ccp( pp.path, outfile ) rescue EPCallError => exc mess = "Wrong method call or conversion not supported or wrong page number" + $/ + exc.message + $/ + exc.backtrace.join( $/ ) write_log( mess ) puts mess - fail StandardError + exit 1 rescue EPBBError => exc mess = "Boundingbox problem" + $/ + exc.message + $/ + exc.backtrace.join( $/ ) write_log( mess ) puts mess - fail StandardError + exit 1 +rescue EPCopyError => exc + mess = "Copying problem" + $/ + + exc.message + $/ + exc.backtrace.join( $/ ) + write_log( mess ) + puts mess + exit 1 rescue EPSystemError => exc mess = "Problem with system call" + $/ + exc.message + $/ + exc.backtrace.join( $/ ) write_log( mess ) puts mess - fail StandardError + exit 1 +rescue StandardError => exc + mess = exc.message + $/ + exc.backtrace.join( $/ ) + write_log( mess ) + puts mess + exit 1 end # rescue block -ccp( pp.path, outfile ) - cleantemp unless $DEBUG == 1 - -rescue => detail -write_log detail.backtrace.join( $/ ) -puts detail.backtrace.join( $/ ) -exit -end # outer rescue block - -end # if called as main program __END__ diff --git a/Master/texmf-dist/scripts/epspdf/epspdfrc.rb b/Master/texmf-dist/scripts/epspdf/epspdfrc.rb index 08bcfdb991a..06073749952 100755 --- a/Master/texmf-dist/scripts/epspdf/epspdfrc.rb +++ b/Master/texmf-dist/scripts/epspdf/epspdfrc.rb @@ -1,4 +1,4 @@ -EPVERSION = '0.4.3' +EPVERSION = '0.5' COPYRIGHT = '2006, 2008, 2009, 2010' # epspdf conversion utility, configuration module @@ -14,7 +14,7 @@ COPYRIGHT = '2006, 2008, 2009, 2010' # 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 1, some programs (converters) are autodetected. # In phase 2, user preferences are read from the epspdf configuration. # # For unix/osx, configuration info is stored in $HOME/.epspdfrc. @@ -85,7 +85,7 @@ end def shell_error_string ( e ) if e > 32 - returl nil + return nil else return case e when 0 then "Out of memory or resources" @@ -122,19 +122,22 @@ end # def # system-dependent location of logfile -LOGFILE = case ARCH -when 'w32' - "#{ENV['USERPROFILE']}\\epspdf.log" -else - "#{ENV['HOME']}/epspdf.log" +epsdir = case ARCH + when 'w32' + "#{ENV['APPDATA'].gsub( /\\/, '/' )}/epspdf" + else + "#{ENV['HOME']}/.epspdf" end +Dir.mkdir( epsdir ) unless test( ?e, epsdir ) +# epsdir may be a regular file, or creation above may have failed +fail("Cannot create directory #{epsdir}" ) if not test( ?d, epsdir ) +LOGFILE = "#{epsdir}/epspdf.log" LOGFILE_OLD = LOGFILE + '.old' +#puts LOGFILE # system-dependent locations of saved settings -RC_FILE = "#{ENV['HOME']}/.epspdfrc" # not used under Windows -REG_K = 'epspdf' -REG_KEY = 'SOFTWARE\\epspdf' +RC_FILE = "#{epsdir}/config" # hash of saved settings from rc file or registry @@ -143,8 +146,7 @@ $rc_settings = {} # test whether a string is a valid program call # 'which' also works with explicit paths. # 'which' returns an error for non-executable files. -# Linux/Unix OS X: for testing existence of gs, pdftops and ps/pdf viewers -# Mac OS X: for testing existence of gs and pdftops +# Linux/Unix/OS X: for testing existence of gs and pdftops # Windows: function not usable and not used def is_a_program( s ) @@ -202,9 +204,8 @@ $settings = { 'gs_prog' => Setting.new( nil, 'auto', nil ), #'gs_version' => Setting.new( nil, 'auto', nil ), 'pdftops_prog' => Setting.new( nil, ARCH=='w32' ? 'config' : 'auto', nil ), - # epspdftk: viewers - 'pdf_viewers' => Setting.new( nil, ARCH=='unix' ? 'auto' : nil, nil ), - 'ps_viewers' => Setting.new( nil, ARCH=='unix' ? 'auto' : nil, nil ), + # epspdftk: viewers; epspdftk.tcl takes care of this, + # but their configuration is stored and retrieved by the Ruby scripts 'pdf_viewer' => Setting.new( nil, ARCH=='unix' ? 'config' : 'auto', nil ), 'ps_viewer' => Setting.new( nil, ARCH=='unix' ? 'config' : 'auto', nil ), # epspdftk: initial dir @@ -224,7 +225,7 @@ $settings = { 'Ignore hi-res boundingbox for pdf generation;' + ' 1=yes, empty or 0=no(default)' ), 'bb_spread' => Setting.new( '1', 'config', - 'margin to be added to computed lores boundingbox; default 1' ) + 'margin in points to be added to computed lores boundingbox; default 1' ) } # Using pdftops or a hires boundingbox should be the norm, not the exception. @@ -267,136 +268,60 @@ class << $settings reverse_of( self['ignore_pdftops'].val ) 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 + 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 # 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 + File.open( RC_FILE, 'w' ) do |f| + f.write( "# This file will be overwritten by epspdf.rb/epspdftk.tcl" \ + + $/ ) + $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 # def def get_settings # phase 1: autodetect - # w32: gs_prog, pdf_viewer, ps_viewer + # w32: gs_prog, pdftops_prog # gs: search path; search registry settings (user and system); # search tex installation. The first one wins. - # viewers: check file type registry entry for valid open commands - # unix: gs_prog, pdftops_prog, pdf_viewers, ps_viewers + # pdftops: search path + # unix: gs_prog, pdftops_prog # osx: gs_prog, pdftops_prog - # viewers: use Preview; don't check anything - # unix/osx are done together, except that for osx - # the viewers code is skipped. + # unix/osx are done together. # Windows: test for TeX, because it may come with a hidden # ghostscript. TeX may also come with pdftops.exe, but pdftops # would then be on the searchpath and not require special treatment. - # Later versions of Ghostscript come with several libraries built-in. - # Hopefully, there is no harm in including too many directories - # in GS_LIB. Better test this. - texbindir = ( ARCH == 'w32' ) ? find_on_path( 'tex' ) : nil texbindir = short_name( File.dirname( texbindir ) ) if texbindir @@ -483,28 +408,11 @@ class << $settings when /unix|osx/ # gs self.gs_prog = is_a_program( 'gs' ) ? 'gs' : nil + fail( "No ghostscript" ) unless self.gs_prog # pdftops self.pdftops_prog = is_a_program( 'pdftops' ) ? 'pdftops' : nil - # viewers - if ARCH == 'unix' - vw = %w{ evince gpdf xpdf acroread epdfview gv gsview okular } - 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', 'epdfview' ].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 # if unix - end # case ARCH # built-in defaults already set during initialization of $settings @@ -515,26 +423,17 @@ class << $settings read_settings - case ARCH - when 'w32' + if ARCH == 'w32' self.pdftops_prog = $rc_settings[ 'pdftops_prog' ] if $rc_settings[ 'pdftops_prog' ] and ! $rc_settings[ 'pdftops_prog' ].empty? and test( ?f, $rc_settings[ 'pdftops_prog' ] ) - 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 + end # ARCH == 'w32' + + if ARCH == 'unix' + self.pdf_viewer = $rc_settings[ 'pdf_viewer' ] # no checks here + self.ps_viewer = $rc_settings[ 'ps_viewer' ] + end if ( $rc_settings[ 'defaultDir' ] and ( not $rc_settings[ 'defaultDir' ].strip.empty? ) and diff --git a/Master/texmf-dist/scripts/epspdf/epspdftk b/Master/texmf-dist/scripts/epspdf/epspdftk index 95c551cf8c1..e1e1fb36064 100755 --- a/Master/texmf-dist/scripts/epspdf/epspdftk +++ b/Master/texmf-dist/scripts/epspdf/epspdftk @@ -1,5 +1,5 @@ #!/bin/sh -script=`kpsewhich -format=texmfscripts epspdftk.rb` +script=`kpsewhich -format=texmfscripts epspdftk.tcl` if test "x$1" = "x"; then "$script" $HOME else diff --git a/Master/texmf-dist/scripts/epspdf/epspdftk.rb b/Master/texmf-dist/scripts/epspdf/epspdftk.rb deleted file mode 100755 index 44ad3a2c063..00000000000 --- a/Master/texmf-dist/scripts/epspdf/epspdftk.rb +++ /dev/null @@ -1,1036 +0,0 @@ -#!/usr/bin/env ruby - -# epspdf conversion utility, GUI frontend - -##### -# Copyright (C) 2006, 2008, 2009, 2010 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! -##### - -#$DEBUG=1 - -# find other pieces of epspdf -$:.unshift( File.dirname( __FILE__ ) ) - -########################################## - -# load conversion engine. epspdf also loads epspdfrc, -# which detects platform and available converters. - -require 'epspdf' - -$VERBOSE = nil - -#require 'pp' - -if $DEBUG - puts ARCH - puts Config::CONFIG['arch'] - puts "Ghostscript command #{$settings.gs_prog}" - puts "Pdftops command #{$settings.pdftops_prog}" -end - -# is there a viewer for the PsPdf object p? - -def viewable( p ) - return nil unless p && p.path - return nil if p.type == 'other' - case ARCH - when 'unix' - return true if p.type =~ /e?ps/ and ( not $settings.ps_viewer.empty? ) - return true if p.type == 'pdf' and ( not $settings.pdf_viewer.empty? ) - else - return true - end # case ARCH - return nil -end # viewable - -#################################### - -# Tk and custom widgets - -require 'tk' -require 'tkscrollbox' - -# For event field strings, which codify event details, see -# the bind man page from the tk man pages (Ubuntu: tk8.x-doc package) - -#################################### - -# combobox adapted from Takaaki Tateishi <ttate / jaist.ac.jp> -# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/18167 - -# literal content of an xbm file, created e.g. with the GIMP - -$DOWN_ARROW_IMG = <<STR -#define dwnarrow.icn_width 15 -#define dwnarrow.icn_height 10 -static unsigned char dwnarrow.icn_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0xfc, 0x1f, 0xf8, 0x0f, 0xf0, 0x07, 0xe0, 0x03, - 0xc0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 }; -STR - -BG = 'gray85' - -class TkACombobox < TkFrame - - include TkComposite - - attr_reader :scrollbox, :tframe - attr_accessor :entries, :is_valid - - def initialize_composite( params = {} ) - - @entries = [] - @is_valid = proc{ |s| true } - @entry = nil - - # entry widget plus arrow for drop-down listbox - - @entry = TkEntry.new( @frame, - 'width' => 30, 'bd' => 1, 'highlightthickness' => 0 ) - image = TkBitmapImage.new( 'data' => $DOWN_ARROW_IMG ) - @bt_arrow = TkButton.new( @frame, 'bd' => 1, 'image' => image, - 'highlightthickness' => 0, 'command' => proc{ cmd_scrollbox } ) - @entry.pack( 'side' => 'left', 'fill' => 'x', 'expand' => 'yes' ) - @bt_arrow.pack( 'side' => 'right' ) - - # drop-down listbox - - @tframe = TkToplevel.new( @frame ) - @tframe.overrideredirect( 1 ) # no window manager decorations - @tframe.transient - @tframe.withdraw - @scrollbox = TkScrollbox.new( @tframe, 'width' => 30, 'border' => 1 ) - @scrollbox.pack( 'fill' => 'both', 'expand' => 'yes' ) - @scrollbox.bind( 'Any-Leave', proc{ hide_scrollbox } ) - # "%y", "%P": event field string; see bind manual from tk8.x-docs - @scrollbox.bind( 'Double-1', proc{ |y| select_this( y ) }, "%y" ) - @scrollbox.bind( 'Return', proc{ |y| select_this( y ) }, "%y" ) - - @entry.bind( 'FocusOut', proc{ entry_proc } ) - @entry.bind( 'Return', proc{ entry_proc } ) - @entry.bind( 'Double-1', proc{ entry_proc } ) - - delegate( :width, @entry, @scrollbox ) - - configure params if params - - end # initialize_composite - - def cmd_scrollbox - case @tframe.state - when "withdrawn" - show_scrollbox( @entries ) - else - hide_scrollbox - end - end - - def show_scrollbox( entries = nil ) - width = TkWinfo.width( @frame ) - height = 5 * TkWinfo.height( @entry ) - rootx = TkWinfo.rootx( @frame ) - rooty = TkWinfo.rooty( @frame ).to_i + TkWinfo.height( @frame ).to_i - geometry = "#{width}x#{height}+#{rootx}+#{rooty}" - @tframe.geometry( geometry ) - @tframe.deiconify - entries.each{ |entry| @scrollbox.insert( "end", entry ) } if entries - end - - def hide_scrollbox - @tframe.withdraw - @scrollbox.delete( 0, "end" ) - @entry.focus - end - - def select_this( y ) - i = @scrollbox.nearest( y ) - s = @scrollbox.get( i ) - @entry.delete( 0, 'end' ) - @entry.insert( 0, s ) - @is_valid.call( s ) # activates side effects - hide_scrollbox - end - - def entry_proc - #puts @entry.value - if @is_valid.call( @entry.value ) - @entries.unshift( @entry.value ).sort! \ - unless @entries.index( @entry.value ) - @tframe.withdraw unless @tframe.state == 'withdrawn' - else - Tk.bell - @entry.focus( true ) - end - end - - def get_entry - @entry.value - end - - def set_entry( s ) - @entry.delete( 0, 'end' ) - @entry.insert( 'end', s ) if s - end - -end # TkACombobox - -#################################### - -# checkboxes and radioboxes with built-in variables. -# use string- rather than symbol keys when creating these widgets. - -def zero_one( v ) # For Tcl/Tk, everything is a string - case v - when /t(rue)?|y(es)?|1/i - '1' - when /f(alse)?|n(o)?|0/i - '0' - when 1 - '1' - when 0 - '0' - else - nil - end -end - -class TkACheck < TkFrame - - include TkComposite - - def initialize_composite( params = {} ) - - Kernel::fail StandardError, "TkACheck doesn\'t allow \'variable\' key" \ - if params.has_key?( 'variable' ) - - v = params.delete( 'value' ) - @value = TkVariable.new( zero_one( v ) ) - - @ck = TkCheckButton.new( @frame, :variable => @value \ - ).pack( :padx => 0, :pady => 0, :ipadx => 0, :ipady => 0 ) - - delegate( 'DEFAULT', @ck ) - - configure params unless params.empty? - - end # initialize_composite - - def value - @value.value - end - - def value=( v ) - @value.value = zero_one( v ) - end - -end # TkACheck - -class TkRadios < TkFrame - - include TkComposite - - def initialize_composite( params = {} ) - - Kernel::fail StandardError, "TkRadios doesn\'t allow \'variable\' key" \ - if params.has_key?( 'variable' ) - - @value = TkVariable.new( params.delete( 'value' ) ) - @values = params.delete( 'values' ) - @packing = params.delete( 'packing' ) - @buttons = [] - - if ( @values.kind_of? Hash ) - @values.each_key { |k| - @buttons << TkRadioButton.new( @frame, - :text => @values[k] || k, - :variable => @value, - :value => k - ).pack( @packing ) - } - elsif ( @values.kind_of? Array ) - @values.each { |k| - @buttons << TkRadioButton.new( @frame, - :text => k, - :variable => @value, - :value => k - ).pack( @packing ) - } - else - Kernel::fail StandardError, "TkRadios requires a values array or hash" - end - - delegate( 'DEFAULT', @frame ) - delegate( 'command', *@buttons ) - delegate( 'state', *@buttons ) - - configure( params ) unless params.empty? - - end # initialize_composite - - def value - @value.value - end - - def value=( v ) - @value.value = v - end - - def get_button_state( v ) - @buttons.each { |b| - if b.value == v - return b.cget( 'state' ) - end - } - return nil - end - - def set_button_state( v, s ) - @buttons.each { |b| - if b.value == v - b.configure( 'state' => s ) - @value.value = nil if s == 'disabled' and @value.value == v - end - } - end - -end # TkRadios - -$root = TkRoot.new { title "PostScript- and pdf conversions" } - -################################## - -# Initial tests: no gs => bail out; no viewers => warning - -if not $settings.gs_prog - Tk.messageBox( - :icon=>'error', - :type=>'ok', - :parent=>$root, - :message=>"No Ghostscript found; aborting..." - ) - abort -end - -if ARCH == 'unix' - if not $settings.pdf_viewer - Tk.messageBox( :icon=>'warning', :type=>'ok', :message => - "No PostScript- or pdf viewer found" ) - elsif not $settings.ps_viewer - Tk.messageBox( :icon=>'warning', :type=>'ok', :message => - "No PostScript viewer found" ) - end -end - -######################################## - -# defaultDir already initialized by epspdfrc - -if ((ARGV.length > 0) and (ARGV[0].length > 0) and File.directory?(ARGV[0])) - $settings.defaultDir = ARGV[0] - #print "Default dir set to #{ARGV[0]} by epspdftk" -end - -$source = PsPdf.new # currently loaded PsPdf object - -$tl_config = nil # configuration screen -# $tl_wait = nil # instead of a wait cursor or progress bar - -# widgets which are configured on the fly, -# e.g. by ep_config, get a global name. -# They don't really have to be declared early. - -# buttons and option widgets -$view_button = nil -$view_with_button = nil -$page_radio = nil -$page_entry = nil -$type_radio = nil -$bbox_check = nil - -# widgets which display file info -$source_dir_label = nil -$source_name_label = nil -$source_type_label = nil - -def set_widget_states - # states (normal/disabled) for various widgets. - # their values should already be mutually consistent. - # widgets concerned: - # view / save - # output format / bbox / single page / page no. - - $view_button.configure( :state => - ( viewable( $source ) ? 'normal' : 'disabled' ) ) - $view_with_button.configure( :state => - ( viewable( $source ) ? 'normal' : 'disabled' ) ) if ARCH == 'w32' - $save_button.configure( :state => - ( ( $source.type and $source.type != 'other' ) ? \ - 'normal' : 'disabled' ) ) - - $type_radio.set_button_state( 'ps', ( \ - ( $settings.pdftops_prog and $settings.use_pdftops and - ( $source.type =~ /ps|pdf/ ) ) ? \ - 'normal' : 'disabled' ) ) - - $page_radio.set_button_state( 'all', 'normal' ) - $page_radio.set_button_state( 'single', 'normal' ) - $page_radio.set_button_state( 'all', 'disabled' ) if \ - $type_radio.value == 'eps' - $page_radio.set_button_state( 'single', 'disabled' ) if \ - $type_radio.value == 'ps' - - $page_entry.configure( :state => \ - ( $page_radio.value == 'all' ? 'disabled' : 'normal' ) ) - - $bbox_check.configure( :state => \ - ( $page_radio.value == 'single' or $source.type =~ /eps/ ) \ - ? 'normal' : 'disabled' ) - -end # set_widget_states - -def load_file( path ) - $source = PsPdf.new( 'file' => path ) - # write info to labels - $source_dir_label.configure( :text => File.dirname( path ) ) - $source_name_label.configure( :text => File.basename( path ) ) - $source_type_label.configure( :text => $source.type ) - $source.pdf_pages if ( $source.type == 'pdf' ) - $source_npages_label.configure( :text => ( - case $source.type - when 'pdf' then ( $source.npages ).to_s - when 'eps' then '1' - else '' - end - ) ) - $page_entry.delete( 0, 'end' ) - $page_entry.insert( 'end', '1' ) - set_widget_states -end - -# ipadx and ipady seem ineffective for frames - -FRM_PACK = { - :side => 'top', - :fill => 'x', - :expand => 1, - :padx => 4, - :pady => 4, - :anchor => 'w' -} - -################################## - -# configuration screen (toplevel widget) - -$tl_config = nil - -def ep_config - - if not $tl_config - - $tl_config = TkToplevel.new( $root, - :title => 'Configure epspdf' ) - - ### viewers frame - - if ARCH == 'unix' - TkFrame.new( $tl_config ) { |frm| - frm.borderwidth 2 - frm.relief 'sunken' - TkLabel.new( frm ) do - text 'Viewers' - font.weight 'bold' - pack( :side => 'top', :padx => 8, :anchor => 'w' ) - end - TkFrame.new( frm ) { |fm| - TkLabel.new( fm, :text => 'Pdf viewer' ).grid( - :in => fm, :row => 0, :column => 0, - :sticky => 'w', :padx => 2 ) - $pdf_vw_combo = TkACombobox.new( fm, :width => 30 ) - $pdf_vw_combo.is_valid = lambda { |s| is_a_program( s ) } - $pdf_vw_combo.grid( :in => fm, :row => 0, :column => 1, - :pady => 2, :padx => 2, :sticky => 'e' ) - - TkLabel.new( fm, :text => 'PostScript viewer' ).grid( - :in => fm, :row => 1, :column => 0, - :sticky => 'w', :padx => 2 ) - $ps_vw_combo = TkACombobox.new( fm, :width => 30 ) - $ps_vw_combo.is_valid = lambda { |s| is_a_program( s ) } - $ps_vw_combo.grid( :in => fm, :row => 1, :column => 1, - :pady => 2, :padx => 2, :sticky => 'e' ) - }.pack( :side => 'top', :anchor => 'w', :fill => 'x' ) - }.pack( FRM_PACK ) - end # if unix - - ### pdf frame - - TkFrame.new( $tl_config ){ |frm| - frm.borderwidth 2 - frm.relief 'sunken' - TkLabel.new( frm ) do - text 'Conversion to pdf' - font.weight 'bold' - pack( :side => 'top', :padx => 4, :anchor => 'w' ) - end - - # internal packing - pack_pdf = { - :side => 'left', :padx => 2, :pady => 4, :anchor => 'w' } - - TkLabel.new( frm, :text => 'Target use' - ).pack( :side => 'top', :padx => 2, :pady => 0, :anchor => 'w' ) - $pdf_target_radio = TkRadios.new( frm, - 'values' => PDF_TARGETS, 'packing' => pack_pdf - ).pack( :side => 'top', :anchor => 'w' ) - - # dummy widget for extra vertical space - TkLabel.new( frm, :text => ' ' ).pack - - TkLabel.new( frm, :text => 'Pdf version' - ).pack( :side => 'top', :padx => 2, :pady => 0, :anchor => 'w' ) - - $pdf_version_radio = TkRadios.new( frm, - 'values' => PDF_VERSIONS, 'packing' => pack_pdf - ).pack( :side => 'top', :anchor => 'w' ) - - TkLabel.new( frm, :text => ' ' ).pack - - TkLabel.new( frm, :text => 'Custom Ghostscript/ps2pdf parameters' - ).pack( :side => 'top', :padx => 2, :pady => 0, :anchor => 'w' ) - - $pdf_custom_entry = TkEntry.new( frm, :width => 50 - ).pack( :side => 'top', :padx => 2, :pady => 2, :anchor => 'w' ) - - }.pack( FRM_PACK ) - - ### postscript frame - - TkFrame.new( $tl_config ){ |frm| - frm.borderwidth 2 - frm.relief 'sunken' - TkLabel.new( frm ) do - text 'Conversion to EPS and PostScript' - font.weight 'bold' - pack( :side => 'top', :padx => 4, :anchor => 'w' ) - end - - if ARCH == 'w32' # others: assume pdftops on search path - TkLabel.new( frm, :text => "Find pdftops" - ).pack( :side => 'top', :anchor => 'w', :padx => 4 ) - - TkFrame.new( frm ) { |fm| - $pdftops_entry = TkEntry.new( fm, :width => 20 - ).pack( 'side'=>'left', :padx => 4 ) - TkButton.new( fm, - :text => 'Browse ...', - :command => lambda { - tryprog = Tk.getOpenFile( - :filetypes => [ [ 'Programs', [ '.exe' ] ] ], - :parent => fm - ) - if tryprog and ( not tryprog.empty? ) - tryprog.sub!( /([\/\\])[^\/\\]+$/, '\1pdftops.exe' ) - if test( ?f, tryprog ) - $pdftops_entry.delete( 0, 'end' ) - $pdftops_entry.insert( 'end', tryprog ) - end - end # ifthenelse tryprog - } # command lambda - ).pack( :side => 'left' ) # TkButton - }.pack( :side => 'top', :pady => 4, :anchor => 'w' ) - end # ARCH == 'w32' - - $pdftops_check = TkACheck.new( frm, - 'text' => "Use pdftops if available (recommended)" - ).pack( :side => 'top', :pady => 4, :anchor => 'w' ) - - }.pack( FRM_PACK ) # TkFrame |frm| - - ### boundingbox frame - - TkFrame.new( $tl_config ){ |frm| - frm.borderwidth 2 - frm.relief 'sunken' - TkLabel.new( frm ) do - text 'Hires BoundingBox' - font.weight 'bold' - pack( :side => 'top', :padx => 4, :anchor => 'w' ) - end - - TkLabel.new( frm ) do - text "Uncheck to prevent clipping" - pack( :side => 'top', :padx => 4, :anchor => 'w' ) - end - - $hires_check = TkACheck.new( frm, - 'text' => "Use hires boundingbox if possible" - ).pack( :side => 'top', :pady => 4, :anchor => 'w' ) - - }.pack( FRM_PACK ) # TkFrame |frm| - - ### button frame - - TkFrame.new( $tl_config ) { |frm| - #frm.bg = BG - - TkButton.new( frm, - :text => 'Cancel', - :command => lambda { - $tl_config.withdraw - $root.focus - } - ).pack( :padx => 4, :side => 'left', :anchor => 'e' ) - - TkButton.new( frm, - :text => 'Done', - :command => lambda { - # copy settings from widgets to $settings - case ARCH - when 'unix' # viewers - $settings.accept_ps_viewer( $ps_vw_combo.get_entry ) - $settings.accept_pdf_viewer( $pdf_vw_combo.get_entry ) - when 'w32' - $settings.pdftops_prog = $pdftops_entry.get - end - $settings.ignore_hires_bb = ( $hires_check.value == '0' ) ? '1' : '0' - $settings.ignore_pdftops = ( $pdftops_check.value == '0' ) ? '1' : '0' - $settings.pdf_target = $pdf_target_radio.value - $settings.pdf_version = $pdf_version_radio.value - $settings.pdf_custom = $pdf_custom_entry.get - $settings.write_settings - $tl_config.withdraw - $root.focus - set_widget_states - } # lambda - ).pack( :side => 'left', :anchor => 'e' ) - - }.pack( :side => 'bottom', :padx => 4, :pady => 4, :anchor => 'e' ) - else - $tl_config.deiconify - end # ifthenelse $tl_config - - # copy data from $settings to widgets - if ARCH == 'unix' - $pdf_vw_combo.set_entry( $settings.pdf_viewer ) - $pdf_vw_combo.entries = $settings.pdf_viewers[0..-1] # deep copy - $ps_vw_combo.set_entry( $settings.ps_viewer ) - $ps_vw_combo.entries = $settings.ps_viewers[0..-1] - elsif ARCH == 'w32' - $pdftops_entry.delete( 0, 'end' ) - $pdftops_entry.insert( 'end', $settings.pdftops_prog ) \ - if $settings.pdftops_prog and not $settings.pdftops_prog.empty? - end # ifthenelse ARCH - $hires_check.value = $settings.use_hires_bb ? '1' : '0' - $pdftops_check.value = $settings.use_pdftops ? '1' : '0' - $pdf_target_radio.value = $settings.pdf_target - $pdf_version_radio.value = $settings.pdf_version - $pdf_custom_entry.delete( 0, 'end' ) - $pdf_custom_entry.insert( 'end', $settings.pdf_custom ) \ - if not $settings.pdf_custom.empty? - -end # def ep_config - -################################### - -### makeshift help - -$tl_help = nil - -def ep_help - if not $tl_help - $tl_help = TkToplevel.new( $root, :title => 'Epspdftk help' ) - TkFrame.new( $tl_help ) { |tf| - txt = TkText.new( tf, - 'width' => 80, - 'height' => 25 - ) { |t| - TkScrollbar.new( tf, - 'command' => lambda{ |*args| t.yview( *args ) } ) { |sc| - t.yscrollcommand( lambda{ |first, last| sc.set first, last } ) - }.pack( 'side' => 'right', 'fill' => 'y' ) - }.pack( 'expand' => 'yes', 'fill' => 'both' ) - - txt.delete( '1.0', 'end' ) - - # LF ok for Win32 and Mac? Otherwise, split and join with $/ - - File.open( File.dirname( __FILE__ ) + '/epspdf.help', 'r' ) { |f| - $s = f.read - } - - txt.insert( '1.0', $s ) - - }.pack( 'side' => 'top', 'fill' => 'x' ) - - TkButton.new( $tl_help, - :text => 'Cancel', - :command => lambda{ - $tl_help.withdraw - $root.focus - } - ).pack( 'anchor' => 'e', 'padx' => 4, 'pady' => 4 ) - else - $tl_help.deiconify - end # ifthenelse $tl_help - -end # def ep_help - -### some buttons - -TkFrame.new( $root ) { |frm| - - TkButton.new( frm, - :text => "Configure", - :command => lambda { ep_config } - ).pack( :side => 'left', :padx => 4, :pady => 4 ) - - # There is pdf- and html help, and it would be simple enough to invoke - # either file from here, but for TL this would be in an entirely - # different directory, so instead we display an ascified helpfile - # packaged in the same directory as the code. - -# TkButton.new( frm, -# :text => 'Help', -# :command => lambda { -# docdir = File.dirname( __FILE__ ) -# docdir.sub!( /[\\\/]$/, '' ) -# docdir = docdir + '/doc' -# if ARCH == 'w32' -# result = shell_open( docdir + "/epspdf_UG.html" ) -# Tk.messageBox( -# 'icon' => 'error', -# 'title' => 'ShellExecute error', -# 'message' => shell_error_string( result ) -# ) if result <= 32 -# elsif ARCH == 'osx' -# fork { exec "open \"#{docdir}/epspdf_UG.html\"" } -# elsif $settings.pdf_viewer -# fork { exec "\"#{$settings.pdf_viewer}\" \"#{docdir}/epspdf.pdf\"" } -# else -# Tk.messageBox( -# 'icon' => 'warning', -# 'title' => 'No help viewer', -# 'message' => "Please select a pdf viewer in the configuration screen" + -# "\nand restart this program." -# ) -# end -# } -# ).pack( :side => 'right', :padx => 4, :pady => 4) - - TkButton.new( frm, - :text => 'Help', - :command => lambda { ep_help } - ).pack( :side => 'right', :padx => 4, :pady => 4) - -}.pack( :side => 'top', :fill => 'x' ) # frm - -######################################## - -### status info - -TkFrame.new( $root ){ |frm| - frm.borderwidth 2 - frm.relief 'sunken' - - ### status info - - TkFrame.new( frm ) { |fm| - TkLabel.new( fm, - :justify => 'left', - :text => 'Directory' - ).grid( :in => fm, :sticky => 'w', :row => 0, :column => 0 ) - $source_dir_label = TkLabel.new( fm, - :justify => 'left' - ).grid( :in => fm, :sticky => 'w', :row => 0, :column => 1 ) - - TkLabel.new( fm, - :justify => 'left', - :text => 'File' - ).grid( :in => fm, :sticky => 'w', :row => 1, :column => 0 ) - $source_name_label = TkLabel.new( frm, - :justify => 'left' - ).grid( :in => fm, :sticky => 'w', :row => 1, :column => 1 ) - - TkLabel.new( fm, - :justify => 'left', - :text => 'Type' - ).grid( :in => fm, :sticky => 'w', :row => 2, :column => 0 ) - $source_type_label = TkLabel.new( fm, - :justify => 'left' - ).grid( :in => fm, :sticky => 'w', :row => 2, :column => 1 ) - - TkLabel.new( fm, - :justify => 'left', - :text => 'Pages' - ).grid( :in => fm, :sticky => 'w', :row => 3, :column => 0 ) - $source_npages_label = TkLabel.new( fm, - :justify => 'left' - ).grid( :in => fm, :sticky => 'w', :row => 3, :column => 1 ) - - TkGrid.columnconfigure( fm, 0, :weight => 1, :minsize => 60, :pad =>4 ) - TkGrid.columnconfigure( fm, 1, :weight => 3, :minsize => 60, :pad =>4 ) - }.pack( :side => 'top', :anchor => 'w', :padx => 4 ) - -}.pack( FRM_PACK ) - -######################################## - -### conversion options: see also $options, defined in epspdf.rb - -TkFrame.new( $root ) { |frm| - - TkFrame.new( frm ) { |fm| # grayscaling, output format - TkFrame.new( fm ) { |f| # grayscaling - TkLabel.new( f, 'text' => 'Grayscaling' - ).pack( :side => 'top', :anchor => 'w' ) - - gray_options = { - 'gRAY' => 'Try harder to grayscale', - 'gray' => 'Try to grayscale', - 'color' => 'No color conversion' - } - - $gray_radio = TkRadios.new( f, - 'values' => gray_options, - 'value' => 'color', - 'packing' => { 'side' => 'top', 'anchor' => 'w' } - ).pack( :side => 'bottom', :anchor => 'w' ) # $gray_radio - }.pack( :side => 'left', :padx => 4 ) # f: grayscaling - - TkFrame.new( fm ) { |f| # output format - TkLabel.new( f, 'text' => 'Output format' - ).pack( :side => 'top', :anchor => 'w' ) - - $type_radio = TkRadios.new( f, - 'values' => [ 'pdf', 'eps', 'ps' ], - 'value' => 'pdf', - 'command' => lambda { - case 'value' - when 'eps' - $page_radio.value = 'single' - when 'ps' - $page_radio.value = 'all' - $bbox_check.value = '0' - end - set_widget_states - }, - 'packing' => { 'side' => 'top', 'anchor' => 'w' } - ).pack( :side => 'bottom', :anchor => 'w' ) - }.pack( :side => 'right', :padx => 4 ) # f: output format - }.pack( :side => 'top', :anchor => 'n', :fill => 'x' ) - - # dummy widget for extra vertical space - TkLabel.new( frm, :text => ' ' ).pack - - $bbox_check = TkACheck.new( frm, - 'text' => 'Compute tight boundingbox', - 'value' => '0', - 'command' => lambda { - $page_radio.value = 'single' if 'value' == '1' - set_widget_states - } - ).pack( :side => 'top', :padx => 4, :anchor => 'w' ) - - TkLabel.new( frm, :text => ' ' ).pack - - TkFrame.new( frm ) { |fm| - page_options = { 'all' => 'Convert all pages', 'single' => 'Page:' } - $page_radio = TkRadios.new( fm, - 'values' => page_options, - 'packing' => { 'side' => 'left', 'padx' => 4 }, - 'value' => 'single', - 'command' => lambda { - $bbox_check.value = '0' if 'value' == 'all' - set_widget_states - } - ).pack( 'side' => 'left', :anchor => 'nw' ) - - $page_entry = TkEntry.new( fm, - :validate => 'focus', - :vcmd => [ lambda { |s| - ( s =~ /\d+/ ) and - ( s.to_i >= 1 ) and - ( $source.type != 'pdf' or s.to_i <= $source.npages ) - }, "%P" ], - :invcmd => lambda { Tk.bell; $page_entry.focus }, - :width => 5 - ).pack( :side => 'left' ) - $page_entry.delete( 0, 'end' ) - $page_entry.insert( 'end', '1' ) - }.pack( 'side' => 'left', :anchor => 'nw' ) -}.pack( FRM_PACK ) - -######################################## - -### wait message packed at bottom - -$cnv_label = TkLabel.new( $root, 'text' => '' -).pack( 'side' => 'bottom', 'fill' => 'x', :anchor => 'nw' ) - -######################################## - -### view | open | save | done buttons - -TkFrame.new( $root ) { |frm| - - $view_button = TkButton.new( frm, - :text => 'View', - :state => 'disabled', - :command => lambda { - # start a viewer - if ARCH == 'w32' - result = shell_open( $source.path ) - Tk.messageBox( - 'icon' => 'error', - 'title' => 'ShellExecute error', - 'message' => shell_error_string( result ) - ) if result <= 32 - elsif ARCH == 'osx' - fork { exec "open \"#{$source.path}\"" } - elsif viewable( $source ) - viewer = - $source.type == 'pdf' ? $settings.pdf_viewer : $settings.ps_viewer - fork { exec "\"#{viewer}\" \"#{$source.path}\"" } - end - } - ).pack( :side=>'left', :anchor => 'w', :padx=>4, :pady=>4 ) - - if ARCH == 'w32' - $view_with_button = TkButton.new( frm, - :text => 'View with...', - :state => 'disabled', - :command => lambda { - result = shell_open_with( $source.path ) - Tk.messageBox( - 'icon' => 'error', - 'title' => 'ShellExecute error', - 'message' => shell_error_string( result ) - ) if result <= 32 - } - ).pack( :side=>'left', :anchor => 'w', :padx=>4, :pady=>4 ) - end # 'w32' - - TkFrame.new( frm ) { |fm| - TkButton.new( fm, - :text => 'Open..', - :command => lambda { - path = Tk.getOpenFile( - :initialdir => $settings.defaultDir, - :filetypes => [ - ['All files', '*'], - ['EPS', ['.eps']], - ['PDF', ['.pdf']], - ['PostScript', ['.ps']] - ], - :parent => $root - ) - if path and ( not path.empty? ) - load_file( path ) - $settings.defaultDir = File.expand_path( File.dirname( path ) ) - end - } - ).pack( :side=>'left', :padx=>4, :pady=>4 ) - - $save_button = TkButton.new( fm, - :text => "Convert and save..", - :command => lambda { - $options.type = $type_radio.value - $options.page = \ - ( ( $page_radio.value == 'single' ) ? $page_entry.value : nil ) - $options.gray = ($gray_radio.value and $gray_radio.value != 'color' ) - $options.gRAY = ($gray_radio.value and $gray_radio.value == 'gRAY' ) - $options.bbox = ( ( $bbox_check.value == '1' ) \ - and ( $page_radio.value == 'single' ) ) - filetypes = case $options.type - when 'pdf' then [ ['Pdf', ['.pdf'] ] ] - when 'ps' then [ ['PostScript', ['.ps'] ] ] - when 'eps' then [ ['EPS (Encapsulated PostScript', ['.eps'] ] ] - end - path = nil - path = Tk.getSaveFile( - :filetypes => filetypes, - :parent => $root, - :initialdir => File.dirname( $source.path ), - :initialfile => File.basename( $source.path, ".*" ) + - '.' + $options.type, - :defaultextension => '.' + $options.type - ) - return unless path && ! path.empty? - $settings.defaultDir = File.expand_path( File.dirname( path ) ) - - $cnv_label.configure( - 'text' => "Converting #{File.basename($source.path)}" + - " to #{ File.basename(path)}..." - ) - $cnv_label.update - - begin - result = $source.any_to_any( $options ) - rescue EPCallError => exc - mess = "Wrong method call or conversion not supported" + - " or wrong page number" - write_log( mess + $/ + - exc.message + $/ + exc.backtrace.join( $/ ) ) - Tk.messageBox( - 'icon' => 'error', - 'type' => 'ok', - 'parent' => $root, - 'message' => "#{mess}\nSee #{LOGFILE} for details." - ) - rescue EPBBError => exc - mess = "Boundingbox problem" + $/ + - exc.message - write_log( mess + $/ + exc.backtrace.join( $/ ) ) - Tk.messageBox( - 'icon' => 'error', - 'type' => 'ok', - 'parent' => $root, - 'message' => "#{mess}\nSee #{LOGFILE} for details." - ) - rescue EPSystemError => exc - mess = "Problem with system call" + $/ + - exc.message - write_log( mess + $/ + exc.backtrace.join( $/ ) ) - Tk.messageBox( - 'icon' => 'error', - 'type' => 'ok', - 'parent' => $root, - 'message' => "#{mess}\nSee #{LOGFILE} for details." - ) - ensure - # $tl_wait.withdraw - $cnv_label.configure( 'text' => '' ) - $cnv_label.update - end - if result - ccp( result.path, path ) - load_file( path ) - Tk.messageBox( - 'icon' => 'info', - 'type' => 'ok', - 'parent' => $root, - 'message' => "Conversion completed" - ) - end - } - ).pack( :side=>'left', :padx=>0, :pady=>4 ) - - TkButton.new( fm, - :text => "Done", - :command => lambda { $root.destroy } - ).pack( :side => 'left', :padx => 4, :pady => 4 ) - }.pack( :side => 'right', :anchor => 'e' ) -}.pack( :side => 'bottom', :fill => 'x' ) - -set_widget_states - -$root.raise - -Tk.mainloop -$settings.write_settings -cleantemp diff --git a/Master/texmf-dist/scripts/epspdf/epspdftk.tcl b/Master/texmf-dist/scripts/epspdf/epspdftk.tcl new file mode 100755 index 00000000000..ac96d844be7 --- /dev/null +++ b/Master/texmf-dist/scripts/epspdf/epspdftk.tcl @@ -0,0 +1,848 @@ +#!/usr/bin/env wish + +# epspdf conversion utility, GUI frontend + +##### +# Copyright (C) 2006, 2008, 2009, 2010 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! +##### + +package require Tk + +# tired of writing out this combined test again and again +set classic_unix [expr {$::tcl_platform(platform) eq "unix" && \ + $::tcl_platform(os) ne "Darwin"}] + +# normally, epspdf.rb should be in the same directory +# and ruby should be on the searchpath. +# However, the Windows installer version includes a Ruby subset +# and wraps this script in a starpack. + +### calling epspdf.rb ######################### + +# Get full path of epspdf.rb. It should be in the same directory as +# either this script or of the starpack containing this script. +# For the windows-only starpack, a ruby subset is included. +# Otherwise, ruby should be on the searchpath. + +proc set_progs {} { + # starpack edition? + set starred 0 + if {$::tcl_platform(platform) eq "windows"} { + foreach l [info loaded] { + if {[lindex $l 1] eq "tclkitpath"} { + set starred 1 + break + } + } + } + if {$starred} { + set eproot [file normalize \ + [regsub {([\\/])([^\\/]+)$} [info nameofexecutable] {}]] + set ::ruby [file normalize "$eproot/../rubysub/bin/ruby.exe"] + } else { + set eproot [file normalize \ + [regsub {([\\/])([^\\/]+)$} [info script] {}]] + set ::ruby "ruby" + } + set ::epspdf_rb [file join $eproot "epspdf.rb"] + if {! [file exists $::epspdf_rb]} { + tk_messageBox -type ok -icon error -message "Epspdf.rb not found" + exit 1 + } + + # no luck with other platforms + if {$::tcl_platform(platform) eq "windows"} { + wm iconbitmap . [file join $eproot "epspdf.ico"] + } +} + +set_progs + +# call epspdf.rb with parameter list l (should be a list): + +set result "" +proc run_epspdf {res args} { + upvar $res result + set failed [catch [linsert $args 0 exec $::ruby $::epspdf_rb --gui] result] + if {$failed} { + wm deiconify .log_t + tk_messageBox -icon error -type ok -message "Error; see log window" + } + # update log window with $result + .log_t.text configure -state normal + .log_t.text insert end "$result\n" + .log_t.text yview moveto 1 + .log_t.text configure -state disabled + + # it is up to the caller to do anything else about failure or not. + # the user, at least, has been warned. + return [expr ! $failed] +} + +### read configured settings ######################################## + +# for checking configured viewers under non-osx unix +proc is_valid {x} { + if {[catch {exec which $x}]} {return 0} else {return 1} +} + +# create a global empty settings array +array set settings [list] + +# ask epspdf.rb for currently configured settings. +# this does not include automatically configured or transient settings. +# the availability of viewers is handled here. +proc getsettings {} { + if [catch {exec $::ruby $::epspdf_rb --gui=config_w} set_str] { + error "Epspdf configuration error: $set_str" + } + #puts "settings from epspdf.rb:\n$set_str" + set l [split $set_str "\r\n"] + foreach e $l { + # $e is either a string "var=value" + # or the empty string between <cr> and <lf> + set i [string first "=" $e] + if {$i>0} { + #puts $e + set ::settings([string range $e 0 [expr $i-1]]) \ + [string range $e [expr $i+1] end] + } + } + + # unix: viewer settings + # configured viewer, if valid, heads the list + if {$::classic_unix} { + + set ::ps_viewers {} + if {$::settings(ps_viewer) ne "" && [is_valid $::settings(ps_viewer)]} { + lappend ::ps_viewers $::settings(ps_viewer) + } + foreach v {evince okular gv kghostview ghostview} { + if {$v ne $::settings(ps_viewer) && [is_valid $v]} { + lappend ::ps_viewers $v + } + } + + set ::pdf_viewers {} + if {$::settings(pdf_viewer) ne "" && [is_valid $::settings(pdf_viewer)]} { + lappend ::pdf_viewers $::settings(pdf_viewer) + } + foreach v {evince okular kpdf xpdf epdfview acroread \ + gv kghostview ghostview} { + if {$v ne $::settings(pdf_viewer) && [is_valid $v]} { + lappend ::pdf_viewers $v + } + } + + if {[llength ::pdf_viewers] == 0 && [llength ::ps_viewers] != 0} { + lappend ::pdf_viewers [lindex $::ps_viewers 0] + } + if {[llength ::pdf_viewers] == 0} { + tk_messageBox -message "No viewers found" + } elseif {[llength ::ps_viewers] == 0} { + tk_messageBox -message "No PostScript viewers found" + } + if {[llength ::pdf_viewers] > 0} { + set ::settings(pdf_viewer) [lindex $::pdf_viewers 0] + } + if {[llength ::ps_viewers] > 0} { + set ::settings(ps_viewer) [lindex $::ps_viewers 0] + } + } +} + +getsettings + +# directory and other file data + +if {$::argc > 0 && [file isdirectory [lindex $::argv 0]]} { + set gfile(dir) [lindex $::argv 0] +} elseif {[file isdirectory $::settings(defaultDir)]} { + set gfile(dir) $::settings(defaultDir) +} else { + set gfile(dir) $::env(HOME) +} +set gfile(path) "" +set gfile(type) "" +set gfile(name) "" +set gfile(npages) "" + +# transient options +array set options [list gray "color" format "pdf" bbox 0 clean 1 \ + pages "single" page 1] + +proc viewable {} { + if { $::gfile(name) eq "" || ! [file exists $::gfile(path)] || \ + $::gfile(type) eq "other" || $::gfile(type) eq ""} { + return 0 + } elseif {! $::classic_unix} { + return 1 + } elseif {$::settings(ps_viewer) ne "" && [regexp {ps} $::gfile(type)]} { + return 1 + } elseif {$::settings(pdf_viewer) ne "" && $::gfile(type) eq "pdf"} { + return 1 + } else { + return 0 + } +} + +### groundwork for GUI ################################# + +# padding for buttons and frames +proc packb {b args} { + eval [linsert $args 0 pack $b -padx 3 -pady 3] + $b configure -border 2 +} + +proc packf {f args} { + eval [linsert $args 0 pack $f -padx 3 -pady 3] +} + +# dummy widget for vertical spacing +set idummy -1 +proc spacing {w} { + incr ::idummy + pack [label $w.$::idummy -text " "] +} + +# bold font +font create boldfont +# create dummy label widget to get at the default label font properties +label .dummy +font configure boldfont -family [font actual [.dummy cget -font] -family] +font configure boldfont -size [font actual [.dummy cget -font] -size] +font configure boldfont -weight bold +destroy .dummy + +# bitmaps for mycombo (no combobox in core tk8.4) +image create bitmap dwnarrow -data { +#define dwnarrow_width 15 +#define dwnarrow_height 10 +static unsigned char dwnarrow_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x1f, 0xf8, 0x0f, 0xf0, 0x07, 0xe0, 0x03, + 0xc0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00 }; +} + +image create bitmap uparrow -data { +#define uparrow_width 15 +#define uparrow_height 10 +static unsigned char uparrow_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x01, 0xe0, 0x03, 0xf0, 0x07, + 0xf8, 0x0f, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00 }; +} + +# mycombo +proc mycombo {w} { + # entry widget and dropdown button + frame $w + frame $w.ef + entry $w.ef.e -width 30 -borderwidth 1 + pack $w.ef.e -side left + button $w.ef.b -image dwnarrow -command "droplist $w" -borderwidth 1 + pack $w.ef.b -side right + pack $w.ef + # 'drop-down' listbox; width should match entry widget above + toplevel $w.lf -bd 0 + listbox $w.lf.l -yscrollcommand "$w.lf.s set" -height 4 -width 30 \ + -bd 1 -relief raised + grid $w.lf.l -column 0 -row 0 -sticky news + scrollbar $w.lf.s -command "$w.lf.l yview" -bd 1 + grid $w.lf.s -column 1 -row 0 -sticky ns + grid columnconfigure $w.lf 0 -weight 1 + wm overrideredirect $w.lf 1 + wm transient $w.lf + wm withdraw $w.lf + # next two bindings: + # final parameter: unmap/toggle listbox + bind $w.lf.l <KeyRelease-space> {update_e %W [%W get active] 1} + bind $w.lf.l <KeyRelease-Tab> {update_e %W [%W get active] 1} + bind $w.lf.l <FocusOut> {update_e %W [%W get active] 1} + bind $w.lf.l <1> {update_e %W [%W get @%x,%y] 0} + bind $w.lf.l <Double-1> {update_e %W [%W get @%x,%y] 1} + bind $w.ef.e <Return> {update_l %W} + bind $w.ef.e <Tab> {update_l %W} + bind $w.ef.e <FocusOut> {update_l %W} + return $w +} + +# toggle state of listbox. +# this involves calculating the place where it should appear +# and toggling the arrow image. +proc droplist {w} { + # $w.ef is the frame with the entry widget + # $w.lf is the toplevel with the listbox + # which needs to turn up right below $w.ef + if {[wm state $w.lf] eq "withdrawn" || [wm state $w.lf] eq "iconified"} { + set lfx [winfo rootx $w.ef] + set lfy [expr [winfo rooty $w.ef] + [winfo height $w.ef]] + wm geometry $w.lf [format "+%d+%d" $lfx $lfy] + wm deiconify $w.lf + $w.ef.b configure -image uparrow + } else { + wm withdraw $w.lf + $w.ef.b configure -image dwnarrow + } +} + +proc update_e {lbox vl unmap} { + set w [winfo parent [winfo parent $lbox]] + $w.ef.e delete 0 end + $w.ef.e insert 0 $vl + if {$unmap} {droplist $w} +} + +# entry => list +proc update_l {v} { + set t [$v get] + set w [winfo parent [winfo parent $v]] + for {set i 0} {$i<[$w.lf.l size]} {incr i} { + if {$t eq [$w.lf.l get $i]} { + $w.lf.l see $i + $w.lf.l activate $i + return + } + } + # $t not found + if {[$v validate]} { + $w.lf.l insert 0 $t + $w.lf.l see 0 + $w.lf.l activate 0 + } else { + tk_messageBox -message "Not a program" + } +} + +# end mycombo + +### and now the actual GUI ################################### + +wm title . "PostScript- and pdf conversions" + +# help toplevel + +proc readhelp {} { + .help_t.text configure -state normal + set helpfile [regsub {\.rb$} $::epspdf_rb {.help}] + if {[catch {set fid [open $helpfile r]}]} { + .help_t.text insert end "No helpfile $helpfile found\n" + } else { + while {[gets $fid line] >= 0} {.help_t.text insert end "$line\n"} + close $fid + } + .help_t.text configure -state disabled + .help_t.text yview moveto 0 +} + +toplevel .help_t +wm title .help_t "EpsPdf help" +packb [button .help_t.done -text "Close" -command {wm withdraw .help_t}] \ + -side bottom -anchor e -padx 50 +text .help_t.text -wrap word -width 60 -height 20 -setgrid 1 \ + -yscrollcommand ".help_t.scroll set" +scrollbar .help_t.scroll -command ".help_t.text yview" +pack .help_t.scroll -side right -fill y +pack .help_t.text -expand 1 -fill both +readhelp +.help_t.text configure -state disabled +wm withdraw .help_t + +# log toplevel + +toplevel .log_t +wm title .log_t "Epspdf log" +packb [button .log_t.b -text "Close" -command {wm withdraw .log_t}] \ + -side bottom -anchor e -padx 50 +text .log_t.text -wrap word -relief flat -height 15 -width 60 \ + -setgrid 1 -yscrollcommand ".log_t.scroll set" +scrollbar .log_t.scroll -command ".log_t.text yview" +pack .log_t.scroll -side right -fill y +pack .log_t.text -expand 1 -fill both +.log_t.text configure -state disabled +wm withdraw .log_t + +### configure toplevel ################### + +toplevel .config_t +wm title .config_t "Configure epspdf" + +# The settings array is edited directly in the configuration screen: +# for most control widgets, we need a global external variable anyway, +# so we better use the global that is already there. +# If the configuration screen is closed via the cancel button, +# the original values will be re-read from disk. +# If it is closed via the ok button, the new settings are written to disk. + +# viewers (not on windows or osx) + +if {$::classic_unix} { + packf [frame .config_t.viewf] -ipadx 4 -fill x + grid [label .config_t.viewf.title -font boldfont -text "Viewers"] \ + -row 0 -column 0 -sticky w + grid [label .config_t.viewf.lb_pdf -text "Pdf"] \ + -row 1 -column 0 -sticky w + grid [mycombo .config_t.viewf.pdf] -row 1 -column 1 -sticky e + .config_t.viewf.pdf.ef.e configure -vcmd {is_valid %P} -validate none + .config_t.viewf.pdf.ef.e configure -textvariable settings(pdf_viewer) + grid [label .config_t.viewf.lb_ps -text "PostScript"] \ + -row 2 -column 0 -sticky w + grid [mycombo .config_t.viewf.ps] -row 2 -column 1 -sticky e -pady 4 + .config_t.viewf.ps.ef.e configure -vcmd {is_valid %P} -validate none + .config_t.viewf.ps.ef.e configure -textvariable settings(ps_viewer) + grid columnconfigure .config_t.viewf 1 -weight 1 -pad 2 + + .config_t.viewf.pdf.lf.l configure -listvariable ::pdf_viewers + .config_t.viewf.ps.lf.l configure -listvariable ::ps_viewers + + spacing .config_t +} + +# settings for conversion to pdf + +packf [frame .config_t.pdff] -ipadx 4 -fill x +pack [label .config_t.pdff.title -font boldfont -text "Conversion to pdf"] \ + -anchor w + +pack [label .config_t.pdff.l_target -text "Target use"] -anchor w +pack [frame .config_t.pdff.f_targets] -fill x +foreach t {default printer prepress screen ebook} { + pack [radiobutton .config_t.pdff.f_targets.$t \ + -variable settings(pdf_target) \ + -text $t -value $t] -side left -padx 2 -pady 4 -anchor w +} + +pack [label .config_t.pdff.l_version -text "Pdf version"] -anchor w +pack [frame .config_t.pdff.f_version] -fill x +foreach t {1.2 1.3 1.4 default} { + regsub {\.} $t _ tp ; # replace dot in name: dots are path separators! + pack [radiobutton .config_t.pdff.f_version.$tp \ + -variable settings(pdf_version) \ + -text $t -value $t] -side left -padx 2 -pady 4 -anchor w +} + +pack [label .config_t.pdff.l_gs \ + -text "Custom Ghostscript/ps2pdf parameters"] -anchor w +pack [entry .config_t.pdff.e_gs -border 1] -fill x -padx 2 -pady 2 +.config_t.pdff.e_gs configure -textvariable settings(pdf_custom) + +spacing .config_t + +# settings for conversion to EPS and PostScript + +packf [frame .config_t.psf] -ipadx 4 -fill x +pack [label .config_t.psf.l_ps -text "Conversion to EPS and PostScript" \ + -font boldfont] -anchor w +if {$tcl_platform(platform) eq "windows"} { + pack [label .config_t.psf.l_pdftops -text "Find pdftops"] -anchor w + pack [frame .config_t.psf.findf] -anchor w + pack [entry .config_t.psf.findf.e -width 40] -side left -padx 4 + .config_t.psf.findf.e configure -textvariable settings(pdftops_prog) + # epspdfrc.rb already checked on this setting so we don't + packb [button .config_t.psf.findf.b -text "Browse..." \ + -command find_pdftops] -side left +} + +proc find_pdftops {} { + set try [tk_getOpenFile -title "Find pdftops.exe" \ + -filetypes {{"Programs" {.exe}}} -initialdir "c:/"] + if {$try ne ""} { + .config_t.psf.findf.e delete 0 end + .config_t.psf.findf.e insert 0 $try + } +} + +pack [checkbutton .config_t.psf.c \ + -text "Use pdftops if available (recommended)"] -anchor w +.config_t.psf.c configure \ + -variable settings(ignore_pdftops) -onvalue 0 -offvalue 1 + +spacing .config_t + +# hires boundingbox setting + +packf [frame .config_t.hiresf] -ipadx 4 -fill x +pack [label .config_t.hiresf.title -font boldfont -text "Hires BoundingBox"] \ + -anchor w +pack [label .config_t.hiresf.l -text "Uncheck to prevent clipping"] \ + -anchor w + +pack [checkbutton .config_t.hiresf.c \ + -text "Use hires boundingbox if possible"] -anchor w +.config_t.hiresf.c configure \ + -variable settings(ignore_hires_bb) -onvalue 0 -offvalue 1 + +spacing .config_t + +# buttons for closing the configuration screen + +pack [frame .config_t.buttonsf] -fill x +packb [button .config_t.buttonsf.done -text "Done" -command putsettings] \ + -side right +packb [button .config_t.buttonsf.cancel -text "Cancel" \ + -command cancelsettings] -side right + +wm transient .config_t +wm overrideredirect .config_t +wm withdraw .config_t + +proc edit_settings {} { + wm deiconify .config_t + raise .config_t + grab set .config_t +} + +# store new settings +proc putsettings {} { + if {$::classic_unix} { + wm withdraw .config_t.viewf.pdf.lf + wm withdraw .config_t.viewf.ps.lf + } + wm withdraw .config_t + grab release .config_t + write_settings +} + +proc write_settings {} { + set s "" + foreach el [array names ::settings] { + set s "$s$el=$::settings($el)\n" + } + #puts "\nsettings for epspdf.rb\n$s" + if [catch {exec $::ruby $::epspdf_rb --gui=config_r << $s} result] { + error "Epspdf configuration error: $result" + } +} + +proc cancelsettings {} { + if {$::classic_unix} { + wm withdraw .config_t.viewf.pdf.lf + wm withdraw .config_t.viewf.ps.lf + } + wm withdraw .config_t + grab release .config_t + # re-read config file / reg entries + getsettings +} + +### main screen ############################# + +proc show_w {w} { + wm deiconify $w + raise $w +} + +# buttons to call up configure-, log- and help screens + +pack [frame .topf] -fill x +packb [button .topf.config_t -text "Configure" \ + -command edit_settings] -side left +packb [button .topf.help_t -text "Help" \ + -command {show_w .help_t}] -side right +packb [button .topf.logb -text "Show log" -command {show_w .log_t}] \ + -side right -anchor w + +# file info in grid layout + +packf [frame .infof -relief sunken -border 1] -fill x +grid [label .infof.dir_label -text "Directory" -anchor w] \ + -row 1 -column 1 -sticky w +grid [label .infof.dir_value -textvariable gfile(dir) -anchor w] \ + -row 1 -column 2 -sticky w + +grid [label .infof.name_label -text "File" -anchor w] \ + -row 2 -column 1 -sticky w +grid [label .infof.name_value -textvariable gfile(name) -anchor w] \ + -row 2 -column 2 -sticky w + +grid [label .infof.type_label -text "Type" -anchor w] \ + -row 3 -column 1 -sticky w +grid [label .infof.type_value -textvariable gfile(type) -anchor w] \ + -row 3 -column 2 -sticky w + +grid [label .infof.npages_label -text "Pages" -anchor w] \ + -row 4 -column 1 -sticky w +grid [label .infof.npages_value -textvariable gfile(npages) -anchor w] \ + -row 4 -column 2 -sticky w + +grid columnconfigure .infof 1 -weight 1 -pad 2 +grid columnconfigure .infof 2 -weight 3 -pad 2 + +spacing . + +# conversion options + +pack [frame .optsf] -fill x + +# grayscaling +pack [frame .optsf.gray] -side left -anchor nw +pack [label .optsf.gray.l -text "Grayscaling"] -anchor w +pack [radiobutton .optsf.gray.off -text "No color conversion" \ + -variable options(gray) -value "color"] -anchor w +pack [radiobutton .optsf.gray.gray -text "Try to grayscale" \ + -variable options(gray) -value "gray"] -anchor w +pack [radiobutton .optsf.gray.gRAY -text "Try harder to grayscale" \ + -variable options(gray) -value "gRAY"] -anchor w + +# output format +pack [label .optsf.format] -side right -anchor ne +pack [label .optsf.format.l -text "Output format"] -anchor w +pack [radiobutton .optsf.format.pdf -text "pdf" -command set_widget_states \ + -variable options(format) -value "pdf"] -anchor w +pack [radiobutton .optsf.format.eps -text "eps" -command set_widget_states \ + -variable options(format) -value "eps"] -anchor w +pack [radiobutton .optsf.format.ps -text "ps" -command set_widget_states \ + -variable options(format) -value "ps"] -anchor w + +spacing . + +# boundingbox +pack [checkbutton .bbox -text "Compute tight boundingbox" \ + -variable options(bbox) -command set_widget_states] -anchor w + +# page selection +pack [frame .pagesf] -fill x +pack [radiobutton .pagesf.all -text "Convert all pages" \ + -variable options(pages) -value "all" -command set_widget_states] \ + -side left +pack [radiobutton .pagesf.single -text "Page:" \ + -variable options(pages) -value "single" -command set_widget_states] \ + -side left +pack [entry .pagesf.e -width 6 -textvariable ::options(page)] -side left +#.pagesf.e configure -vcmd {page_valid %W} -validate focusout \ +# -invcmd "focusAndFlash %W [.pagesf.e cget -fg] [.pagesf.e cget -bg]" +.pagesf.e configure -vcmd {page_valid %W} -validate focusout \ + -invcmd "see_red %W" + +spacing . + +# temp files +pack [checkbutton .clean -text "Remove temp files" \ + -variable options(clean)] -anchor w + +proc focusAndFlash {w fg bg {count 9}} { + focus $w + if {$count<1} { + $w configure -foreground $fg -background $bg + } else { + if {$count%2} { + $w configure -foreground $bg -background $fg + } else { + $w configure -foreground $fg -background $bg + } + after 200 [list focusAndFlash $w $fg $bg [expr {$count-1}]] + } +} + +proc see_red {w} { + focus $w + set orig [$w cget -bg] + $w configure -bg red + update idletasks + after 1000 + $w configure -bg $orig + update idletasks +} + +proc page_valid {w} { + # w entry widget + set p [$w get] + set isvalid 1 + #puts "check pageno $p" + if {! [string is integer $p] || $p<=0} { + set isvalid 0 + } elseif {$::gfile(npages) ne "" && [scan $p "%d"] > $::gfile(npages)} { + set isvalid 0 + } + return $isvalid +} + +# end conversion options + +pack [label .status] -side bottom -anchor w -fill x + +# main buttons + +pack [frame .bottomf] -side bottom -fill x +packb [button .bottomf.view -text "View" -command view] -side left +packb [button .bottomf.open -text "Open" -command openDialog] \ + -side left -padx 2 +packb [button .bottomf.convert -text "Convert and save..." \ + -command saveDialog] -side left -padx 2 +packb [button .bottomf.done -text "Done" -command exit] -side right + +proc view {} { + if {! [viewable]} { + tk_messageBox -icon warning -type ok \ + -message "No viewer for $::gfile(path)" + return + } + if {$::tcl_platform(os) eq "Darwin"} { + catch {exec open $::gfile(path) &} + } elseif {$::tcl_platform(platform) ne "unix"} { + # use shortname to sidestep quoting problems + catch {exec cmd /x /c start [file attributes $::gfile(path) -shortname]} + } else { + if {$::gfile(type) eq "pdf"} { + catch {exec $::settings(pdf_viewer) $::gfile(path) &} + } elseif {$::gfile(type) ne "other" && $::gfile(type) ne ""} { + catch {exec $::settings(ps_viewer) $::gfile(path) &} + } + } +} + +proc openDialog {} { + set types { + {"Encapsulated PostScript" {.eps .epi .epsi}} + {"General PostScript" {.ps .prn}} + {"Pdf" {.pdf}} + {"All files" *} + } + if {[file isdirectory $::gfile(dir)]} { + set try [tk_getOpenFile -filetypes $types -initialdir $::gfile(dir)] + } else { + set try [tk_getOpenFile -filetypes $types] + } + if {$try != ""} { + set ::gfile(path) [file normalize $try] + set ::gfile(dir) [file dirname $::gfile(path)] + set ::gfile(name) [file tail $::gfile(path)] + if {[run_epspdf result -i $::gfile(path)]} { + # parse output + regexp { is (\w+)(?: with (\d+) pages)?[\r\n]*$} $result \ + mtc ::gfile(type) ::gfile(npages) + if {[regexp {^eps} $::gfile(type)]} {set ::gfile(npages) 1} + } + set ::settings(defaultDir) $::gfile(dir) + putsettings + } + set_widget_states +} + +proc saveDialog {} { + if {$::options(format) eq "pdf"} { + set types {{"Pdf" {.pdf}}} + } elseif {$::options(format) eq "ps"} { + set types {{"PostScript" {.ps}}} + } elseif {$::options(format) eq "eps"} { + set types {{"Encapsulated PostScript" {.eps}}} + } + set try [tk_getSaveFile -filetypes $types -initialdir $::gfile(dir)] + if {$try != ""} { + # fix extension + set try [file normalize $try] + set idot [string last "." [file tail $try]] + if {$idot == -1} { + append try ".$::options(format)" + } else { + # don't bother checking whether the extension is already correct + set try [string range $try 0 [string last "." $try]] + append try $::options(format) + } + # epspdf can read persistent options from configuration. + # only options from the options array need to be converted to parameters. + set cmd [list run_epspdf result] + if {$::options(gray) eq "gray"} { + lappend cmd "-g" + } elseif {$::options(gray) eq "gRAY"} { + lappend cmd "-G" + } + if {$::options(bbox)} {lappend cmd "-b"} + if {! $::options(clean)} {lappend cmd "-d"} + if {$::options(pages) eq "single"} { + if {$::options(page) eq ""} {set ::options(page) 1} + lappend cmd "-p" $::options(page) + } + lappend cmd $::gfile(path) + lappend cmd $try + # $cmd/run_epspdf never bombs, but returns 1 (success) or 0 (fail) + .status configure -text "Working..." + foreach b {view open convert done} { + .bottomf.$b configure -state disabled + } + update idletasks; # force immediate redisplay main window + + if {[eval $cmd]} { + # if failure, there has already been an error message + set ::gfile(path) $try + set ::gfile(dir) [file dirname $try] + set ::gfile(type) $::options(format) + set ::gfile(name) [file tail $try] + set ::gfile(path) [file normalize $try] + set ::gfile(dir) [file dirname $::gfile(path)] + set ::gfile(name) [file tail $::gfile(path)] + # parse result output + regexp { is (\w+)(?: with (\d+) pages)?[\r\n]*$} \ + [string range $result [string last "File type of" $result] end] \ + mtc ::gfile(type) ::gfile(npages) + if {$::gfile(type) eq "eps"} {set ::gfile(npages) 1} + set ::settings(defaultDir) $::gfile(dir) + putsettings + } + .status configure -text "" + foreach b {view open convert done} { + .bottomf.$b configure -state normal + } + set_widget_states + } +} + +proc set_widget_states {} { + # states (normal/disabled) for various widgets. + # their values should already be mutually consistent. + # widgets concerned: + # view / save + # output format / bbox / single page / page no. + + # view + if {[viewable]} { + .bottomf.view configure -state normal + } else { + .bottomf.view configure -state disabled + } + + # convert + if {$::gfile(path) ne "" && [file exists $::gfile(path)] && \ + $::gfile(type) ne "other"} { + .bottomf.convert configure -state normal + } else { + .bottomf.convert configure -state disabled + } + + # type + if {[regexp {ps|pdf} $::gfile(type)]} { + foreach f {pdf eps ps} {.optsf.format.$f configure -state normal} + } else { + foreach f {pdf eps ps} {.optsf.format.$f configure -state disabled} + } + + # pages and page + foreach f {all single} {.pagesf.$f configure -state normal} + if {$::options(format) eq "eps"} { + .pagesf.all configure -state disabled + set ::options(pages) "single" + } + if {$::options(format) eq "ps"} { + .pagesf.single configure -state disabled + set ::options(pages) "all" + } + if {$::options(pages) eq "all"} { + .pagesf.e configure -state disabled + } else { + .pagesf.e configure -state normal + } + + # boundingbox + if {$::options(format) eq "eps"} { + .bbox configure -state normal + } elseif {$::options(pages) eq "all"} { + .bbox configure -state disabled + set ::options(bbox) 0 + } else { + .bbox configure -state normal + } +} + +set_widget_states |