# jbindtext.tcl - support for Text bindings
#
######################################################################
# 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.     #
######################################################################

######################################################################
######################################################################
# NOTE : this library is heavily dependent on jtext.tcl as a wrapper
# around the widget commands
######################################################################
######################################################################


######################################################################
# j:selection_if_any - return selection if it exists, else {}
#   this is from kjx@comp.vuw.ac.nz (R. James Noble)
#   defined elsewhere, but copied here so the bindings libraries
#   don't depend on jtkutils
######################################################################

if {[info procs j:selection_if_any] == {}} {
  proc j:selection_if_any {} {
    if {[catch {selection get} s]} {return ""} {return $s}
  }
}

######################################################################
####
###  GENERAL BINDING ROUTINES
####
######################################################################

######################################################################
# j:tb:init - initialise info for bindings
######################################################################

proc j:tb:init { {t Text} } {
  global J_PREFS env
  if {! [info exists J_PREFS(typeover)]} {set J_PREFS(typeover) 1}
  switch -exact $J_PREFS(bindings) {
    basic {
      j:tb:basic_init $t
    }
    emacs {
      j:tb:emacs_init $t
    }
    edt {
      j:tb:edt_init $t
    }
    vi {
      j:tb:vi_init $t
    }
  }

  # read in user's supplementary text bindings
  j:source_config textbindings.tcl
}

######################################################################
# j:tb:no_op - do nothing
######################################################################

proc j:tb:no_op { args } {
  return 0
}

######################################################################
# j:tb:beep W - beep
######################################################################

proc j:tb:beep { W args } {
  j:beep $W
  return 0
}

######################################################################
# j:tb:move W index - move, possibly clearing selection and resetting state
######################################################################

proc j:tb:move { W index } {
  global J_PREFS
  
  if $J_PREFS(typeover) {
    # clear current selection:
    $W tag remove sel 1.0 end
  }
  j:text:move $W $index
}

######################################################################
# j:tb:clear_selection W - clear the selection in widget W
######################################################################

proc j:tb:clear_selection { W args } {
  $W tag remove sel 1.0 end
}

######################################################################
# j:tb:select_all W - select all text in widget W
######################################################################

proc j:tb:select_all { W args } {
  $W tag add sel 1.0 end
}

######################################################################
# j:tb:is_bol W - return true if insert is at beginning of line
#   from Achim Bohnet <ach@rosat.mpe-garching.mpg.de>
######################################################################

proc j:tb:is_bol { W } {
  return [$W compare insert == "insert linestart"]
}

######################################################################
# j:tb:is_eol W - return true if insert is at end of line
#   from Achim Bohnet <ach@rosat.mpe-garching.mpg.de>
######################################################################

proc j:tb:is_eol { W } {
  return [$W compare insert == "insert lineend"]
}

######################################################################
# j:tb:is_first_line W - return true if insert is on top line
######################################################################

proc j:tb:is_first_line { W } {
  return [$W compare "insert linestart" == 1.0]
}

######################################################################
# j:tb:is_last_line W - return true if insert is on last line
######################################################################

proc j:tb:is_last_line { W } {
  return [$W compare "insert lineend" == end]
}

######################################################################
######################################################################
# ROUTINES TO SET UP TEXT BINDINGS
######################################################################
######################################################################

# j:tb:key_bind W - set up bindings to process keys
proc j:tb:key_bind { W args } {
  # get rid of a few default Tk bindings:
  
  j:tk3 {
    foreach binding  {
      <Control-Key-v> <Control-Key-d> <Control-Key-h> <Any-Key>
      <Key-Delete> <Key-BackSpace> <Key-Return>
    } {
      bind $W $binding {}
    }
  }
  j:tk4 {
    foreach binding {
      <Enter> <FocusIn>
    } {
      bind $W $binding {}
    }
    foreach binding {
      <Left>
      <Right>
      <Up>
      <Down>
      <Shift-Left>
      <Shift-Right>
      <Shift-Up>
      <Shift-Down>
      <Prior>
      <Shift-Prior>
      <Next>
      <Shift-Next>
      <Home>
      <Shift-Home>
      <End>
      <Shift-End>
      <Tab>
      <Shift-Tab>
      <Return>
      <Delete>
      <BackSpace>
      <Select>
      <Shift-Select>
      <Insert>
      <KeyPress>
      <Shift-KeyPress>
      <Escape>
    } {
      bind $W $binding {
        j:tkb:process_key %W "" %K %A
        break
      }
    }
    #
    # note that <Control-Tab> and <Control-Shift-Tab> are NOT rebound!
    #
    foreach binding {
      <Control-Left>
      <Control-Right>
      <Control-Up>
      <Control-Down>
      <Shift-Control-Left>
      <Shift-Control-Right>
      <Shift-Control-Up>
      <Shift-Control-Down>
      <Control-Prior>
      <Control-Next>
      <Control-Home>
      <Control-Shift-Home>
      <Control-End>
      <Control-Shift-End>
      <Control-i>
      <Control-space>
      <Control-Shift-space>
      <Control-slash>
      <Control-backslash>
      <Control-a>
      <Control-b>
      <Control-d>
      <Control-e>
      <Control-f>
      <Control-k>
      <Control-n>
      <Control-o>
      <Control-p>
      <Control-t>
      <Control-w>
      <Control-h>
      <Control-v>
      <Control-y>
      <Control-Key> <Control-Shift-Key>
    } {
      bind $W $binding {
        j:tkb:process_key %W Control %K %A
        break
      }
    }
    foreach binding {
      <Meta-b>
      <Meta-d>
      <Meta-f>
      <Meta-w>
      <Alt-w>
      <Meta-y>
      <Alt-y>
      <Meta-less>
      <Meta-greater>
      <Meta-BackSpace>
      
      <Alt-KeyPress> <Meta-KeyPress>
      <Meta-Shift-KeyPress> <Alt-Shift-KeyPress>
    } {
      bind $W $binding { }
    }
  }
  
  # and create null bindings for modifiers, so they don't trigger commands:
  foreach binding {
    <Shift_L> <Shift_R> <Control_L> <Control_R> <Caps_Lock>
    <Shift_Lock> <Meta_L> <Meta_R> <Alt_L> <Alt_R>
  } {
    bind $W $binding { }
  }
  j:tk3 {
    bind $W <Key>		{j:tkb:process_key %W "" %K %A}
    bind $W <Shift-Key>		{j:tkb:process_key %W "" %K %A}
    bind $W <Control-Key>	{j:tkb:process_key %W Control %K %A}
  }
  
  # Compose (Multi_key) key support:
  bind $W <Multi_key>		{# nothing}
  bind $W <Multi_key><Any-Key>	{j:tc:start_sequence %W %K %A}
  bind $W <Multi_key><Any-Key><Any-Key> \
  				{j:tc:finish_sequence %W %K %A}
  bind $W <Multi_key><Any-KeyRelease><Any-Key> \
    				{j:tc:start_sequence %W %K %A}
  bind $W <Multi_key><Any-Key><Any-Key> \
  				{j:tc:finish_sequence %W %K %A}
  bind $W <Multi_key><Any-Key><Any-KeyRelease><Any-Key> \
  				{j:tc:finish_sequence %W %K %A}
  bind $W <Multi_key><Any-KeyRelease><Any-Key><Any-KeyRelease><Any-Key> \
  				{j:tc:finish_sequence %W %K %A}

}






