home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 16 / 16.iso / w / w055 / 4.ddi / SOURCES.LIF / KEYS.PEL < prev    next >
Encoding:
Text File  |  1990-09-27  |  29.8 KB  |  1,229 lines

  1. # $Header:   P:/source/ppee/macros/keys.pev   1.76   15 Aug 1990 12:02:48   ericj  $
  2.  
  3. ##############################################################################
  4. #
  5. #           Sage Software - POLYTRON Division
  6. #             1700 NW 167th Place
  7. #               Beaverton, OR 97006
  8. #
  9. #   Copyright 1990, Sage Software, Inc.
  10. #
  11. #   Permission is hereby granted for licensed users of Sage Professional
  12. #   Editor and PolyAwk to copy and modify this source code for their own
  13. #   personal use.  These derivative works may be distributed only to other
  14. #   licensed Sage Professional Editor and PolyAwk users.  All other usage
  15. #   is prohibited without express written permission from Sage Software.
  16. #
  17. ##############################################################################
  18.  
  19. #### $Workfile:   keys.pel  $: Key binding code
  20. #
  21. #
  22.  
  23.     ## keyboard status keys:
  24.  
  25. global    KB_SHIFTR    = 0x01
  26. global    KB_SHIFTL    = 0x02
  27. global    KB_CTRL        = 0x04
  28. global    KB_ALT        = 0x08
  29. global    KB_SCROLL_LOCK    = 0x10
  30. global    KB_NUM_LOCK    = 0x20
  31. global    KB_CAPS_LOCK    = 0x40
  32. global    KB_INSERT    = 0x80
  33.  
  34.     ## the following codes ambiguously define the equivalent
  35.     ## keys on the two auxiliary "cursor" keypads:
  36.  
  37. global    SCANCODE_HOME        = 0x47
  38. global    SCANCODE_UP        = 0x48
  39. global    SCANCODE_PGUP        = 0x49
  40. global    SCANCODE_LEFT        = 0x4b
  41. global    SCANCODE_CENTER        = 0x4c
  42. global    SCANCODE_RIGHT        = 0x4d
  43. global    SCANCODE_END        = 0x4f
  44. global    SCANCODE_DOWN        = 0x50
  45. global    SCANCODE_PGDN        = 0x51
  46. global    SCANCODE_CTRL_HOME    = 0x47
  47. global    SCANCODE_CTRL_UP    = 0x8d
  48. global    SCANCODE_CTRL_PGUP    = 0x84
  49. global    SCANCODE_CTRL_LEFT    = 0x73
  50. global    SCANCODE_CTRL_CENTER    = 0x8f
  51. global    SCANCODE_CTRL_RIGHT    = 0x74
  52. global    SCANCODE_CTRL_END    = 0x75
  53. global    SCANCODE_CTRL_DOWN    = 0x91
  54. global    SCANCODE_CTRL_PGDN    = 0x76
  55.  
  56. global    SCANCODE_ESC        = 0x01
  57.  
  58.     ## other useful keycodes:
  59. global    KEYCODE_ESC        = 0x011b
  60. global    KEYCODE_TAB        = 0x0f09
  61. global    KEYCODE_END        = 0x4f00
  62. global    KEYCODE_ENTER        = 0x1c0d
  63. global    KEYCODE_KEYPAD_ENTER    = 0xe00d
  64. global    KEYCODE_CTRL_AT        = 0x0300 # Ctrl-@ (== ctrl-2), ascii byte is 0
  65.  
  66.     ## useful ascii codes:
  67. global    ASCII_BACKSPACE        = 8
  68. global    ASCII_TAB        = 9
  69. global    ASCII_CR        = 13
  70. global    ASCII_ESC        = 27
  71.  
  72. local    key_names        # key code--name equivalences
  73.  
  74. local    EOF = -1        # value returned upon EOF
  75.  
  76.  
  77. ### program a key to playback a recorded sequence
  78. #
  79. local    learning        # semaphore for recursive calls to learn_key
  80. local    learned_key        # array of key->playback string associations
  81.  
  82. global function learn_key(){                    #PUBLIC #VOID
  83.     local    learn_name        # name of key being learned
  84.     local    key
  85.     local    binding
  86.  
  87.     # a recursive call to this function ends the recording process
  88.     if ( learning ) {
  89.         process_end()
  90.         return
  91.     }
  92.  
  93.     # prompt for the key to learn and get the name
  94.     begin_dialog()
  95.     notify( "Press key to be recorded" )
  96.     key = getKey()
  97.     end_dialog()
  98.  
  99.     if ( key == EOF ) {
  100.         message( "Canceled." )
  101.         return
  102.     }
  103.  
  104.     # get the name of the key to learn
  105.     learn_name = key_name( key )
  106.  
  107.     # make sure it is alright to overwrite the previous binding
  108.     binding = keymap_binding( learn_name )
  109.     if ( binding ) {
  110.         binding = sprintf( "%s is bound to %s; redefine?", learn_name, binding )
  111.         if ( tolower( confirm( binding, "YyNn" )) != "y" ) {
  112.             message( "Canceled." )
  113.             return
  114.         }
  115.     }
  116.     assign_key( learn_name, "learn_key" )    # terminator
  117.  
  118.     begin_dialog()
  119.     notify( "Recording key sequence for %s...press %s again to terminate", \
  120.             learn_name, learn_name )
  121.     while ( !keyboard_input_pending ) {
  122.         # idle
  123.     }
  124.     end_dialog()
  125.  
  126.     # enable recording
  127.     record( 1 )
  128.     learning = 1    # recursion flag
  129.     process_begin()
  130.  
  131.     # we continue here after the process_end, which will happen during
  132.     # the next recursive call to learn_key().
  133.  
  134.     learning = 0
  135.  
  136.     # create a key binding for the learned sequence
  137.     learned_key[ key ] = record( 0 )
  138.     assign_key( learn_name, "playback_learn_key" )
  139.  
  140.     notify( "Reprogrammed %s Key", learn_name )
  141. }
  142.  
  143. global function playback_learn_key(){
  144.     playback( learned_key[ current_key ])
  145. }
  146.  
  147.  
  148. ### print statistics about keys as they are entered
  149. #
  150.  
  151. global function print_keys(){
  152.     local key
  153.  
  154.     key_names_init()
  155.     begin_dialog()
  156.     notify( "Press keys to be printed..." )
  157.  
  158.     while(( key = getKey()) != EOF ){
  159.         notify( "Keycodes: 0x%04x  #%05u  (%03u)  \"%s\"",    \
  160.             key,                        \
  161.             key,                        \
  162.             and( key, 255 ),                \
  163.             key_name( key ))
  164.             # ambiguous_ascii( key ) ? "(ambiguous)" : "" )
  165.     }
  166.  
  167.     message( "" )
  168.     end_dialog()
  169. }
  170.  
  171.  
  172. ### read a key and print its binding
  173. #
  174.  
  175. global function print_bindings(){
  176.     local seq, key
  177.  
  178.     key_names_init()
  179.     begin_dialog()
  180.     notify( "Press keys to be looked-up..." )
  181.  
  182.     while(( key = getKey()) != EOF ){
  183.         seq = key_encoding( key, 1 )
  184.  
  185.         notify( "0x%04x  #%05u  (%03u)  \"%s\"  is bound to %s",\
  186.             key,                        \
  187.             key,                        \
  188.             and( key, 255 ),                \
  189.             key_name( key ),                \
  190.             keymap_binding( seq ))
  191.             # ambiguous_ascii( key ) ? "  (ambiguous)" : "",
  192.     }
  193.  
  194.     message( "" )
  195.     end_dialog()
  196. }
  197.  
  198. ### read a key and insert the corresponding "#"-sequence
  199. #
  200.  
  201. global function insert_keys(){
  202.     local    key
  203.     local    str
  204.     local    priorWindow = current_window
  205.  
  206.     key_names_init()
  207.     begin_dialog()
  208.     notify( "Press keys to be converted and inserted..." )
  209.  
  210.     while(( key = getKey()) != EOF ){
  211.         if(( str = key_encoding( key ))){
  212.             if (priorWindow)
  213.                 current_window = priorWindow
  214.             insert_string( str )
  215.             raise_window( dialog_window )
  216.             display_update()
  217.         } else {
  218.             break
  219.         }
  220.     }
  221.  
  222.     # remove temp dialog window if we created one above
  223.     message( "" )
  224.     end_dialog()
  225. }
  226.  
  227. ### Read keys from the keyboard and insert them into the buffer if
  228. #    they represent valid ASCII characters.
  229. #
  230. # See also:     insert_quoted_key()    # singluar
  231.  
  232. global function insert_quoted_keys(){
  233.     local    key
  234.     local    ascii
  235.     local    priorWindow = current_window
  236.  
  237.     key_names_init()
  238.     begin_dialog()
  239.     notify( "Press ASCII keys to be inserted..." )
  240.  
  241.     while(( key = getKey()) != EOF ){
  242.         ascii = and( key, 255 )
  243.         if ( (ascii == 0 && key != KEYCODE_CTRL_AT) ||
  244.                 (ascii == 0xe0 && key != ascii) ){
  245.             warning( "non-ASCII key ignored" )
  246.         } else {
  247.             if (priorWindow)
  248.                 current_window = priorWindow
  249.             if (ascii == 9)
  250.                 insert_string( "\t" );
  251.             else
  252.                 insert_key( ascii )
  253.             raise_window( dialog_window )
  254.             display_update()
  255.         }
  256.     }
  257.  
  258.     # remove temp dialog window if we created one above
  259.     message( "" )
  260.     end_dialog()
  261. }
  262.  
  263. ### Read the next key from the keyboard and insert it into the buffer if
  264. #    it represents a valid ASCII character.
  265. #
  266. # See also:     insert_quoted_keys()  # plural
  267.  
  268. global function insert_quoted_key(){
  269.     local    key, ascii
  270.     local    priorWindow = current_window
  271.  
  272.     key_names_init()
  273.     begin_dialog()
  274.     notify( "Press ASCII key to be inserted..." )
  275.  
  276.     if (( key = getKey()) != EOF ) {
  277.         ascii = and( key, 255 )
  278.         if ( (ascii == 0 && key != KEYCODE_CTRL_AT) ||
  279.                 (ascii == 0xe0 && key != ascii) ){
  280.             warning( "non-ASCII key ignored" )
  281.         } else {
  282.             if (priorWindow)
  283.                 current_window = priorWindow
  284.             if (ascii == 9)
  285.                 insert_string( "\t" );
  286.             else
  287.                 insert_key( ascii )
  288.             message( "" )
  289.         }
  290.     }
  291.  
  292.     # remove temp dialog window if we created one above
  293.     end_dialog()
  294. }
  295.  
  296.  
  297. ### convert a keycode to a "#"-sequence
  298. #
  299.  
  300. global function key_encoding( key, distinguish ){
  301.     local ascii = and( key, 255 )
  302.     local value, p = "n"
  303.  
  304.     key_names_init()
  305.  
  306.     if( ascii == 0                            \
  307.     || ascii == 0xE0                        \
  308.     || distinguish                            \
  309.     || ( ambiguous_ascii( key )                    \
  310.     && (( p = prompt( "Distinguish alternate " key_name( ascii )    \
  311.             " characters? ", p ))  ~ "[yY]" ))){
  312.         value = key
  313.     } else
  314.         value = ascii
  315.  
  316.     if( p )
  317.         return sprintf( "#%u", value )
  318.     else
  319.         return ""
  320. }
  321.  
  322. ## determine if an ascii code is represented by multiple keys
  323. #
  324. global function ambiguous_ascii( key ){
  325.     key_names_init()
  326.     return and( key, 255 ) in key_names
  327. }
  328.  
  329.  
  330. ### returns the name of a key given a key code
  331. #
  332.  
  333. global function key_name( keycode ){
  334.     local    ascii
  335.  
  336.     key_names_init()
  337.  
  338.     # strip off the leading '#' if necessary
  339.     if ( keycode ~ /^#/ ) {
  340.         keycode = substr( keycode, 2 )
  341.     }
  342.  
  343.     if ( keycode in key_names )
  344.         return "<" key_names[ keycode ] ">"
  345.  
  346.     ascii = and( keycode, 0x00FF )
  347.  
  348.     if ( 0+ascii && ascii in key_names )
  349.         return "<" key_names[ ascii ] ">"
  350.  
  351.     if ( ascii >= 32 )
  352.         return chr( ascii )
  353.     else
  354.         return "#" keycode
  355. }
  356.  
  357. local function key_names_init() {
  358.  
  359.     if ( 03849 in key_names )
  360.         return
  361.  
  362.     message( "[Initializing key names...]" )
  363.  
  364.     ## key sequences on main keyboard with ASCII codes:
  365.  
  366.     key_names[ 0 ]     = "NUL"
  367.     key_names[ 07681 ] = "Ctrl-A"        # ASCII code 1
  368.     key_names[ 12290 ] = "Ctrl-B"        # ASCII code 2
  369.     key_names[ 11779 ] = "Ctrl-C"        # ASCII code 3
  370.     key_names[ 08196 ] = "Ctrl-D"        # ASCII code 4
  371.     key_names[ 04613 ] = "Ctrl-E"        # ASCII code 5
  372.     key_names[ 08454 ] = "Ctrl-F"        # ASCII code 6
  373.     key_names[ 08711 ] = "Ctrl-G"        # ASCII code 7
  374.     key_names[ 08968 ] = "Ctrl-H"        # ASCII code 8
  375.     key_names[ 03592 ] = "Bksp"        # ASCII code 8
  376.     key_names[ 05897 ] = "Ctrl-I"        # ASCII code 9
  377.     key_names[ 03849 ] = "Tab"        # ASCII code 9
  378.     key_names[ 09226 ] = "Ctrl-J"        # ASCII code 10
  379.     key_names[ 07178 ] = "Ctrl-Enter"    # ASCII code 10
  380.     key_names[ 09483 ] = "Ctrl-K"        # ASCII code 11
  381.     key_names[ 09740 ] = "Ctrl-L"        # ASCII code 12
  382.     key_names[ 12813 ] = "Ctrl-M"        # ASCII code 13
  383.     key_names[ 07181 ] = "Enter"        # ASCII code 13
  384.     key_names[ 12558 ] = "Ctrl-N"        # ASCII code 14
  385.     key_names[ 06159 ] = "Ctrl-O"        # ASCII code 15
  386.     key_names[ 06416 ] = "Ctrl-P"        # ASCII code 16
  387.     key_names[ 04113 ] = "Ctrl-Q"        # ASCII code 17
  388.     key_names[ 04882 ] = "Ctrl-R"        # ASCII code 18
  389.     key_names[ 07955 ] = "Ctrl-S"        # ASCII code 19
  390.     key_names[ 05140 ] = "Ctrl-T"        # ASCII code 20
  391.     key_names[ 05653 ] = "Ctrl-U"        # ASCII code 21
  392.     key_names[ 12054 ] = "Ctrl-V"        # ASCII code 22
  393.     key_names[ 04375 ] = "Ctrl-W"        # ASCII code 23
  394.     key_names[ 11544 ] = "Ctrl-X"        # ASCII code 24
  395.     key_names[ 05401 ] = "Ctrl-Y"        # ASCII code 25
  396.     key_names[ 11290 ] = "Ctrl-Z"        # ASCII code 26
  397.     key_names[ 06683 ] = "Ctrl-["        # ASCII code 27
  398.     key_names[ 00283 ] = "Esc"        # ASCII code 27
  399.     key_names[ 11036 ] = "Ctrl-\\"        # ASCII code 28
  400.     key_names[ 06941 ] = "Ctrl-]"        # ASCII code 29
  401.     key_names[ 01822 ] = "Ctrl-^"        # ASCII code 30
  402.     key_names[ 03103 ] = "Ctrl-Minus"    # ASCII code 31
  403.     key_names[ 14624 ] = "Space"        # ASCII code 32
  404.     key_names[ 03711 ] = "Ctrl-Bksp"    # ASCII code 127
  405.  
  406.     ## keys on main keyboard without ASCII codes:
  407.  
  408.     key_names[ 03840 ] = "Shift-Tab"
  409.     key_names[ 37888 ] = "Ctrl-Tab"
  410.     key_names[ 00768 ] = "Ctrl-@"
  411.     key_names[ 00256 ] = "Alt-Esc"
  412.     key_names[ 10496 ] = "Alt-`"
  413.     key_names[ 33280 ] = "Alt-Minus"
  414.     key_names[ 33536 ] = "Alt-="
  415.     key_names[ 11008 ] = "Alt-\\"
  416.     key_names[ 03584 ] = "Alt-Bksp"
  417.     key_names[ 42240 ] = "Alt-Tab"
  418.     key_names[ 06656 ] = "Alt-["
  419.     key_names[ 06912 ] = "Alt-]"
  420.     key_names[ 07168 ] = "Alt-Enter"
  421.     key_names[ 09984 ] = "Alt-;"
  422.     key_names[ 10240 ] = "Alt-'"
  423.     key_names[ 13056 ] = "Alt-,"
  424.     key_names[ 13312 ] = "Alt-."
  425.     key_names[ 13568 ] = "Alt-/"
  426.  
  427.     ## numeric keypad keys:
  428.  
  429.     key_names[ 57391 ] = "Keypad-/"
  430.     key_names[ 14122 ] = "Keypad-*"
  431.     key_names[ 18989 ] = "Keypad-Minus"
  432.     key_names[ 20011 ] = "Keypad-+"
  433.     key_names[ 57357 ] = "Keypad-Enter"
  434.  
  435.     key_names[ 21040 ] = "Keypad-0"
  436.     key_names[ 20273 ] = "Keypad-1"
  437.     key_names[ 20530 ] = "Keypad-2"
  438.     key_names[ 20787 ] = "Keypad-3"
  439.     key_names[ 19252 ] = "Keypad-4"
  440.     key_names[ 19509 ] = "Keypad-5"
  441.     key_names[ 19766 ] = "Keypad-6"
  442.     key_names[ 18231 ] = "Keypad-7"
  443.     key_names[ 18488 ] = "Keypad-8"
  444.     key_names[ 18745 ] = "Keypad-9"
  445.     key_names[ 21294 ] = "Keypad-."
  446.  
  447.     key_names[ 20992 ] = "Keypad-Ins"
  448.     key_names[ 21248 ] = "Keypad-Del"
  449.     key_names[ 18176 ] = "Keypad-Home"
  450.     key_names[ 20224 ] = "Keypad-End"
  451.     key_names[ 18688 ] = "Keypad-PgUp"
  452.     key_names[ 20736 ] = "Keypad-PgDn"
  453.     key_names[ 18432 ] = "Keypad-Up"
  454.     key_names[ 20480 ] = "Keypad-Down"
  455.     key_names[ 19200 ] = "Keypad-Left"
  456.     key_names[ 19712 ] = "Keypad-Right"
  457.     key_names[ 19456 ] = "Keypad-Center"
  458.  
  459.     # note: unshifted keypad keys with num-lock off are equivalent
  460.     #    to shifted keypad keys with num-lock on, and vice versa.
  461.     #    Therefore, it is necessary to refer to the key by name
  462.     #    rather than by using the "Shift-" prefix.  For example,
  463.     #    instead of "Shift-Keypad-Up" one would use either
  464.     #    "Keypad-8" or "Keypad-Up" depending on how one wants to
  465.     #    treat num-lock.
  466.  
  467.     key_names[ 38144 ] = "Ctrl-Keypad-/"
  468.     key_names[ 38400 ] = "Ctrl-Keypad-*"
  469.     key_names[ 36352 ] = "Ctrl-Keypad-Minus"
  470.     key_names[ 36864 ] = "Ctrl-Keypad-+"
  471.     key_names[ 57354 ] = "Ctrl-Keypad-Enter"
  472.  
  473.     key_names[ 37376 ] = "Ctrl-Keypad-Ins"
  474.     key_names[ 37632 ] = "Ctrl-Keypad-Del"
  475.     key_names[ 30464 ] = "Ctrl-Keypad-Home"
  476.     key_names[ 29952 ] = "Ctrl-Keypad-End"
  477.     key_names[ 33792 ] = "Ctrl-Keypad-PgUp"
  478.     key_names[ 30208 ] = "Ctrl-Keypad-PgDn"
  479.     key_names[ 36096 ] = "Ctrl-Keypad-Up"
  480.     key_names[ 37120 ] = "Ctrl-Keypad-Down"
  481.     key_names[ 29440 ] = "Ctrl-Keypad-Left"
  482.     key_names[ 29696 ] = "Ctrl-Keypad-Right"
  483.     key_names[ 36608 ] = "Ctrl-Keypad-Center"
  484.  
  485.     key_names[ 41984 ] = "Alt-Keypad-/"
  486.     key_names[ 14080 ] = "Alt-Keypad-*"
  487.     key_names[ 18944 ] = "Alt-Keypad-Minus"
  488.     key_names[ 19968 ] = "Alt-Keypad-+"
  489.     key_names[ 42496 ] = "Alt-Keypad-Enter"
  490.  
  491.     ## keys on the auxiliary (non-numeric) keypad;
  492.     ## these are not available on non-extended keyboards:
  493.  
  494.     key_names[ 21216 ] = "Ins"
  495.     key_names[ 21472 ] = "Del"
  496.     key_names[ 18400 ] = "Home"
  497.     key_names[ 20448 ] = "End"
  498.     key_names[ 18912 ] = "PgUp"
  499.     key_names[ 20960 ] = "PgDn"
  500.     key_names[ 18656 ] = "Up"
  501.     key_names[ 20704 ] = "Down"
  502.     key_names[ 19424 ] = "Left"
  503.     key_names[ 19936 ] = "Right"
  504.  
  505.     # note: shift staus is ignored on auxiliary keypad
  506.  
  507.     key_names[ 37600 ] = "Ctrl-Ins"
  508.     key_names[ 37856 ] = "Ctrl-Del"
  509.     key_names[ 30688 ] = "Ctrl-Home"
  510.     key_names[ 30176 ] = "Ctrl-End"
  511.     key_names[ 34016 ] = "Ctrl-PgUp"
  512.     key_names[ 30432 ] = "Ctrl-PgDn"
  513.     key_names[ 36320 ] = "Ctrl-Up"
  514.     key_names[ 37344 ] = "Ctrl-Down"
  515.     key_names[ 29664 ] = "Ctrl-Left"
  516.     key_names[ 29920 ] = "Ctrl-Right"
  517.  
  518.     key_names[ 41472 ] = "Alt-Ins"
  519.     key_names[ 41728 ] = "Alt-Del"
  520.     key_names[ 38656 ] = "Alt-Home"
  521.     key_names[ 40704 ] = "Alt-End"
  522.     key_names[ 39168 ] = "Alt-PgUp"
  523.     key_names[ 41216 ] = "Alt-PgDn"
  524.     key_names[ 38912 ] = "Alt-Up"
  525.     key_names[ 40960 ] = "Alt-Down"
  526.     key_names[ 39680 ] = "Alt-Left"
  527.     key_names[ 40192 ] = "Alt-Right"
  528.  
  529.     # Alt key combinations on the main keyboard:
  530.  
  531.     key_names[ 07680 ] = "Alt-A"
  532.     key_names[ 12288 ] = "Alt-B"
  533.     key_names[ 11776 ] = "Alt-C"
  534.     key_names[ 08192 ] = "Alt-D"
  535.     key_names[ 04608 ] = "Alt-E"
  536.     key_names[ 08448 ] = "Alt-F"
  537.     key_names[ 08704 ] = "Alt-G"
  538.     key_names[ 08960 ] = "Alt-H"
  539.     key_names[ 05888 ] = "Alt-I"
  540.     key_names[ 09216 ] = "Alt-J"
  541.     key_names[ 09472 ] = "Alt-K"
  542.     key_names[ 09728 ] = "Alt-L"
  543.     key_names[ 12800 ] = "Alt-M"
  544.     key_names[ 12544 ] = "Alt-N"
  545.     key_names[ 06144 ] = "Alt-O"
  546.     key_names[ 06400 ] = "Alt-P"
  547.     key_names[ 04096 ] = "Alt-Q"
  548.     key_names[ 04864 ] = "Alt-R"
  549.     key_names[ 07936 ] = "Alt-S"
  550.     key_names[ 05120 ] = "Alt-T"
  551.     key_names[ 05632 ] = "Alt-U"
  552.     key_names[ 12032 ] = "Alt-V"
  553.     key_names[ 04352 ] = "Alt-W"
  554.     key_names[ 11520 ] = "Alt-X"
  555.     key_names[ 05376 ] = "Alt-Y"
  556.     key_names[ 11264 ] = "Alt-Z"
  557.  
  558.     key_names[ 30720 ] = "Alt-1"
  559.     key_names[ 30976 ] = "Alt-2"
  560.     key_names[ 31232 ] = "Alt-3"
  561.     key_names[ 31488 ] = "Alt-4"
  562.     key_names[ 31744 ] = "Alt-5"
  563.     key_names[ 32000 ] = "Alt-6"
  564.     key_names[ 32256 ] = "Alt-7"
  565.     key_names[ 32512 ] = "Alt-8"
  566.     key_names[ 32768 ] = "Alt-9"
  567.     key_names[ 33024 ] = "Alt-0"
  568.  
  569.     # Function key combinations:
  570.  
  571.     key_names[ 15104 ] = "F1"
  572.     key_names[ 15360 ] = "F2"
  573.     key_names[ 15616 ] = "F3"
  574.     key_names[ 15872 ] = "F4"
  575.     key_names[ 16128 ] = "F5"
  576.     key_names[ 16384 ] = "F6"
  577.     key_names[ 16640 ] = "F7"
  578.     key_names[ 16896 ] = "F8"
  579.     key_names[ 17152 ] = "F9"
  580.     key_names[ 17408 ] = "F10"
  581.     key_names[ 34048 ] = "F11"
  582.     key_names[ 34304 ] = "F12"
  583.  
  584.     key_names[ 21504 ] = "Shift-F1"
  585.     key_names[ 21760 ] = "Shift-F2"
  586.     key_names[ 22016 ] = "Shift-F3"
  587.     key_names[ 22272 ] = "Shift-F4"
  588.     key_names[ 22528 ] = "Shift-F5"
  589.     key_names[ 22784 ] = "Shift-F6"
  590.     key_names[ 23040 ] = "Shift-F7"
  591.     key_names[ 23296 ] = "Shift-F8"
  592.     key_names[ 23552 ] = "Shift-F9"
  593.     key_names[ 23808 ] = "Shift-F10"
  594.     key_names[ 34560 ] = "Shift-F11"
  595.     key_names[ 34816 ] = "Shift-F12"
  596.  
  597.     key_names[ 24064 ] = "Ctrl-F1"
  598.     key_names[ 24320 ] = "Ctrl-F2"
  599.     key_names[ 24576 ] = "Ctrl-F3"
  600.     key_names[ 24832 ] = "Ctrl-F4"
  601.     key_names[ 25088 ] = "Ctrl-F5"
  602.     key_names[ 25344 ] = "Ctrl-F6"
  603.     key_names[ 25600 ] = "Ctrl-F7"
  604.     key_names[ 25856 ] = "Ctrl-F8"
  605.     key_names[ 26112 ] = "Ctrl-F9"
  606.     key_names[ 26368 ] = "Ctrl-F10"
  607.     key_names[ 35072 ] = "Ctrl-F11"
  608.     key_names[ 35328 ] = "Ctrl-F12"
  609.  
  610.     key_names[ 26624 ] = "Alt-F1"
  611.     key_names[ 26880 ] = "Alt-F2"
  612.     key_names[ 27136 ] = "Alt-F3"
  613.     key_names[ 27392 ] = "Alt-F4"
  614.     key_names[ 27648 ] = "Alt-F5"
  615.     key_names[ 27904 ] = "Alt-F6"
  616.     key_names[ 28160 ] = "Alt-F7"
  617.     key_names[ 28416 ] = "Alt-F8"
  618.     key_names[ 28672 ] = "Alt-F9"
  619.     key_names[ 28928 ] = "Alt-F10"
  620.     key_names[ 35584 ] = "Alt-F11"
  621.     key_names[ 35840 ] = "Alt-F12"
  622.  
  623.     key_names[ 61440 ] = "Mouse-Left-Press"
  624.     key_names[ 61696 ] = "Mouse-Right-Press"
  625.     key_names[ 61952 ] = "Mouse-Middle-Press"
  626.     key_names[ 62208 ] = "Mouse-Left-Release"
  627.     key_names[ 62464 ] = "Mouse-Right-Release"
  628.     key_names[ 62720 ] = "Mouse-Middle-Release"
  629.     key_names[ 62976 ] = "Mouse-Left-Click"
  630.     key_names[ 63232 ] = "Mouse-Right-Click"
  631.     key_names[ 63488 ] = "Mouse-Middle-Click"
  632.     key_names[ 63744 ] = "Mouse-Left-Double-Click"
  633.     key_names[ 64000 ] = "Mouse-Right-Double-Click"
  634.     key_names[ 63256 ] = "Mouse-Middle-Double-Click"
  635.  
  636.     message( "" )
  637. }
  638.  
  639. ## Return a keycode from the keyboard, waiting until a key is actually pressed.
  640. #    Escape prompts the user to return either the escape keycode or EOF.
  641.  
  642. local function getKey(){
  643.     local ch, resp
  644.  
  645.  
  646.     while ( !keyboard_input_pending ) {
  647.         # idle
  648.     }
  649.     ch = getkey()
  650.  
  651.     if ( ch == KEYCODE_ESC &&
  652.         tolower(confirm( "Terminate key sequence? ", "YyNn\r" )) != "n")
  653.         return EOF
  654.  
  655.     return ch;
  656. }
  657.  
  658. #----------------------------------------------------------------------
  659.  
  660. ### view or edit the current key bindings
  661. #
  662.  
  663. local    startingKeymap;
  664. local    bindingKeymap;
  665. local    bindingListBuffer;
  666. local    bindingDispBuffer;
  667. local    bindingListWindow;
  668. local    bindingDispWindow;
  669. local    lastBindingLine;
  670. local    bindingsInitialized = 0;
  671. local    windowHeight;
  672. local    rightmost_column = 30;
  673. local    currentFunction = "";
  674. local    keyBindings[];
  675. local    deletedKeys[];
  676. local    insertedKeys[];
  677.  
  678.  
  679. local function binding_init() {
  680.     local    txtfile;
  681.     local    buffOff;
  682.     local    len;
  683.     local    str;
  684.     local    cw = current_buffer;
  685.     local    size;
  686.     local    eol_str;
  687.  
  688.  
  689.     key_names_init();
  690.  
  691.     init_menu_colors();
  692.  
  693.     # search sageedit path for the help menu file
  694.     if ( !(txtfile = locate_sageedit_file(SAGEEDIT_FILE_BINDINGS))) {
  695.         txtfile = editor_path( SAGEEDIT_FILE_BINDINGS );
  696.     }
  697.  
  698.     eol_str = default_buffer_eol_string;
  699.     default_buffer_eol_string = "\r\n";
  700.     current_buffer =        \
  701.         bindingListBuffer =    \
  702.         create_buffer( txtfile, txtfile, BUFFER_SYSTEM + BUFFER_NO_UNDO );
  703.     default_buffer_eol_string = eol_str;
  704.     size = buffer_size;
  705.     current_buffer = cw;
  706.     if (!size) {
  707.         # couldn't find the help information
  708.         notify( "Cannot find binding information in: %s", txtfile );
  709.         delete_buffer( bindingListBuffer );
  710.         return FALSE;
  711.     }
  712.  
  713.     bindingDispBuffer = create_buffer( "Binding", "", BUFFER_SYSTEM + BUFFER_NO_UNDO);
  714.  
  715.     current_buffer = cw;
  716.     message( "" );
  717.  
  718.     return TRUE;
  719. }
  720.  
  721.  
  722.  
  723. global function keys() {
  724.     local    x0 = 8
  725.     local    y0 = 3
  726.     local    width = rightmost_column
  727.     local    cw = current_window;
  728.     local    cb = current_buffer;
  729.     local    isDiag = dialog_window+0;
  730.     local    i;
  731.  
  732.  
  733.     windowHeight = display_height - y0 -y0;
  734.  
  735.     if (!bindingsInitialized) {
  736.         if (!binding_init())
  737.             return;
  738.     } else bindingsInitialized = 1;
  739.  
  740.     init_menu_colors();
  741.  
  742.     toggle_dialog( 1 );
  743.  
  744.     lastBindingLine = 0;
  745.     startingKeymap = current_keymap;
  746.     bindingKeymap = create_keymap( empty_keymap );
  747.     push_keymap( bindingKeymap );
  748.  
  749.     #
  750.     # create the display window and shadow which will contain the function names
  751.     #
  752.     current_window = bindingDispWindow =    \
  753.         create_factory_window( x0+width+2, y0, width, windowHeight,
  754.             WINDOW_SYSTEM + WINDOW_BORDER );
  755.     color_border = BAR_COLOR;
  756.     color_text   = BAR_COLOR;
  757.     initBindingAttributes();
  758.     attach_window_buffer( bindingDispWindow, bindingDispBuffer );
  759.  
  760.  
  761.     #
  762.     # create the list window and shadow which will contain the list of keys
  763.     # binding items
  764.     #
  765.     current_window = bindingListWindow =    \
  766.         create_factory_window( x0, y0, width, windowHeight,
  767.             WINDOW_SYSTEM + WINDOW_SB_RIGHT + WINDOW_BORDER );
  768.     color_border = BAR_COLOR;
  769.     color_text   = BAR_COLOR;
  770.     attach_window_buffer( bindingListWindow, bindingListBuffer );
  771.     initBindingAttributes();
  772.  
  773.     highlight_screen( x0+width, y0+1, 1, windowHeight, SHADOW_COLOR );
  774.     highlight_screen( x0+1, y0+windowHeight, width, 1, SHADOW_COLOR );
  775.  
  776.     x0 += width;
  777.     highlight_screen( x0+2+width, y0+1, 1, windowHeight, SHADOW_COLOR );
  778.     highlight_screen( x0+3, y0+windowHeight, width, 1, SHADOW_COLOR );
  779.  
  780.     current_window = bindingListWindow;
  781.  
  782.     delete( keyBindings );
  783.     delete( deletedKeys );
  784.     delete( insertedKeys );
  785.  
  786.     goto_buffer_top();
  787.     drop_anchor( LINE_SELECTION );
  788.     updateBindItem();
  789.  
  790.     assign_key( "<Esc>",        "process_end" );
  791.     assign_key( "<Home>",        "bindHome" );
  792.     assign_key( "<End>",        "bindEnd" );
  793.     assign_key( "<Up>",        "bindUp 1" );
  794.     assign_key( "<Down>",        "bindDown 1" );
  795.     assign_key( "<PgUp>",        "bindPageUp" );
  796.     assign_key( "<PgDn>",        "bindPageDown" );
  797.     assign_key( "<Tab>",        "bindToggleWindow" );
  798.     assign_key( "<Left>",        "bindToggleWindow 1" );
  799.     assign_key( "<Right>",        "bindToggleWindow 0" );
  800.     assign_key( "#61440",        "bindLeftPress" );
  801.     assign_key( "#62976",        "bindLeftPress" );
  802.     assign_key( "#62208",        "bindLeftRelease" );
  803.     assign_key( "<Alt-H>",        "display_help_item keys" );
  804.     assign_key( "<Del>",        "bindDelete" );
  805.     assign_key( "<Ins>",        "bindIns" );
  806.  
  807.     
  808.     current_window = bindingDispWindow;
  809.     bindToggleWindow( 1 );
  810.     process_begin();
  811.     pop_keymap();
  812.  
  813.     
  814.     assign_current_window( cw );
  815.     current_buffer = cb;
  816.  
  817.     delete_keymap( bindingKeymap );
  818.     delete_window( bindingListWindow );
  819.     delete_window( bindingDispWindow );
  820.     current_key = 0;
  821.     display_redraw();
  822.     message( "" );
  823.  
  824.     saveKeys();
  825.  
  826.     toggle_dialog( isDiag );
  827. }
  828.  
  829.  
  830.  
  831.  
  832. #
  833. # initialize the attribute and window names for the binding windows
  834. # win == 1 setting display window, win == 2 setting list window
  835. #
  836. local function initBindingAttributes() {
  837.     color_highlight = HBAR_COLOR;
  838.     visible_virtual_lines  = "";
  839.     visible_virtual_spaces = "";
  840.     visible_end_buffer     = "";
  841. }
  842.  
  843.  
  844. function showBindingItem( lineNum ) {
  845.     local    cw = current_window;
  846.     local    ln;
  847.     local    i;
  848.     local    arr;
  849.     local    msg_lvl;
  850.  
  851.  
  852.     if (current_window == bindingDispWindow)
  853.         return;
  854.  
  855.     delete( keyBindings );
  856.  
  857.     goto_bol();
  858.     current_column = rightmost_column;
  859.     ln = read_buffer();
  860.     goto_bol();
  861.  
  862.     current_window = bindingDispWindow;
  863.  
  864.     goto_buffer_top();
  865.     while (delete_line())
  866.         continue;
  867.     goto_bol();
  868.  
  869.     if ((ln != "") && (!keyboard_input_pending)) {
  870.         msg_lvl = message_level;
  871.         message_level = 2;
  872.         currentFunction = ln;
  873.         ln = function_binding( function_id( ln ), startingKeymap );
  874.         message_level = msg_lvl;
  875.         split( ln, arr, " " ) + 1;
  876.         for (i in arr) {
  877.             ln = keyAssignmentName( arr[i] );
  878.             insert_string( ln );
  879.             keyBindings[ ln ] = arr[i];
  880.             if (i+1 in arr)
  881.                 insert_newline();
  882.         }
  883.     }
  884.  
  885.     goto_buffer_top()
  886.     if (cw)
  887.         current_window = cw;
  888. }
  889.  
  890.  
  891. local function keyAssignmentName( str ){
  892.     local    keyarr;
  893.     local    i;
  894.     local    ln = "";
  895.  
  896.     split( str, keyarr, "#" )
  897.     for (i in keyarr) {
  898.         if (keyarr[i])
  899.             ln = ln key_name( atoi(keyarr[i]) );
  900.     }
  901.     delete( keyarr );
  902.     return ln;
  903. }
  904.  
  905.  
  906. global function bindLeftPress() {
  907.     local    xy_win;
  908.     local    mpos;
  909.  
  910.     xy_win = window_containing( mouse_event_x, mouse_event_y );
  911.  
  912.     if (xy_win == bindingDispWindow) {
  913.         bindToggleWindow( 0 );
  914.         return;
  915.     } else if (xy_win == bindingListWindow) {
  916.         bindToggleWindow( 1 );
  917.         mpos = mouse_position(1);
  918.         if ( !and(mpos,MOUSE_W+MOUSE_S+MOUSE_N) ){
  919.             raise_anchor();
  920.             setHighlightedScrolling( 1 );
  921.             left_press( 1 );
  922.             setHighlightedScrolling( 0 );
  923.         }
  924.         updateBindItem();
  925.     }
  926.  
  927.     if ( !region_type() )
  928.         drop_anchor( LINE_SELECTION );
  929. }
  930.  
  931.  
  932. function bindToggleWindow( left ){
  933.     if (current_window == bindingDispWindow) {
  934.         message( " , \x1a=window, <Esc>, <Ins>,           <Alt-H>=HELP" );
  935.         if (argcount() && !(left+0))
  936.             return;
  937.         raise_anchor();
  938.         display_update();
  939.         current_window = bindingListWindow;
  940.     } else {
  941.         message( " , \x1b=window, <Esc>, <Ins>, <Del>     <Alt-H>=HELP" );
  942.         if (argcount() && left+0)
  943.             return;
  944.         current_window = bindingDispWindow;
  945.         drop_anchor( LINE_SELECTION );
  946.     }
  947.  
  948.  
  949. }
  950.  
  951.  
  952.  
  953. global function bindLeftRelease(){
  954.     updateBindItem();
  955. }
  956.  
  957. global function bindHome() {
  958.     raise_anchor()
  959.     current_line = 1;
  960.     drop_anchor( LINE_SELECTION )
  961.     updateBindItem();
  962. }
  963.  
  964. global function bindEnd() {
  965.     raise_anchor()
  966.     current_line = 65535;
  967.     drop_anchor( LINE_SELECTION )
  968.     updateBindItem();
  969. }
  970.  
  971. global function bindPageUp( lines ) {
  972.     bindUp( windowHeight )
  973. }
  974.  
  975. global function bindPageDown( lines ) {
  976.     bindDown( windowHeight )
  977. }
  978.  
  979.  
  980. global function bindDown( lines ) {
  981.     if ( down( lines )) {
  982.         raise_anchor()
  983.         drop_anchor( LINE_SELECTION )
  984.     }
  985.     updateBindItem();
  986. }
  987.  
  988.  
  989. global function bindUp( lines ){
  990.     if ( up( lines )) {
  991.         raise_anchor()
  992.         drop_anchor( LINE_SELECTION )
  993.     }
  994.     updateBindItem();
  995. }
  996.  
  997.  
  998. global function bindDelete(){
  999.     local    ln;
  1000.     local    kn;
  1001.  
  1002.     if (current_window == bindingDispWindow) {
  1003.         goto_bol();
  1004.         kn = read_buffer();
  1005.         ln = keyBindings[ kn ];
  1006.         if (ln) {
  1007.             current_keymap = startingKeymap;
  1008.             assign_key( ln, "beep" );
  1009.             current_keymap = bindingKeymap;
  1010.  
  1011.             if (ln in insertedKeys)
  1012.                 delete( insertedKeys[ ln ] );
  1013.             else
  1014.                 deletedKeys[ kn ] = ln;
  1015.  
  1016.  
  1017.             delete_line();
  1018.             if (read_buffer() == "")
  1019.                 backspace();
  1020.         }
  1021.         goto_bol();
  1022.     } else
  1023.         beep();
  1024. }
  1025.  
  1026.  
  1027. local function waitForKey(){
  1028.     local ch;
  1029.     while ((ch = getkey()) == -1)
  1030.         continue;
  1031.     return ch;
  1032. }
  1033.  
  1034. global function bindIns(){
  1035.     local    ch;
  1036.     local    ln = "";
  1037.     local    kn;
  1038.     local    switchWindows = (current_window == bindingListWindow);
  1039.  
  1040.     if (switchWindows)
  1041.         bindToggleWindow( 0 );
  1042.  
  1043.     raise_anchor();
  1044.     insert_newline();
  1045.     up();
  1046.     drop_anchor( LINE_SELECTION );
  1047.     display_update();
  1048.  
  1049.     message( " <ESC>=discard,  <CR>=accept " );
  1050.  
  1051.     ch = waitForKey();
  1052.  
  1053.     while( (ch != KEYCODE_ENTER )                \
  1054.             && (ch != KEYCODE_KEYPAD_ENTER )    \
  1055.             &&  (ch != KEYCODE_ESC)) {
  1056.         kn = key_name( ch );
  1057.         insert_string( kn );
  1058.         ln = ln "#" ch;
  1059.         display_update();
  1060.         ch = waitForKey();
  1061.     }
  1062.  
  1063.     if ( (ch == KEYCODE_ENTER) || (ch == KEYCODE_KEYPAD_ENTER) ) {
  1064.         if ( !function_id( currentFunction )){
  1065.             warning( "Assignment to nonexistent function: " currentFunction );
  1066.             if (!pause_on_error)
  1067.                 ch = waitForKey();
  1068.             goto_bol();
  1069.             delete_line();
  1070.             display_update();
  1071.         } else {
  1072.             current_keymap = startingKeymap;
  1073.             assign_key( ln, currentFunction );
  1074.             current_keymap = bindingKeymap;
  1075.             goto_bol();
  1076.             kn = read_buffer();
  1077.             keyBindings[ kn ] = ln;
  1078.  
  1079.             if (kn in deletedKeys)
  1080.                 delete( deletedKeys[ kn ] );
  1081.             insertedKeys[ ln ] = currentFunction;
  1082.         }
  1083.     } else {
  1084.         delete_line();
  1085.         goto_bol();
  1086.         if (read_buffer() == "") {
  1087.             backspace();
  1088.         }
  1089.     }
  1090.     goto_bol();
  1091.  
  1092.     if (switchWindows)
  1093.         bindToggleWindow( 1 );
  1094.  
  1095. }
  1096.  
  1097.  
  1098.  
  1099. local function updateBindItem() {
  1100.     local    cb = current_buffer;
  1101.  
  1102.     if (keyboard_input_pending == 0) {
  1103.         if (lastBindingLine != current_line) {
  1104.             showBindingItem( current_line );
  1105.             lastBindingLine = current_line;
  1106.         }
  1107.     }
  1108. }
  1109.  
  1110.  
  1111.  
  1112.  
  1113. local function saveKeys(){
  1114.     local    fn;
  1115.     local    i;
  1116.     local    found = FALSE;
  1117.     local    cb = current_buffer;
  1118.     local    changeString = ""
  1119.     local   searchFlag = 0x0034     # ignore case | regex | forward
  1120.     local    keyname
  1121.  
  1122.  
  1123.     for (i in insertedKeys) {
  1124.         found = TRUE;
  1125.         break;
  1126.     }
  1127.  
  1128.     for (i in deletedKeys) {
  1129.         found = TRUE;
  1130.         break;
  1131.     }
  1132.  
  1133.  
  1134.     if (found) {
  1135.         # search sageedit path for the config file
  1136.         if ( !(fn = locate_sageedit_file(SAGEEDIT_FILE_CONFIG))) {
  1137.             fn = editor_path( SAGEEDIT_FILE_CONFIG )
  1138.         }
  1139.  
  1140.         i = confirm( "Save changes to " fn " [yn]? ", "yYnN" );
  1141.         if (toupper( i ) != "Y")
  1142.             return;
  1143.  
  1144.         current_buffer = create_buffer( "", fn,BUFFER_SYSTEM + BUFFER_NO_UNDO );
  1145.  
  1146.  
  1147.         #
  1148.         # clean out conflicting options
  1149.         #
  1150.         if ( emulation_mode ) {
  1151.             while ( search( \
  1152.                     "^[ /t]*(native|brief|vi|wordstar|epsilon|msword)>", \
  1153.                     searchFlag ) ) {
  1154.                 delete_line()
  1155.                 goto_buffer_top()
  1156.             }
  1157.         }
  1158.  
  1159.         insert_string( emulation_mode "\n" );
  1160.  
  1161.         search( "$STATE$", SEARCH_FORWARD );
  1162.  
  1163.         for (i in deletedKeys) {
  1164.             if ( match( i, /#/ )) {
  1165.                 keyname = i
  1166.             } else {
  1167.                 keyname = "#" i
  1168.             }
  1169.             changeString = changeString keyname "\nassign_key " \
  1170.                 deletedKeys[i] " \"beep\"\n";
  1171.         }
  1172.         insert_string( changeString );
  1173.         changeString = ""
  1174.  
  1175.         for (i in insertedKeys)
  1176.             changeString = changeString "#" keyAssignmentName(i)  "\n"\
  1177.                 "assign_key " i " " insertedKeys[i] "\n" ;
  1178.         insert_string( changeString );
  1179.  
  1180.         write_buffer();
  1181.         delete_buffer();
  1182.         current_buffer = cb;
  1183.     }
  1184. }
  1185.  
  1186. ## display names of keys bound to a specified function
  1187. #
  1188. global function function_binding_key( functionName ) {
  1189.     local    fid
  1190.     local    list, arry, keynum, i
  1191.     local    element, delimiter, msg
  1192.  
  1193.     key_names_init()
  1194.  
  1195.     # prompt for function name if not specified
  1196.     if ( !functionName ) {
  1197.         functionName = prompt_history(
  1198.                 "XMACRO",
  1199.                 "Enter function name: ",
  1200.                 "")
  1201.     }
  1202.  
  1203.     # invoke function_binding to get list of keys in #number form
  1204.     if (( fid = function_id( functionName ))) {
  1205.         list = function_binding( fid )
  1206.  
  1207.         # look up key name corresponding to each #number
  1208.         split( list, arry, "#" )
  1209.         for ( i in arry ) {
  1210.             element = arry[i]
  1211.             delimiter = (element ~ / $/) ? "; " : ""
  1212.             if (( keynum = 0+arry[i] )) {
  1213.                 if ( keynum in key_names ) {
  1214.                     element = key_names[ keynum ]
  1215.                 } else if ( keynum > 31 && keynum < 256 ) {
  1216.                     element = chr( keynum )
  1217.                 } else {
  1218.                     element = "#" keynum
  1219.                 }
  1220.                 msg = msg "<" element ">" delimiter
  1221.             }
  1222.         }
  1223.  
  1224.         # display the list
  1225.         notify( "\"%s\" keys: %s", functionName, msg )
  1226.     }
  1227. }
  1228.  
  1229.