#!/usr/local/bin/wish -f
# procedures for an installation tool

global jinstall

######################################################################
# the following sets the header for each script.  note that %s marks the
# place where $jinstall(normallib) will be inserted.
set jinstall(preamble) {## begin boiler_header

global VERSION
set VERSION {3.6/3.0}

if {[info exists env(JSTOOLS_LIB)]} {
  set jstools_library $env(JSTOOLS_LIB)
} else {
  set jstools_library {%s}
}

# add the jstools library to the library search path:

set auto_path [concat [list $jstools_library] $auto_path]

# check for ~/.tk and prepend it to the auto_path if it exists.
# that way the user can override and customise the jstools libraries.

if {[file isdirectory ~/.tk]} then {
  set auto_path [concat [list [glob ~/.tk]] $auto_path]
}

## end boiler_header
}
######################################################################

proc jinstall:show_help { help } {
  set ext 0
  set pref .jinstall_help
  while {[catch {toplevel $pref$ext}]} {
    incr ext
  }
  set w $pref$ext
  
  set text {}
  
  foreach part $help {
    append text $part
  }
  
  message $w.m -aspect 200 -text $text
  frame $w.f -height 5p
  label $w.l -text {(Click window to close.)}
  
  pack $w.m -padx 5p -pady 5p -fill both
  pack $w.f -fill x
  pack $w.l -fill x
  
  foreach widget [list $w.m $w.f $w.l] {
    bind $widget <Any-ButtonRelease> "destroy $w"
  }
  
  return $w
}

proc jinstall:mkentry { w prompt var default help } {
  global jinstall
  if ![info exists jinstall($var)] {set jinstall($var) $default}
  
  frame $w
  label $w.l \
    -anchor e \
    -width 30 \
    -text $prompt
  entry $w.e \
    -width 40 \
    -borderwidth 2p \
    -relief sunken \
    -textvariable jinstall($var)
  button $w.b \
    -text Help \
    -command [list jinstall:show_help $help]
  
  pack $w.l -side left
  pack $w.e -side left -fill x
  pack $w.b -side right -padx 8p -pady 2p
  
  return $w
}

proc jinstall:mkcheckbox { w prompt var default help } {
  global jinstall
  if ![info exists jinstall($var)] {set jinstall($var) $default}
  
  frame $w
  label $w.l \
    -anchor e \
    -width 30 \
    -text $prompt
  checkbutton $w.cb \
    -text Yes \
    -relief flat \
    -variable jinstall($var)
  button $w.b \
    -text Help \
    -command [list jinstall:show_help $help]
  
  pack $w.l -side left
  pack $w.cb -side left -fill x
  pack $w.b -side right -padx 8p -pady 2p
  
  return $w
}

proc jinstall:tab_ring { args } {
  # index of last widget
  set last [expr {[llength $args] - 1}]
  
  for {set i 0} {$i < $last} {incr i} {
    set this [lindex $args $i]
    set next [lindex $args [expr {$i + 1}]]
    bind $this <Tab> "focus $next"
    bind $next <Shift-Tab> "focus $this"
  }
  
  # ... and bind last to focus on first:
  set this [lindex $args $last]
  set next [lindex $args 0]
  bind $this <Tab> "focus $next"
  bind $next <Shift-Tab> "focus $this"
}

proc jinstall:log { string } {
  if 0 {
    puts stderr $string
  }
}

proc jinstall:read { filename } {
  set file [open $filename r]
  set string [read $file]
  close $file
  return $string
}

proc jinstall:mkdir { directory } {
  if ![file exists $directory] {
    if [catch [list exec mkdir -p $directory]] {
      jinstall:log "Unable to create directory $directory."
      return 1
    } else {
      jinstall:log "Making directory $directory."
      return 0
    }
  } else {
    if ![file isdirectory $directory] {
      jinstall:log \
        "File $directory exists, but is not a directory - cannot proceed."
      return 1
    } else {
      jinstall:log "Directory $directory already exists."
      return 0
    }
  }
}

proc jinstall:cp-r { file directory } {
  jinstall:log "Installing $file in $directory."
  if [catch [list exec cp -r $file $directory]] {
    jinstall:log "Unable to install $file in $directory."
    return 1
  } else {
    return 0
  }
}

proc jinstall:install_script { script destination {interpreter wish} } {
  global jinstall
  
  jinstall:log "Installing script $script with preamble as $destination."
  
  if [catch {set scriptfile [open $script r]}] {
    jinstall:log "Unable to open $script for reading."
    return 1
  }
  
  set scripttext [read $scriptfile]
  
  # change interpreter name in magic line:
  regsub -- \
    "^#!\[^ \t\n\]*" \
    $scripttext \
    "#!$jinstall($interpreter)" \
    scripttext
  
  # replace preamble:
  set preamble [format $jinstall(preamble) $jinstall(normallib)]
  regsub -- \
    "\n## begin boiler_header\n.*\n## end boiler_header\n" \
    $scripttext \
    $preamble \
    scripttext
  
  if [catch {set outputfile [open $destination w]}] {
    jinstall:log "Unable to open $destination for writing."
    return 1
  }
  
  if [catch {puts $outputfile $scripttext}] {
    jinstall:log "Unable to write to $outputfile."
    return 1
  }
  close $outputfile
  
  if [catch {exec chmod 755 $destination}] {
    jinstall:log "Unable to set permissions on $destination."
    return 1
  }
  
  return 0
}

######################################################################

proc jinstall:cancel {} {
  exit 0
}

proc jinstall:install_jstools {} {
  global jinstall
  jinstall:mkdir $jinstall(normalbin)
  jinstall:mkdir $jinstall(normallib)
  
  foreach file [glob lib/j*] {
    jinstall:cp-r $file $jinstall(normallib)
  }
  jinstall:cp-r lib/samples $jinstall(normallib)
  auto_mkindex $jinstall(normallib) *.tcl
  
  foreach script {jabbrevs jbrowser jdoc jedit jhelp jmore jprefs} {
    jinstall:install_script bin/$script $jinstall(normalbin)/$script
  }
  
  if $jinstall(installtoys) {
    jinstall:mkdir $jinstall(toybin)
    foreach script {jcalendar jhotlist jlaunchpad jmsgs jnewbrowser jpeople } {
      jinstall:install_script w-in-p/$script $jinstall(toybin)/$script
    }
    jinstall:install_script w-in-p/jperson $jinstall(toybin)/jperson
  }
  
  if {[tk_dialog .done \
    "Done" "Installation is complete." info "Quit" \
    "Quit" "Reinstall"] == 0} {
    exit 0
  }
}

######################################################################

jinstall:mkentry .wish \
  {Path to wish:} \
  wish \
  "/usr/local/bin/wish" \
  {
    {This is the full pathname to your wish interpreter, }
    {normally /usr/local/bin/wish.  If you have a choice, }
    {you should specify a Tk 3.6 wish interpreter.}
  }

jinstall:mkentry .normalbin \
  {Directory for production scripts:} \
  normalbin \
  "/usr/local/bin" \
  {
    {This is the pathname to the directory where you want to }
    {install the "production" (i.e., documented and reasonably }
    {robust) scripts, including jabbrevs, jbrowser, jdoc, jedit, }
    {jmore, and jprefs.  This is also where jhelp, which is }
    {obsolete, will be installed.  This is typically /usr/local/bin , }
    {or something like /usr/local/jstools-3.0/bin .}
  }

jinstall:mkentry .normallib \
  {Directory for jstools libraries:} \
  normallib \
  "/usr/local/lib/jstools" \
  {
    {This is the pathname to the directory where you want to }
    {install the jstools libraries.  The Tcl library files will be }
    {installed here, and various other supporting files will be }
    {installed in subdirectories of this directory.  This is typically }
    {/usr/local/lib/jstools , or something like }
    {/usr/local/jstools-3.0/lib .}
  }

jinstall:mkcheckbox .installtoys \
  {Install worksinprogress:} \
  installtoys \
  1 \
  {
    {If this is selected, then the jstools "works in progress" }
    {will be installed - applications that aren't yet quite ready }
    {for production work, as well as "toy" or "demo" applications.}
  }

jinstall:mkentry .toybin \
  {Works-in-progress directory:} \
  toybin \
  "/usr/local/lib/jstools/w-in-p" \
  {
    {This is the pathname to the directory where you want to }
    {install the worksinprogress - unsupported jstools scripts.  }
    {At present that includes jcalendar, jhotlist, jlaunchpad, }
    {jmsgs, jnewbrowser, jpeople, and jperson.  These can be installed in }
    {the same directory as the `production' scripts, but if you do }
    {that, please make sure your users know that they are not as }
    {robust as the documented scripts.}
    "\n\n"
    {The term `Worksinprogress' isn't completely accurate, since }
    {I'm not doing any more work on jcalendar or jmsgs.}
    "\n\n"
    {You can ignore this entry if you're not installing the }
    {worksinprogress.}
  }

jinstall:mkentry .tclsh \
  {Path to tclsh:} \
  tclsh \
  "/usr/local/bin/tclsh" \
  {
    {This is the full pathname of your tclsh interpreter.  }
    {It's only used by jperson, so you can ignore this entry }
    {if you're not installing the worksinprogress.}
  }

pack [frame .topframe -height 5 -relief flat] -fill x
pack .wish -fill x
pack .normalbin -fill x
pack .normallib -fill x
pack .installtoys -fill x
pack .toybin -fill x
pack .tclsh -fill x
pack [frame .bottomframe -height 5 -relief flat] -fill x
pack [frame .rule -relief sunken -height 2 -borderwidth 1] -fill x

jinstall:tab_ring .wish.e .normalbin.e .normallib.e .toybin.e .tclsh.e

######################################################################

frame .b
button .b.install -text Install -width 8 -command jinstall:install_jstools
button .b.cancel -text Cancel -width 8 -command jinstall:cancel

frame .b.spacer -width 5p
pack .b.spacer -side right

pack .b.install .b.cancel -side right -padx 5p -pady 10p
pack .b -fill x

