#!/usr/local/bin/wish -f
# jabbrevs - abbreviation manager for jedit (and vi and Emacs)
# 
# Copyright 1992-1994 by Jay Sekora.  All rights reserved, except 
# that this file may be freely redistributed in whole or in part 
# for non-profit, noncommercial use.

## 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 /usr/local/lib/jstools
}

# 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

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

global HOME env
set HOME $env(HOME)

global ABBREVPREFS
set ABBREVPREFS(filename) "$HOME/.tk/abbrevs.tcl"
set ABBREVPREFS(vi_filename) "$HOME/vi-abbrevs"
set ABBREVPREFS(emacs_filename) "$HOME/.abbrev_defs"

######################################################################
# jabbrevs:init - basic initialisation
######################################################################

proc jabbrevs:init {} {
  global J_PREFS			;# cross-application prefs
  global THIS_ABBREV			;# abbrev being entered
  global THIS_EXPANSION			;# expansion being entered
  
  j:jstools_init			;# prefs, libraries, bindings...
  
  global ABBREVS			;# text-indexed array of expansions
  set ABBREVS(0) {0}			;# to make sure it's an array
}


######################################################################
# jabbrevs:userinit - user customisation
######################################################################

proc jabbrevs:userinit {} {
  global J_PREFS			;# cross-application prefs
  global NAME
  global HOME
  
  # read in user's .tk/jabbrevsrc.tcl
  j:source_config jabbrevsrc.tcl
}

######################################################################
# jabbrevs:apply_prefs
######################################################################

proc jabbrevs:apply_prefs {} {
  global J_PREFS			;# cross-application prefs
  global NAME
  global HOME
  global tk_strictMotif
  
  # set user's text bindings:
  
  switch -exact $J_PREFS(bindings) {
    basic {
      j:eb:basic_bind Entry
    }
    emacs {
      j:eb:emacs_bind Entry
    }
    vi {
      j:eb:vi_bind Entry
    }
  }

  if {$J_PREFS(tk_strictMotif)} {
    set tk_strictMotif 1
  } else {
    set tk_strictMotif 0
  }
}

######################################################################
# abbrev - set an abbreviation (used by .tk/abbrevs.tcl
######################################################################

proc abbrev {{abbrev} {expansion}} {
  global ABBREVS
  
  set ABBREVS($abbrev) $expansion
}

######################################################################
# jabbrevs:mkmenus - make menu bar
######################################################################

proc jabbrevs:mkmenus {} {
  frame .menu -borderwidth 2 -relief raised
  menubutton .menu.abbrevs -text {Abbrevs} -menu .menu.abbrevs.m
  menubutton .menu.file -text {File} -menu .menu.file.m
  
  menu .menu.abbrevs.m
  .menu.abbrevs.m add command -label {Help} -accelerator {[h]} \
    -command {jabbrevs:cmd:help}
  .menu.abbrevs.m add command -label {About the Abbrevs Manager . . .} \
    -command {jabbrevs:cmd:about}
  .menu.abbrevs.m add command -label {Global Preferences . . .} \
    -command {j:global_pref_panel}
  .menu.abbrevs.m add separator
  .menu.abbrevs.m add command -label {Issue Tcl Command . . .} \
    -accelerator {[T]} -command {j:prompt_tcl}
  .menu.abbrevs.m add command -label {Issue Unix Command . . .} \
    -accelerator {[U]} -command {j:prompt_unix}
  .menu.abbrevs.m add separator
  .menu.abbrevs.m add command -label {Quit . . .} -accelerator {[q]} \
    -command {jabbrevs:cmd:quit}
  
  menu .menu.file.m
  .menu.file.m add command -label {Reload} \
    -command jabbrevs:cmd:read
  
  pack .menu.abbrevs .menu.file -side left
  pack .menu -side top -fill x
}

######################################################################
# jabbrevs:mkmain - make main body with fields and buttons
######################################################################

proc jabbrevs:mkmain {} {
  global J_PREFS			;# cross-application prefs
  global THIS_ABBREV			;# abbrev being entered
  global THIS_EXPANSION			;# expansion being entered
  
  frame .main
  frame .main.abbrev
  label .main.abbrev.l -width 15 -text "Abbreviation:" -anchor w \
    -relief flat
  entry .main.abbrev.e -width 40 -textvariable THIS_ABBREV \
    -relief sunken -borderwidth 2
  frame .main.expn
  label .main.expn.l -width 15 -text "Expansion:" -anchor w \
    -relief flat
  entry .main.expn.e -width 40 -textvariable THIS_EXPANSION \
    -relief sunken -borderwidth 2
  
  pack .main.abbrev.l .main.abbrev.e -side left
  pack .main.expn.l .main.expn.e -side left
  pack \
    [j:filler .main]\
    .main.abbrev \
    [j:filler .main] \
    .main.expn \
    [j:filler .main] \
    -side top -fill x
  
  j:buttonbar .b -default add -buttons {
    {
      add Add {jabbrevs:cmd:add}
    }
    {
      delete Delete {jabbrevs:cmd:delete}
    }
    {
      write Write {jabbrevs:cmd:write}
    }
    {
      quit Quit {exit 0}
    }
  }
  
  j:default_button .b.add .main.abbrev.e .main.expn.e
  j:cancel_button .b.quit .main.abbrev.e .main.expn.e
  j:tab_ring .main.abbrev.e .main.expn.e
  
  pack .b [j:rule .] -side bottom -fill x
  pack [j:filler .] .main [j:filler .] -side left -fill y
  
  focus .main.abbrev.e
  catch {focus default .main.abbrev.e}	;# caught for Tk 4.0
}

######################################################################
####
#    OUTPUT PROCEDURES
####
######################################################################

proc jabbrevs:write_native {} {
  global ABBREVS THIS_ABBREV THIS_EXPANSION ABBREVPREFS
  
  set file [open $ABBREVPREFS(filename) w]
  
  foreach abbrev [lsort [array names ABBREVS]] {
    puts $file "abbrev [list $abbrev] [list $ABBREVS($abbrev)]"
  }
  
  close $file
  return 0
}

### THIS DOESN'T WORK YET
### 
proc jabbrevs:write_emacs {} {
  global ABBREVS THIS_ABBREV THIS_EXPANSION ABBREVPREFS
  
  set file [open $ABBREVPREFS(emacs_filename) w]
  
  puts $file {(define-abbrev-table 'c-mode-abbrev-table '( ))}
  puts $file {(define-abbrev-table 'text-mode-abbrev-table '(}
  foreach abbrev [lsort [array names ABBREVS]] {
    if {! [regexp -- {"} $abbrev] && ! [regexp -- {"} $ABBREVS($abbrev)]} {
      puts $file [format \
        {    ("%s" "%s" nil 0)} \
        $abbrev $ABBREVS($abbrev)]
    }
  }
  puts $file {    ))}
  puts $file {(define-abbrev-table 'lisp-mode-abbrev-table '( ))}
  puts $file {(define-abbrev-table 'fundamental-mode-abbrev-table '( ))}
  puts $file {(define-abbrev-table 'global-abbrev-table '( ))}
  
  close $file
  return 0
}

proc jabbrevs:write_vi {} {
  global ABBREVS THIS_ABBREV THIS_EXPANSION ABBREVPREFS
  
  set file [open $ABBREVPREFS(vi_filename) w]
  
  foreach abbrev [lsort [array names ABBREVS]] {
    puts $file "ab $abbrev $ABBREVS($abbrev)"
  }
  
  close $file
  return 0
}

######################################################################
####
#    COMMAND PROCEDURES
####
######################################################################

proc jabbrevs:cmd:about {} {
  global VERSION
  set about_jabbrevs [format {
    j:rt:hl "jabbrevs"
    j:rt:cr
    j:rt:rm "by Jay Sekora, "
    j:rt:tt "js@bu.edu"
    j:rt:par
    j:rt:rm "An X Windows tool for managing abbreviations."
    j:rt:cr
    j:rt:rm "Version %s."
    j:rt:par
    j:rt:rm "Copyright \251 1994 by Jay Sekora.  "
    j:rt:rm "All rights reserved, except that this file may be freely "
    j:rt:rm "redistributed in whole or in part for non\255profit, "
    j:rt:rm "noncommercial use."
    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."
  } $VERSION]
  j:about .about $about_jabbrevs
  j:about:button .about {About jabbrevs} $about_jabbrevs
  j:about:button .about {About the Author} [j:about_jay]
  j:about:button .about {About Tk and Tcl} [j:about_tktcl]
  
  tkwait window .about
}

proc jabbrevs:cmd:help {} {
  exec jdoc jabbrevs &
  return 0
}

proc jabbrevs:cmd:quit {} {
  if [j:confirm -text "Are you sure you want to quit?"] {
    exit 0
  }
  return 0
}

proc jabbrevs:cmd:add {} {
  global ABBREVS THIS_ABBREV THIS_EXPANSION
  
  set THIS_ABBREV [string trim $THIS_ABBREV]
  
  set THIS_EXPANSION [string trim $THIS_EXPANSION]
  
  if {"x$THIS_ABBREV" == "x"} {
    j:alert -text "No abbreviation specified."
    focus .main.abbrev.e
    return 1
  }
  
  if {"x$THIS_EXPANSION" == "x"} {
    if {[lsearch -exact [array names ABBREVS] $THIS_ABBREV] != -1} {
      set THIS_EXPANSION $ABBREVS($THIS_ABBREV)
      focus .main.expn.e
      return 0
    } else {
      j:alert -text \
        "No expansion given, and no abbreviation `$THIS_ABBREV' is defined."
    }
    focus .main.abbrev.e
    return 1
  }
  
  set ABBREVS($THIS_ABBREV) $THIS_EXPANSION
  set THIS_ABBREV {}
  set THIS_EXPANSION {}
  focus .main.abbrev.e
  return 0
}

proc jabbrevs:cmd:delete {} {
  global ABBREVS THIS_ABBREV THIS_EXPANSION
  
  set THIS_ABBREV [string trim $THIS_ABBREV]
  
  if {"x$THIS_ABBREV" == "x"} {
    j:alert -text "No abbreviation specified."
    focus .main.abbrev.e
    return 1
  }
  
  if {"x$THIS_EXPANSION" == "x"} {
    j:alert -text "No expansion specified."
    focus .main.abbrev.e
    return 1
  }
  
  unset ABBREVS($THIS_ABBREV)
  set THIS_ABBREV {}
  set THIS_EXPANSION {}
  focus .main.abbrev.e
  return 0
}

proc jabbrevs:cmd:read {} {
  global ABBREVS ABBREVPREFS
  
  catch {unset ABBREVS}
  set ABBREVS(0) {0}
  
  if [file exists $ABBREVPREFS(filename)] {
    uplevel #0 {catch {source $ABBREVPREFS(filename)}}
  }
  
  catch {focus .main.abbrev.e}
  return 0
}

proc jabbrevs:cmd:write {} {
  jabbrevs:write_native
#  jabbrevs:write_emacs
#  jabbrevs:write_vi
  
  # tell all the jedit applications to re-read the abbrevs file:
  foreach interp [winfo interps] {
    switch -glob -- $interp {
      {jedit} -
      {jedit #*} {
        catch {send $interp {after 1 jedit:cmd:read_abbrevs}}
      }
    }
  }
  
  focus .main.abbrev.e
  return 0
}

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

jabbrevs:init
jabbrevs:userinit

jabbrevs:mkmenus
jabbrevs:mkmain

jabbrevs:cmd:read

jabbrevs:apply_prefs

