#!/usr/local/bin/wish4.0
# jabbrevs - abbreviation manager for jedit (and vi and Emacs)
#
# 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.
## begin boiler_header

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

j:ldb:set_defaults {
  {Abbrevs Abbrevs 0}
  {File File 0}
  {Help Help 0}
  {{Help on jabbrevs} {Help on jabbrevs} 0}
  {{Help on Using Abbreviations in jedit}
    {Help on Using Abbreviations in jedit} 8}
  {{Help on jstools} {Help on jstools} 10}

  {jabbrevs:cmd:about {About the Abbrevs Manager...} 0 <Meta-Key-A> {[h]}}
  {jabbrevs:cmd:help {Help} 0 <Meta-Key-h> {[H]}}
  {jabbrevs:cmd:quit {Quit} 0 <Meta-Key-q> {[q]}}
  {jabbrevs:cmd:add {Add}}
  {jabbrevs:cmd:delete {Delete}}
  {jabbrevs:cmd:reload {Reload} 2 <Meta-Key-l> {[l]}}
  {jabbrevs:cmd:save {Save} 0 <Meta-Key-s> {[s]}}
}

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

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 jabbrevs		;# 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 { mb w } {
  frame $mb -borderwidth 2 -relief raised
  
  j:menu:menubutton $mb.abbrevs $mb.abbrevs.m Abbrevs
  j:menu:commands $mb.abbrevs.m $w {
    jabbrevs:cmd:about
    j:cmd:global_pref_panel
    -
    j:cmd:prompt_tcl
    j:cmd:prompt_unix
  }
  
  j:menu:menubutton $mb.file $mb.file.m File
  j:menu:commands $mb.file.m $w {
    jabbrevs:cmd:reload
    jabbrevs:cmd:save
    -
    jabbrevs:cmd:quit
  }
  
  j:menu:menubutton $mb.help $mb.help.m Help
  j:menu:docs $mb.help.m {
    {{Help on jabbrevs} {jabbrevs.jdoc}}
    {{Help on Using Abbreviations in jedit} {jedit.jdoc#Abbreviations}}
    -
    {{Help on jstools} {jstools.jdoc}}
  }
  
  pack $mb.abbrevs $mb.file -side left
  pack $mb.help -side right
  pack $mb -side top -fill x
  
  tk_menuBar $mb $mb.abbrevs $mb.file $mb.help
}

######################################################################
# 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
  frame .main.expn
  label .main.expn.l -width 15 -text "Expansion:" -anchor w \
    -relief flat
  entry .main.expn.e -width 40 -textvariable THIS_EXPANSION
  
  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:command:buttonbar .b . {
    jabbrevs:cmd:add
    jabbrevs:cmd:delete
    jabbrevs:cmd:save
    jabbrevs:cmd:quit
  } -default jabbrevs:cmd:add
  j:default_button .b.jabbrevs:cmd:add .main.abbrev.e .main.expn.e
  j:cancel_button .b.jabbrevs:cmd: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
####
######################################################################

j:command:register jabbrevs:cmd:about {About the Abbrevs Manager...}
proc jabbrevs:cmd:about { w args } {
  global JSTOOLS_VERSION
  set about_jabbrevs [format {
    j:rt:hl "jabbrevs"
    j:rt:cr
    j:rt:rm "by Jay Sekora, "
    j:rt:tt "js@calumet.org"
    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-1995 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."
  } $JSTOOLS_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
}

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

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

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

j:command:register jabbrevs:cmd:add {Add}
proc jabbrevs:cmd:add { w args } {
  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
}

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

j:command:register jabbrevs:cmd:delete {Delete}
proc jabbrevs:cmd:delete { w args } {
  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
}

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

j:command:register jabbrevs:cmd:reload {Reload}
proc jabbrevs:cmd:reload { w args } {
  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
}

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

j:command:register jabbrevs:cmd:save {Save}
proc jabbrevs:cmd:save { w args } {
  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 .menu .
jabbrevs:mkmain

tk_bindForTraversal all
j:command:bind all . [j:command:list]

jabbrevs:cmd:reload .

jabbrevs:apply_prefs







