home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 3 / CD ACTUAL 3.iso / linux / incoming / jstools-.6v3 / jstools- / jstools-tk3.6v3.0 / lib / jtextkeys.tcl < prev    next >
Encoding:
Text File  |  1995-02-09  |  12.5 KB  |  436 lines

  1. # jtextkeys.tcl - support for Text keyboard bindings
  2. # Copyright 1992-1994 by Jay Sekora.  All rights reserved, except 
  3. # that this file may be freely redistributed in whole or in part 
  4. # for non-profit, noncommercial use.
  5.   
  6. ######################################################################
  7. # j:tkb:mkmap w map next {{key command ?args?}...} - set up pseudo-binding
  8. #   Note that key includes modifier
  9. ######################################################################
  10.  
  11. proc j:tkb:mkmap { w map next bindings } {
  12.   global j_teb
  13.   
  14.   set j_teb(tkm_next,$w,$map) $next
  15.   foreach list $bindings {
  16.     set key [lindex $list 0]
  17.     set command [lreplace $list 0 0]
  18.     
  19.     set j_teb(tkm,$w,$map,$key) $command
  20.   }
  21. }
  22.  
  23. ######################################################################
  24. # j:tkb:process_key W mod K A - process keystrokes
  25. ######################################################################
  26.  
  27. proc j:tkb:process_key {W mod K A} {
  28.   global j_teb
  29.   
  30.   set j_teb(next_keymap,$W) ""        ;# some bindings change this
  31.   
  32.   if {"x$mod" != "x"} {
  33.     set K "$mod-$K"
  34.     set default "$mod-DEFAULT"
  35.   } else {
  36.     set default "DEFAULT"
  37.   }
  38.   
  39.   # if this widget hasn't been used before, set its keymap from default
  40.   if {! [info exists j_teb(keymap,$W)]} {
  41.     set j_teb(keymap,$W) $j_teb(keymap,Text)
  42.   }
  43.   # if no last command, set it to {}
  44.   if {! [info exists j_teb(last_command,$W)]} {
  45.     set j_teb(last_command,$W) {}
  46.   }
  47.   set map $j_teb(keymap,$W)
  48.  
  49.   if [info exists j_teb(tkm,$W,$map,$K)] {
  50.     # specific action for this widget
  51.     set command $j_teb(tkm,$W,$map,$K)
  52.     eval $command [list $W $K $A]
  53.   } else {
  54.     if [info exists j_teb(tkm,Text,$map,$K)] {
  55.       # specific binding for all Text widgets
  56.       set command $j_teb(tkm,Text,$map,$K)
  57.       eval $command [list $W $K $A]
  58.     } else {
  59.       if [info exists j_teb(tkm,$W,$map,$default)] {
  60.         # default key action for this widget
  61.         set command $j_teb(tkm,$W,$map,$default)
  62.         eval $command [list $W $K $A]
  63.       } else {
  64.         # default key action for Text widgets
  65.         set command $j_teb(tkm,Text,$map,$default)
  66.         eval $command [list $W $K $A]
  67.       }
  68.     }
  69.   }
  70.   set j_teb(last_command,$W) $command
  71.   
  72.   # if a binding hasn't explicitly chosen a different keymap for the next
  73.   #   key, switch to the default next keymap for this keymap:
  74.   if {"x$j_teb(next_keymap,$W)" == "x"} {
  75.     if [info exists j_teb(tkm_next,$W,$map)] {
  76.       set j_teb(next_keymap,$W) $j_teb(tkm_next,$W,$map)
  77.     } else {
  78.       set j_teb(next_keymap,$W) $j_teb(tkm_next,Text,$map)
  79.     }
  80.   }
  81.   set j_teb(keymap,$W) $j_teb(next_keymap,$W)
  82. }
  83.  
  84. ######################################################################
  85. # j:tkb:new_mode mode W K A - change modes
  86. ######################################################################
  87.  
  88. proc j:tkb:new_mode { mode W K A } {
  89.   global j_teb
  90.   set j_teb(next_keymap,$W) $mode
  91. }
  92.  
  93. ######################################################################
  94. # j:tkb:repeatable tclcode W - execute tclcode one or more times
  95. ######################################################################
  96.  
  97. proc j:tkb:repeatable { tclcode W args } {
  98.   global j_teb
  99.   
  100.   # set up prefix/repeat information if this widget hasn't been used yet
  101.   if {! [info exists j_teb(prefix,$W)]} {
  102.     set j_teb(prefix,$W) 0
  103.   }
  104.   if {! [info exists j_teb(repeat_count,$W)]} {
  105.     set j_teb(repeat_count,$W) 1
  106.   }
  107.  
  108.   # special-case prefix == 1 and repeat_count == 0 for Emacs ^U:
  109.   #
  110.   if {$j_teb(prefix,$W) == 1 && $j_teb(repeat_count,$W) == 0} {
  111.     set j_teb(repeat_count,$W) 4
  112.   }
  113.   
  114.   set j_teb(prefix,$W) 0            ;# no longer collectig digits
  115.   for {set jri 0} {$jri < $j_teb(repeat_count,$W)} {incr jri} {
  116.     uplevel 1 "eval [list $tclcode]"        ;# variables in caller
  117.   }
  118.   set j_teb(repeat_count,$W) 1
  119. }
  120.  
  121. ######################################################################
  122. # j:tkb:clear_count W - clear argument count
  123. ######################################################################
  124.  
  125. proc j:tkb:clear_count { W args } {
  126.   global j_teb
  127.  
  128.   # set up prefix/repeat information if this widget hasn't been used yet
  129.   if {! [info exists j_teb(prefix,$W)]} {
  130.     set j_teb(prefix,$W) 0
  131.   }
  132.   if {! [info exists j_teb(repeat_count,$W)]} {
  133.     set j_teb(repeat_count,$W) 1
  134.   }
  135.  
  136.   set j_teb(repeat_count,$W) 1
  137.   set j_teb(prefix,$W) 0
  138. }
  139.  
  140. ######################################################################
  141. # j:tkb:start_number W K digit - start a numeric argument
  142. #   invalid if not bound to (a sequence ending in) a digit key
  143. ######################################################################
  144.  
  145. proc j:tkb:start_number { W K digit } {
  146.   global j_teb
  147.   
  148.   # set up prefix/repeat information if this widget hasn't been used yet
  149.   if {! [info exists j_teb(prefix,$W)]} {
  150.     set j_teb(prefix,$W) 0
  151.   }
  152.   if {! [info exists j_teb(repeat_count,$W)]} {
  153.     set j_teb(prefix,$W) 1
  154.   }
  155.  
  156.   set j_teb(prefix,$W) 1            ;# collecting # prefix
  157.   set j_teb(repeat_count,$W) [expr "$digit"]
  158. }
  159.  
  160. ######################################################################
  161. # j:tkb:continue_number digit - continue a numeric argument
  162. #   invalid if not bound to a digit key
  163. ######################################################################
  164.  
  165. proc j:tkb:continue_number { W K digit } {
  166.   global j_teb
  167.   
  168.   # set up prefix/repeat information if this widget hasn't been used yet
  169.   if {! [info exists j_teb(prefix,$W)]} {
  170.     set j_teb(prefix,$W) 0
  171.   }
  172.   if {! [info exists j_teb(repeat_count,$W)]} {
  173.     set j_teb(prefix,$W) 1
  174.   }
  175.  
  176.   if {! $j_teb(prefix,$W)} {        ;# (can start as well as continue)
  177.     set j_teb(prefix,$W) 1    
  178.     set j_teb(repeat_count,$W) 0
  179.   }
  180.   set j_teb(repeat_count,$W) [expr {($j_teb(repeat_count,$W)*10)+$digit}]
  181. }
  182.  
  183. ######################################################################
  184. # j:tkb:paste_selection W - insert X selection into W
  185. ######################################################################
  186.  
  187. # j:tkb:paste_selection W - insert selection into W
  188. #  (could also be used as mouse or key binding)
  189. proc j:tkb:paste_selection { W K A } {
  190.   set selection [j:selection_if_any]
  191.   
  192.   if {[string length $selection] != 0} {
  193.     j:text:insert_string $W $selection
  194.   }
  195. }
  196.  
  197. ######################################################################
  198. ###  TEXT SCROLLING COMMANDS - fragile - assume widget has a scrollbar
  199. ######################################################################
  200. # fragile---assumes first word of yscrollcommand is name of scrollbar!
  201. # should catch case of no yscrollcommand!
  202. # ALSO---should handle arguments (scroll by line rather than windowful)
  203.  
  204. proc j:tkb:scroll_down { W K A } {
  205.   global j_teb
  206.   j:tkb:clear_count $W
  207.   
  208.   set yscrollcommand [lindex [$W configure -yscrollcommand] 4]
  209.   set scrollbar [lindex $yscrollcommand 0]    ;# cross fingers and hope!
  210.   
  211.   j:tb:move $W "[lindex [$scrollbar get] 3].0"
  212.   $W yview insert                ;# this is essential!
  213. }
  214.  
  215. proc j:tkb:scroll_up { W K A } {
  216.   global j_teb
  217.   j:tkb:clear_count $W
  218.   
  219.    set yscrollcommand [lindex [$W configure -yscrollcommand] 4]
  220.    set scrollbar [lindex $yscrollcommand 0]    ;# cross fingers and hope!
  221.  
  222.    set currentstate [$scrollbar get]
  223.    # following is buggy if lines wrap:
  224.    set newlinepos [expr {[lindex $currentstate 2] - [lindex $currentstate 1]}]
  225.    j:tb:move $W "$newlinepos.0-2lines"
  226.    $W yview insert
  227. }
  228.  
  229.  
  230.  
  231. ######################################################################
  232. ### INSERTION COMMANDS
  233. ######################################################################
  234.  
  235. ######################################################################
  236. # j:tkb:insert_newline W K A - insert "\n" into W, clear arg flag
  237. ######################################################################
  238.  
  239. proc j:tkb:insert_newline { W K A } {
  240.   global j_teb
  241.  
  242.   j:tkb:repeatable {
  243.     j:text:insert_string $W "\n"
  244.   } $W
  245. }
  246.  
  247. ######################################################################
  248. # j:tkb:self_insert W K A - insert A into text widget W, clear arg flag
  249. ### (was j:tb:self_insert_nondigit
  250. ######################################################################
  251.  
  252. proc j:tkb:self_insert { W K A } {
  253.   global j_teb
  254.  
  255.   if {"x$A" != "x"} {
  256.     j:tkb:repeatable {
  257.       j:text:insert_string $W $A
  258.     } $W
  259.   }
  260. }
  261.  
  262. ######################################################################
  263. # j:tkb:self_insert_digit W K A - insert digit A into W, unless collecting arg
  264. ######################################################################
  265.  
  266. proc j:tkb:self_insert_digit { W K A } {
  267.   global j_teb
  268.     
  269.   # set up prefix/repeat information if this widget hasn't been used yet
  270.   if {! [info exists j_teb(prefix,$W)]} {
  271.     set j_teb(prefix,$W) 0
  272.   }
  273.  
  274.   if $j_teb(prefix,$W) {
  275.     j:tkb:continue_number $W $K $A
  276.     return 0
  277.   } else {
  278.     if {"x$A" != "x"} {
  279.       j:tkb:repeatable {
  280.         j:text:insert_string $W $A
  281.       } $W
  282.     }
  283.   }
  284. }
  285.  
  286. ######################################################################
  287. ###  TEXT MOVEMENT COMMANDS
  288. ######################################################################
  289.  
  290. # j:tkb:bol W K A - move to start of line (ignores count)
  291. proc j:tkb:bol { W K A } {
  292.   j:tkb:repeatable {j:tb:move $W {insert linestart}} $W
  293. }
  294.  
  295. # j:tkb:eol W K A - move to end of line (ignores count)
  296. proc j:tkb:eol { W K A } {
  297.   j:tkb:repeatable {j:tb:move $W {insert lineend}} $W
  298. }
  299.  
  300. # j:tkb:up W K A - move up
  301. proc j:tkb:up { W K A } {
  302.   j:tkb:repeatable {j:tb:move $W {insert - 1 line}} $W
  303. }
  304.  
  305. # j:tkb:down W K A - move down
  306. proc j:tkb:down { W K A } {
  307.   j:tkb:repeatable {j:tb:move $W {insert + 1 line}} $W
  308. }
  309.  
  310. # j:tkb:left W K A - move left
  311. proc j:tkb:left { W K A } {
  312.   j:tkb:repeatable {j:tb:move $W {insert - 1 char}} $W
  313. }
  314.  
  315. # j:tkb:right W K A - move right
  316. proc j:tkb:right { W K A } {
  317.   j:tkb:repeatable {j:tb:move $W {insert + 1 char}} $W
  318. }
  319.  
  320. # j:tkb:bof W K A - move to beginning of file (widget)
  321. proc j:tkb:bof { W K A } {
  322.   j:tkb:repeatable {
  323.     j:tb:move $W 0.0
  324.   } $W
  325. }
  326.  
  327. # j:tkb:eof W K A - move to end of file (widget)
  328. proc j:tkb:eof { W K A } {
  329.   j:tkb:repeatable {
  330.     j:tb:move $W end
  331.   } $W
  332. }
  333.  
  334. # j:tkb:word_left W K A - move back one word
  335. proc j:tkb:word_left { W K A } {
  336.   j:tkb:repeatable {
  337.     while {[$W compare insert != 1.0] &&
  338.            [string match "\[ \t\n\]" [$W get {insert - 1 char}]]} {
  339.       j:tb:move $W {insert - 1 char}
  340.     }
  341.     while {[$W compare insert != 1.0] &&
  342.            ![string match "\[ \t\n\]" [$W get {insert - 1 char}]]} {
  343.       j:tb:move $W {insert - 1 char}
  344.     }
  345.   } $W
  346. }
  347.  
  348. # j:tkb:word_right W K A - move forward one word
  349. proc j:tkb:word_right { W K A } {
  350.   j:tkb:repeatable {
  351.     while {[$W compare insert != end] &&
  352.            [string match "\[ \t\n\]" [$W get insert]]} {
  353.       j:tb:move $W {insert + 1 char}
  354.     }
  355.     while {[$W compare insert != end] &&
  356.            ![string match "\[ \t\n\]" [$W get insert]]} {
  357.       j:tb:move $W {insert + 1 char}
  358.     }
  359.   } $W
  360. }
  361.  
  362. ######################################################################
  363. ###  TEXT DELETION COMMANDS
  364. ######################################################################
  365.  
  366. # j:tkb:delete_right W K A - delete character at insert
  367. proc j:tkb:delete_right { W K A } {
  368.   global J_PREFS
  369.   
  370.   if [$W compare insert != end] {
  371.     global j_teb
  372.     set j_teb(modified,$W) 1
  373.     
  374.     if {[j:text:insert_touches_selection $W] && $J_PREFS(typeover)} {
  375.       j:text:delete $W sel.first sel.last
  376.       j:tkb:clear_count $W
  377.       return 0
  378.     }
  379.     
  380.     set delete_from [$W index insert]
  381.     j:tkb:right $W $K $A    ;# handles repeat count
  382.     set delete_to [$W index insert]
  383.     j:text:delete $W $delete_from $delete_to
  384.   }
  385. }
  386.  
  387. # j:tkb:delete_left W K A - delete character before insert
  388. proc j:tkb:delete_left { W K A } {
  389.   global J_PREFS
  390.   
  391.   if [$W compare insert != 1.0] {
  392.     global j_teb
  393.     set j_teb(modified,$W) 1
  394.     
  395.     if {[j:text:insert_touches_selection $W] && $J_PREFS(typeover)} {
  396.       j:text:delete $W sel.first sel.last
  397.       j:tkb:clear_count $W
  398.       return 0
  399.     }
  400.     
  401.     set delete_to [$W index insert]
  402.     j:tkb:left $W $K $A        ;# handles repeat count
  403.     set delete_from [$W index insert]
  404.     j:text:delete $W $delete_from $delete_to
  405.   }
  406. }
  407.  
  408. #### FOLLOWING TWO NEED TO HANDLE CUTBUFFER!
  409.  
  410. # j:tkb:delete_left_word W K A - move back one word
  411. proc j:tkb:delete_left_word { W K A } {
  412.   if [$W compare insert != 1.0] {
  413.     global j_teb
  414.     set j_teb(modified,$W) 1
  415.   
  416.     set delete_to [$W index insert]
  417.     j:tkb:word_left $W $K $A    ;# handles repeat count
  418.     set delete_from [$W index insert]
  419.     j:text:delete $W $delete_from $delete_to
  420.   }
  421. }
  422.  
  423. # j:tkb:delete_right_word W K A - move forward one word
  424. proc j:tkb:delete_right_word { W K A } {
  425.   if [$W compare insert != end] {
  426.     global j_teb
  427.     set j_teb(modified,$W) 1
  428.   
  429.     set delete_from [$W index insert]
  430.     j:tkb:word_right $W $K $A    ;# handles repeat count
  431.     set delete_to [$W index insert]
  432.     j:text:delete $W $delete_from $delete_to
  433.   }
  434. }
  435.