# eev/libeeg/k - a library for eeg4.
# By edrx, 2001nov26.
# Htmlized version: <http://angg.twu.net/eev/libeeg/k.html>.
# This file defines the "k" function and its friends, for e-scripts
# that need to send individual key sequences.
#
# The functions related to terminal-dependent key sequences are in
# another file:
# (find-angg "eev/libeeg/term")
#
# In the names of variables and functions in this file a "ks" is a
# human-readable list of names of keys, and a "str" is a sequence of
# characters, possibly depending on $TERM, that we intend to `send' to
# the program being controlled.



#####
#
# defkeys  (to ".defkeys")
#
#####

# This block is for the key definitions that are independent of the
# terminal type. The $TERM-dependent part is in another library
# ("term").

# We keep two arrays for reverse key lookups: prefixtable and
# keyseqtable. The functions that use them are in the next section.

proc defkey {keyname keyseq} {
  global K
  set K($keyname) $keyseq
  #
  # The rest is to prepare for reverse key lookups...
  global keyseqtable prefixtable
  set keyseqtable($keyseq) $keyname
  for {set i 0} {$i<[string length $keyseq]-1} {incr i} {
    set prefixtable([string range $keyseq 0 $i]) yes
  }
}
proc defkey+meta {keyname n} {
  upvar defkey defkey
  $defkey $keyname [char $n]
  $defkey M-$keyname "\033[char $n]"
}
proc defkeys {{defkey defkey}} {
  for {set i 0} {$i<=255} {incr i} {
    defkey+meta [char $i] $i
  }
  for {set i 0} {$i<=31} {incr i} {
    set C [char [expr $i+64]]
    set c [char [expr $i+96]]
    set byte [char $i]
    $defkey  ^$C $byte
    $defkey C-$C $byte
    # if {$c>="a" && $c<="z"} {...}
    defkey+meta C-$c $i
  }
  foreach {keyname n} {spc 32 cr 13 enter 13 ret 13 esc 27 nl 10 tab 9} {
    defkey+meta $keyname $n
  }
  defkey C-spc "\000"
}

# bsp 8 del 127?

# We run the "defkeys" functions right now to set the key table.

defkeys




#####
#
# k  (to ".k")
#
#####

proc k1tostr {kstr} {
  global K
  # Hack: if kstr starts with a space return the rest of it.
  if {[string index $kstr 0]==" " && $kstr!=" "} {
    return [string range $kstr 1 end]
  }
  return $K($kstr)
}
proc kstostr {list} {
  set str {}
  foreach kstr $list { append str [k1tostr $kstr] }
  return $str
}

proc _k {list} { send [kstostr $list] }
proc k {args} { appendaction [list _k $args] }




#####
#
# rev_key_lookups  (to ".rev_key_lookups")
#
#####

# Functions to take a string made of a series of characters sent to
# the controlled program and convert it to a series of names of keys
# that correspond to those characters; for example, "\001 ab\033b" ->
# "C-a spc a b M-b".

proc isprefix {str} { global prefixtable; info exists prefixtable($str) }
proc isnamedkeyseq {str} { global keyseqtable; info exists keyseqtable($str) }
proc strposlen2str {str pos len} { string range $str $pos [expr $pos+$len-1] }
proc maxnamedkeyseqlen {str pos} {
  set len 1
  while {$pos+$len<[string length $str]} {
    set substr [strposlen2str $str $pos $len]
    if {![isprefix $substr]} { break }
    incr len
  }
  # now len is such that [strposlen2str $str $pos $len] is either
  # everything up to the end of str or the shortest string that is not
  # a prefix.
  while {$len>1} {
    set substr [strposlen2str $str $pos $len]
    if {[isnamedkeyseq $substr]} { break }
    incr len -1
  }
  return $len
}
proc strtoks {str} {
  global keyseqtable
  set names {}
  set pos 0
  while {$pos<[string length $str]} {
    set len [maxnamedkeyseqlen $str $pos]
    lappend names $keyseqtable([strposlen2str $str $pos $len])
    incr pos $len
  }
  return $names
}



#
#  Local Variables:
#  mode:		 tcl
#  coding:               no-conversion
#  ee-anchor-format:     "%s"
#  ee-charset-indicator: ""
#  End:
