summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/epspdf/epspdftk.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/scripts/epspdf/epspdftk.tcl')
-rwxr-xr-xMaster/texmf-dist/scripts/epspdf/epspdftk.tcl848
1 files changed, 848 insertions, 0 deletions
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