# jbr_cmds.tcl - most user-visible commands for jbrowser
#
######################################################################
# Copyright 1992-1995 by Jay Sekora.  This file may be freely        #
# distributed, modified or unmodified, for any purpose, provided     #
# that this copyright notice is retained verbatim in all copies and  #
# no attempt is made to obscure the authorship of this file.  If you #
# distribute any modified versions, I ask, but do not require, that  #
# you clearly mark any changes you make as such and that you provide #
# your users with instructions for getting the original sources.     #
######################################################################

######################################################################
#
# COMMAND ROUTINES
#
######################################################################

######################################################################
# jbr:cmd:about - make the about box
######################################################################

j:command:register jbr:cmd:about {About the Browser...}
proc jbr:cmd:about { w args } {
  global JSTOOLS_VERSION
  set about_browser [format {
    j:rt:hl "jbrowser"
    j:rt:cr
    j:rt:rm "by Jay Sekora, "
    j:rt:tt "js@aq.org"
    j:rt:par
    j:rt:rm "A customisable directory browser for X Windows."
    j:rt:cr
    j:rt:rm "Version %s."
    j:rt:par
    j:rt:rm "Copyright \251 1992-1995 by Jay Sekora.  "
    j:rt:rm "Terms for copying are specified in the documentation and "
    j:rt:rm "in comments in the code."
    j:rt:par
    j:rt:rm "If you find bugs or have suggestions for improvement, "
    j:rt:rm "please let me know.  "
    j:rt:rm "Feel free to use bits of this code in your own "
    j:rt:tt "wish"
    j:rt:rm " scripts."
  } $JSTOOLS_VERSION]
  j:about .about $about_browser
  j:about:button .about {jbrowser} $about_browser
  j:about:button .about {Author} [j:about_jay]
  j:about:button .about {Tk and Tcl} [j:about_tktcl]
  j:about:button .about {Donations} [j:about_donations]
  
  tkwait window .about
}

######################################################################
# jbr:cmd:quit - exit the script
######################################################################

j:command:register jbr:cmd:quit {Quit}
proc jbr:cmd:quit { w args } {
  if [j:confirm -text {Are you sure you want to quit?}] then {
    destroy .
    exit
  }
}

######################################################################
# jbr:cmd:browser_prefs - preferences panel
######################################################################

j:command:register jbr:cmd:prefs {Browser Preferences...}
proc jbr:cmd:browser_prefs { w args } {
  global J_PREFS BROWSERPREFS env tk_strictMotif
  
  set old_focus [focus]			;# so we can restore original focus

  toplevel .bprefs
  wm title .bprefs "Browser Preferences"

  frame .bprefs.fancy
  checkbutton .bprefs.fancy.cb -anchor w \
    -text {Long file listings} -variable BROWSERPREFS(fancy)
  frame .bprefs.font
  frame .bprefs.font.top
  label .bprefs.font.top.l -text {Font:}
  button .bprefs.font.top.default -width 8 -text {Default} -command {
    set BROWSERPREFS(lbfont) {default}
  }
  button .bprefs.font.top.choose -text {Choose . . .} -command {
    set BROWSERPREFS(lbfont) [j:prompt_font]
  }
  frame .bprefs.font.bot
  entry .bprefs.font.bot.e -width 50 \
    -textvariable BROWSERPREFS(lbfont)
  frame .bprefs.size
  label .bprefs.size.wl -text {Width:}
  entry .bprefs.size.we -width 5 \
    -textvariable BROWSERPREFS(lbwidth)
  label .bprefs.size.hl -text {Height:}
  entry .bprefs.size.he -width 5 \
    -textvariable BROWSERPREFS(lbheight)

  j:buttonbar .bprefs.b -default save -buttons {
    {
      save Save {
        j:write_prefs -array BROWSERPREFS -file jbrowser-defaults
        .bprefs.b.done invoke
      }
    } {
      done Done {
        if {$BROWSERPREFS(lbwidth) < 10} {set BROWSERPREFS(lbwidth) 10}
        if {$BROWSERPREFS(lbheight) < 3} {set BROWSERPREFS(lbheight) 3}
        .cur.list configure -geometry \
          [format {%sx%s} $BROWSERPREFS(lbwidth) $BROWSERPREFS(lbheight)]
        j:configure_font .cur.list $BROWSERPREFS(lbfont)
        jbr:fill_browser
        destroy .bprefs
      }
    }
  }
  
  pack append .bprefs.fancy .bprefs.fancy.cb {left expand fillx}
  pack append .bprefs.font.top \
    .bprefs.font.top.l {left} \
    .bprefs.font.top.choose {right padx 10 pady 5} \
    .bprefs.font.top.default {right pady 5}
  pack append .bprefs.font.bot \
    .bprefs.font.bot.e {left padx 10 pady 5}
  pack append .bprefs.font \
    .bprefs.font.top {top expand fillx} \
    .bprefs.font.bot {top expand fillx}
  pack append .bprefs.size .bprefs.size.wl {left fillx}
  pack append .bprefs.size .bprefs.size.we {left}
  pack append .bprefs.size .bprefs.size.hl {left fillx}
  pack append .bprefs.size .bprefs.size.he {left}

  pack append .bprefs \
    .bprefs.fancy {top fill} \
    [j:rule .bprefs -width 200] {top fillx} \
    .bprefs.font {top fillx} \
    [j:rule .bprefs -width 200] {top fillx} \
    .bprefs.size {top expand fill} \
    [j:rule .bprefs -width 200] {top fillx} \
    .bprefs.b {top expand fillx}

  j:dialogue .bprefs		;# position in centre of screen

  focus .bprefs
  bind .bprefs.font.bot.e <Key-Return> {.bprefs.b.save invoke}
  bind .bprefs.size.we <Key-Return> {.bprefs.b.save invoke}
  bind .bprefs.size.he <Key-Return> {.bprefs.b.save invoke}
  bind .bprefs.font.bot.e <Key-Tab> {focus .bprefs.size.we}
  bind .bprefs.size.we <Key-Tab> {focus .bprefs.size.he}
  bind .bprefs.size.he <Key-Tab> {focus .bprefs.printer.e}
  bind .bprefs <Key-Return> {.bprefs.b.save invoke}
  bind .bprefs <Key-Tab> {focus .bprefs.size.we}
  grab .bprefs
  tkwait window .bprefs
  j:tk3 {focus $old_focus}
  j:tk4 {focus -force $old_focus}	;# can't figure out a better way...
}

######################################################################
# jbr:cmd:cd - let user type directory to cd to
######################################################################

j:command:register jbr:cmd:cd {Change Directory...}
proc jbr:cmd:cd { w args } {
  set dirname [j:fs -buttons {here cancel home root} \
    -prompt "Change directory to..."]
  if {$dirname != {}} then {
    if [file isdirectory $dirname] {
      jbr:cd $dirname
    } else {
      j:alert -text "Directory \"$dirname\" does not exist."
    }
  }
}

######################################################################
# jbr:cmd:newdir - make a new directory
######################################################################

j:command:register jbr:cmd:newdir {Create Directory...}
proc jbr:cmd:newdir { w args } {
  set dirname [j:fs -prompt "Create a new directory named..."]
  if {$dirname != {}} then {
    jbr:attempt "mkdir \"$dirname\""
    jbr:update_browser
  }
}

######################################################################
# jbr:cmd:duplicate - make a copy of a file or directory
######################################################################

j:command:register jbr:cmd:duplicate {Duplicate}
proc jbr:cmd:duplicate { w args } {
  foreach i [jbr:getfiles $w] {
    jbr:attempt "cp -r \"$i\" \"copy_of_$i\""
  }
  jbr:update_browser
}

######################################################################
# jbr:cmd:destroy - delete a file or directory
######################################################################
# PROBLEM: rm seems to return 0 even on permission failure

j:command:register jbr:cmd:destroy {Destroy}
proc jbr:cmd:destroy { w args } {
  foreach i [jbr:getfiles $w] {
    if {[file isdirectory $i]} then {
      if [j:confirm -priority 75 -text \
      "Are you sure you want to destroy ``$i'' and all its contents?"] {
        jbr:attempt "rm -r \"$i\""
      }
    } else {
      if [j:confirm -priority 75 -text "Are you sure you want to destroy ``$i''?"] {
        jbr:attempt "rm \"$i\""
      }
    }
  }
  jbr:update_browser
}

######################################################################
# jbr:cmd:move - rename or move a file or directory
######################################################################
# NEED TO CHECK FOR SYMLINKS TOO!

j:command:register jbr:cmd:move {Move...}
proc jbr:cmd:move { w args } {
  set old_cwd [pwd]
  if {$old_cwd == "/"} {set old_cwd ""}

  foreach i [jbr:getfiles $w] {
    if {[file isdirectory $i]} then {set i [file dirname $i]}
    set j [j:fs -buttons {here cancel home root} \
      -prompt "Move `$i' to..."]

    if {$j == {}} then {return 0}

    if [j:confirm -text "Are you sure you want to move `$i' to `$j'?"] then {
      jbr:attempt "mv \"$old_cwd/$i\" \"$j\""
    }
  }
  jbr:update_browser
}

######################################################################
# jbr:cmd:rename - rename a file or directory
######################################################################
# NEED TO CHECK FOR SYMLINKS TOO!

j:command:register jbr:cmd:rename {Rename...}
proc jbr:cmd:rename { w args } {
  set old_cwd [pwd]
  if {$old_cwd == "/"} {set old_cwd ""}

  foreach i [jbr:getfiles $w] {
    if {[file isdirectory $i]} then {set i [file dirname $i]}
    set j [j:prompt -file 1 -text "Rename `$i' to..."]

    if {$j == {}} then {return 0}

    if [j:confirm -text "Are you sure you want to rename `$i' to `$j'?"] then {
      jbr:attempt "mv \"$old_cwd/$i\" \"$j\""
    }
  }
  jbr:update_browser
}

######################################################################
# jbr:cmd:execute - run an executable X application
######################################################################
#
# NOT CURRENTLY USED - the menu item is commented out

j:command:register jbr:cmd:execute {Execute}
proc jbr:cmd:execute { w args } {
  foreach i [jbr:getfiles $w] {
    jbr:attempt "\"$i\" &"
  }
}

######################################################################
# jbr:cmd:xterm_execute - run a command in an xterm window
######################################################################
#
# NOT CURRENTLY USED - the menu item is commented out

j:command:register jbr:cmd:xterm_execute {Exectute in an xterm}
proc jbr:cmd:xterm_execute { w args } {
  foreach i [jbr:getfiles $w] {
    jbr:attempt "xterm -e \"$i\" &"
  }
}

######################################################################
# jbr:cmd:tex - process a file with tex
#   this routine is needed because the .tex extension is ambiguous
#   between tex and latex.
######################################################################

j:command:register jbr:cmd:tex {TeX File}
proc jbr:cmd:tex { w args } {
  foreach i [jbr:getfiles $w] {
    if {![file isdirectory $i]} {
      jbr:attempt "tex \"$i\" < /dev/null"
    } else {
      set i [file dirname $i]
      j:alert -text "`$i' is a directory."
    }
  }
}

######################################################################
# jbr:cmd:latex - process a file with latex
#   this routine is needed because the .tex extension is ambiguous
#   between tex and latex.
######################################################################

j:command:register jbr:cmd:latex {LaTeX File}
proc jbr:cmd:latex { w args } {
  foreach i [jbr:getfiles $w] {
    if {![file isdirectory $i]} {
      jbr:attempt "latex \"$i\" < /dev/null"
    } else {
      set i [file dirname $i]
      j:alert -text "`$i' is a directory."
    }
  }
}

######################################################################
# jbr:cmd:make - run make in the current (NOT the selected) directory
######################################################################

j:command:register jbr:cmd:make {Run `make' in This Directory}
proc jbr:cmd:make { w args } {
  j:more -title {Output of `make':} -text [jbr:attempt make]
}

######################################################################
# jbr:cmd:jedit - edit a file with jedit
#   this routine is needed in case you have something you _can_ view
#   or edit with another tool (say .eps with a drawing tool) but you
#   want to edit the actual ASCII text.
######################################################################
# can't use jbr:attempt with background execs

j:command:register jbr:cmd:jedit {Edit with `jedit'}
proc jbr:cmd:jedit { w args } {
  foreach i [jbr:getfiles $w] {
    if {![file isdirectory $i]} {
      exec jedit "$i" &
    } else {
      set i [file dirname $i]
      j:alert -text "`$i' is a directory."
    }
  }
}

######################################################################
# jbr:cmd:xedit - edit a file with xedit
#   this routine is needed in case you have something you _can_ view
#   or edit with another tool (say .eps with a drawing tool) but you
#   want to edit the actual ASCII text.
######################################################################
# can't use jbr:attempt with background execs

j:command:register jbr:cmd:xedit {Edit with `xedit'}
proc jbr:cmd:xedit { w args } {
  foreach i [jbr:getfiles $w] {
    if {![file isdirectory $i]} {
      exec xedit "$i" &
    } else {
      set i [file dirname $i]
      j:alert -text "`$i' is a directory."
    }
  }
}

######################################################################
# jbr:cmd:lpr - print a file with lpr
#   this routine is needed in case you have something you _can_
#   print with another tool (say tex source with a script that
#   processes it) and you want to print the actual source file.
######################################################################

j:command:register jbr:cmd:lpr {Print with `lpr'}
proc jbr:cmd:lpr { w args } {
  global J_PREFS
  foreach i [jbr:getfiles $w] {
    if {![file isdirectory $i]} {
      jbr:attempt "lpr -P$J_PREFS(printer) \"$i\""
    } else {
      set i [file dirname $i]
      j:alert -text "`$i' is a directory."
    }
  }
}

######################################################################
# jbr:cmd:compress - compress a file
######################################################################

j:command:register jbr:cmd:compress {Compress File}
proc jbr:cmd:compress { w args } {
  foreach i [jbr:getfiles $w] {
    if {![file isdirectory $i]} {
      jbr:attempt "compress $i"
      jbr:update_browser
    } else {
      set i [file dirname $i]
      j:alert -text "`$i' is a directory."
    }
  }
}

######################################################################
# jbr:cmd:maketar - make a tar file of a directory
######################################################################

j:command:register jbr:cmd:maketar {Tar Directory}
proc jbr:cmd:maketar { w args } {
  foreach i [jbr:getfiles $w] {
    if {[file isdirectory $i]} then {
      set i [file dirname $i]
      j:more \
        -title "Output of `tar cvf $i':" \
        -text [jbr:attempt "tar cvf \"$i.tar\" \"$i\""]
    } else {
      j:alert -text "`$i' is not a directory."
    }
  }
  jbr:update_browser
}

######################################################################
# jbr:cmd:info - get information about a file
######################################################################

j:command:register jbr:cmd:info {Get Info}
proc jbr:cmd:info { w args } {
  foreach i [jbr:getfiles $w] {
    if {![file isdirectory $i]} {
      if {[regexp "text" [exec file $i]]} then {
        j:more \
          -title "Information about file `$i'" \
          -text \
          [format "\tls -l:\n\n%s\n\n\tfile:\n\n%s\n\n\thead:\n\n%s" \
          [exec ls -l $i] [exec file $i] [jbr:attempt "head -20 \"$i\""]]
      } else {
        j:more \
          -title "Information about file `$i'" \
          -text [format "\tls -l:\n\n%s\n\n\tfile:\n\n%s" \
          [exec ls -l $i] [exec file $i]]
      }
    } else {
      j:more -title "Information about directory `$i'" \
        -text [format "\tls -ld:\n\n%s" \
        [exec ls -ld $i]]
    }
  }
}


######################################################################
#
# DEFAULT FILE-MANIPULATION PROCEDURES
#   these are minimal `file-manipulation' procedures.
#   the user can redefine them (as all procedures) by putting
#   new procedures in hir ~/.tk/jbrowserrc file
#
######################################################################

######################################################################
# jbr:cmd:view - view contents of a file
######################################################################

j:command:register jbr:cmd:view {View}
proc jbr:cmd:view { w args } {
  foreach i [jbr:getfiles $w] {
    if {![file isdirectory $i]} {
      case $i in {

*.jdoc		{exec jdoc [pwd]/$i}
*.dvi		{j:alert -text "I don't know how to view .dvi files."}
*.Z		{j:more -title {Uncompressed file} \
		  -text [jbr:attempt "zcat \"$i\""]}
*.tar.Z		{j:more -title {Contents of uncompressed tar file} \
		  -text [jbr:attempt "uncompress -c \"$i\" | tar -tvf -"]}
*.tar		{j:more -title {Contents of tar file} \
		  -text [jbr:attempt "tar -tvf \"$i\""]}
{*.tiff *.gif *.jpeg *.jpg}
		{exec xv $i &}
default		{j:more -title "Contents of `$i'" \
		  -text [jbr:attempt "cat \"$i\""]}

      }
    } else {
      set i [file dirname $i]
      j:alert -text "`$i' is a directory."
    }
  }
}

######################################################################
# jbr:cmd:edit - edit a file
######################################################################

j:command:register jbr:cmd:edit {Edit}
proc jbr:cmd:edit { w args } {
  foreach i [jbr:getfiles $w] {
    if {![file isdirectory $i]} {
      case $i in {
*.dvi		{j:alert -text "This is a binary file and can't be edited."}
{*.Z *.tar}	{j:alert -text \
		"This file can't be edited without further processing."}
{*.tiff *.gif *.jpeg *.jpg}
		{j:alert -text "I don't know how to deal with image files."}
default		{exec jedit $i &}

      }
    } else {
      set i [file dirname $i]
      j:alert -text "`$i' is a directory."
    }
  }
}

######################################################################
# jbr:cmd:process - compile or otherwise process a file
######################################################################

j:command:register jbr:cmd:process {Process}
proc jbr:cmd:process { w args } {
  foreach i [jbr:getfiles $w] {
    if {![file isdirectory $i]} {
      case $i in {

[mM]akefile*	{jbr:more "Output of `make -f $i'" [jbr:attempt "make -f \"$i\""]}
*.tex		{jbr:more {Output of `tex'} \
                  [jbr:attempt "tex \"$i\" < /dev/null"]}
*.latex		{jbr:more {Output of `latex'} \
                  [jbr:attempt "latex \"$i\" < /dev/null"]}
*.Z		{jbr:attempt "uncompress \"$i\""; jbr:update_browser}
*.tar		{jbr:more "Output of `tar xvf $i'" [jbr:attempt "tar xvf \"$i\""]}
{*.troff *.tr}	{j:alert -text "I don't know how to process `troff' files."}
{*.tiff *.gif *.jpeg *.jpg}
		{j:alert -text "I don't know how to deal with image files."}
default		{j:alert -text "I don't know what to do with this file."}

      }
    } else {
      set i [file dirname $i]
      j:alert -text "`$i' is a directory."
    }
  }
}

######################################################################
# jbr:cmd:print - send a file to the printer
######################################################################

# NOTE: for tex files, assumes dvips is available

j:command:register jbr:cmd:print {Print}
proc jbr:cmd:print { w args } {
  global env J_PREFS
  set env(PRINTER) $J_PREFS(printer)
  foreach i [jbr:getfiles $w] {
    if {![file isdirectory $i]} {
      case $i in {

*.dvi		{jbr:more {Output of `dvips'} [jbr:attempt "dvips \"$i\""]}
*.tex		{j:alert \
		-text "Process this file, and then print the .dvi file."}
*.latex		{j:alert \
		-text "Process this file, and then print the .dvi file."}
core		{j:alert -text \
		"You don't really want to print a core file, do you?"}
{*.Z *.tar}	{j:alert -text \
		"This file can't be printed without further processing."}
{*.tiff *.gif *.jpeg *.jpg}
		{j:alert -text "I don't know how to deal with image files."}
default		{jbr:attempt "lpr \"$i\""}

      }
    } else {
      set i [file dirname $i]
      j:alert -text "`$i' is a directory."
    }
  }
}

######################################################################
# dummy to force autoloading of this file (for registration of cmds):

proc jbr:register_commands {} {}



