home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / p2demo21.exe / PEL / KEYS.PEL < prev    next >
Text File  |  1995-02-10  |  67KB  |  2,301 lines

  1. # $Header:   P:\source\wmacros\keys.pev   1.77   10 Feb 1995 12:32:14   PFHJXM0  $
  2.  
  3. ##############################################################################
  4. #
  5. #       Compuware Corporation
  6. #         31440 Northwestern Highway
  7. #           Farmington Hills, Michigan 48334-2564
  8. #
  9. #   This source code listing contains information that is
  10. #   proprietary to Compuware Corporation and may not be copied
  11. #   duplicated, translated, transmitted, stored, retrieved
  12. #   or in any manner or by any method conveyed or disclosed
  13. #   to a third party or parties without express written
  14. #   permission from Compuware Corporation.
  15. #
  16. #  
  17. ##############################################################################
  18.  
  19. #### $Workfile:   keys.pel  $: Key binding code
  20. #
  21. #
  22.         ## keyboard status keys:
  23.  
  24. global  KB_SHIFTR       = 0x01
  25. global  KB_SHIFTL       = 0x02
  26. global  KB_CTRL         = 0x04
  27. global  KB_ALT          = 0x08
  28. global  KB_SCROLL_LOCK  = 0x10
  29. global  KB_NUM_LOCK     = 0x20
  30. global  KB_CAPS_LOCK    = 0x40
  31. global  KB_INSERT       = 0x80
  32.  
  33.         ## the following codes ambiguously define the equivalent
  34.         ## keys on the two auxiliary "cursor" keypads:
  35.  
  36. global  KEYCODE_HOME
  37. global  KEYCODE_UP
  38. global  KEYCODE_PAGEUP
  39. global  KEYCODE_LEFT
  40. global  KEYCODE_CENTER
  41. global  KEYCODE_RIGHT
  42. global  KEYCODE_END
  43. global  KEYCODE_DOWN
  44. global  KEYCODE_PAGEDOWN
  45.  
  46. global  KEYCODE_CTRL_HOME
  47. global  KEYCODE_CTRL_UP
  48. global  KEYCODE_CTRL_PAGEUP
  49. global  KEYCODE_CTRL_LEFT
  50. global  KEYCODE_CTRL_CENTER
  51. global  KEYCODE_CTRL_RIGHT
  52. global  KEYCODE_CTRL_END
  53. global  KEYCODE_CTRL_DOWN
  54. global  KEYCODE_CTRL_PAGEDOWN
  55.  
  56. global  KEYCODE_NUM_HOME
  57. global  KEYCODE_NUM_UP
  58. global  KEYCODE_NUM_PAGEUP
  59. global  KEYCODE_NUM_LEFT
  60. global  KEYCODE_NUM_RIGHT
  61. global  KEYCODE_NUM_END
  62. global  KEYCODE_NUM_DOWN
  63. global  KEYCODE_NUM_PAGEDOWN
  64.  
  65. global  KEYCODE_CTRL_NUM_HOME
  66. global  KEYCODE_CTRL_NUM_UP
  67. global  KEYCODE_CTRL_NUM_PAGEUP
  68. global  KEYCODE_CTRL_NUM_LEFT
  69. global  KEYCODE_CTRL_NUM_RIGHT
  70. global  KEYCODE_CTRL_NUM_END
  71. global  KEYCODE_CTRL_NUM_DOWN
  72. global  KEYCODE_CTRL_NUM_PAGEDOWN
  73.  
  74. global  KEYCODE_ESC
  75.  
  76.         ## other useful keycodes:
  77. global  KEYCODE_TAB
  78. global  KEYCODE_ENTER
  79. global  KEYCODE_SHIFT
  80. global  KEYCODE_CTRL
  81. global  KEYCODE_ALT
  82. global  KEYCODE_ESC
  83. global  KEYCODE_END
  84. global  KEYCODE_KEYPAD_ENTER
  85. global  KEYCODE_F1
  86. global  KEYCODE_F2
  87. global  KEYCODE_F3
  88. global  KEYCODE_F4
  89. global  KEYCODE_F5
  90. global  KEYCODE_F6
  91. global  KEYCODE_F7
  92. global  KEYCODE_F8
  93. global  KEYCODE_F9
  94. global  KEYCODE_F10
  95. global  KEYCODE_F11
  96. global  KEYCODE_F12
  97. global  KEYCODE_CTRL_AT         # Ctrl-@ (== ctrl-2), ascii byte is 0
  98. global  KEYCODE_CTRL_R
  99. global  KEYCODE_ALT_1
  100. global  KEYCODE_ALT_2
  101. global  KEYCODE_ALT_3
  102. global  KEYCODE_ALT_4
  103. global  KEYCODE_ALT_5
  104. global  KEYCODE_ALT_6
  105. global  KEYCODE_ALT_7
  106. global  KEYCODE_ALT_8
  107. global  KEYCODE_ALT_9
  108. global  KEYCODE_ALT_0
  109.  
  110.  
  111.         ## useful ascii codes:
  112. global  ASCII_BACKSPACE         = 8
  113. global  ASCII_TAB               = 9
  114. global  ASCII_ENTER             = 10
  115. global  ASCII_CR                = 13
  116. global  ASCII_ESC               = 27
  117.  
  118. local   EOF = -1                # value returned upon EOF
  119. local   keystroke
  120. local   symbol_list[]
  121. local   addToBindings[]
  122.  
  123. global function setup_global_keycodes()
  124. {
  125.    # keys on the two auxiliary "cursor" keypads:
  126.  
  127.    KEYCODE_HOME           = key_to_int("<Home>")
  128.    KEYCODE_UP             = key_to_int("<Up>")
  129.    KEYCODE_PAGEUP         = key_to_int("<PageUp>")
  130.    KEYCODE_LEFT           = key_to_int("<Left>")
  131.    KEYCODE_CENTER         = key_to_int("<Num-5>")
  132.    KEYCODE_RIGHT          = key_to_int("<Right>")
  133.    KEYCODE_END            = key_to_int("<End>")
  134.    KEYCODE_DOWN           = key_to_int("<Down>")
  135.    KEYCODE_PAGEDOWN       = key_to_int("<PageDown>")
  136.  
  137.    KEYCODE_CTRL_HOME      = key_to_int("<Ctrl-Home>")
  138.    KEYCODE_CTRL_UP        = key_to_int("<Ctrl-Up>")
  139.    KEYCODE_CTRL_PAGEUP    = key_to_int("<Ctrl-PageUp>")
  140.    KEYCODE_CTRL_LEFT      = key_to_int("<Ctrl-Left>")
  141.    KEYCODE_CTRL_CENTER    = key_to_int("<Ctrl-Num-5>")
  142.    KEYCODE_CTRL_RIGHT     = key_to_int("<Ctrl-Right>")
  143.    KEYCODE_CTRL_END       = key_to_int("<Ctrl-End>")
  144.    KEYCODE_CTRL_DOWN      = key_to_int("<Ctrl-Down>")
  145.    KEYCODE_CTRL_PAGEDOWN  = key_to_int("<Ctrl-PageDown>")
  146.    
  147.    KEYCODE_NUM_HOME       = key_to_int("<Num-Home>")
  148.    KEYCODE_NUM_UP         = key_to_int("<Num-Up>")
  149.    KEYCODE_NUM_PAGEUP     = key_to_int("<Num-PageUp>")
  150.    KEYCODE_NUM_LEFT       = key_to_int("<Num-Left>")
  151.    KEYCODE_NUM_RIGHT      = key_to_int("<Num-Right>")
  152.    KEYCODE_NUM_END        = key_to_int("<Num-End>")
  153.    KEYCODE_NUM_DOWN       = key_to_int("<Num-Down>")
  154.    KEYCODE_NUM_PAGEDOWN   = key_to_int("<Num-PageDown>")
  155.  
  156.    KEYCODE_ALT_1          = key_to_int("<ALT-1>")
  157.    KEYCODE_ALT_2          = key_to_int("<ALT-2>")
  158.    KEYCODE_ALT_3          = key_to_int("<ALT-3>")
  159.    KEYCODE_ALT_4          = key_to_int("<ALT-4>")
  160.    KEYCODE_ALT_5          = key_to_int("<ALT-5>")
  161.    KEYCODE_ALT_6          = key_to_int("<ALT-6>")
  162.    KEYCODE_ALT_7          = key_to_int("<ALT-7>")
  163.    KEYCODE_ALT_8          = key_to_int("<ALT-8>")
  164.    KEYCODE_ALT_9          = key_to_int("<ALT-9>")
  165.    KEYCODE_ALT_0          = key_to_int("<ALT-0>")
  166.    
  167.    KEYCODE_CTRL_NUM_HOME      = key_to_int("<Ctrl-Num-Home>")
  168.    KEYCODE_CTRL_NUM_UP        = key_to_int("<Ctrl-Num-Up>")
  169.    KEYCODE_CTRL_NUM_PAGEUP    = key_to_int("<Ctrl-Num-PageUp>")
  170.    KEYCODE_CTRL_NUM_LEFT      = key_to_int("<Ctrl-Num-Left>")
  171.    KEYCODE_CTRL_NUM_RIGHT     = key_to_int("<Ctrl-Num-Right>")
  172.    KEYCODE_CTRL_NUM_END       = key_to_int("<Ctrl-Num-End>")
  173.    KEYCODE_CTRL_NUM_DOWN      = key_to_int("<Ctrl-Num-Down>")
  174.    KEYCODE_CTRL_NUM_PAGEDOWN  = key_to_int("<Ctrl-Num-PageDown>")
  175.    
  176.    KEYCODE_ESC            = key_to_int("<Esc>")
  177.    
  178.    ## other useful keycodes:
  179.    KEYCODE_TAB             = key_to_int("<Tab>")
  180.    KEYCODE_ENTER           = key_to_int("<Enter>")
  181.    KEYCODE_SHIFT           = key_to_int("<Shift>")
  182.    KEYCODE_CTRL            = key_to_int("<Ctrl>")
  183.    KEYCODE_ALT             = key_to_int("<Alt>")
  184.    KEYCODE_ESC             = key_to_int("<Esc>")
  185.    KEYCODE_END             = key_to_int("<End>")
  186.    KEYCODE_KEYPAD_ENTER    = key_to_int("<Num-Enter>")
  187.    KEYCODE_F1              = key_to_int("<F1>")
  188.    KEYCODE_F2              = key_to_int("<F2>")
  189.    KEYCODE_F3              = key_to_int("<F3>")
  190.    KEYCODE_F4              = key_to_int("<F4>")
  191.    KEYCODE_F5              = key_to_int("<F5>")
  192.    KEYCODE_F6              = key_to_int("<F6>")
  193.    KEYCODE_F7              = key_to_int("<F7>")
  194.    KEYCODE_F8              = key_to_int("<F8>")
  195.    KEYCODE_F9              = key_to_int("<F9>")
  196.    KEYCODE_F10             = key_to_int("<F10>")
  197.    KEYCODE_F11             = key_to_int("<F11>")
  198.    KEYCODE_F12             = key_to_int("<F12>")
  199.    KEYCODE_CTRL_AT         = key_to_int("<Ctrl-2>")
  200.    KEYCODE_CTRL_R          = key_to_int("<Ctrl-R>")
  201. }
  202.  
  203. ### program a key to playback a recorded sequence
  204. #
  205. local   learning                # semaphore for recursive calls to learn_key
  206. local   learned_key             # array of key->playback string associations
  207.  
  208. global function learn_key()                                     #PUBLIC #VOID
  209. {
  210.    local   learn_name              # name of key being learned
  211.    local   key
  212.    local   binding
  213.  
  214.    # a recursive call to this function ends the recording process
  215.    if ( learning )
  216.    {
  217.       process_end()
  218.       return
  219.    }
  220.  
  221.    # prompt for the key to learn and get the name
  222.    optional_function( "enable_status_bar_messages" )
  223.    notify( "Press key to be recorded" )
  224.    key = getKey()
  225.    optional_function( "restore_status_bar" )
  226.  
  227.    if ( key == EOF )
  228.    {
  229.       message( "Cancelled." )
  230.       return
  231.    }
  232.  
  233.    # get the name of the key to learn
  234.    learn_name = key_name( key )
  235.  
  236.    # make sure it is alright to overwrite the previous binding
  237.    binding = keymap_binding( learn_name )
  238.    if ( binding )
  239.    {
  240.       binding = sprintf( "%s is bound to %s; redefine?", learn_name, binding )
  241.       if ( tolower( confirm( binding, "YyNn" )) != "y" )
  242.       {
  243.          message( "Canceled." )
  244.          return
  245.       }
  246.    }
  247.    assign_key( learn_name, "learn_key" )   # terminator
  248.  
  249.    optional_function( "enable_status_bar_messages" )
  250.    notify( "Recording key sequence for %s...press %s again to terminate", \
  251.            learn_name, learn_name )
  252.  
  253.    while ( !keyboard_input_pending )
  254.       idle()
  255.  
  256.    optional_function( "restore_status_bar ")
  257.  
  258.    # enable recording
  259.    record( 1 )
  260.    learning = 1    # recursion flag
  261.    process_begin()
  262.  
  263.    # we continue here after the process_end, which will happen during
  264.    # the next recursive call to learn_key().
  265.  
  266.    learning = 0
  267.  
  268.    # create a key binding for the learned sequence
  269.    learned_key[ key ] = record( 0 )
  270.    assign_key( learn_name, "playback_learn_key" )
  271.  
  272.    notify( "Reprogrammed %s Key", learn_name )
  273. }
  274.  
  275. global function playback_learn_key()
  276. {
  277.    playback( learned_key[ current_key ])
  278. }
  279.  
  280. ### print statistics about keys as they are entered
  281. #
  282. global function print_keys()
  283. {
  284.    local key
  285.  
  286.    optional_function( "enable_status_bar_messages" )
  287.    notify( "Press keys to be printed..." )
  288.  
  289.    while(( key = getKey()) != EOF )
  290.    {
  291.       notify( "Keycodes: 0x%04x  #%05u  (%03u)  \"%s\"",      \
  292.               key,                                            \
  293.               key,                                            \
  294.               int_to_ascii(key),                              \
  295.               key_name( key ))
  296.    }
  297.  
  298.    message( "" )
  299.    optional_function( "restore_status_bar ")
  300. }
  301.  
  302. global function print_chars()
  303. {
  304.    local key
  305.  
  306.    optional_function( "enable_status_bar_messages" )
  307.    notify( "Press keys to be printed..." )
  308.  
  309.    while(( key = getchar()) != ASCII_ESC )
  310.    {
  311.       notify( "Keycodes: 0x%04x  #%05u  (%03u)  \"%s\"",      \
  312.               key,                                            \
  313.               key,                                            \
  314.               int_to_ascii(key),                              \
  315.               key_name( key ))
  316.    }
  317.  
  318.    message( "" )
  319.    optional_function( "restore_status_bar ")
  320. }
  321.  
  322. ### read a key and print its binding
  323. #
  324. local reentrant_print_bindings = 0
  325.  
  326. global function print_bindings()
  327. {
  328.    local seq, key
  329.  
  330.    # don't allow reentering the print_bindings if we
  331.    # are already in here
  332.    if ( reentrant_print_bindings )
  333.    {
  334.       # just in case message has disappeared
  335.       notify( "Press keys to be looked-up..." )
  336.       return;
  337.    }
  338.  
  339.    reentrant_print_bindings = 1
  340.  
  341.    optional_function( "enable_status_bar_messages" )
  342.    notify( "Press keys to be looked-up..." )
  343.  
  344.    while(( key = getKey()) != EOF )
  345.    {
  346.       seq = key_encoding( key, 1 )
  347.  
  348.       notify( "0x%04x  #%05u  (%03u)  \"%s\"  is bound to %s",\
  349.               key,                                            \
  350.               key,                                            \
  351.               int_to_ascii(key),                              \
  352.               key_name( key ),                                \
  353.               keymap_binding( seq ))
  354.    }
  355.  
  356.    message( "" )
  357.    optional_function( "restore_status_bar" )
  358.  
  359.    reentrant_print_bindings = 0
  360. }
  361.  
  362. ## display names of keys bound to a specified function
  363. #
  364. global function function_binding_key( functionName, noBrackets, plus, noShow )
  365. {
  366.    local   fid
  367.    local   list, arry, keynum, i
  368.    local   element, delimiter, msg
  369.  
  370.    # prompt for function name if not specified
  371.    if (!functionName)
  372.         functionName = prompt_history( "XMACRO", "Enter function name: ", "", 1, 1, "function_binding_dialog" )
  373.  
  374.    # invoke function_binding to get list of keys in #number form
  375.    if (( fid = function_id( functionName )))
  376.    {
  377.       list = function_binding( fid )
  378.  
  379.       # look up key name corresponding to each #number
  380.       split( list, arry, "#" )
  381.       for ( i in arry )
  382.       {
  383.          element = arry[i]
  384.          delimiter = (element ~ / $/) ? " | " : ""
  385.          if (( keynum = 0+arry[i] ))
  386.          {
  387.             element = int_to_key( keynum, plus )
  388.             
  389.             # remove the angle brackets
  390.             #
  391.             if ( noBrackets )
  392.             {
  393.                gsub("\\<", "", element)
  394.                gsub("\\>", "", element)
  395.             }
  396.  
  397.             # append new key and delimiter to list of keys
  398.             #
  399.             msg = msg element delimiter
  400.          }
  401.       }
  402.  
  403.       # display the list of keys on status bar
  404.       #
  405.       if (!noShow)
  406.          notify( "\"%s\" keys: %s", functionName, msg )
  407.    }
  408.    return msg
  409. }
  410.  
  411. ## 
  412. #
  413. global function list_keymap( format, noBrackets, plus )
  414. {
  415.    local   i
  416.    local   j
  417.    local   len
  418.    local   str
  419.    local   fid
  420.    local   keys
  421.    local   list
  422.    local   arry
  423.    local   count
  424.    local   keynum
  425.    local   txtfile
  426.    local   symbol_list
  427.    local   LIST_LENGTH = 30
  428.    local   cb          = current_buffer
  429.  
  430.    # coerce format to a number.
  431.    format = tolower(format)
  432.    if (format == 2 || prefix(format, 1) == "p" || format ~ "pel")
  433.       format = 2
  434.    else if (format == 1 || prefix(format, 1) == "c" || format ~ "cfg")
  435.       format = 1
  436.    else
  437.       format = 0
  438.  
  439.    # coerce other params to numbers.
  440.    noBrackets = noBrackets+0
  441.    plus = plus+0
  442.  
  443.    # search cpe path for the help menu file
  444.    if ( !(txtfile = locate_cpe_file(CPE_FILE_KEYMAP)))
  445.           txtfile = editor_path(CPE_FILE_KEYMAP)
  446.  
  447.    if (format == 2)
  448.       txtfile = bld_fnam(txtfile, txtfile, "pel")
  449.    else if (format)
  450.       txtfile = bld_fnam(txtfile, txtfile, "cfg")
  451.  
  452.    current_buffer = create_buffer( txtfile, txtfile, BUFFER_SCRATCH )
  453.  
  454.    if (buffer_size)
  455.    {
  456.       goto_buffer_top()
  457.       begin_selection( LINE_SELECTION )
  458.       goto_buffer_bottom()
  459.       delete_chars()
  460.    }
  461.  
  462.    # in case symbol_match takes a long time
  463.    if ( status_bar_flags )
  464.       message( "Working..." )
  465.  
  466.    # read a list of all primitives & global functions.
  467.    symbol_list = symbol_match("", PRIMITIVE_FUN + GLOBAL_FUN)
  468.    if (symbol_list)
  469.    {
  470.       for (i in symbol_list)
  471.       {
  472.          str = symbol_list[i]
  473.          if (str != "insert_key")
  474.          {
  475.             if (format)
  476.             {
  477.                if (( fid = function_id( str )))
  478.                {
  479.                   list = function_binding( fid )
  480.             
  481.                   # look up key name corresponding to each #number
  482.                   split( list, arry, "#" )
  483.                   for ( j in arry )
  484.                   {
  485.                      if (( keynum = 0+arry[j] ))
  486.                      {
  487.                         if (format == 2)  # PEL File Format
  488.                         {
  489.                            insert_string("\tassign_key(\"" \
  490.                                          int_to_key( keynum, plus ) \
  491.                                          "\", \"" str "\")" )
  492.                            insert_newline()
  493.                         }
  494.                         else              # Config file format
  495.                         {
  496.                            insert_string("assign_key \"" \
  497.                                          int_to_key( keynum, plus ) \
  498.                                          "\" \"" str "\"" )
  499.                            insert_newline()
  500.                         }
  501.                      }
  502.                   }
  503.                }
  504.             }
  505.             else                          # Text Report Format
  506.             {
  507.                keys = function_binding_key(str, noBrackets, plus, TRUE)
  508.                if (keys && length(keys))
  509.                {
  510.                   len = length(str)
  511.                   if (len < LIST_LENGTH)
  512.                      str = str strrepeat(" ", LIST_LENGTH - len)
  513.    
  514.                   insert_string(str " : " keys)
  515.                   insert_newline()
  516.    
  517.                   if (count++ > 10)
  518.                   {
  519.                      update_current_view()
  520.                      count = 0
  521.                   }
  522.                }
  523.             }
  524.          }
  525.       }
  526.  
  527.       if ( status_bar_flags )
  528.          message( "Working........." )
  529.  
  530.       filter("sort")
  531.       goto_buffer_top()
  532.       buffer_flags = and(buffer_flags, not(BUFFER_MODIFIED))
  533.    }
  534.    else
  535.    {
  536.       notify( "Cannot find keymap information")
  537.       delete_buffer( current_buffer )
  538.       current_buffer = cb
  539.    }
  540.  
  541.    if ( status_bar_flags )
  542.       message( "" )
  543. }
  544.  
  545. ### read a key and insert the corresponding "#"-sequence
  546. #
  547. global function insert_keys()
  548. {
  549.    local   key
  550.    local   str
  551.    local   priorWindow = current_window
  552.  
  553.    optional_function( "enable_status_bar_messages" )
  554.    notify( "Press keys to be converted and inserted..." )
  555.  
  556.    while(( key = getKey()) != EOF )
  557.    {
  558.       if(( str = key_encoding( key, 1 )))
  559.       {
  560.          if (priorWindow)
  561.             current_window = priorWindow
  562.  
  563.          insert_string( str )
  564.          ## raise_window( dialog_window )
  565.          update_current_view()
  566.       }
  567.       else
  568.          break
  569.    }
  570.  
  571.    # remove temp dialog window if we created one above
  572.    message( "" )
  573.    optional_function( "restore_status_bar ")
  574. }
  575.  
  576. ### Read keys from the keyboard and insert them into the buffer if
  577. #       they represent valid ASCII characters.
  578. #
  579. # See also:     insert_quoted_key()     # singluar
  580.  
  581. local reentrant_insert_quoted_keys = 0
  582.  
  583. global function insert_quoted_keys()
  584. {
  585.    local   key
  586.    local   ascii
  587.    local   priorWindow = current_window
  588.  
  589.    # don't allow reentering the insert_quoted_keys if we
  590.    # are already in here
  591.    if ( reentrant_insert_quoted_keys )
  592.    {
  593.       # just in case message has disappeared
  594.       notify( "Press ASCII keys to be inserted..." )
  595.       return;
  596.    }
  597.  
  598.    reentrant_insert_quoted_keys = 1
  599.  
  600.    optional_function( "enable_status_bar_messages" )
  601.    notify( "Press ASCII keys to be inserted..." )
  602.  
  603.    while(( key = getKey()) != EOF )
  604.    {
  605.       notify( "Press ASCII keys to be inserted..." )
  606.  
  607.       ascii = int_to_ascii(key)
  608.  
  609.       if ( (ascii == 0    && key != KEYCODE_CTRL_AT) ||
  610.            (ascii == 0xe0 && key != ascii) )
  611.       {
  612.          warning( "non-ASCII key ignored" )
  613.       }
  614.       else
  615.       {
  616.          if (priorWindow)
  617.             current_window = priorWindow
  618.  
  619.          if (ascii == ASCII_TAB)
  620.             insert_string( "\t" )
  621.          else
  622.             insert_key( ascii )
  623.  
  624.          ## raise_window( dialog_window )
  625.          update_current_view()
  626.       }
  627.    }
  628.  
  629.    # remove temp dialog window if we created one above
  630.    message( "" )
  631.    optional_function( "restore_status_bar" )
  632.  
  633.    reentrant_insert_quoted_keys = 0
  634. }
  635.  
  636. ### Read the next key from the keyboard and insert it into the buffer if
  637. #       it represents a valid ASCII character.
  638. #
  639. # See also:     insert_quoted_keys()  # plural
  640.  
  641. local reentrant_insert_quoted_key = 0
  642.  
  643. global function insert_quoted_key()
  644. {
  645.    local   key, ascii
  646.    local   priorWindow = current_window
  647.  
  648.    # don't allow reentering the insert_quoted_key if we
  649.    # are already in here
  650.    if ( reentrant_insert_quoted_key )
  651.    {
  652.       # just in case message has disappeared
  653.       notify( "Press ASCII key to be inserted..." )
  654.       return;
  655.    }
  656.  
  657.    reentrant_insert_quoted_key = 1
  658.  
  659.    optional_function( "enable_status_bar_messages" )
  660.    notify( "Press ASCII key to be inserted..." )
  661.  
  662.    if (( key = getKey()) != EOF )
  663.    {
  664.       ascii = int_to_ascii(key)
  665.       if ( (ascii == 0    && key != KEYCODE_CTRL_AT) ||
  666.            (ascii == 0xe0 && key != ascii) )
  667.       {
  668.          warning( "non-ASCII key ignored" )
  669.       }
  670.       else
  671.       {
  672.          if (priorWindow)
  673.             current_window = priorWindow
  674.  
  675.          if (ascii == ASCII_TAB)
  676.             insert_string( "\t" )
  677.          else
  678.             insert_key( ascii )
  679.  
  680.          message( "" )
  681.       }
  682.    }
  683.  
  684.    # remove temp dialog window if we created one above
  685.    optional_function( "restore_status_bar" )
  686.  
  687.    reentrant_insert_quoted_key = 0
  688. }
  689.  
  690. ### convert a keycode to a "#"-sequence
  691. #
  692.  
  693. global function key_encoding( key, distinguish )
  694. {
  695.    if( distinguish )
  696.       return sprintf( "#%u", key )
  697.    else
  698.       return sprintf( "#%u", int_to_ascii(key) )
  699. }
  700.  
  701. ### returns the name of a key given a key code
  702. #
  703.  
  704. global function key_name( keycode )
  705. {
  706.    local   ascii
  707.  
  708.    # strip off the leading '#' if necessary
  709.    if ( keycode ~ /^#/ ) 
  710.    {
  711.       keycode = substr( keycode, 2 )
  712.    }
  713.  
  714.    # there was code here that used the key_names[] array. int_to_key() seems
  715.    # much easier to use
  716.    return int_to_key( keycode )
  717. }
  718.  
  719. ## Return a keycode from the keyboard, waiting until a key is actually pressed.
  720. #       Escape prompts the user to return either the escape keycode or EOF.
  721.  
  722. local function getKey(esc_ok)
  723. {
  724.    local ch, resp
  725.  
  726.    ch = getkey()
  727.  
  728.    if ( argcount() && esc_ok)
  729.       return ch
  730.  
  731.    else if ( ( ch == KEYCODE_ESC ) &&
  732.              tolower(confirm( "Terminate key sequence? ", "YyNn\r" )) != "n")
  733.    {
  734.       return EOF
  735.    }
  736.    else
  737.       return ch
  738. }
  739.  
  740. ## Prompts the user to press a key and returns the Keycode pressed.
  741.  
  742. global function getKeystroke(text, handle)
  743. {
  744.    local char
  745.    local id = function_id( "key_pressed" );
  746.    attach_event_handler( EVENT.INVALID_PCHAR, id )
  747.    keystroke = 0
  748.    char      = confirm( text, "", handle )
  749.    if (!keystroke)
  750.    {
  751.       if (char == " ")
  752.          keystroke = key_to_int("<Space>")
  753.       else
  754.          keystroke = key_to_int(char)
  755.    }
  756.    delete_event( EVENT.INVALID_PCHAR, id )
  757.    return keystroke
  758. }
  759.  
  760. global function key_pressed()
  761. {
  762.    keystroke   = current_key
  763.    current_key = KEYCODE_ESC
  764. }
  765.  
  766. #----------------------------------------------------------------------
  767.  
  768. ### view or edit the current key bindings
  769. #
  770.  
  771. local IDM_FIRST_ITEM    = 3809
  772. local IDM_NEXT          = 3809
  773. local IDM_PREV          = 3810
  774. local IDM_DEL           = 3811
  775. local IDM_INS           = 3812
  776. local IDM_WIN           = 3813
  777. local IDM_EXIT_KEYS     = 3814
  778. local IDM_MKEYS         = 3815
  779. local IDM_LAST_ITEM     = 3815
  780.  
  781. local   bindingsInitialized = 0
  782. local   currentFunction     = ""
  783. local   keysRead            = 0
  784.  
  785. local   bindingListBuffer
  786. local   bindingDispBuffer
  787. local   bindingListWindow
  788. local   bindingDispWindow
  789. local   lastBindingLine
  790. local   startingKeymap
  791. local   bindingKeymap
  792. local   windowHeight
  793. local   keyBindings[]
  794. local   deletedKeys[]
  795. local   insertedKeys[]
  796.  
  797. local   old_window
  798. local   old_buffer
  799. local   old_mdi_mode
  800. local   old_toolbar
  801. local   old_menu
  802.  
  803. local function binding_init()
  804. {
  805.    local   i
  806.    local   len
  807.    local   str
  808.    local   line
  809.    local   eol_str
  810.    local   txtfile
  811.    local   buffOff
  812.    local   symbol_list
  813.    local   cb = current_buffer
  814.  
  815.    # retrieve the current user key assignments from the config file.
  816.    #
  817.    if (!keysRead)
  818.    {
  819.       delete( keyBindings )
  820.       delete( deletedKeys )
  821.       delete( insertedKeys )
  822.       read_key_assignments()
  823.       keysRead = TRUE;
  824.    }
  825.  
  826.    # search cpe path for the help menu file
  827.    if ( !(txtfile = locate_cpe_file(CPE_FILE_BINDINGS)))
  828.           txtfile = editor_path( CPE_FILE_BINDINGS )
  829.  
  830.    eol_str                   = default_buffer_eol_string
  831.    default_buffer_eol_string = "\r\n"
  832.  
  833.    current_buffer    = \
  834.    bindingListBuffer = create_buffer( txtfile, txtfile, BUFFER_SYSTEM + \
  835.                                                         BUFFER_NO_UNDO )
  836.  
  837.    default_buffer_eol_string = eol_str
  838.  
  839.    if (buffer_size)
  840.    {
  841.       while(current_line < buffer_last_line)
  842.       {
  843.          line = read_buffer(1)
  844.          if (line == "#")
  845.             delete_line()
  846.          else
  847.             down()
  848.       }
  849.       goto_buffer_top()
  850.    }
  851.    else
  852.    {
  853.       # couldn't find the help information
  854.       # in case symbol_match takes a long time
  855.       if ( status_bar_flags )
  856.          message( "Working..." )
  857.  
  858.       # read a list of all primitives & global functions.
  859.       symbol_list = symbol_match("", 0x05)
  860.       if (symbol_list)
  861.       {
  862.          for (i in symbol_list)
  863.          {
  864.             insert_string(symbol_list[i])
  865.             insert_newline()
  866.          }
  867.       }
  868.       else
  869.       {
  870.          # couldn't find the help information
  871.          notify( "Cannot find binding information in: %s", txtfile )
  872.          current_buffer = cb
  873.          delete_buffer( bindingListBuffer )
  874.          return FALSE
  875.       }
  876.    }
  877.  
  878.    filter("sort")
  879.  
  880.    if ( status_bar_flags )
  881.       message( "" )
  882.  
  883.    bindingDispBuffer = create_buffer( "Binding", "", \
  884.                                       BUFFER_SYSTEM+BUFFER_NO_UNDO)
  885.  
  886.    current_buffer = cb
  887.    message( "" )
  888.  
  889.    return TRUE
  890. }
  891.  
  892. global function keys()
  893. {
  894.    local i
  895.    local width
  896.  
  897.    old_window = current_window
  898.    old_buffer = current_buffer
  899.  
  900.    if (!bindingsInitialized)
  901.    {
  902.       if ( binding_init() )
  903.          bindingsInitialized = 1
  904.       else
  905.          return
  906.    }
  907.  
  908.    optional_function( "enable_status_bar_messages" )
  909.  
  910.    lastBindingLine = 0
  911.    startingKeymap  = current_keymap
  912.    bindingKeymap   = create_keymap( empty_keymap )
  913.    push_keymap( bindingKeymap )
  914.  
  915.    # hide toolbar and change menus during keys
  916.    #
  917.    old_toolbar = optional_function( "toggle_toolbar", 0 )
  918.  
  919.    # Turn MDI on,
  920.    #
  921.    old_mdi_mode = mdi_mode
  922.    if (!old_mdi_mode)
  923.    {
  924.       optional_function( "switch_to_mdi" )
  925.       delete_window( current_window )
  926.    }
  927.  
  928.    keys_menu()
  929.    old_menu = change_menu(menu)
  930.    
  931.    # calculate the window sizes.
  932.    #
  933.    windowHeight   = display_height
  934.    width          = display_width / 2
  935.  
  936.    # create the list window and shadow which will contain the list of keys
  937.    # binding items
  938.    #
  939.    current_window    = \
  940.    bindingListWindow = create_factory_window( 0, 0, width, windowHeight,
  941.                                               WINDOW_PLAIN + WINDOW_SYSTEM + \
  942.                                               WINDOW_VERT_SB )
  943.    window_name  = "Functions"
  944. #  color_border = BAR_COLOR
  945. #  color_text   = BAR_COLOR
  946.    attach_window_buffer( bindingListWindow, bindingListBuffer )
  947.    initBindingAttributes()
  948.    restore_window(bindingListWindow)
  949.  
  950.    #
  951.    # create the display window and shadow which will contain the function names
  952.    #
  953.    current_window    = \
  954.    bindingDispWindow = create_factory_window(width, 0, width, windowHeight, \
  955.                                              WINDOW_PLAIN + WINDOW_SYSTEM)
  956. #  color_border = BAR_COLOR
  957. #  color_text   = BAR_COLOR
  958.    window_name  = "Bindings"
  959.    initBindingAttributes()
  960.    attach_window_buffer( bindingDispWindow, bindingDispBuffer )
  961.    restore_window(bindingDispWindow)
  962.  
  963.    current_window = bindingListWindow
  964.  
  965.    goto_buffer_top()
  966.    begin_selection( LINE_SELECTION )
  967.    end_selection()
  968.    update_current_view()
  969.    updateBindItem()
  970.  
  971.    # create a keymap for use in the keys windows
  972.    #
  973.    assign_key( "<Esc>",            "exit_keys" )
  974.    assign_key( "<Home>",           "bindHome" )
  975.    assign_key( "<End>",            "bindEnd" )
  976.    assign_key( "<Up>",             "bindUp 1" )
  977.    assign_key( "<Down>",           "bindDown 1" )
  978.    assign_key( "<PageUp>",         "bindPageUp" )
  979.    assign_key( "<PageDown>",       "bindPageDown" )
  980.    assign_key( "<Tab>",            "bindToggleWindow" )
  981.    assign_key( "<Left>",           "bindToggleWindow 1" )
  982.    assign_key( "<Right>",          "bindToggleWindow 0" )
  983.    assign_key( "<Alt-H>",          "display_help_item keys" )
  984.    assign_key( "<Delete>",         "bindDelete" )
  985.    assign_key( "<Insert>",         "bindIns" )
  986.  
  987.    # redefine the mouse actions.
  988.    #
  989.    attach_event_handler(EVENT.MOUSE_LEFT_DOWN, function_id("bindMouseDown"))
  990.    attach_event_handler(EVENT.MOUSE_LEFT_UP,   function_id("updateBindItem"))
  991.    attach_event_handler(EVENT.LMOUSE_DRAG,     function_id("bindMouseDown"))
  992.    attach_event_handler(EVENT.RESIZE_EDITWIN,  function_id("bindResize"))
  993.    delete_event(EVENT.LMOUSE_DRAG,             function_id("lmouse_drag"))
  994.    delete_event(EVENT.MOUSE_LEFT_DOWN,         function_id("mouse_left_down"))
  995.    delete_event(EVENT.MOUSE_LEFT_UP,           function_id("mouse_left_up"))
  996.    delete_event(EVENT.RESIZE_EDITWIN,          function_id("resize_editwin"))
  997.  
  998.    current_window = bindingDispWindow
  999.    bindToggleWindow( 1 )
  1000. #  process_begin()
  1001. }
  1002.  
  1003. global function read_key_assignments()
  1004. {
  1005.    local i
  1006.    local p
  1007.    local s
  1008.    local key
  1009.    local fun
  1010.    local cmt
  1011.    local data = read_config_section( "$KEY_ASSIGNMENTS$", 0, 1, 1 )
  1012.  
  1013.    for (i in data)
  1014.    {
  1015.       s = data[i]
  1016.       if (prefix(s, 11) == "assign_key ")
  1017.       {
  1018.          s   = substr(s, 12)
  1019.          p   = cindex(s, " ")
  1020.          key = unquote_string(substr(s, 2, p-3))
  1021.          fun = substr(s, p+1)
  1022.  
  1023.          # strip off surrounding quotes
  1024.          if ( prefix(fun, 1) == "\"" && suffix(fun, 1) == "\"" )
  1025.             fun = substr( fun, 2, length(fun) - 2 )
  1026.  
  1027.          if (fun == "beep")
  1028.          {
  1029.             if (match(cmt, /\<.*\> was /))
  1030.                deletedKeys[ key ] = substr(cmt, RSTART+RLENGTH)
  1031.             else
  1032.                deletedKeys[ key ] = "unknown"
  1033.          }
  1034.          else
  1035.             insertedKeys[ key ] = fun
  1036.       }
  1037.       else if(prefix(s, 1) == "#")
  1038.          cmt = s
  1039.    }
  1040. }
  1041.  
  1042. global function exit_keys()
  1043. {
  1044.    local i
  1045.  
  1046. #  process_end()
  1047.    pop_keymap()
  1048.  
  1049.    saveKeys()
  1050.  
  1051.    attach_event_handler(EVENT.LMOUSE_DRAG,     function_id("lmouse_drag"))
  1052.    attach_event_handler(EVENT.MOUSE_LEFT_DOWN, function_id("mouse_left_down"))
  1053.    attach_event_handler(EVENT.MOUSE_LEFT_UP,   function_id("mouse_left_up"))
  1054.    attach_event_handler(EVENT.RESIZE_EDITWIN,  function_id("resize_editwin"))
  1055.    delete_event(EVENT.MOUSE_LEFT_DOWN,         function_id("bindMouseDown"))
  1056.    delete_event(EVENT.MOUSE_LEFT_UP,           function_id("updateBindItem"))
  1057.    delete_event(EVENT.LMOUSE_DRAG,             function_id("bindMouseDown"))
  1058.    delete_event(EVENT.RESIZE_EDITWIN,          function_id("bindResize"))
  1059.  
  1060.    delete_keymap( bindingKeymap )
  1061.    delete_window( bindingListWindow )
  1062.    delete_window( bindingDispWindow )
  1063.  
  1064.    change_menu( old_menu )
  1065.  
  1066.    # delete our local list that maps function id's to menu item
  1067.    # id's.  This list was created during the append_menuitem calls.   
  1068.    for ( i = IDM_FIRST_ITEM; i <= IDM_LAST_ITEM; i++ )
  1069.       if ( i in menu_functions )
  1070.          delete menu_functions[i]
  1071.  
  1072.    delete_menu( submenu )
  1073.    delete_menu( menu )
  1074.  
  1075.    # Restore the MDI mode to it's previous value.
  1076.    #
  1077.    if (!old_mdi_mode)
  1078.       optional_function( "switch_to_sdi" )
  1079.  
  1080.    current_buffer = old_buffer
  1081.  
  1082.    # re-enable both toolbar and menu
  1083.    optional_function( "toggle_toolbar", old_toolbar )
  1084.  
  1085.    current_key = 0
  1086.    display_redraw()
  1087.    optional_function( "restore_status_bar" )
  1088.    message( "" )
  1089. }
  1090.  
  1091. #
  1092. # initialize the attribute and window names for the binding windows
  1093. # win == 1 setting display window, win == 2 setting list window
  1094. #
  1095. local function initBindingAttributes()
  1096. {
  1097. #  color_highlight = HBAR_COLOR
  1098.    visible_virtual_lines  = ""
  1099.    visible_virtual_spaces = ""
  1100.    visible_end_buffer     = ""
  1101. }
  1102.  
  1103.  
  1104. function showBindingItem( lineNum )
  1105. {
  1106.    local   cw = current_window
  1107.    local   ln
  1108.    local   i
  1109.    local   arr
  1110.    local   msg_lvl
  1111.  
  1112.    if (current_window == bindingDispWindow)
  1113.       return
  1114.  
  1115.    delete( keyBindings )
  1116.  
  1117.    goto_bol()
  1118.    ln = read_buffer()
  1119.    if (match(ln, chr(29)".*$"))
  1120.       ln = suffix(ln, RLENGTH - 1)
  1121.  
  1122.    goto_bol()
  1123.  
  1124.    current_window = bindingDispWindow
  1125.  
  1126.    goto_buffer_top()
  1127.    while (delete_line())
  1128.       continue
  1129.    goto_bol()
  1130.  
  1131.    if ((ln != "") && (!keyboard_input_pending))
  1132.    {
  1133.       msg_lvl = message_level
  1134.       message_level = 2
  1135.       currentFunction = ln
  1136.       ln = function_binding( function_id( ln ), startingKeymap )
  1137.       message_level = msg_lvl
  1138.       split( ln, arr, " " ) + 1
  1139.       for (i in arr)
  1140.       {
  1141.          ln = keyAssignmentName( arr[i] )
  1142.          insert_string( ln )
  1143.          keyBindings[ ln ] = arr[i]
  1144.          if (i+1 in arr)
  1145.             insert_newline()
  1146.       }
  1147.    }
  1148.  
  1149.    goto_buffer_top()
  1150.    current_window = cw
  1151. }
  1152.  
  1153. local function keyAssignmentName( str )
  1154. {
  1155.    local   keyarr
  1156.    local   i
  1157.    local   ln = ""
  1158.  
  1159.    if (prefix(str, 1) == "<" && suffix(str, 1) == ">")
  1160.       return str
  1161.    else
  1162.    {
  1163.       split( str, keyarr, "#" )
  1164.       for (i in keyarr)
  1165.       {
  1166.          if (keyarr[i])
  1167.             ln = ln key_name( atoi(keyarr[i]) )
  1168.       }
  1169.       delete( keyarr )
  1170.       return ln
  1171.    }
  1172. }
  1173.  
  1174. global function bindResize()
  1175. {
  1176.    local width, height
  1177.    frame_window( 0, 0, display_width / 2, display_height, bindingListWindow )
  1178.  
  1179.    frame_window( display_width / 2, 0, display_width / 2, display_height, \
  1180.                  bindingDispWindow )
  1181. }
  1182.  
  1183. global function bindMouseDown()
  1184. {
  1185.    local line
  1186.  
  1187.    if (current_window == bindingDispWindow)
  1188.       bindToggleWindow( 0 )
  1189.  
  1190.    else if (current_window == bindingListWindow)
  1191.       bindToggleWindow( 1 )
  1192.  
  1193.    line = mouse_event_y + window_first
  1194.    if (line != mark_line(selection_mark_top()))
  1195.    {
  1196.       remove_selection()
  1197.       update_current_view()
  1198.       goto_pos(line, mouse_event_x + 1 )
  1199.       begin_selection( LINE_SELECTION )
  1200.       end_selection()
  1201.       update_current_view()
  1202.    }
  1203. }
  1204.  
  1205. function bindToggleWindow( left )
  1206. {
  1207.    if (current_window == bindingDispWindow)
  1208.    {
  1209.       message( " , \x1a=window, <Esc>, <Ins>,           <Alt-H>=HELP" )
  1210.       if (argcount() && !(left+0))
  1211.          return
  1212.  
  1213.       remove_selection()
  1214.       update_current_view()
  1215.       current_window = bindingListWindow
  1216.    }
  1217.    else
  1218.    {
  1219.       message( " , \x1b=window, <Esc>, <Ins>, <Del>     <Alt-H>=HELP" )
  1220.       if (argcount() && left+0)
  1221.          return
  1222.  
  1223.       current_window = bindingDispWindow
  1224.       begin_selection( LINE_SELECTION )
  1225.       end_selection()
  1226.       update_current_view()
  1227.    }
  1228. }
  1229.  
  1230. global function bindHome()
  1231. {
  1232.    remove_selection()
  1233.    update_current_view()
  1234.    current_line = 1
  1235.    begin_selection( LINE_SELECTION )
  1236.    end_selection()
  1237.    update_current_view()
  1238.    updateBindItem()
  1239. }
  1240.  
  1241. global function bindEnd()
  1242. {
  1243.    remove_selection()
  1244.    update_current_view()
  1245.    current_line = 65535
  1246.    begin_selection( LINE_SELECTION )
  1247.    end_selection()
  1248.    update_current_view()
  1249.    updateBindItem()
  1250. }
  1251.  
  1252. global function bindPageUp()
  1253. {
  1254.    remove_selection()
  1255.    update_current_view()
  1256.    page_up( 1 )
  1257.    begin_selection( LINE_SELECTION )
  1258.    end_selection()
  1259.    update_current_view()
  1260.    updateBindItem()
  1261. }
  1262.  
  1263. global function bindPageDown()
  1264. {
  1265.    remove_selection()
  1266.    update_current_view()
  1267.    page_down( 1 )
  1268.    begin_selection( LINE_SELECTION )
  1269.    end_selection()
  1270.    update_current_view()
  1271.    updateBindItem()
  1272. }
  1273.  
  1274. global function bindDown( lines )
  1275. {
  1276.    if ( down( lines ))
  1277.    {
  1278.       remove_selection()
  1279.       update_current_view()
  1280.       begin_selection( LINE_SELECTION )
  1281.       end_selection()
  1282.       update_current_view()
  1283.    }
  1284.    updateBindItem()
  1285. }
  1286.  
  1287. global function bindUp( lines )
  1288. {
  1289.    if ( up( lines ))
  1290.    {
  1291.       remove_selection()
  1292.       update_current_view()
  1293.       begin_selection( LINE_SELECTION )
  1294.       end_selection()
  1295.       update_current_view()
  1296.    }
  1297.    updateBindItem()
  1298. }
  1299.  
  1300. global function bindDelete()
  1301. {
  1302.    local   ln
  1303.    local   kn
  1304.    local   fn
  1305.  
  1306.    if (current_window == bindingDispWindow)
  1307.    {
  1308.       goto_bol()
  1309.       kn = read_buffer()
  1310.       ln = keyBindings[ kn ]
  1311.       if (ln)
  1312.       {
  1313.          current_keymap = startingKeymap
  1314.          fn = keymap_binding( ln )
  1315.          assign_key( ln, "beep" )
  1316.          current_keymap = bindingKeymap
  1317.  
  1318.          if (ln in insertedKeys)
  1319.             delete( insertedKeys[ ln ] )
  1320.          else
  1321.             deletedKeys[ kn ] = fn
  1322.  
  1323.          delete_line()
  1324.          if (read_buffer() == "")
  1325.             backspace()
  1326.       }
  1327.       goto_bol()
  1328.    }
  1329.    else
  1330.       beep()
  1331. }
  1332.  
  1333. local function waitForKey()
  1334. {
  1335.    local ch
  1336.    while ((ch = getkey()) == -1)
  1337.       continue
  1338.  
  1339.    return ch
  1340. }
  1341.  
  1342. global function bindIns()
  1343. {
  1344.    local   ch
  1345.    local   ln = ""
  1346.    local   kn
  1347.    local   switchWindows = (current_window == bindingListWindow)
  1348.  
  1349.    if (switchWindows)
  1350.       bindToggleWindow( 0 )
  1351.  
  1352.    remove_selection()
  1353.    update_current_view()
  1354.    insert_newline()
  1355.    up()
  1356.    begin_selection( LINE_SELECTION )
  1357.    end_selection()
  1358.    update_current_view()
  1359.  
  1360.    message( " <Esc>=discard,  <Enter>=accept " )
  1361.  
  1362.    ch = waitForKey()
  1363.  
  1364.    while( (ch != KEYCODE_ENTER ) && (ch != KEYCODE_KEYPAD_ENTER ) \
  1365.                                  && (ch != KEYCODE_ESC))
  1366.    {
  1367.       kn = key_name( ch )
  1368.       insert_string( kn )
  1369.       ln = ln "#" ch
  1370.       update_current_view()
  1371.       ch = waitForKey()
  1372.    }
  1373.  
  1374.    if ( (ch == KEYCODE_ENTER) || (ch == KEYCODE_KEYPAD_ENTER) )
  1375.    {
  1376.       if ( !function_id( currentFunction ))
  1377.       {
  1378.          warning( "Assignment to nonexistent function: " currentFunction )
  1379.          if (!pause_on_error)
  1380.             ch = waitForKey()
  1381.  
  1382.          goto_bol()
  1383.          delete_line()
  1384.          update_current_view()
  1385.       }
  1386.       else
  1387.       {
  1388.          current_keymap = startingKeymap
  1389.          assign_key( ln, currentFunction )
  1390.          current_keymap = bindingKeymap
  1391.          goto_bol()
  1392.          kn = read_buffer()
  1393.          keyBindings[ kn ] = ln
  1394.  
  1395.          if (kn in deletedKeys)
  1396.             delete( deletedKeys[ kn ] )
  1397.  
  1398.          insertedKeys[ ln ] = currentFunction
  1399.       }
  1400.    }
  1401.    else
  1402.    {
  1403.       delete_line()
  1404.       goto_bol()
  1405.       if (read_buffer() == "")
  1406.          backspace()
  1407.    }
  1408.    goto_bol()
  1409.  
  1410.    if (switchWindows)
  1411.       bindToggleWindow( 1 )
  1412. }
  1413.  
  1414. global function updateBindItem()
  1415. {
  1416.    local cb = current_buffer
  1417.  
  1418.    if (keyboard_input_pending == 0)
  1419.    {
  1420.       if (lastBindingLine != current_line)
  1421.       {
  1422.          showBindingItem( current_line )
  1423.          lastBindingLine = current_line
  1424.       }
  1425.    }
  1426. }
  1427.  
  1428. local function saveKeys(save_now, handle)
  1429. {
  1430.    local   i
  1431.    local   fn
  1432.    local   index
  1433.    local   keyname
  1434.    local   save_keys
  1435.  
  1436.    local   cb         = current_buffer
  1437.    local   found      = FALSE
  1438.    local   searchFlag = 0x0034     # ignore case | regex | forward
  1439.  
  1440.    for (i in insertedKeys)
  1441.    {
  1442.       found = TRUE
  1443.       break
  1444.    }
  1445.  
  1446.    for (i in deletedKeys)
  1447.    {
  1448.       found = TRUE
  1449.       break
  1450.    }
  1451.  
  1452.    if (found)
  1453.    {
  1454.       # search cpe path for the config file
  1455.       if ( !(fn = locate_cpe_file(CPE_FILE_CONFIG)))
  1456.       {
  1457.          fn = editor_path( CPE_FILE_CONFIG )
  1458.       }
  1459.  
  1460.       if (argcount() && save_now)
  1461.          i = "Y"
  1462.       else
  1463.          i = toupper(confirm("Save changes to the keymap in " fn " [yn]? ",
  1464.                              "yYnN", handle))
  1465.  
  1466.       if (i == "Y")
  1467.       {
  1468.          for (i in deletedKeys)
  1469.          {
  1470.             if (deletedKeys[i] != "unknown")
  1471.                save_keys[index++] = "# " i " was " deletedKeys[i] "\n"
  1472.          }
  1473.  
  1474.          for (i in insertedKeys)
  1475.          {
  1476.             if (!(i in deletedKeys))
  1477.                save_keys[index++] = "assign_key \"" quote_string(keyAssignmentName(i)) "\" \"" \
  1478.                                                     insertedKeys[i] "\"\n"
  1479.          }
  1480.  
  1481.          save_keys[index++] = "fix_menu_keys\n"
  1482.  
  1483.          update_config_section( "$KEY_ASSIGNMENTS$", save_keys )
  1484.          return TRUE
  1485.       }
  1486.    }
  1487.    return FALSE
  1488. }
  1489.  
  1490. global function fix_menu_keys()
  1491. {
  1492.    local fid
  1493.  
  1494.    if ((fid = function_id(emulation_mode "_menu")))
  1495.       execute_function(fid)
  1496.    else if ((fid = function_id(tolower(emulation_mode) "_menu")))
  1497.       execute_function(fid)
  1498.    else
  1499.       optional_function( "fix_menu_text" )
  1500. }
  1501.  
  1502. local menu    = 0
  1503. local submenu = 0
  1504.  
  1505. local function keys_menu()
  1506. {
  1507.    menu    = create_menu()
  1508.    submenu = create_menu()
  1509.  
  1510.    append_menuitem( submenu, IDM_PREV,  0x0408, "~Previous", "bindUp 1" )
  1511.  
  1512.    append_menuitem( submenu, IDM_NEXT,  0x0408, "~Next", "bindDown 1" )
  1513.  
  1514.    append_menuitem( submenu, 0, 0x0100)
  1515.  
  1516.    append_menuitem( submenu, IDM_DEL,   0x0408, "~Delete", "bindDelete" )
  1517.  
  1518.    append_menuitem( submenu, IDM_INS,   0x0408, "~Insert", "bindIns" )
  1519.  
  1520.    append_menuitem( submenu, 0, 0x0100)
  1521.  
  1522.    append_menuitem( submenu, IDM_EXIT_KEYS, 0x0408, "~Exit Keys", "exit_keys" )
  1523.  
  1524.    append_menuitem( submenu, 0, 0x0100)
  1525.  
  1526.    append_menuitem( submenu, IDM_WIN,   0x0408, "Switch ~Windows", "bindToggleWindow" )
  1527.  
  1528.    append_menuitem( menu,    IDM_MKEYS ,    0x0208, "~Keys", submenu )
  1529.  
  1530.    return menu
  1531. }
  1532.  
  1533. ######################## KEYMAP BINDINGS DIALOG #############################
  1534.  
  1535. local IDD_KEY_BINDINGS          = 1190
  1536. local IDT_FNAME                 = 1191
  1537. local IDB_BIND                  = 1192
  1538. local IDB_UNBIND                = 1193
  1539. local IDT_FUNCTION_NAME         = 1194
  1540. local IDB_SAVE                  = 1195
  1541. local IDC_CTRL_KEY              = 1196
  1542. local IDC_ALT_KEY               = 1197
  1543. local IDC_SHIFT_KEY             = 1198
  1544. local IDC_NUM                   = 1199
  1545. local IDL_KEY_LIST              = 1200
  1546. local IDL_KEYS                  = 1201
  1547. local IDL_COMMANDS              = 1202
  1548. local IDB_SELECT                = 1203
  1549. local IDB_FUNCTION_HELP         = 1204
  1550. local IDE_PARMS                 = 1205
  1551. local IDB_SHOW_BINDINGS         = 1206
  1552.  
  1553. local  key_lists_created        = 0
  1554. local  selecting_key            = 0
  1555. local  keys_set                 = 0
  1556. local  dhKeysDialog
  1557.  
  1558. global function keys_dialog()
  1559. {
  1560.    set_busy_cursor()
  1561.    dhKeysDialog = create_dialog(function_id( "keys_dialog_callback" ), 0,
  1562.                                 IDD_KEY_BINDINGS, resource_dll)
  1563.  
  1564.    attach_help(editor_helpfile, dhKeysDialog)
  1565.    set_dialog_item(dhKeysDialog, IDL_KEYS,     DAC_SORT_ASCENDING)
  1566.    add_dialog_item(dhKeysDialog, IDL_KEY_LIST, DCTRL_COMBO_BOX)
  1567.    set_dialog_item(dhKeysDialog, IDL_KEY_LIST, DAC_SORT_ASCENDING)
  1568.    add_dialog_item(dhKeysDialog, IDL_COMMANDS, DCTRL_COMBO_BOX)
  1569.    set_dialog_item(dhKeysDialog, IDL_COMMANDS, DAC_SORT_ASCENDING)
  1570.    set_dialog_item(dhKeysDialog, IDT_FUNCTION_NAME, DAC_TEXT, "")
  1571.    set_dialog_item(dhKeysDialog, IDT_FNAME, DAC_TEXT, "")
  1572.  
  1573.    key_lists_created = FALSE
  1574.    initialize_keys_dialog( dhKeysDialog )
  1575.  
  1576.    set_normal_cursor()
  1577.    begin_dialog(dhKeysDialog)
  1578.  
  1579.    delete_dialog(dhKeysDialog)
  1580.    key_lists_created = FALSE
  1581. }
  1582.  
  1583. global function initialize_keys_dialog( handle )
  1584. {
  1585.    if (!key_lists_created)
  1586.    {
  1587.       # retrieve the current user key assignments from the config file.
  1588.       #
  1589.       if (!keysRead)
  1590.       {
  1591.          delete( keyBindings )
  1592.          delete( deletedKeys )
  1593.          delete( insertedKeys )
  1594.          read_key_assignments()
  1595.          keysRead = TRUE;
  1596.       }
  1597.  
  1598.       load_keys(handle)
  1599.       load_commands(handle)
  1600.       key_lists_created = TRUE
  1601.    }
  1602.    set_buttons(handle)
  1603. }
  1604.  
  1605. local function load_keys(handle)
  1606. {
  1607.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Alt")
  1608.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Ctrl")
  1609.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Shift")
  1610.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Backspace")
  1611.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "BackTab")
  1612.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "CapsLock")
  1613.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Delete")
  1614.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Down")
  1615.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Enter")
  1616.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Execute")
  1617.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "End")
  1618.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Esc")
  1619.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Home")
  1620.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Insert")
  1621.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Left")
  1622.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Num Lock")
  1623.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "PageUp")
  1624.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "PageDown")
  1625.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Right")
  1626.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Space")
  1627.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Tab")
  1628.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Up")
  1629.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F1")
  1630.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F2")
  1631.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F3")
  1632.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F4")
  1633.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F5")
  1634.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F6")
  1635.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F7")
  1636.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F8")
  1637.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F9")
  1638.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F10")
  1639.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F11")
  1640.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F12")
  1641.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F13")
  1642.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F14")
  1643.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F15")
  1644.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F16")
  1645.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F17")
  1646.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F18")
  1647.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F19")
  1648.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F20")
  1649.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F21")
  1650.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F22")
  1651.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F23")
  1652.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F24")
  1653.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "A")
  1654.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "B")
  1655.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "C")
  1656.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "D")
  1657.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "E")
  1658.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "F")
  1659.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "G")
  1660.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "H")
  1661.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "I")
  1662.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "J")
  1663.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "K")
  1664.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "L")
  1665.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "M")
  1666.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "N")
  1667.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "O")
  1668.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "P")
  1669.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Q")
  1670.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "R")
  1671.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "S")
  1672.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "T")
  1673.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "U")
  1674.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "V")
  1675.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "W")
  1676.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "X")
  1677.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Y")
  1678.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "Z")
  1679.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "1")
  1680.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "2")
  1681.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "3")
  1682.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "4")
  1683.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "5")
  1684.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "6")
  1685.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "7")
  1686.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "8")
  1687.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "9")
  1688.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "0")
  1689.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "-")
  1690.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "=")
  1691.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "[")
  1692.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "]")
  1693.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "\\")
  1694.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, ";")
  1695.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "'")
  1696.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, ",")
  1697.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, ".")
  1698.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "/")
  1699.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "`")
  1700.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "!")
  1701.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "@")
  1702.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "#")
  1703.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "$")
  1704.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "%")
  1705.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "^")
  1706.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "&")
  1707.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "*")
  1708.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "(")
  1709.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, ")")
  1710.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "_")
  1711.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "+")
  1712.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "{")
  1713.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "}")
  1714.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "|")
  1715.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, ":")
  1716.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "\"")
  1717.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "<")
  1718.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, ">")
  1719.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "?")
  1720.    set_dialog_item(handle, IDL_KEY_LIST, DAC_ADD_ITEM, "~")
  1721. }
  1722.  
  1723. local function load_commands(handle)
  1724. {
  1725.    local   i
  1726.    local   len
  1727.    local   str
  1728.    local   size
  1729.    local   line
  1730.    local   func
  1731.    local   eol_str
  1732.    local   txtfile
  1733.    local   buffOff
  1734.    local   cb = current_buffer
  1735.  
  1736.    if ( symbol_list )
  1737.    {
  1738.       for (i in symbol_list)
  1739.       {
  1740.          set_dialog_item(handle, IDL_COMMANDS, DAC_ADD_ITEM, symbol_list[i])
  1741.       }
  1742.  
  1743.       for (i in addToBindings)
  1744.       {
  1745.          set_dialog_item(handle, IDL_COMMANDS, DAC_ADD_ITEM, i )
  1746.       }
  1747.    }
  1748.    else
  1749.    {
  1750.       # search cpe path for the help menu file
  1751.       if ( !(txtfile = locate_cpe_file(CPE_FILE_BINDINGS)))
  1752.              txtfile = editor_path( CPE_FILE_BINDINGS )
  1753.  
  1754.       current_buffer = create_buffer( txtfile, txtfile, BUFFER_SYSTEM + \
  1755.                                                         BUFFER_NO_UNDO )
  1756.       # couldn't find the help information
  1757.       # in case symbol_match takes a long time
  1758.       if ( status_bar_flags )
  1759.          message( "Working..." )
  1760.    
  1761.       if (buffer_size)
  1762.       {
  1763.          for(;current_line < buffer_last_line; down())
  1764.          {
  1765.             line = read_buffer()
  1766.             if (line && length(line) && prefix(line, 1) != "#")
  1767.             {
  1768.                if (match(line, chr(29)".*$"))
  1769.                   func = suffix( line, RLENGTH - 1 )
  1770.                else
  1771.                   func = line
  1772.    
  1773.                set_dialog_item( handle, IDL_COMMANDS, DAC_ADD_ITEM, func )
  1774.                symbol_list[ current_line ] = func
  1775.             }
  1776.          }
  1777.       }
  1778.       else
  1779.       {
  1780.          # read a list of all primitives & global functions.
  1781.          symbol_list = symbol_match("", 0x05)
  1782.    
  1783.          if (symbol_list)
  1784.          {
  1785.             for (i in symbol_list)
  1786.             {
  1787.               set_dialog_item(handle, IDL_COMMANDS, DAC_ADD_ITEM, symbol_list[i])
  1788.             }
  1789.             if ( status_bar_flags )
  1790.                message( "" )
  1791.          }
  1792.          else
  1793.          {
  1794.             # couldn't find the help information
  1795.             notify( "Cannot find binding information in: %s", txtfile )
  1796.          }
  1797.       }
  1798.       delete_buffer()
  1799.    }
  1800.    current_buffer = cb
  1801. }
  1802.  
  1803. global function keys_dialog_callback()
  1804. {
  1805.    local func
  1806.  
  1807.    if ( ( callback_msg == DM_CLICK && callback_index == DI_HELP ) ||
  1808.         ( callback_msg == DM_HELPREQUESTED ) ) 
  1809.    {
  1810.       display_help("keys", callback_dialog_handle)
  1811.       return DRC_MSG_PROCESSED
  1812.    }
  1813.    else if ( (callback_msg == DM_CLICK) )
  1814.    {
  1815.       if ( callback_index == IDB_SHOW_BINDINGS )
  1816.       {
  1817.          lookup_commands( callback_dialog_handle )
  1818.          lookup_keys( callback_dialog_handle )
  1819.          set_buttons( callback_dialog_handle )
  1820.       }
  1821.       else if ( callback_index == IDB_SELECT ) 
  1822.       {
  1823.          selecting_key = TRUE
  1824.          optional_function( "disable_status_bar_prompts" )
  1825.          getKeystroke("Press key to be bound...", callback_dialog_handle)
  1826.          optional_function( "restore_status_bar" )
  1827.          selecting_key = FALSE
  1828.          select_key(callback_dialog_handle, key_name(keystroke))
  1829.  
  1830.          func  = keymap_binding( query_key_name( callback_dialog_handle ) )
  1831.          set_dialog_item(callback_dialog_handle, IDT_FUNCTION_NAME, DAC_TEXT, func)
  1832.          set_buttons(callback_dialog_handle)
  1833.       }
  1834.       else if ( callback_index == IDB_BIND ) 
  1835.       {
  1836.          bind_key(callback_dialog_handle)
  1837.       }
  1838.       else if ( callback_index == IDB_FUNCTION_HELP ) 
  1839.       {
  1840.          func = query_function_name(callback_dialog_handle)
  1841.          if (length(func))
  1842.             display_help_item(func)
  1843.       }
  1844.       else if ( callback_index == IDB_UNBIND ) 
  1845.       {
  1846.          unbind_key(callback_dialog_handle)
  1847.       }
  1848.       else if ( callback_index == IDB_SAVE ) 
  1849.       {
  1850.          saveKeys(TRUE)
  1851.          keys_set = FALSE
  1852.       }
  1853.       else if ( callback_index == IDC_CTRL_KEY  ||
  1854.                 callback_index == IDC_ALT_KEY   ||
  1855.                 callback_index == IDC_SHIFT_KEY ||
  1856.                 callback_index == IDC_NUM       )
  1857.       {
  1858.          set_buttons(callback_dialog_handle)
  1859.       }
  1860.       return DRC_MSG_PROCESSED
  1861.    }
  1862.    else if ( callback_msg == DM_SELECT )
  1863.    {
  1864.       if ( callback_index == IDL_KEY_LIST )
  1865.       {
  1866.          func  = keymap_binding( query_key_name( callback_dialog_handle ) )
  1867.          set_dialog_item(callback_dialog_handle, IDT_FUNCTION_NAME, DAC_TEXT, func)
  1868.  
  1869.          set_buttons(callback_dialog_handle)
  1870.          return DRC_MSG_PROCESSED
  1871.       }
  1872.       else if ( callback_index == IDL_COMMANDS )
  1873.       {
  1874.          set_dialog_item(callback_dialog_handle, IDE_PARMS, DAC_EDIT_TEXT, "")
  1875.          lookup_keys(callback_dialog_handle)
  1876.          set_buttons(callback_dialog_handle)
  1877.          return DRC_MSG_PROCESSED
  1878.       }
  1879.       else if ( callback_index == IDL_KEYS )
  1880.       {
  1881.          set_buttons(callback_dialog_handle)
  1882.          return DRC_MSG_PROCESSED
  1883.       }
  1884.    }
  1885.    else if ( callback_msg == DM_KILL_FOCUS )
  1886.    {
  1887.       if ( callback_index == IDE_PARMS )
  1888.       {
  1889.          lookup_keys(callback_dialog_handle)
  1890.          set_buttons(callback_dialog_handle)
  1891.          return DRC_MSG_PROCESSED
  1892.       }
  1893.    }
  1894.    else if ( callback_msg == DM_CHANGE )
  1895.    {
  1896.       if ( callback_index == IDE_PARMS )
  1897.       {
  1898.          set_buttons(callback_dialog_handle)
  1899.          return DRC_MSG_PROCESSED
  1900.       }
  1901.       else if (   callback_index == IDL_COMMANDS &&  
  1902.                   query_dialog_item(   callback_dialog_handle, 
  1903.                                        IDL_COMMANDS, 
  1904.                                        DAC_SELECT_INDEX) == -1 )
  1905.       {
  1906.          lookup_keys(callback_dialog_handle)
  1907.          set_buttons(callback_dialog_handle)
  1908.          return DRC_MSG_PROCESSED
  1909.       }
  1910.    }
  1911.    else if ( callback_msg == DM_DOUBLE_CLICK )
  1912.    {
  1913.       if ( callback_index == IDL_COMMANDS )
  1914.       {
  1915.       #  bind_key(callback_dialog_handle)
  1916.          set_dialog_item(callback_dialog_handle, IDL_COMMANDS, DAC_DESELECT_INDEX)
  1917.          set_dialog_item(callback_dialog_handle, IDE_PARMS, DAC_EDIT_TEXT, "")
  1918.          lookup_keys(callback_dialog_handle)
  1919.          set_buttons(callback_dialog_handle)
  1920.          return DRC_MSG_PROCESSED
  1921.       }
  1922.       else if ( callback_index == IDL_KEYS )
  1923.       {
  1924.       #  unbind_key(callback_dialog_handle)
  1925.          return DRC_MSG_PROCESSED
  1926.       }
  1927.    }
  1928.    else if ( callback_msg == DM_OK || callback_msg == DM_CLOSE )
  1929.    {
  1930.       set_busy_cursor()
  1931.       if (keys_set)
  1932.       {
  1933.          optional_function( "disable_status_bar_prompts" )
  1934.          saveKeys(FALSE, callback_dialog_handle)
  1935.          optional_function( "restore_status_bar" )
  1936.          keys_set = FALSE
  1937.       }
  1938.       updateBindings()
  1939.  
  1940.       fix_menu_keys()
  1941.       set_normal_cursor()
  1942.       return DRC_EXIT
  1943.    }
  1944.    else if ( callback_msg == DM_CANCEL )
  1945.    {
  1946.       set_busy_cursor()
  1947.       updateBindings()
  1948.       set_normal_cursor()
  1949.       return DRC_EXIT
  1950.    }
  1951.  
  1952.    return DRC_CONTINUE
  1953. }
  1954.  
  1955. local function updateBindings()
  1956. {
  1957.    local func
  1958.    local bind_buf
  1959.    local old_buf = current_buffer
  1960.  
  1961.    if ( addToBindings )
  1962.    {
  1963.       if ( (bind_buf = create_buffer("", editor_path( CPE_FILE_BINDINGS ), 
  1964.                                      BUFFER_SYSTEM + BUFFER_NO_UNDO )) )
  1965.       {
  1966.          current_buffer = bind_buf
  1967.    
  1968.          goto_buffer_bottom()
  1969.    
  1970.          for ( func in addToBindings )
  1971.          {
  1972.             if ( addToBindings[func] )
  1973.             {
  1974.                addToBindings[ func ] = FALSE
  1975.    
  1976.                if ( current_line_length )
  1977.                {
  1978.                   goto_eol()
  1979.                   insert_newline()
  1980.                }
  1981.    
  1982.                insert_string( "User Functions" )
  1983.                current_column = 25
  1984.                insert_string( chr(29) func "\n" )
  1985.             }
  1986.          }
  1987.    
  1988.          write_buffer()
  1989.          delete_buffer()
  1990.    
  1991.          current_buffer = old_buf
  1992.       }
  1993.    }
  1994. }
  1995.  
  1996. local function query_function_name(handle)
  1997. {
  1998.    local func = query_dialog_item(handle, IDL_COMMANDS, DAC_SELECT_ITEM)
  1999.    local parm = query_dialog_item(handle, IDE_PARMS,    DAC_EDIT_TEXT)
  2000.  
  2001.    if (func && length(func))
  2002.    {
  2003.       if (parm && length(parm))
  2004.          func = func " " parm
  2005.    }
  2006.    else
  2007.    {
  2008.       func = query_dialog_item( handle, IDL_COMMANDS, DAC_EDIT_TEXT )
  2009.  
  2010.       if ( !function_id( func ) )
  2011.          func = ""
  2012.    }
  2013.    return func
  2014. }
  2015.  
  2016. local function query_key_name(handle)
  2017. {
  2018.    local name
  2019.    local key  = query_dialog_item(handle, IDL_KEY_LIST, DAC_SELECT_ITEM)
  2020.  
  2021.    if (length(key))
  2022.    {
  2023.       name = "<"
  2024.  
  2025.       if (query_dialog_item(handle, IDC_CTRL_KEY,  DAC_CHECK))
  2026.          name = name "Ctrl-"
  2027.  
  2028.       if (query_dialog_item(handle, IDC_ALT_KEY,   DAC_CHECK))
  2029.          name = name "Alt-"
  2030.  
  2031.       if (query_dialog_item(handle, IDC_SHIFT_KEY, DAC_CHECK))
  2032.          name = name "Shift-"
  2033.  
  2034.       if (numOK(key))
  2035.       {
  2036.          set_dialog_item(handle, IDC_NUM, DAC_ENABLE)
  2037.          if (query_dialog_item(handle, IDC_NUM, DAC_CHECK))
  2038.             name = name "Num-"
  2039.       }
  2040.       else
  2041.       {
  2042.          if (query_dialog_item(handle, IDC_NUM, DAC_CHECK))
  2043.              set_dialog_item(handle, IDC_NUM, DAC_UNCHECK)
  2044.          set_dialog_item(handle, IDC_NUM, DAC_DISABLE)
  2045.       }
  2046.       return name key ">"
  2047.    }
  2048.    return key
  2049. }
  2050.  
  2051. local function numOK(key)
  2052. {
  2053.    return (key == "Home"     || key == "End"   || key == "PageUp" ||
  2054.            key == "PageDown" || key == "Up"    || key == "Left"   ||
  2055.            key == "Right"    || key == "Down"  || key == "Insert" ||
  2056.            key == "Delete"   || key == "Enter" || key == "Center" ||
  2057.            key == "/"        || key == "*"     || key == "-"      || 
  2058.            key == "+"        || key == "."     || (key >= "0" && key <= "9"))
  2059. }
  2060.  
  2061. local function select_key(handle, name)
  2062. {
  2063.    local pos, cmp, label
  2064.  
  2065.    if (name)
  2066.    {
  2067.       if (length(name) == 1)
  2068.       {
  2069.          set_dialog_item(handle, IDC_CTRL_KEY, DAC_UNCHECK)
  2070.          set_dialog_item(handle, IDC_ALT_KEY,  DAC_UNCHECK)
  2071.          set_dialog_item(handle, IDC_NUM,      DAC_UNCHECK)
  2072.  
  2073.          if (isupper(name))
  2074.             set_dialog_item(handle, IDC_SHIFT_KEY, DAC_CHECK)
  2075.          else
  2076.             set_dialog_item(handle, IDC_SHIFT_KEY, DAC_UNCHECK)
  2077.  
  2078.          label = toupper(name)
  2079.       }
  2080.       else
  2081.       {
  2082.          cmp = tolower(name)
  2083.  
  2084.          if (index(cmp, "ctrl-"))
  2085.             set_dialog_item(handle, IDC_CTRL_KEY, DAC_CHECK)
  2086.          else
  2087.             set_dialog_item(handle, IDC_CTRL_KEY, DAC_UNCHECK)
  2088.  
  2089.          if (index(cmp, "alt-"))
  2090.             set_dialog_item(handle, IDC_ALT_KEY, DAC_CHECK)
  2091.          else
  2092.             set_dialog_item(handle, IDC_ALT_KEY, DAC_UNCHECK)
  2093.  
  2094.          if (index(cmp, "shift-"))
  2095.             set_dialog_item(handle, IDC_SHIFT_KEY, DAC_CHECK)
  2096.          else
  2097.             set_dialog_item(handle, IDC_SHIFT_KEY, DAC_UNCHECK)
  2098.  
  2099.          if (index(cmp, "num-"))
  2100.             set_dialog_item(handle, IDC_NUM, DAC_CHECK)
  2101.          else
  2102.             set_dialog_item(handle, IDC_NUM, DAC_UNCHECK)
  2103.  
  2104.          if ((pos = rindex(name, "-")) > 0)
  2105.          {
  2106.             if (pos < length(name))
  2107.                label = substr(name, pos + 1, length(name) - pos - 1)
  2108.             else
  2109.                label = "-"
  2110.          }
  2111.          else
  2112.             label = substr(name, 2, length(name) - 2)
  2113.       }
  2114.       set_dialog_item(handle, IDL_KEY_LIST, DAC_SELECT_ITEM, label)
  2115.    }
  2116. }
  2117.  
  2118. local function lookup_keys(handle)
  2119. {
  2120.    local i
  2121.    local pos
  2122.    local list
  2123.    local keys
  2124.    local func = query_function_name(handle)
  2125.  
  2126.    if (length(func))
  2127.    {
  2128.       if (func == "insert_key") # The insert_key list is too HUGE!!!!!
  2129.       {
  2130.          set_dialog_item(handle, IDL_KEYS,  DAC_CLEAR_LIST)
  2131.          set_dialog_item(handle, IDT_FNAME, DAC_TEXT, "")
  2132.       }
  2133.       else if (func != query_dialog_item(handle, IDT_FNAME, DAC_TEXT))
  2134.       {
  2135.          set_dialog_item(handle, IDL_KEYS,  DAC_CLEAR_LIST)
  2136.          set_dialog_item(handle, IDT_FNAME, DAC_TEXT, func)
  2137.          keys = function_binding_key(func, FALSE, FALSE, TRUE)
  2138.          if (keys && length(keys))
  2139.          {
  2140.             split(keys, list, "|")
  2141.             for (i in list)
  2142.             {
  2143.                set_dialog_item(handle, IDL_KEYS, DAC_ADD_ITEM,
  2144.                                ltrim(trim(list[i])))
  2145.             }
  2146.          }
  2147.       }
  2148.    }
  2149.    else
  2150.    {
  2151.       set_dialog_item(handle, IDL_KEYS,  DAC_CLEAR_LIST)
  2152.       set_dialog_item(handle, IDT_FNAME, DAC_TEXT, "")
  2153.    }
  2154. }
  2155.  
  2156. local function lookup_commands(handle)
  2157. {
  2158.    local pos
  2159.    local func
  2160.    local parm
  2161.    local name = query_key_name(handle)
  2162.  
  2163.    if (length(name))
  2164.    {
  2165.       func = keymap_binding(name)
  2166.       if (length(func))
  2167.       {
  2168.          set_dialog_item(handle, IDT_FUNCTION_NAME, DAC_TEXT, func)
  2169.  
  2170.          if ((pos = cindex(func, " ")))
  2171.          {
  2172.             parm = substr(func, pos+1)
  2173.             func = prefix(func, pos-1)
  2174.          }
  2175.          else
  2176.             parm = ""
  2177.  
  2178.          if (!set_dialog_item(handle, IDL_COMMANDS, DAC_SELECT_ITEM, func))
  2179.          {
  2180.             addToBindings[ func ] = TRUE
  2181.             set_dialog_item(handle, IDL_COMMANDS, DAC_ADD_ITEM,    func)
  2182.             set_dialog_item(handle, IDL_COMMANDS, DAC_SELECT_ITEM, func)
  2183.          }
  2184.          set_dialog_item(handle, IDE_PARMS, DAC_EDIT_TEXT, parm)
  2185.       }
  2186.       else
  2187.       {
  2188.          set_dialog_item(handle, IDT_FUNCTION_NAME, DAC_TEXT, "")
  2189.          set_dialog_item(handle, IDE_PARMS, DAC_EDIT_TEXT, "")
  2190.          set_dialog_item(handle, IDL_COMMANDS, DAC_DESELECT_INDEX)
  2191.       }
  2192.    }
  2193. }
  2194.  
  2195. local function set_buttons(handle)
  2196. {
  2197.    if (length(query_function_name(handle)))
  2198.    {
  2199.       set_dialog_item(dhKeysDialog, IDB_FUNCTION_HELP, DAC_ENABLE)
  2200.  
  2201.       if (query_dialog_item(handle, IDL_KEY_LIST, DAC_SELECT_INDEX) >= 0)
  2202.          set_dialog_item(dhKeysDialog, IDB_BIND, DAC_ENABLE)
  2203.       else
  2204.          set_dialog_item(dhKeysDialog, IDB_BIND, DAC_DISABLE)
  2205.    }
  2206.    else
  2207.    {
  2208.       set_dialog_item(dhKeysDialog, IDB_BIND,          DAC_DISABLE)
  2209.       set_dialog_item(dhKeysDialog, IDB_FUNCTION_HELP, DAC_DISABLE)
  2210.    }
  2211.  
  2212.    if (query_dialog_item(handle, IDL_KEYS, DAC_SELECT_INDEX) >= 0)
  2213.       set_dialog_item(dhKeysDialog, IDB_UNBIND, DAC_ENABLE)
  2214.    else
  2215.       set_dialog_item(dhKeysDialog, IDB_UNBIND, DAC_DISABLE)
  2216. }
  2217.  
  2218. # DWM This function will bind the current key with the current function and
  2219. #     parameters, and keep track of this information in order to save it to
  2220. #     the config file.  If function_id() of the function and its parameters
  2221. #     returns 0, it will warn the user that the parameters are invalid, and
  2222. #     not try to bind.
  2223. local function bind_key(handle)
  2224. {
  2225.    local i
  2226.    local key
  2227.    local func
  2228.    local list
  2229.    local old_poe
  2230.    local name = query_key_name(handle)
  2231.  
  2232.    if (length(name))
  2233.    {
  2234.       if (name == "<Ctrl-Esc>"       || name == "<Ctrl-Alt-Delete>" || \
  2235.           name == "<Ctrl-Alt-Num-.>" || name == "<Ctrl-Alt-Num-Delete>")
  2236.       {
  2237.          warning("Invalid key %s can not be bound", name)
  2238.       }
  2239.       else
  2240.       {
  2241.          func = query_function_name(handle)
  2242.          if ( length(func) )
  2243.          {
  2244.             if ( function_id(func) )
  2245.             {
  2246.                # Make sure the key is not already bound to this function.
  2247.       
  2248.                key = key_to_int(name)
  2249.                split(function_binding(function_id(func)), list, "#")
  2250.                for (i in list)
  2251.                {
  2252.                   if (list[i]+0 == key)
  2253.                      return
  2254.                }
  2255.       
  2256.                if ( query_dialog_item(handle, IDL_COMMANDS, DAC_FIND, func) == -1 )
  2257.                {
  2258.                   addToBindings[ func ] = TRUE
  2259.                   set_dialog_item(handle, IDL_COMMANDS, DAC_ADD_ITEM,    func)
  2260.                   set_dialog_item(handle, IDL_COMMANDS, DAC_SELECT_ITEM, func)
  2261.                }
  2262.                   
  2263.                # Assign the function to the key.
  2264.                set_dialog_item(handle, IDL_KEYS, DAC_ADD_ITEM, name)
  2265.       
  2266.                if (name in deletedKeys)
  2267.                   delete( deletedKeys[ name ] )
  2268.    
  2269.                assign_key(name, func)
  2270.                insertedKeys[ name ] = func
  2271.                keys_set             = TRUE
  2272.             }
  2273.             else
  2274.             {
  2275.                old_poe = pause_on_error
  2276.                pause_on_error = TRUE
  2277.                warning( "You must provide valid parameters to function " func )
  2278.                pause_on_error = old_poe
  2279.             }
  2280.          }
  2281.       }
  2282.    }
  2283. }
  2284.  
  2285. local function unbind_key(handle)
  2286. {
  2287.    local name = query_dialog_item(handle, IDL_KEYS, DAC_SELECT_ITEM)
  2288.  
  2289.    if (length(name))
  2290.    {
  2291.       if (name in insertedKeys)
  2292.          delete( insertedKeys[ name ] )
  2293.       else
  2294.          deletedKeys[ name ] = keymap_binding( name )
  2295.  
  2296.       set_dialog_item(handle, IDL_KEYS, DAC_DELETE_ITEM, name)
  2297.       assign_key(name, "beep")
  2298.       keys_set = TRUE
  2299.    }
  2300. }
  2301.