home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / p2demo21.exe / PEL / EMACS.PEL < prev    next >
Text File  |  1995-03-22  |  70KB  |  2,746 lines

  1. # $Header:   P:\source\wmacros\emacs.pev   1.55   22 Mar 1995 11:01:50   PFHJXM0  $
  2. ## $Tabs:4 7$
  3.  
  4. ##############################################################################
  5. #
  6. #       Compuware Corporation
  7. #         31440 Northwestern Highway
  8. #           Farmington Hills, Michigan 48334-2564
  9. #
  10. #   This source code listing contains information that is
  11. #   proprietary to Compuware Corporation and may not be copied
  12. #   duplicated, translated, transmitted, stored, retrieved
  13. #   or in any manner or by any method conveyed or disclosed
  14. #   to a third party or parties without express written
  15. #   permission from Compuware Corporation.
  16. #
  17. #  
  18. ##############################################################################
  19.  
  20.  
  21. #### $Workfile:   emacs.pel  $: Key bindings for emacs compatibility
  22.  
  23. # local variables:
  24.  
  25. local markx;
  26. local marky;
  27. local last_column;
  28. local last_command = 0;
  29. local KILL         = 1;
  30. local VERT         = 2;
  31. local YANK         = 3;
  32. local search_strings;
  33. local search_string_count = 0;
  34. local current_search_string = 0;
  35. local line_prefix = "";
  36. local emacc = 0;
  37. local keymac;
  38. local savedmacs;
  39. local fid, tid;
  40. local NUMKILLBUFFERS = 30;
  41. local killbuffers;
  42. local currentkill=0;
  43. local lastyankx1 = (-1);
  44. local lastyanky1 = (-1);
  45. local lastyankx2 = (-1);
  46. local lastyanky2 = (-1);
  47. local errfile;
  48. local makebuffer = 0;
  49. local em_sta_file = 0;
  50. local em_sta_name = "emem.sta";
  51.  
  52. #  local old_default_buffer_flags;
  53. local old_search_flags;
  54.  
  55. global ctrlxr_keymap;
  56. global ctrlx_keymap;
  57. global emacs_keymap = -1;
  58. global emacs_music = 0;
  59.  
  60. local comments;
  61. local matching;
  62.  
  63. # establish emacs mode:
  64.  
  65. global function emacs()
  66. {
  67.    local prevPauseOnError, first;
  68.  
  69.    if (emulation_mode != "emacs")
  70.    {
  71. #        attach_event_handler(EVENT.EDITOR_RUNNING, function_id("em_change_buffer_flags"));
  72.  
  73.       emulation_mode = "emacs";
  74.       execute_event_handler(EVENT.EMULATION_CHANGED);
  75.       attach_event_handler(EVENT.EMULATION_CHANGED, function_id("emacs_exit"));
  76.       attach_event_handler(EVENT.MOUSE_LEFT_DOWN, function_id("em_mouse_set_mark"));
  77. #        attach_event_handler(EVENT.EMULATION_CHANGED, function_id("em_change_buffer_flags"));
  78.  
  79.       # pause if an error or warning occurs during initialization
  80.       prevPauseOnError = pause_on_error
  81.       pause_on_error   = 1
  82.  
  83. #        old_default_buffer_flags = default_buffer_flags;
  84.       old_search_flags         = search_flags;
  85.       markx = 0;
  86.       marky = 0;
  87.    
  88. #     toggle_dialog(1);
  89.    
  90.       if (!em_read_state())
  91.          emacs_set_keymap()
  92.  
  93. #        default_buffer_flags = 0 + BUFFER_EXPAND_TABS + BUFFER_REAL_SPACE_ONLY \
  94. #                                 + BUFFER_SNAP_TO_EOL + BUFFER_TABS_TO_SPACES;
  95.  
  96.       emacs_menu();
  97.       em_fix_toolbar();
  98.  
  99.       pause_on_error = prevPauseOnError;
  100.    }
  101.  
  102.    return 23;
  103. }
  104.  
  105. global function emacs_set_keymap()
  106. {
  107.    local i, name;
  108.  
  109.    # Enable the keymap.  Subsequent mods to the keymap will persist
  110.    #       through the end of the session.
  111.    # Only one-time initialization should follow this point.
  112.  
  113.    if( emacs_keymap >= 0 )
  114.    {
  115.       current_keymap = emacs_keymap
  116.       return
  117.    }
  118.    else
  119.    {
  120.       em_comments();    # Initialize comment structure array
  121.  
  122.       current_keymap = ctrlxr_keymap   = create_keymap(empty_keymap);
  123.       assign_ctrlxr_keys()
  124.       # assert: ctrlxr_keymap exists and has the C-X r keys mapped to it.
  125.  
  126.       current_keymap = ctrlx_keymap   = create_keymap(empty_keymap);
  127.       assign_ctrlx_keys()
  128.       # assert: ctrlx_keymap exists and has the C-X keys mapped to it.
  129.  
  130.       current_keymap = emacs_keymap = create_keymap(ascii_keymap);
  131.       assign_emacs_keys()
  132.       # assert: emacs_keymap exists and has the emacs keys mapped to it.
  133.  
  134. #     assign_mouse_buttons()
  135.  
  136.       optional_function("local_keys")
  137.  
  138.       for (i = 0; i < NUMKILLBUFFERS; i++)
  139.       {
  140.          name = "killbufer" i "";
  141.          killbuffers[i].bufid = create_buffer( name, name, BUFFER_SYSTEM+BUFFER_NO_UNDO);
  142.       }
  143.       # assert: NUMKILLBUFFERS empty system buffers exist in the killbuffers array.
  144.    }
  145. }
  146.  
  147. #global function em_change_buffer_flags()
  148. #{
  149. # first = current_buffer;
  150. # do {
  151. #    current_buffer = next_buffer();
  152. #    if(!and(buffer_flags, BUFFER_SYSTEM))
  153. #       buffer_flags = default_buffer_flags;
  154. # } while(current_buffer != first);
  155. #}
  156.  
  157. local function em_comments()
  158. {
  159.    comments[".c"]   = "/*  */";
  160.    comments[".h"]   = "/*  */";
  161.    comments[".cpp"] = "// ";
  162.    comments[".hpp"] = "// ";
  163.    comments[".pel"] = "#  ";
  164.    comments[".pas"] = "(*  *)";
  165.  
  166.    matching["("] = ")";
  167.    matching["{"] = "}";
  168.    matching["["] = "]";
  169. }
  170.  
  171. global function emacs_menu()
  172. {
  173.    local prefix;
  174.    local menu = menu_info( 0, MI_MENUHANDLE )
  175.    local temp_array
  176.  
  177.    #  modify what functions are called by the cut, copy and paste functions
  178.  
  179.    if(!(fid[IDM_CUT] || fid[IDM_COPY] || fid[IDM_PASTE]))
  180.    {
  181.  
  182.       fid[IDM_CUT]   = menu_functions[IDM_CUT]
  183.       fid[IDM_COPY]  = menu_functions[IDM_COPY]
  184.       fid[IDM_PASTE] = menu_functions[IDM_PASTE]
  185.  
  186.    }
  187.  
  188.    menu_functions[IDM_CUT]   = "em_kill_region"
  189.    menu_functions[IDM_COPY]  = "em_copy_to_scrap"
  190.    menu_functions[IDM_PASTE] = "em_yank"
  191.  
  192.    if ( menu )
  193.    {
  194.       # add keys to menu that contain non-special-dialog box functions
  195.       
  196.       # set the default keymap
  197.       set_default_keymap( emacs_keymap )
  198.  
  199.       temp_array[ IDM_UNDO    ].mapped =  "em_undo"
  200.       temp_array[ IDM_CUT     ].mapped =  "em_kill_region"
  201.       temp_array[ IDM_COPY    ].mapped =  "em_copy_to_scrap"
  202.       temp_array[ IDM_PASTE   ].mapped =  "em_yank"
  203.       temp_array[ IDM_UPPER   ].mapped =  "em_upper"
  204.       temp_array[ IDM_LOWER   ].mapped =  "em_lower"
  205.       
  206.       temp_array[ IDM_ISEARCH ].mapped = "em_i_search"
  207.       temp_array[ IDM_CHANGE  ].mapped = "em_query_replace"
  208.       
  209.       temp_array[ IDM_COMMAND ].mapped = "em_invoke_function"
  210.       
  211.       prefix = "Ctrl+x-";
  212.       
  213.       temp_array[ IDM_ADDFILE    ] = set_menu_mappings( "em_find_file",    prefix, ctrlx_keymap )
  214.       temp_array[ IDM_INSERTFILE ] = set_menu_mappings( "em_insert_file",  prefix, ctrlx_keymap )
  215.       temp_array[ IDM_SAVE       ] = set_menu_mappings( "em_save_file",    prefix, ctrlx_keymap )
  216.       temp_array[ IDM_SAVEAS     ] = set_menu_mappings( "em_write_file",   prefix, ctrlx_keymap )
  217.       temp_array[ IDM_SAVEALL    ] = set_menu_mappings( "em_save_all",     prefix, ctrlx_keymap )
  218.       temp_array[ IDM_EXIT       ] = set_menu_mappings( "em_exit",         prefix, ctrlx_keymap )
  219.                                                                      
  220.       temp_array[ IDM_UNDO       ] = set_menu_mappings( "em_undo",         prefix, ctrlx_keymap )
  221.       temp_array[ IDM_REDO       ] = set_menu_mappings( "em_redo",         prefix, ctrlx_keymap )
  222.                                                                      
  223.       temp_array[ IDM_GOTOLINE   ] = set_menu_mappings( "em_goto_line",    prefix, ctrlx_keymap )
  224.                                                                      
  225.       temp_array[ IDM_NEXT       ] = set_menu_mappings( "em_next_buffer",  prefix, ctrlx_keymap )
  226.       temp_array[ IDM_PREV       ] = set_menu_mappings( "em_prev_buffer",  prefix, ctrlx_keymap )
  227.       temp_array[ IDM_CLOSE      ] = set_menu_mappings( "em_kill_buffer",  prefix, ctrlx_keymap )
  228.       temp_array[ IDM_BUFFERLIST ] = set_menu_mappings( "em_bufed",        prefix, ctrlx_keymap )
  229.  
  230.       temp_array[ IDM_HSPLIT_WINDOW ] = set_menu_mappings( "em_horizontal_window", prefix, ctrlx_keymap )
  231.       temp_array[ IDM_VSPLIT_WINDOW ] = set_menu_mappings( "em_vertical_window", prefix, ctrlx_keymap )
  232.  
  233.       mapped_menu_functions = temp_array
  234.    }
  235. }
  236.  
  237. global function em_fix_toolbar()
  238. {
  239.    local tbhand;
  240.  
  241.    if ( !( tbhand = toolbar_info(0) ) )
  242.       return FALSE
  243.  
  244.    if(!(tid[IDM_CUT] || tid[IDM_COPY] || tid[IDM_PASTE]))
  245.    {
  246.  
  247.       tid[IDM_CUT]   = toolbar_info(tbhand, TI_FUNCTIONID, IDM_CUT, 1);
  248.       tid[IDM_COPY]  = toolbar_info(tbhand, TI_FUNCTIONID, IDM_COPY, 1);
  249.       tid[IDM_PASTE] = toolbar_info(tbhand, TI_FUNCTIONID, IDM_PASTE, 1);
  250.  
  251.    }
  252.  
  253.    modify_toolbaritem(tbhand, IDM_CUT,   TI_FUNCTIONID, function_id("em_kill_region"));
  254.    modify_toolbaritem(tbhand, IDM_COPY,  TI_FUNCTIONID, function_id("em_copy_to_scrap"));
  255.    modify_toolbaritem(tbhand, IDM_PASTE, TI_FUNCTIONID, function_id("em_yank"));
  256. }
  257.  
  258. ###############################################################################
  259. # pre:  current_keymap == emacs_keymap == ascii_keymap
  260. # post: current_keymap == emacs_keymap == emacs standard keymappings
  261. ###############################################################################
  262. global function assign_emacs_keys()
  263. {
  264.    local i;
  265.  
  266.    for(i = 32; i < 128; i++)                          # perform normal operations
  267.       assign_key(int_to_key(i), "donormal");
  268.  
  269.    # Normal keys that do extra things
  270.  
  271.    assign_key( "]", "paren" );                        # find matching character
  272.    assign_key( "}", "paren" );
  273.    assign_key( ")", "paren" );
  274.  
  275.    # Main keyboard special keys that do extra things
  276.  
  277.    assign_key( "<Backspace>", "em_bksp" );            # delete previous character
  278.    assign_key( "<Enter>",     "em_insert_newline" );  # insert a new line
  279.    assign_key( "<Esc>",       "em_get_arg 0");        # allows user to enter integers into the argument
  280.    assign_key( "<Num-5>",     "em_scroll_window_middle" ); # centers the current window around current line
  281.    
  282.    # Alt (meta) functions
  283.  
  284.    assign_key( "<Alt-Backspace>", "em_delete_prev_word" );    #  
  285.    assign_key( "<Alt-Delete>",    "em_delete_prev_word");     # deletes word to the left
  286.    assign_key( "<Alt-\\>",        "em_remove_white_space" );  #
  287. #   assign_key( "<Alt-,>",         "em_goto_window_top");     # moves cursor to the top of the window
  288.    assign_key( "<Alt-.>",         "em_tags");                 # finds the first occurence of the tag under the cursor
  289. #     assign_key( "<Alt-/>",         "expand_template" );        #
  290.    set_expand_template_key("<Alt-/>");
  291.    assign_key( "<Alt-;>",         "em_start_comment");        # moves cursor to the bottom of the window
  292.  
  293.    assign_key( "<Alt-A>", "em_prev_sentence" );        # goes to the beginning of previous sentence
  294.    assign_key( "<Alt-B>", "em_prev_word" );            # goes to the beginning of word
  295.    assign_key( "<Alt-C>", "em_capitalize" );
  296.    assign_key( "<Alt-D>", "em_delete_next_word");      # deletes word to the right
  297.    assign_key( "<Alt-E>", "em_next_sentence" );        # goes to beginning of next sentence
  298.    assign_key( "<Alt-F>", "em_next_word" );            # goes to the beginning of the next word
  299.    assign_key( "<Alt-H>", "em_mark_paragraph" );       
  300.    assign_key( "<Alt-K>", "em_delete_next_sentence");  # deletes next sentence
  301.    assign_key( "<Alt-L>", "em_lower" );
  302.    assign_key( "<Alt-Q>", "em_wrap_paragraph" );
  303.    assign_key( "<Alt-S>", "em_center" );
  304.    assign_key( "<Alt-T>", "em_transpose_words" );
  305.    assign_key( "<Alt-U>", "em_upper" );
  306.    assign_key( "<Alt-V>", "em_page_up" );              # scrolls the window up one page
  307.    assign_key( "<Alt-W>", "em_copy_to_scrap" );        # copies the marked region to the next kill buffer
  308.    assign_key( "<Alt-X>", "em_invoke_function");       # brings up the command dialog
  309.    assign_key( "<Alt-Y>", "em_yankpop" );
  310.    assign_key( "<Alt-Z>", "em_delete_to_char" );
  311.  
  312.    assign_key( "<Alt-F4>", "em_exit" );
  313.  
  314.    #  alt-shift functions
  315.  
  316.    assign_key( "<Alt-Shift->>", "em_goto_buffer_bottom" );    # moves cursor to the bottom of the buffer
  317.    assign_key( "<Alt-Shift-<>", "em_goto_buffer_top"); # moves cursor to the top of the buffer
  318.    assign_key( "<Alt-Shift-{>", "em_prev_paragraph");  # moves cursor to the previous blank line
  319.    assign_key( "<Alt-Shift-}>", "em_next_paragraph");  # moves cursor to the next blank line
  320.    assign_key( "<Alt-Shift-%>", "em_query_replace");   # moves cursor to the next blank line
  321.    assign_key( "<Alt-Shift-!>", "em_shell" );              
  322.    assign_key( "<Alt-Shift-|>", "em_filter" );              
  323.    assign_key( "<Alt-Shift-@>", "em_set_far_mark" );              
  324.  
  325.    # normal control keys
  326.    assign_key( "<Ctrl-A>", "em_goto_bol" );            # move to beginning of the current line
  327.    assign_key( "<Ctrl-B>", "em_prev_char" );           # move to the previous character in the buffer
  328.    assign_key( "<Ctrl-D>", "em_delete_chars" );        # delete character to the right
  329.    assign_key( "<Ctrl-E>", "em_goto_eol" );            # move to the end of the current line
  330.    assign_key( "<Ctrl-F>", "em_next_char" );           # move to the next character in the buffer
  331.    assign_key( "<Ctrl-G>", "em_cancel" );              # cancels command and restores emacs keymap
  332.    assign_key( "<Ctrl-H>", "em_help" );                # pull up the help index
  333.    assign_key( "<Ctrl-K>", "em_kill_to_eol" );         # kills to end of line
  334.    assign_key( "<Ctrl-L>", "em_scroll_window_middle" ); # scrolls the current line to the center of the screen
  335.    assign_key( "<Ctrl-N>", "em_down" );                # moves the cursor down one line
  336.    assign_key( "<Ctrl-O>", "em_open_line" );           # inserts a new line after the cursor
  337.    assign_key( "<Ctrl-P>", "em_up" );                  # moves the cursor up one line
  338.    assign_key( "<Ctrl-R>", "em_i_search" );            # reverse incremental search
  339.    assign_key( "<Ctrl-S>", "em_i_search" );            # forward incremental search
  340.    assign_key( "<Ctrl-T>", "em_transpose_characters" ); # transposes the two characters following the cursor
  341.    assign_key( "<Ctrl-U>", "em_quad_arg" );            # multiply the argument by 4
  342.    assign_key( "<Ctrl-V>", "em_page_down" );           # scrolls to next page down
  343.    assign_key( "<Ctrl-W>", "em_kill_region" );         
  344.    assign_key( "<Ctrl-X>", "ctrlx" );                  # invoke C-X key map
  345.    assign_key( "<Ctrl-Y>", "em_yank" );                # yanks last thing killed
  346.    assign_key( "<Ctrl-Z>", "em_iconify");              # minimize the editor
  347.    assign_key( "<Ctrl-1>", "em_redraw" );              # redraws the current screen
  348.    assign_key( "<Ctrl-2>", "em_revert_buffer" );       # restores the buffer to its original contents
  349.    assign_key( "<Ctrl-Shift-@>", "em_set_mark" );      # set mark 
  350.    assign_key( "<Ctrl-Shift-_>", "em_undo");           # undoes the previous edit
  351.    assign_key( "<Ctrl-Space>", "em_set_column_mark" ); # set mark
  352.  
  353.    # ctrl function keys
  354.  
  355.    assign_key( "<Ctrl-F1>", "display_help_item" );
  356.  
  357.    # ctrl-alt keys
  358.  
  359.    assign_key("<Ctrl-Alt-A>", "em_prev_function");    # move to the previous function
  360.    assign_key("<Ctrl-Alt-E>", "em_next_function");    # moce to the next function
  361.    assign_key("<Ctrl-Alt-H>", "em_mark_function");    # mark a function
  362.    assign_key("<Ctrl-Alt-K>", "em_kill_to_bol");      # kills from the current position to beginning of line
  363.    assign_key("<Ctrl-Alt-R>", "em_i_search");         # invokes reverse regular expression incremental search
  364.    assign_key("<Ctrl-Alt-S>", "em_i_search");         # invokes regular expression incremental search
  365.    assign_key("<Ctrl-Alt-Shift-@>", "em_mark_sexp");  # marks an s expression
  366.  
  367.    # normal function keys
  368. #  assign_key( "<F1>", "em_help" );
  369.    assign_key( "<F2>", "expand_template" );
  370.    assign_key( "<F4>", "bind_to_key" );
  371.    assign_key( "<F6>", "whatiskey" );                 # find what function is bound to a key
  372.    assign_key( "<F7>", "em_cd" );                     # change directories
  373. #     assign_key( "<F8>", "em_get_arg 0"); #setvar" );
  374.    assign_key( "<F9>", "em_undo" );
  375.    assign_key( "<F10>", "em_redo" );
  376.  
  377.    # normal cursor keys
  378.    assign_key( "<Home>",     "em_goto_window_top" );
  379.    assign_key( "<End>",      "em_goto_window_bottom" );
  380.    assign_key( "<Left>",     "em_prev_char" );
  381.    assign_key( "<PageDown>", "em_page_down" );
  382.    assign_key( "<PageUp>",   "em_page_up" );
  383.    assign_key( "<Right>",    "em_next_char" );
  384.    assign_key( "<Up>",       "em_up" );
  385.    assign_key( "<Down>",     "em_down" );
  386.    assign_key( "<Insert>",   "em_toggle_insert_mode" );
  387.    assign_key( "<Delete>",   "em_delete_chars" );
  388.    assign_key( "<Tab>",      "em_indent_tab_maybe" );
  389. }
  390.  
  391. ################################################################################
  392. #
  393. ################################################################################
  394. global function assign_ctrlx_keys()
  395. {
  396.    assign_key( "<Delete>", "em_delete_prev_sentence" );  # deletes the sentence before the cursor
  397.    assign_key( "<Backspace>", "em_delete_prev_sentence" );  # deletes the sentence before the cursor
  398.  
  399.    assign_key( "<Ctrl-B>", "em_bufed" );              # displays the buffer list
  400.    assign_key( "<Ctrl-C>", "em_exit" );               # exits the editor
  401. #??   assign_key( "<Ctrl-E>", "em_push" );
  402.    assign_key( "<Ctrl-F>", "em_find_file" );          # loads a buffer from a file
  403.    assign_key( "<Ctrl-G>", "em_cancel" );             # cancels command and restores emacs keymap
  404. #??   assign_key( "<Ctrl-I>", "em_indent_rigidly" );
  405.    assign_key( "<Ctrl-L>", "em_lower_region" );                 #  lower cases region
  406.    assign_key( "<Ctrl-M>", "em_start_process" );
  407. #??   assign_key( "<Ctrl-N>", "em_next_error" );
  408. #??   assign_key( "<Ctrl-O>", "em_delete_blank_lines" );
  409.    assign_key( "<Ctrl-S>", "em_save_file" );          # saves the current buffer to disk
  410.    assign_key( "<Ctrl-T>", "em_transpose_lines" );    # transposes current line with line above
  411.    assign_key( "<Ctrl-U>", "em_upper_region" );                 # upper cases region
  412.    assign_key( "<Ctrl-V>", "em_replace" );            # replace buffer with specified file
  413.    assign_key( "<Ctrl-W>", "em_write_file" );         # writes buffer to file
  414.    assign_key( "<Ctrl-X>", "em_exchange_point_and_mark" ); # echanges point and mark
  415. #??   assign_key( "<Ctrl-Z>", "em_exit" );
  416.  
  417.  
  418.    assign_key( "(", "em_start_kbd_macro" );           # starts recording a macro
  419.    assign_key( ")", "em_end_kbd_macro" );             # stops recording a macro
  420.    assign_key( "[", "em_page_up" );                   # move back in the the buffer by one page
  421.    assign_key( "]", "em_page_down" );                 # move forward in the the buffer by one page
  422.    assign_key( "0", "em_delete_window" );             # deletes the current window
  423.    assign_key( "1", "em_one_window" );                # makes the current window the only 
  424.    assign_key( "2", "em_horizontal_window" );         # splits the current window in two horizontally
  425.    assign_key( "3", "em_vertical_window" );           # splits the current window in two vertically
  426.    assign_key( "=", "em_show_point" );
  427.    assign_key( "<", "em_scroll_right" );              # scroll window right
  428.    assign_key( ">", "em_scroll_left" );               # scroll window left
  429.    assign_key( ".", "em_set_line_prefix" );           # sets the string that prefixes each new line
  430.    assign_key( "b", "em_bufed" );                     # invoke buffer list
  431.    assign_key( "e", "em_last_kbd_macro" );            # play last keyboard macro
  432.    assign_key( "f", "em_set_fill_column" );
  433.    assign_key( "g", "em_goto_line" );                 # go to specified line number
  434.    assign_key( "h", "em_mark_buffer" );               # mark entire buffer
  435.    assign_key( "i", "em_insert_file" );               # unserts a file into the current buffer
  436.    assign_key( "j", "em_redo" );                      # redoes the last undo
  437.    assign_key( "k", "em_kill_buffer" );               # delete the buffer from the buffer list
  438.    assign_key( "l", "em_count_lines" );
  439.    assign_key( "n", "em_next_buffer" );               # make next buffer current
  440.    assign_key( "o", "em_next_window" );               # make next window current
  441.    assign_key( "p", "em_prev_buffer" );               # make previous buffer current
  442.    assign_key( "r", "em_ctrlxr" );                    # switch to the ctrlxr keymap
  443.    assign_key( "s", "em_save_all" );                  # saves all buffers to disk
  444.    assign_key( "u", "em_undo" );                      # undoes the previous edit      
  445.    assign_key( "w", "em_write_region" );              # write the specified region to disk
  446.  
  447.    assign_key( "B", "em_bufed" );
  448.    assign_key( "E", "em_last_kbd_macro" );
  449.    assign_key( "F", "em_set_fill_column" );
  450.    assign_key( "G", "em_goto_line" );                 # go to specified line number
  451.    assign_key( "H", "em_mark_buffer" );
  452.    assign_key( "I", "em_insert_file" );               # unserts a file into the current buffer
  453.    assign_key( "J", "em_redo" );                      # redoes the last undo
  454.    assign_key( "K", "em_kill_buffer" );
  455.    assign_key( "L", "em_count_lines" );
  456.    assign_key( "N", "em_next_buffer" );
  457.    assign_key( "O", "em_next_window" );
  458.    assign_key( "P", "em_prev_buffer" );
  459.    assign_key( "R", "em_ctrlxr" );
  460.    assign_key( "S", "em_save_all" );                  # saves all buffers to disk
  461.    assign_key( "U", "em_undo" );                      # undoes the previous edit      
  462.    assign_key( "W", "em_write_region" );
  463.  
  464.    assign_key( "<Alt-N>", "name_last_kbd_macro" );
  465.    assign_key( "<Esc>", "em_cancel" );
  466.  
  467.    assign_key( "<F6>", "whatiskey" );
  468.  
  469. #   assign_key( "<Esc>b", "em_bufed" );
  470. #   assign_key( "<Esc>n", "name_macro" );
  471. }
  472.  
  473. global function assign_ctrlxr_keys()
  474. {
  475.    assign_key( "b", "em_clear_rectangle" );           # clears the defined rectangle
  476.    assign_key( "k", "em_rect_kill" );                 # kills rectangle to current killbuffer
  477.    assign_key( "o", "em_rect_open" );                 # shifts rectangle right by the width of the rectangle
  478.    assign_key( "p", "em_string_rectangle" );          # prefixes each line of the rectangle with the prompted string
  479.    assign_key( "r", "em_rect_copy_to_register" );
  480.    assign_key( "y", "em_rect_yank" );
  481.  
  482.    assign_key( "B", "em_clear_rectangle" );           # clears the defined rectangle
  483.    assign_key( "K", "em_rect_kill" );                 # kills rectangle to current killbuffer
  484.    assign_key( "O", "em_rect_open" );                 # shifts rectangle right by the width of the rectangle
  485.    assign_key( "P", "em_string_rectangle" );          # prefixes each line of the rectangle with the prompted string
  486.    assign_key( "R", "em_rect_copy_to_register" );
  487.    assign_key( "Y", "em_rect_yank" );
  488.    assign_key( "<Ctrl-G>", "em_cancel" );             # cancels command and restores emacs keymap
  489.    assign_key( "<Esc>", "em_cancel" );
  490.  
  491.    assign_key( "<F6>", "whatiskey" );
  492. }
  493.  
  494. global function em_always(command, new_message)
  495. {
  496.    local val, msg, response;
  497.  
  498.    while(current_keymap != emacs_keymap)
  499.       pop_keymap();
  500.  
  501.    last_command = command;
  502.  
  503.    val = em_num();
  504.    if(val > 100)
  505.    {
  506.       msg = sprintf("Argument is very large (%d).  Are you sure you want to use it [yn]?", val);
  507.       response = confirm(msg, "YyNn");
  508.       if(tolower(response) == "n")
  509.          val = 1;
  510.    }
  511.  
  512.    if((last_message != " ") || (!new_message))
  513.       message(" ");
  514.    else
  515.       message(new_message);
  516.  
  517.    return val;
  518. }
  519.  
  520. global function ctrlx()
  521. {
  522.    message("C-X ");
  523.    push_keymap(ctrlx_keymap);
  524. }
  525.  
  526. global function em_ctrlxr()
  527. {
  528.    message("C-X r");
  529.    push_keymap(ctrlxr_keymap);
  530. }
  531.  
  532. ###############################################################################
  533. # post: if (last_command == KILL) em_num lines, including the current line from
  534. #     the current position is the last block in the current kill buffer and are
  535. #     removed from the current buffer.
  536. #     if !(last_was_kill == KILL) em_num lines, including the current line from
  537. #     the current position is the only block in the current kill buffer and are
  538. #     removed from the current buffer.
  539. ###############################################################################
  540. global function em_kill_to_bol()
  541. {
  542.    local normal, last = last_command;
  543.  
  544.    save_position();
  545.    begin_selection(NORMAL_SELECTION);
  546.  
  547.    if(emacc)
  548.       up(em_always(KILL) - 1);
  549.    else
  550.       em_always(KILL);
  551.  
  552.    normal = goto_bol();
  553.    if (last == KILL)
  554.    {
  555.       em_append_to_scrap(!normal);
  556.       if(!normal)
  557.          delete_chars();
  558.    }
  559.    else
  560.       em_delete_to_scrap();
  561.    restore_position(TRUE);
  562.    end_selection();
  563. }
  564.  
  565. ###############################################################################
  566. # post: if (last_command == KILL) em_num lines, including the current line from
  567. #     the current position is the last block in the current kill buffer and are
  568. #     removed from the current buffer.
  569. #     if !(last_was_kill == KILL) em_num lines, including the current line from
  570. #     the current position is the only block in the current kill buffer and are
  571. #     removed from the current buffer.
  572. ###############################################################################
  573. global function em_kill_to_eol()
  574. {
  575.    local normal, last = last_command;
  576.  
  577.    save_position();
  578.    begin_selection(NORMAL_SELECTION);
  579.  
  580.    if(emacc)
  581.       down(em_always(KILL) - 1);
  582.    else
  583.       em_always(KILL);
  584.  
  585.    normal = goto_eol();
  586.    if (last == KILL)
  587.    {
  588.       em_append_to_scrap(!normal);
  589.       if(!normal)
  590.          delete_chars();
  591.    }
  592.    else
  593.       em_delete_to_scrap();
  594.  
  595.    restore_position(TRUE);
  596.    end_selection();
  597. }
  598.  
  599. global function em_kill_region()
  600. {
  601.    if (last_command == KILL)
  602.       em_append_to_scrap();
  603.    else
  604.       em_delete_to_scrap();
  605.  
  606.    end_selection();
  607.    em_always(KILL, "Region killed");
  608. }
  609.  
  610. global function em_delete_next_word()
  611. {
  612.    local last = last_command;
  613.  
  614.    begin_selection(NORMAL_SELECTION);
  615.  
  616.    next_word(em_always(), ">");
  617.  
  618.    if (last == KILL)
  619.       em_append_to_scrap();
  620.    else em_delete_to_scrap();
  621.  
  622.    end_selection();
  623.  
  624.    last_command = KILL;
  625. }
  626.  
  627. local function massage_string(instr, direction, regex)
  628. {
  629.    local outstr = instr;
  630.  
  631.    if(!regex)
  632.       outstr = quote_regex(instr);
  633.  
  634.    if(direction)
  635.       outstr = outstr "\\c"
  636.  
  637.    return outstr;
  638. }
  639.  
  640. global function em_i_search()
  641. {
  642.    local   ch,
  643.            savex, savey,
  644.            char,
  645.            key_to_do,
  646.            found,
  647.            search_name,
  648.            old_current_search_string = current_search_string,
  649.            ESC          = key_to_int("<Esc>"),
  650.            RET          = key_to_int("<Enter>"),
  651.            BKSP         = key_to_int("<Backspace>"),
  652.            CTRLR        = key_to_int("<Ctrl-R>"),
  653.            CTRLS        = key_to_int("<Ctrl-S>"),
  654.            CTRLG        = key_to_int("<Ctrl-G>"),
  655.            CAR          = key_to_int("<Ctrl-Alt-R>"),
  656.            CAS          = key_to_int("<Ctrl-Alt-S>"),
  657.            MN           = key_to_int("<Alt-N>"),
  658.            MP           = key_to_int("<Alt-P>"),
  659.            level        = 0,
  660.            pattern      = "",
  661.            spattern     = "",
  662.            dokey        = FALSE,
  663.            direction    = 1,
  664.            finished     = FALSE,
  665.            wrap         = FALSE,
  666.            regex        = FALSE,
  667.            restore      = FALSE,
  668.            flags        = SEARCH_MAXIMAL_MATCH + SEARCH_FORWARD + SEARCH_REGEX
  669.  
  670.    em_always();
  671.    search_name[0] = "Reverse I-Search";
  672.    search_name[1] = "I-Search";
  673.  
  674.    #  Set the direction and determine regular expressions for the search;
  675.    if((current_key == CTRLR) || (current_key == CAR))
  676.    {
  677.       direction = 0;
  678.       flags = and(flags,not(SEARCH_FORWARD));
  679.    }
  680.    if((current_key == CAR) || (current_key == CAS))
  681.       flags = or(flags, SEARCH_REGEX);
  682.  
  683.    message(search_name[direction] " for:");
  684.    save_position();
  685.    while (!finished)
  686.    {
  687.       ch = getkey();
  688.  
  689.       if (ch == BKSP)
  690.       {
  691. #         if (level) {
  692. #            restore_position(TRUE);
  693. #            restore_position(TRUE);
  694. #            level --;
  695. #            save_position();
  696. #         }
  697. #         if(direction)
  698. #            prev_char(length(pattern));
  699. #         else
  700. #            next_char(length(pattern));
  701. #         pattern = substr( pattern, 0, length( pattern ) - 1)
  702. #
  703. #         spattern = massage_string(pattern, direction, regex);
  704. #
  705. #         if (search(spattern, flags)) {
  706. #            message(search_name[direction] " for: %s",pattern);
  707. #            save_position();
  708. #            level++;
  709. #         }
  710. #         else {
  711. #            message("Failing " search_name[direction] " for: %s",pattern);
  712. #            restore_position(TRUE);
  713. #            save_position();
  714. #         }
  715.  
  716.          savex = current_column;
  717.          savey = current_line;
  718.          if (level)
  719.          {
  720.             restore_position(TRUE);
  721.             level --;
  722.          }
  723.          if(direction)
  724.             prev_char(length(pattern));
  725.          else
  726.             next_char(length(pattern));
  727.          pattern = substr( pattern, 0, length( pattern ) - 1)
  728.  
  729.          spattern = massage_string(pattern, direction, regex);
  730.  
  731.          if (search(spattern, flags))
  732.          {
  733.             message(search_name[direction] " for: %s",pattern);
  734.             save_position();
  735.             level++;
  736.          }
  737.          else
  738.          {
  739.             message("Failing " search_name[direction] " for: %s",pattern);
  740.             goto_pos(savey, savex);
  741.             save_position();
  742.             level++
  743.          }
  744.       }
  745.  
  746.       else if((ch == CTRLS) || (ch == CTRLR) || (ch == CAR) || (ch == CAS))
  747.       {
  748.          if (pattern == "")
  749.              pattern = search_strings[current_search_string];
  750. #               pattern = search_strings[(current_search_string + search_string_count - 1) % search_string_count];
  751.  
  752.          direction = ((ch == CTRLS) || (ch == CAS));
  753.          regex     = ((ch == CAS)   || (ch == CAR));
  754.  
  755.          spattern = massage_string(pattern, direction, regex);
  756.  
  757.          if(direction)
  758.          {
  759.             flags = or(flags, SEARCH_FORWARD);
  760.             found = search(spattern, flags);
  761.          }
  762.          else
  763.          {
  764.             flags = and(flags, not(SEARCH_FORWARD));
  765.             found = search(spattern, flags+SEARCH_ADVANCE);
  766.          }
  767.  
  768.          if(found)
  769.          {
  770.             if(wrap)
  771.             {
  772.                message("Wrapped " search_name[direction] " for: %s",pattern);
  773.                wrap = FALSE;
  774.                flags = and(flags, not(SEARCH_WRAPS));
  775.             }
  776.             else
  777.                message(search_name[direction] " for: %s",pattern);
  778.  
  779.             save_position();
  780.             level++;
  781.          }
  782.          else
  783.          {
  784.             if(!wrap)
  785.             {
  786.                wrap = TRUE;
  787.                flags = or(flags, SEARCH_WRAPS);
  788.                message("Failing " search_name[direction] " for: %s",pattern);
  789.             }
  790.             else
  791.             {
  792.                wrap = FALSE;
  793.                flags = and(flags, not(SEARCH_WRAPS));
  794.                message("Failing Wrapped " search_name[direction] " for: %s",pattern);
  795.             }
  796.          }
  797.       }
  798.       else if(ch == MN)
  799.       {
  800.          current_search_string++;
  801.          if(current_search_string >= search_string_count)
  802.             current_search_string = 0;
  803.          pattern = search_strings[current_search_string];
  804.          message("Pattern: " search_strings[current_search_string]);
  805.       }
  806.       else if(ch == MP)
  807.       {
  808.          current_search_string--;
  809.          if(current_search_string < 0)
  810.             current_search_string = search_string_count - 1;
  811.          pattern = search_strings[current_search_string];
  812.          message("Pattern: " search_strings[current_search_string]);
  813.       }
  814.       else if(ch == CTRLG)
  815.       {
  816.          finished = TRUE;
  817.          restore  = TRUE;
  818.          current_search_string = old_current_search_string;
  819.       }
  820.       else if(ch == RET)
  821.       {
  822.          finished = TRUE;
  823.       }
  824.       else if (isprint( chr(int_to_ascii(ch) )) )
  825.       {
  826.          char     = chr(int_to_ascii(ch));
  827.          pattern  = pattern char;
  828.          spattern = massage_string(pattern, direction, regex);
  829.          current_search_string = search_string_count;
  830.  
  831.          if(direction)
  832.             prev_char(length(pattern) - 1);
  833.          else
  834.             next_char(length(pattern));
  835.  
  836.          if (search(spattern, flags))
  837.          {
  838.             message(search_name[direction] " for: %s",pattern);
  839.             level++;
  840.          }
  841.          else
  842.          {
  843.             restore_position(TRUE);
  844. #            save_position();
  845. #            level++;
  846.             message("Failing " search_name[direction] " for: %s",pattern);
  847.          }
  848.          save_position();
  849.       }
  850.       else
  851.       {
  852.           finished = TRUE;
  853. #         message("key not recognized");
  854.          dokey = TRUE;
  855.          key_to_do = ch;
  856.       }
  857.       display_update();
  858. #      message(spattern);
  859.    }
  860. # This is commented out while I try to find the goofy character bug.
  861.    while (level)
  862.    {
  863.       restore_position(FALSE);
  864.       level --;
  865.    }
  866.    restore_position(restore);
  867.    if( (!restore) && (pattern != "") && 
  868.        (current_search_string == search_string_count) )
  869.    {
  870.       search_strings[search_string_count] = pattern;
  871.       search_string_count++;
  872. #        message("getting here");
  873. #         message("ss[css] = " search_strings[search_string_count-1]);
  874.    }
  875.    message("Search complete.");
  876.  
  877.    if (dokey)
  878.       invoke_function(keymap_binding(int_to_key(key_to_do)));
  879. #execute_key_action(int_to_key(key_to_do));
  880. }
  881.  
  882. global function em_iconify()
  883. {
  884.    em_always();
  885.    set_editwin_property(EWC_MINIMIZE);
  886. }
  887.  
  888. global function em_redraw()
  889. {
  890.    em_always();
  891.    display_redraw();
  892.    message("Window redrawn");
  893. }
  894.  
  895. global function em_revert_buffer()
  896. {
  897.    em_always();
  898.  
  899.    if(undo_index())
  900.    {
  901.       undo(1);  #  this is done to preserve the first cursor movement performed by the config file
  902.       if(and(buffer_flags, BUFFER_MODIFIED))
  903.          undo();
  904.    }
  905.  
  906.    message("Buffer restored");
  907. }
  908.  
  909. global function em_mouse_set_mark()
  910. {
  911.    em_always();
  912.  
  913.    marky = current_line;
  914.    markx = current_column;
  915.  
  916.    message("Mark set");
  917. }
  918.  
  919. global function em_set_far_mark()
  920. {
  921.    marky = current_line;
  922.    markx = current_column;
  923.    save_position();
  924.    em_next_word();
  925.    begin_selection(NORMAL_SELECTION);
  926.    restore_position(TRUE);
  927.  
  928.    em_always();
  929.  
  930.    message("Mark set");
  931. }
  932.  
  933. global function em_set_mark()
  934. {
  935.    em_always();
  936.  
  937.    marky = current_line;
  938.    markx = current_column;
  939.    begin_selection(NORMAL_SELECTION);
  940.  
  941.    message("Mark set");
  942. }
  943.  
  944. global function em_set_column_mark()
  945. {
  946.    em_always();
  947.  
  948.    marky = current_line;
  949.    markx = current_column;
  950.    set_column_mark();
  951.    message("Column mark set");
  952. }
  953.  
  954. global function em_unset_mark()
  955. {
  956.    em_always();
  957.    marky = 0;
  958.    markx = 0;
  959.    end_selection();
  960.    remove_selection();
  961.  
  962.    message("Mark unset");
  963. }
  964.  
  965. global function em_next_word()
  966. {
  967.    next_word(em_always());
  968. }
  969.  
  970. global function em_prev_word()
  971. {
  972.    prev_word(em_always());
  973. }
  974.  
  975. global function em_transpose_characters()
  976. {
  977.    local char, goleft;
  978.  
  979.    em_always();
  980.    if (current_line_length < 2)
  981.       return;
  982.  
  983.    goleft = !left(1);
  984.    char = read_buffer(1);
  985.    delete_chars(1);
  986.    right(1);
  987.    insert_string(char);
  988.    left(1);
  989.    if (goleft) left(1);
  990. }
  991.  
  992. global function em_delete_prev_word()
  993. {
  994.    local count = em_num();
  995.  
  996.    begin_selection(NORMAL_SELECTION);
  997.  
  998.    prev_word(count);
  999.  
  1000.    if (last_command == KILL)
  1001.       em_append_to_scrap();
  1002.  
  1003.    else
  1004.       em_delete_to_scrap();
  1005.  
  1006.    end_selection();
  1007.  
  1008.    em_always(KILL);
  1009. }
  1010.  
  1011. global function em_delete_prev_sentence()
  1012. {
  1013.    local count = em_num();
  1014.  
  1015.    begin_selection(NORMAL_SELECTION);
  1016.  
  1017.    prev_sentence(count);
  1018.  
  1019.    end_selection();
  1020.  
  1021.    if (last_command == KILL)
  1022.       em_append_to_scrap();
  1023.  
  1024.    else
  1025.       em_delete_to_scrap();
  1026.  
  1027.  
  1028.    em_always(KILL);
  1029. }
  1030.  
  1031. global function em_capitalize()
  1032. {
  1033.    local count;
  1034.  
  1035.    count = em_always();
  1036.    do
  1037.    {
  1038.       capitalize();
  1039.       next_word();
  1040.       count--;
  1041.    } while(count > 0);
  1042. }
  1043.  
  1044. global function em_upper()
  1045. {
  1046.    save_position();
  1047.    begin_selection(NORMAL_SELECTION);
  1048.  
  1049.    next_word(em_always());
  1050.  
  1051.    upper();
  1052.  
  1053.    restore_position(TRUE);
  1054. }
  1055.  
  1056. global function em_upper_region()
  1057. {
  1058.    em_always();
  1059.  
  1060.    upper();
  1061. }
  1062.  
  1063. global function em_delete_next_sentence()
  1064. {
  1065.    begin_selection(NORMAL_SELECTION);
  1066.  
  1067.    next_sentence(em_num());
  1068.  
  1069.    em_kill_region();
  1070.  
  1071.    message("Sentence deleted");
  1072. }
  1073.  
  1074. global function em_lower()
  1075. {
  1076.    save_position();
  1077.    begin_selection(NORMAL_SELECTION);
  1078.  
  1079.    next_word(em_always());
  1080.  
  1081.    lower();
  1082.  
  1083.    restore_position(TRUE);
  1084. }
  1085.  
  1086. global function em_lower_region()
  1087. {
  1088.    em_always();
  1089.  
  1090.    lower();
  1091. }
  1092.  
  1093. global function em_center()
  1094. {
  1095.    local s,e,c;
  1096.    local ft;
  1097.  
  1098.    em_num();
  1099.  
  1100.    if (and(keyboard_flags,4))
  1101.    {
  1102.       toggle_search_flags( SEARCH_REGEX, TRUE);
  1103.       search_forward();
  1104.       return;
  1105.    }
  1106.  
  1107.    goto_bol();
  1108.    if (!search("[^ \t]",SEARCH_FORWARD+SEARCH_REGEX))
  1109.       return;
  1110.  
  1111.    s = current_column;
  1112.    goto_eol();
  1113.    search("[^ \t]",SEARCH_REGEX);
  1114.    e = current_column;
  1115.    c = 40-((s + e)/2);
  1116.    current_column = s;
  1117.    ft = first_tab_distance();
  1118.    indent_tabs(c/ft);
  1119.    indent_columns(c%ft);
  1120.    last_command = FALSE;
  1121. }
  1122.  
  1123. global function em_remove_white_space()
  1124. {
  1125.    local col = current_column;
  1126.  
  1127.    em_always();
  1128.  
  1129.    search("[^ \t]|^", SEARCH_REGEX);
  1130.  
  1131.    if(!(read_buffer(1) ~ "[ \t]"))
  1132.       next_char();
  1133.  
  1134.    col = (current_column < col) ? current_column : col;
  1135.  
  1136.    begin_selection(NORMAL_SELECTION);
  1137.    search("[^ \t]|$", SEARCH_FORWARD+SEARCH_REGEX);
  1138.    delete_chars();
  1139.  
  1140.    goto_pos(0, col);
  1141. }
  1142.  
  1143. global function em_goto_buffer_top()
  1144. {
  1145.    em_always();
  1146.    goto_buffer_top();
  1147.  
  1148.    message("Top of buffer");
  1149. }
  1150.  
  1151. global function em_goto_buffer_bottom()
  1152. {
  1153.    em_always();
  1154.    goto_buffer_bottom();
  1155.  
  1156.    message("Bottom of buffer");
  1157. }
  1158.  
  1159. global function em_shell()
  1160. {
  1161.    local command;
  1162.  
  1163.    em_always();
  1164.    
  1165.    command = prompt("OS/2 command: ", "" );
  1166.    if(command)
  1167.       system(command);
  1168. }
  1169.  
  1170. global function em_filter()
  1171. {
  1172.    local command, code;
  1173.  
  1174.    em_always();
  1175.    command = prompt_history("XMACRO", "Enter command: ", "", 1, 1, "em_filter_prompt" );
  1176.    if(command)
  1177.    {
  1178.       code  = filter(command);
  1179.       if(!code)
  1180.          message("Command executed successfully");
  1181.       else
  1182.          warning("Command encountered an error.  Return code %d", code);
  1183.    }
  1184.    else
  1185.       message("Command canceled");
  1186. }
  1187.  
  1188. global function bind_to_key()
  1189. {
  1190.    local key, comm, ch;
  1191.  
  1192.    comm = prompt_history("XMACRO", "Bind command: ", "", 1, 1, "em_bind_to_key_prompt" );
  1193.  
  1194.    if (comm != "")
  1195.    {
  1196.       message("To key: ");
  1197.  
  1198.       ch = getkey();
  1199.  
  1200.       if (comm in savedmacs)
  1201.          assign_key(int_to_key(ch), "replay " comm);
  1202.       else
  1203.          assign_key(int_to_key(ch),comm);
  1204.    }
  1205.    em_always();
  1206. }
  1207.  
  1208. global function paren()
  1209. {
  1210.    local i,j, ch;
  1211.  
  1212.    j = em_always();
  1213.  
  1214.    ch = chr(int_to_ascii(current_key));
  1215.    for (i=0; i<j; i++)
  1216.    {
  1217.       insert_string(ch);
  1218.       save_position();
  1219.       prev_char();
  1220.       goto_matching();
  1221.       create_linecol_selection(COLUMN_SELECTION, current_line, current_column, current_line, current_column);
  1222.       play("P1P1P1P1P1");
  1223.       end_selection();
  1224.  
  1225.       if(ch == "}")
  1226.          move_bracket();
  1227.  
  1228.       restore_position(TRUE);
  1229.    }
  1230. }
  1231.  
  1232. global function first_nonwhite()
  1233. {
  1234.    local ch;
  1235.  
  1236.    goto_bol();
  1237.           
  1238.    do
  1239.    {
  1240.       ch = read_buffer(1);
  1241.       if(ch)
  1242.          next_char();
  1243.    } while(((ch == " ") || (ch == "\t")) && (ch != ""));
  1244.  
  1245.    return (ch == "") ? 0 : (current_column - 1);
  1246. }
  1247.  
  1248. local function move_bracket()
  1249. {
  1250.    local start, col = first_nonwhite(), offset = "";
  1251.  
  1252.    restore_position(TRUE);
  1253.    prev_char();
  1254.    start = current_column;
  1255.  
  1256.    if(start < col)
  1257.       offset = strrepeat(" ", col - start);
  1258.  
  1259.    insert_string(offset);
  1260.    next_char();
  1261. }
  1262.  
  1263. global function em_transpose_words()
  1264. {
  1265.    local s1,e1,s2,e2, save1, save2;
  1266.  
  1267.    em_num();
  1268.    next_word();
  1269.    e1 = current_column;
  1270.    prev_word();
  1271.    s1 = current_column;
  1272.    save1 = read_buffer(e1-s1);
  1273.  
  1274.    prev_word();
  1275.  
  1276.    next_word();
  1277.    e2 = current_column;
  1278.    prev_word();
  1279.    s2 = current_column;
  1280.    save2 = read_buffer(e2-s2);
  1281.  
  1282.    current_column = s1;
  1283.    delete_chars(e1-s1);
  1284.    insert_string(save2);
  1285.  
  1286.    current_column = s2;
  1287.    delete_chars(e2-s2);
  1288.    insert_string(save1);
  1289.    last_command = FALSE;
  1290. }
  1291.  
  1292. global function em_mark_paragraph()
  1293. {
  1294.    local i,j;
  1295.  
  1296.    j = em_always();
  1297.    prev_paragraph();
  1298.    em_set_mark();
  1299.    for (i=0; i<j; i++)
  1300.       next_paragraph();
  1301. }
  1302.  
  1303. global function em_query_replace()
  1304. {
  1305.    em_always();
  1306.    sf_replace();
  1307. }
  1308.  
  1309. global function em_delete_chars()
  1310. {
  1311.       delete_chars(em_always());
  1312. }
  1313.  
  1314. global function em_down()
  1315. {
  1316.    local count = em_always(last_command);
  1317.  
  1318.    if(last_command == VERT)
  1319.       goto_pos(current_line + count, last_column);
  1320.    else
  1321.    {
  1322.       last_column = current_column;
  1323.       last_command = VERT;
  1324.       down(count);
  1325.    }
  1326. }
  1327.  
  1328. global function em_insert_newline()
  1329. {
  1330.    local i, j;
  1331.  
  1332.    j = em_always();
  1333.    for (i = 0; i < j; i ++)
  1334.    {
  1335.       auto_indent_cr()
  1336.       insert_string(line_prefix);
  1337.    }
  1338. }
  1339.  
  1340. global function em_open_line()
  1341. {
  1342.    save_position()
  1343.    em_insert_newline()
  1344.    restore_position(TRUE)
  1345. }
  1346.  
  1347. global function em_insert_scrap()
  1348. {
  1349.    local i, j;
  1350.  
  1351.    j = em_always();
  1352.  
  1353.    lastyankx1 = current_column;
  1354.    lastyanky1 = current_line;
  1355.  
  1356.    for (i = 0; i < j; i ++)
  1357.       insert_scrap()
  1358.  
  1359.    lastyankx2 = current_column;
  1360.    lastyanky2 = current_line;
  1361. }
  1362.  
  1363. ###############################################################################
  1364. # pre:  killbuffers[currentkill].bufid exists
  1365. # post: killbuffers[currentkill].bufis is in the current buffer at current_position'
  1366. #     current_position is next character after killbuffers[currentkill]
  1367. ###############################################################################
  1368. global function em_yank()
  1369. {
  1370.    local buffer = current_buffer, 
  1371.          count  = em_always(YANK), i;
  1372.  
  1373.    lastyankx1 = current_column;
  1374.    lastyanky1 = current_line;
  1375.  
  1376.    current_buffer = killbuffers[currentkill].bufid;
  1377.  
  1378.    goto_buffer_top();
  1379.    begin_selection(killbuffers[currentkill].type);
  1380.    goto_buffer_bottom();
  1381.    if(killbuffers[currentkill].type == COLUMN_SELECTION)
  1382.       prev_char();
  1383.  
  1384.    copy_to_scrap();
  1385.    end_selection();
  1386.  
  1387.    current_buffer = buffer;
  1388.  
  1389.    for(i=0; i<count; i++)
  1390.       insert_scrap();
  1391.  
  1392.    lastyankx2 = current_column;
  1393.    lastyanky2 = current_line;
  1394. }
  1395.  
  1396. global function em_next_char()
  1397. {
  1398.    next_char(em_always());
  1399. }
  1400.  
  1401. global function em_next_paragraph()
  1402. {
  1403.    next_paragraph(em_always())
  1404. }
  1405.  
  1406. global function em_next_function()
  1407. {
  1408.    next_section(em_always())
  1409. }
  1410.  
  1411. global function em_next_sentence()
  1412. {
  1413.    next_sentence(em_always());
  1414. }
  1415.  
  1416. global function em_page_down()
  1417. {
  1418.    local i, count;
  1419.  
  1420.    count = em_always();
  1421.  
  1422.    for (i = 0; i < count; i++)
  1423.       page_down()
  1424. }
  1425.  
  1426. global function em_page_up()
  1427. {
  1428.    local i, count;
  1429.  
  1430.    count = em_always();
  1431.  
  1432.    for (i = 0; i < count; i++)
  1433.       page_up()
  1434. }
  1435.  
  1436. global function em_prev_char()
  1437. {
  1438.    prev_char(em_always())
  1439. }
  1440.  
  1441. global function em_prev_paragraph()
  1442. {
  1443.    prev_paragraph(em_always())
  1444. }
  1445.  
  1446. global function em_prev_function()
  1447. {
  1448.    prev_section(em_always())
  1449. }
  1450.  
  1451. global function em_prev_sentence()
  1452. {
  1453.    prev_sentence(em_always())
  1454. }
  1455.  
  1456. global function em_scroll_vertical_up()
  1457. {
  1458.    scroll_vertical(-em_always())
  1459. }
  1460.  
  1461. global function em_scroll_vertical_down()
  1462. {
  1463.    scroll_vertical(em_always())
  1464. }
  1465.  
  1466. global function em_up()
  1467. {
  1468.    local count = em_always(last_command);
  1469.  
  1470.    if(last_command == VERT)
  1471.       goto_pos(max(1, current_line - count), last_column);
  1472.    else
  1473.    {
  1474.       last_column = current_column;
  1475.       last_command = VERT;
  1476.       up(count);
  1477.    }
  1478. }
  1479.  
  1480. global function em_bksp()
  1481. {
  1482.    local i,j;
  1483.  
  1484.    j = em_always();
  1485.    for (i=0; i<j; i++)
  1486.       backspace();
  1487. }
  1488.  
  1489. global function em_num()
  1490. {
  1491.    local i;
  1492.  
  1493.    i = ((emacc) ? emacc : 1);
  1494.    emacc = 0;
  1495.  
  1496.    return i;
  1497. }
  1498.  
  1499. global function em_quad_arg()
  1500. {
  1501.    if (!emacc) emacc++;
  1502.    emacc *= 4;
  1503.    message("Argument %d",emacc);
  1504. }
  1505.  
  1506. global function em_get_arg(n)
  1507. {
  1508.    local   ch;
  1509.  
  1510.    do
  1511.    {
  1512.       emacc *= 10;
  1513.       emacc += n;
  1514.       message("Arg: %d", emacc);
  1515.  
  1516.       ch = getkey();
  1517.       n  = int_to_ascii(ch) - ord("0");
  1518.    } while (isdigit( chr(int_to_ascii(ch))));
  1519.  
  1520.    ungetkey(ch);
  1521. }
  1522.  
  1523. global function donormal()
  1524. {
  1525.    local ch, count = em_always(), note, tune;
  1526.  
  1527.    ch = chr(int_to_ascii(current_key));
  1528.    if(count > 1)
  1529.    {
  1530.       insert_string(strrepeat(ch, count));
  1531.  
  1532.       if(and(buffer_flags, BUFFER_OVERTYPE_MODE))
  1533.       {
  1534.  
  1535.          if((count + current_column) > current_line_width)
  1536.             delete_to_eol();
  1537.          else
  1538.             delete_chars(count);
  1539.       }
  1540.    }
  1541.    else
  1542.       insert_key();
  1543.  
  1544.    if(emacs_music)
  1545.    {
  1546.       note = (( (ord(ch) - 32) * 83 ) / 95) + 16;
  1547.       tune = "L16N" note;
  1548.       message(tune); 
  1549.       play(tune);
  1550.    }
  1551. }
  1552.  
  1553. global function em_cd()
  1554. {
  1555.    em_always();
  1556.    chdir(prompt_history("EDITFILE", "Change directory to: ", getcwd(), 1, 1, "em_cd_dialog" ));
  1557. }
  1558.  
  1559. global function em_help()
  1560. {
  1561.    em_always();
  1562.    gui_help_index();
  1563. }
  1564.  
  1565. global function em_delete_to_char()
  1566. {
  1567.    local ch;
  1568.  
  1569.    em_always();
  1570.    message("Enter search character: ");
  1571.    ch = chr(int_to_ascii(getkey()));
  1572.    save_position();
  1573.    begin_selection(NORMAL_SELECTION);
  1574.  
  1575.    if(search(ch, SEARCH_FORWARD+SEARCH_CASE))
  1576.    {
  1577.       em_kill_region();
  1578.  
  1579.       message("Text deleted");
  1580.    }
  1581.    else
  1582.       message("Character not found");
  1583.    restore_position(TRUE);
  1584.          end_selection();
  1585. }
  1586.  
  1587. global function em_invoke_function()
  1588. {
  1589.    local comm;
  1590.  
  1591.    em_always();
  1592.  
  1593.    comm = prompt_history("XMACRO","Command: ","em_", 1, 1, "command" );
  1594.  
  1595.    if (comm in savedmacs)
  1596.       replay(comm);
  1597.    else if(comm)
  1598.       invoke_function(comm);
  1599. }
  1600.  
  1601. global function em_redo()
  1602. {
  1603.    em_always();
  1604.    redo();
  1605. }
  1606.  
  1607. global function em_scroll_window_middle()
  1608. {
  1609.    em_always();
  1610.    scroll_window_middle();
  1611. }
  1612.  
  1613. global function em_toggle_insert_mode()
  1614. {
  1615.    em_always();
  1616.    toggle_buffer_flags( BUFFER_OVERTYPE_MODE );
  1617. }
  1618.  
  1619. global function em_undo()
  1620. {
  1621.    em_always();
  1622.    undo();
  1623. }
  1624.  
  1625. global function em_goto_bol()
  1626. {
  1627.    em_always();
  1628.    goto_bol();
  1629. }
  1630.  
  1631. global function em_goto_eol()
  1632. {
  1633.    em_always();
  1634.    goto_eol();
  1635. }
  1636.  
  1637. global function em_goto_window_bottom()
  1638. {
  1639.    em_always();
  1640.    goto_window_bottom();
  1641. }
  1642.  
  1643. global function em_tags()
  1644. {
  1645.    local symbol;
  1646.  
  1647.    em_always();
  1648.    symbol = symbol_under_cursor();
  1649.    tags(symbol);
  1650. }
  1651.  
  1652. global function em_start_comment()
  1653. {
  1654.    local key;
  1655.  
  1656.    em_always();
  1657.  
  1658.    key = path_ext(buffer_filename);
  1659.    message(key);
  1660.    if(key in comments)
  1661.    {
  1662.       save_position();
  1663.       insert_string(comments[key]);
  1664.       restore_position(TRUE);
  1665.       current_column += 3;
  1666.    }
  1667.    else
  1668.       warning("Unrecognized file extension.");
  1669. }
  1670.  
  1671. global function em_goto_window_top()
  1672. {
  1673.    em_always();
  1674.    goto_window_top();
  1675. }
  1676.  
  1677. global function name_last_kbd_macro()
  1678. {
  1679.    local s;
  1680.  
  1681.    if (current_keymap == ctrlx_keymap)
  1682.       pop_keymap();
  1683.  
  1684.    if (keymac == "")
  1685.       return;
  1686.  
  1687.    s = prompt("Macro name: ", "", "em_name_kbd_macro_prompt" );
  1688.  
  1689.    if (s == "")
  1690.       return;
  1691.  
  1692.    savedmacs[s] = keymac;
  1693.    message("");
  1694. }
  1695.  
  1696. global function replay(comm)
  1697. {
  1698.    local s;
  1699.  
  1700.    em_always();
  1701.    s = savedmacs[comm];
  1702.    playback(substr(s, 1, length(s) -1));
  1703. }
  1704.  
  1705. ################################################################################
  1706. #  C-x r keymap functions.
  1707. #  These functions handle all rectangle commands.
  1708. ################################################################################
  1709.  
  1710. global function em_clear_rectangle()
  1711. {
  1712.    local    prefix, i, flags,
  1713.             start  = min(marky, current_line),
  1714.             end    = max(marky, current_line),
  1715.             col    = min(markx, current_column),
  1716.             len    = abs(markx - current_column) + 1,
  1717.             old_buffer = buffer_flags;
  1718.  
  1719.    em_always();
  1720.  
  1721.    if(em_rectangle_defined())
  1722.    {
  1723.       em_rect_kill();
  1724.       prefix = strrepeat(" ", len);
  1725.  
  1726.       for(i = start; i <= end; i++)
  1727.       {
  1728.          goto_pos(i, col);
  1729.          insert_string(prefix);
  1730.       }
  1731.       remove_selection();
  1732.  
  1733.       message("Rectangle blanked out");
  1734.    }
  1735. }
  1736.  
  1737. global function em_rect_kill()
  1738. {
  1739.    em_always();
  1740.  
  1741.    if(em_rectangle_defined())
  1742.    {
  1743.       create_linecol_selection(COLUMN_SELECTION, marky, markx, current_line, current_column);
  1744.       em_delete_to_scrap();
  1745.       remove_selection();
  1746.          
  1747.       message("Rectangle killed");
  1748.    }
  1749. }
  1750.  
  1751. global function em_rect_open()
  1752. {
  1753.    local col = current_column, scol;
  1754.  
  1755.    em_always();
  1756.    if(em_rectangle_defined())
  1757.    {
  1758.       scol = min(markx, col);
  1759.       create_linecol_selection(COLUMN_SELECTION, min(marky, current_line), scol, max(marky, current_line), scol);
  1760.       indent_columns(abs(col - markx)+1);
  1761.       message("Rectangle shifted right");
  1762.       remove_selection();
  1763.    }
  1764. }
  1765.  
  1766. global function em_string_rectangle()
  1767. {
  1768.    local    prefix, i, start, end, col;
  1769.  
  1770.    em_always();
  1771.  
  1772.    if(em_rectangle_defined())
  1773.    {
  1774.       start  = min(marky, current_line);
  1775.       end    = max(marky, current_line);
  1776.       col    = min(markx, current_column);
  1777.  
  1778.       prefix = prompt_history("PREFIX", "String to prefix rectangle: ", "", 1, 1, "em_prefix_rectangle_prompt");
  1779.       for(i = start; i <= end; i++)
  1780.       {
  1781.          goto_pos(i, col);
  1782.          insert_string(prefix);
  1783.       }
  1784.       remove_selection();
  1785.  
  1786.       message("Rectangle prefixed");
  1787.    }
  1788. }
  1789.  
  1790. global function em_rect_copy_to_register()
  1791. {
  1792.    em_always();
  1793.    message("Find out what a register is");
  1794. }
  1795.  
  1796. global function em_rect_yank()
  1797. {
  1798.    local this_buffer;
  1799.  
  1800.    em_always();
  1801.  
  1802.    this_buffer = current_buffer;
  1803.    current_buffer = killbuffers[currentkill].bufid;
  1804.  
  1805.    goto_buffer_top();
  1806.    begin_selection(killbuffers[currentkill].type);
  1807.  
  1808.    goto_buffer_bottom();
  1809.    if(killbuffers[currentkill].type == COLUMN_SELECTION)
  1810.       prev_char();
  1811.  
  1812.    copy_to_scrap();
  1813.  
  1814.    current_buffer = this_buffer;
  1815.    insert_scrap();
  1816.  
  1817.    message("Yank rectangle from kill buffer");
  1818. }
  1819.  
  1820. global function em_rectangle_defined()
  1821. {
  1822.    local markset = !((markx + marky) == 0);
  1823.  
  1824.    if(!markset)
  1825.       warning("Rectangle not defined");
  1826.  
  1827.    return markset;
  1828. }
  1829.  
  1830. ######## end rectangle functions
  1831.  
  1832. global function em_indent_tab_maybe()
  1833. {
  1834.    local i, cnt = em_always();
  1835.  
  1836.    for(i = 0; i < cnt; i++)
  1837.       indent_tab_maybe();
  1838. }
  1839.  
  1840. #  
  1841. #  Current line is adjusted to line up with line above or indented one stop if required
  1842. #  
  1843. #  Indent if line above has an open structure ( ([{" )
  1844. #         or does not end in a semi-colon followed by white space
  1845. #  
  1846. global function em_indent()
  1847. {
  1848.    local ch, pos = 0, fnw = 0, fnw2 = 0, line, level = 0, quote = 0, tablevel = FALSE;
  1849.    local savex = current_column, savey = current_line, newx;
  1850.    local save_buffer_flags = buffer_flags;
  1851.  
  1852.    if(and(save_buffer_flags, BUFFER_OVERTYPE_MODE))
  1853.       buffer_flags = xor(buffer_flags, BUFFER_OVERTYPE_MODE);
  1854.  
  1855.    em_always();
  1856.  
  1857.    do
  1858.    {
  1859.       pos = up(1);
  1860.       fnw = first_nonwhite();
  1861.    } while(!fnw && pos)
  1862.  
  1863.    if(!pos)
  1864.    {
  1865.       tablevel = TRUE;
  1866.       fnw = 1;
  1867.    }
  1868.    else
  1869.    {
  1870.       goto_pos(0, fnw);
  1871.       ch = read_buffer(1);
  1872.  
  1873.       pos = 0;
  1874.       while(ch != "")
  1875.       {
  1876.          
  1877.          #  Only count characters that are outside of quotes
  1878.          if(ch == "\"")
  1879.             quote = xor(quote, TRUE);
  1880.  
  1881.          else if(!quote)
  1882.          {
  1883.             if(match(ch, "[\\{\\(\\[]"))
  1884.                level++;
  1885.             else if(match(ch, "[\\}\\)\\]]"))
  1886.                level--;
  1887.             else if(match(ch, "[ \t]") && pos)
  1888.                pos++;
  1889.             else if(ch == ";")
  1890.                pos = current_column;
  1891.          }
  1892.          next_char();
  1893.          ch = read_buffer(1);
  1894.       }
  1895.       if( ((pos != current_line_width) && (level >= 0)) || (level > 0) || quote )
  1896.          tablevel = TRUE;
  1897.    }
  1898.    goto_pos(savey, 0);
  1899.    fnw2 = first_nonwhite();
  1900.    goto_pos(0, fnw2);
  1901.    line = read_buffer();
  1902.    delete_line();
  1903.    goto_bol();
  1904.       
  1905.    insert_string(strrepeat(" ", fnw-1));
  1906.    if(tablevel)
  1907.    {
  1908.       fnw += distance_next_tab;
  1909.       insert_string(strrepeat(" ", distance_next_tab));
  1910.    }
  1911.    newx = current_column;
  1912.    savex = savex - fnw2 + fnw;
  1913.  
  1914.    insert_string(line "\n");
  1915.    if(savex > newx)
  1916.       goto_pos(savey, savex);
  1917.    else
  1918.       goto_pos(savey, newx);
  1919.  
  1920.    buffer_flags = save_buffer_flags;
  1921.  
  1922. }
  1923.  
  1924. global function whatiskey()
  1925. {
  1926.    local ch, func, bound, name;
  1927.  
  1928.    message("What is key: ");
  1929.    ch    = getkey();
  1930.    name  = int_to_key(ch);
  1931.    bound = keymap_binding(name);
  1932.  
  1933.    em_always();
  1934.    if(bound)
  1935.       func = "Mapped to: " "\"" bound "\"";
  1936.    else
  1937.       func = "Key not mapped."
  1938.  
  1939.    message("Key ID: " ch "; String: " name "; " func);
  1940. }
  1941.  
  1942. global function em_wrap_paragraph()
  1943. {
  1944.    em_always();
  1945.    wrap_paragraph();
  1946. }
  1947.  
  1948. global function em_yankpop()
  1949. {
  1950.    local width;
  1951.    local thisbuffer = current_buffer;
  1952.    local type = killbuffers[currentkill].type;
  1953.  
  1954.    if(last_command == YANK)
  1955.    {
  1956.       if(type == COLUMN_SELECTION)
  1957.       {
  1958.          current_buffer = killbuffers[currentkill].bufid;
  1959.          save_position();
  1960.          goto_buffer_top();
  1961.          restore_position(TRUE);
  1962.          width = current_line_width;
  1963.  
  1964.          current_buffer = thisbuffer;
  1965.          current_line --;
  1966.          current_column = lastyankx1 + width - 1;
  1967.       }
  1968.  
  1969.       begin_selection(type);
  1970.  
  1971.       current_column = lastyankx1;
  1972.       current_line = lastyanky1;
  1973.  
  1974.       delete_chars();
  1975.       end_selection();
  1976.  
  1977.       prevkillbuf(1);
  1978.       em_yank();
  1979.    }
  1980.    else
  1981.       warning("Last command was not a yank");
  1982. }
  1983.  
  1984. global function em_delete_to_scrap()
  1985. {
  1986.    local thisbuffer, 
  1987.          name,
  1988.          type = selection_type();
  1989.  
  1990.    thisbuffer = current_buffer;
  1991.  
  1992.    delete_to_scrap();
  1993.  
  1994.    nextkillbuf(1);
  1995.  
  1996.    delete_buffer(killbuffers[currentkill].bufid);
  1997.    name = "killbuffer" currentkill "";
  1998.    killbuffers[currentkill].bufid = create_buffer(name, name, BUFFER_SYSTEM+BUFFER_NO_UNDO);
  1999.  
  2000.    killbuffers[currentkill].type = type;
  2001.    current_buffer = killbuffers[currentkill].bufid;
  2002.    insert_scrap();
  2003.  
  2004.    current_buffer = thisbuffer;
  2005. }
  2006.  
  2007. global function em_append_to_scrap(newline)
  2008. {
  2009.    local thisbuffer;
  2010.  
  2011.    thisbuffer = current_buffer;
  2012.  
  2013.    delete_to_scrap();
  2014.  
  2015.    current_buffer = killbuffers[currentkill].bufid;
  2016.  
  2017.    if(newline)
  2018.       insert_newline();
  2019.    else
  2020.      insert_scrap();
  2021.  
  2022.    current_buffer = thisbuffer;
  2023. }
  2024.  
  2025. global function em_copy_to_scrap()
  2026. {
  2027.    local thisbuffer,
  2028.          name,
  2029.          type = selection_type();
  2030.  
  2031.    thisbuffer = current_buffer;
  2032.  
  2033.    copy_to_scrap();
  2034.  
  2035.    nextkillbuf(1);
  2036.  
  2037.    delete_buffer(killbuffers[currentkill].bufid);
  2038.    name = "killbuffer" currentkill "";
  2039.    killbuffers[currentkill].bufid = create_buffer(name, name, BUFFER_SYSTEM);
  2040.    killbuffers[currentkill].type = type;
  2041.    current_buffer = killbuffers[currentkill].bufid;
  2042.    insert_scrap();
  2043.  
  2044.    current_buffer = thisbuffer;
  2045.    
  2046.    em_unset_mark();
  2047. }
  2048.  
  2049. global function nextkillbuf(adv)
  2050. {
  2051.    currentkill += adv;
  2052.    currentkill %= NUMKILLBUFFERS;
  2053. }
  2054.  
  2055. global function prevkillbuf(adv)
  2056. {
  2057.    adv %= NUMKILLBUFFERS;
  2058.    currentkill += (NUMKILLBUFFERS - adv);
  2059.    currentkill %= NUMKILLBUFFERS;
  2060. }
  2061.  
  2062. global function em_display_next_kill()
  2063. {
  2064. #     local old_flags = window_flags;
  2065.  
  2066.    nextkillbuf(em_always());
  2067.    window_flags = or(window_flags, WINDOW_SHOW_SYSTEM);
  2068.    current_buffer = killbuffers[currentkill].bufid;
  2069.  
  2070. #     window_flags = old_flags;
  2071. }
  2072.  
  2073. global function em_display_prev_kill()
  2074. {
  2075. #     local old_flags = window_flags;
  2076.  
  2077.    prevkillbuf(em_always());
  2078.    window_flags = or(window_flags, WINDOW_SHOW_SYSTEM);
  2079.    current_buffer = killbuffers[currentkill].bufid;
  2080.  
  2081. #     window_flags = old_flags;
  2082. }
  2083.  
  2084. global function em_modified()
  2085. {
  2086.    em_always();
  2087.    buffer_flags = xor(buffer_flags, BUFFER_MODIFIED);
  2088.  
  2089.    if (and(buffer_flags,BUFFER_MODIFIED))
  2090.       message("Buffer is marked changed");
  2091.    else
  2092.       message("Buffer is marked unchanged");
  2093. }
  2094.  
  2095. global function em_showvar()
  2096. {
  2097.    local showme;
  2098.  
  2099.    em_always();
  2100.  
  2101.    showme = prompt_history("XMACRO","Show variable: ","", 1, 1);
  2102.  
  2103.    if(showme)
  2104.       message(showme " == " execute_function(showme));
  2105. }
  2106.  
  2107. global function setvar()
  2108. {
  2109.    local setme;
  2110.    local to;
  2111.  
  2112.    em_always();
  2113.  
  2114.    setme = prompt_history("XMACRO","set variable: ","", 1, 1);
  2115.    to = prompt("to: ");
  2116.    message(setme " == " execute_function(setme"="to));
  2117. }
  2118.  
  2119. global function em_copytofile()
  2120. {
  2121.    local t;
  2122.  
  2123.    em_always();
  2124.    t = and(buffer_flags,BUFFER_MODIFIED);
  2125.    write_buffer(prompt_history("EDITFILE","Copy to file: ", getcwd(), 1, 1, "em_copytofile_dialog"));
  2126.    buffer_flags = set_flag_bits(buffer_flags, BUFFER_MODIFIED, t);
  2127. }
  2128.  
  2129. global function em_set_line_prefix()
  2130. {
  2131.    local prefix_string;
  2132.  
  2133.    prefix_string = prompt_history("PREFIX", "New line prefix: " , line_prefix, 1, 1, "em_set_line_prefix_prompt" );
  2134.  
  2135.    line_prefix = prefix_string;
  2136.    em_always();
  2137. }
  2138.  
  2139. global function em_bufed()
  2140. {
  2141.    em_always();
  2142.    buffer_list();
  2143. }
  2144.  
  2145. global function em_count_lines()
  2146. {
  2147.    em_always();
  2148.    message("%d lines, point on line %d",buffer_last_line, current_line);
  2149. }
  2150.  
  2151. global function em_cancel()
  2152. {
  2153.    em_always();
  2154.    message("Command canceled");
  2155. }
  2156.  
  2157. global function em_delete_blank_lines()
  2158. {
  2159.    em_always();
  2160.    goto_bol();
  2161.  
  2162.    save_position();
  2163.    while (up() && isblank(read_buffer()))
  2164.    {
  2165.       restore_position(FALSE);
  2166.       save_position();
  2167.    }
  2168.    restore_position(TRUE);
  2169.    begin_selection(NORMAL_SELECTION);
  2170.  
  2171.    save_position();
  2172.    while (isblank(read_buffer()) && down())
  2173.    {
  2174.       restore_position(FALSE);
  2175.       save_position();
  2176.    }
  2177.    restore_position(TRUE);
  2178.  
  2179.    delete_chars();
  2180. }
  2181.  
  2182. global function em_end_kbd_macro()
  2183. {
  2184.    em_always();
  2185.    keymac=record(0);
  2186.    message("Done Recording");
  2187. }
  2188.  
  2189. global function em_exchange_point_and_mark()
  2190. {
  2191.    local t;
  2192.  
  2193.    em_always();
  2194.    end_selection();
  2195.  
  2196.    update_current_view();
  2197.    begin_selection(NORMAL_SELECTION);
  2198.  
  2199.    t = markx;
  2200.    markx = current_column;
  2201.    current_column = t;
  2202.    t = marky;
  2203.    marky = current_line;
  2204.    current_line = t;
  2205. }
  2206.  
  2207. global function em_exit()
  2208. {
  2209.    em_always();
  2210. #     em_write_state();
  2211.    done();
  2212. }
  2213.  
  2214. global function em_find_file()
  2215. {
  2216.    local fn
  2217.    em_always();
  2218.    fn = prompt_history("EDITFILE", "Find file: ", getcwd(), 1, 1, "create_buf_and_win_prompt" )
  2219.  
  2220.    if ( fn )
  2221.       create_buf_and_win(fn);
  2222. }
  2223.  
  2224. global function em_goto_line()
  2225. {
  2226.    local t=0, j, response;
  2227.  
  2228.    t = emacc;
  2229.    j = em_always();
  2230.  
  2231.    if(t)
  2232.       goto_line(j);
  2233.  
  2234.    else
  2235.       goto_line_key();
  2236.  
  2237. }
  2238.  
  2239. global function em_mark_sexp()
  2240. {
  2241.    em_always();
  2242.    message("mark sexp");
  2243. }
  2244.  
  2245. global function em_mark_function()
  2246. {
  2247.    em_always();
  2248.    message("mark function");
  2249. }
  2250.  
  2251. global function em_mark_buffer()
  2252. {
  2253.    em_always();
  2254.    goto_buffer_top();
  2255.    begin_selection(NORMAL_SELECTION);
  2256.  
  2257.    goto_buffer_bottom();
  2258. }
  2259.  
  2260. global function em_indent_rigidly()
  2261. {
  2262.    local i, j, t;
  2263.  
  2264.    t = emacc;
  2265.    j = em_always();
  2266.  
  2267.    begin_selection(NORMAL_SELECTION);
  2268.  
  2269.    current_column = markx;
  2270.    current_line = marky;
  2271.    indent_columns((t) ? j : first_tab_distance());
  2272.    end_selection();
  2273. }
  2274.  
  2275. global function em_insert_file(file)
  2276. {
  2277.    em_always();
  2278.    markx = current_column;
  2279.    marky = current_line;
  2280.  
  2281.    if(!file)   
  2282.       read_file(prompt_history("EDITFILE", "Insert file: ", getcwd(), 1, 1, "insert_prompt" ));
  2283.    else
  2284.       read_file(file);       
  2285. }
  2286.  
  2287. global function em_kill_buffer()
  2288. {
  2289.    em_always();
  2290.    delete_buffer_key();
  2291. }
  2292.  
  2293. global function em_kill_window()
  2294. {
  2295.    em_always();
  2296.    delete_window();
  2297. }
  2298.  
  2299. global function em_last_kbd_macro()
  2300. {
  2301.    local i, j;
  2302.  
  2303.    j = em_always();
  2304.    for (i=0; i<j; i++)
  2305.       playback(substr(keymac,1,length(keymac)-1));
  2306. }
  2307.  
  2308. global function em_make()
  2309. {
  2310.    local status;
  2311.    local old_window = current_window, old_buffer = current_buffer;
  2312.  
  2313.    em_always();
  2314.  
  2315.    if (makebuffer)
  2316.       delete_buffer(makebuffer);
  2317.  
  2318.    if (buffers_modified && toupper(prompt("Save buffers?")) == "Y")
  2319.       write_all_buffers();
  2320.  
  2321.    errfile=create_temp_name();
  2322.    current_window = create_window(3,8,display_width-6,display_height-16)
  2323. #                                  WINDOW_MENU0);
  2324. #     window_cursor_x = 0;
  2325. #     window_cursor_y = 0;
  2326.    display_update();
  2327.    status = dos_window("make >& "errfile);
  2328.    makebuffer = current_buffer =
  2329.                 create_buffer("", errfile, BUFFER_SYSTEM + BUFFER_NO_UNDO);
  2330.    attach_window_buffer(current_window, current_buffer);
  2331.    goto_buffer_bottom();
  2332.    goto_eol();
  2333.    display_update();
  2334.    confirm( "Press <ENTER> to continue.", "" );
  2335.    goto_buffer_top();
  2336.    goto_bol();
  2337.    delete_window();
  2338.    current_buffer = old_buffer;
  2339.    if (old_window)
  2340.       current_window = old_window;
  2341.  
  2342.    display_redraw();
  2343.    unlink(errfile);
  2344.    message("make returns %d",status);
  2345. }
  2346.  
  2347. global function em_next_error()
  2348. {
  2349.    em_always();
  2350. #  goto_next_error( errorSrcName );
  2351. }
  2352.  
  2353. global function em_next_buffer()
  2354. {
  2355.    local i, count;
  2356.  
  2357.    count = em_always();
  2358.    for(i = 0; i < count; i++)
  2359.       next_buffer_mask();
  2360. }
  2361.  
  2362. global function em_prev_buffer()
  2363. {
  2364.    local i, count;
  2365.  
  2366.    count = em_always();
  2367.    for(i = 0; i < count; i++)
  2368.       prev_buffer_mask();
  2369. }
  2370.  
  2371. global function em_next_window()
  2372. {
  2373.    em_always();
  2374.    next_window();
  2375. }
  2376.  
  2377. # post: mdi_mode = FALSE
  2378.  
  2379. global function em_previous_window()
  2380. {
  2381.    em_always();
  2382.    prev_window();
  2383. }
  2384.  
  2385. global function em_push()
  2386. {
  2387.    em_always();
  2388.    system("p");
  2389. }
  2390.  
  2391. global function em_save_file()
  2392. {
  2393.    em_always();
  2394.    write_buffer_key();
  2395. #   message("File saved.");
  2396. }
  2397.  
  2398. global function em_save_all()
  2399. {
  2400.    em_always();
  2401.    gui_saveall();
  2402. }
  2403.  
  2404. global function em_set_fill_column()
  2405. {
  2406.    local t, j;
  2407.  
  2408.    t = emacc;
  2409.    j = em_always();
  2410.    wp_right_margin = (t) ? j : current_column;
  2411. }
  2412.  
  2413. global function em_show_point()
  2414. {
  2415.    em_always();
  2416.    message("%d Characters, point at %d",buffer_size, buffer_offset);
  2417. }
  2418.  
  2419. global function em_scroll_right()
  2420. {
  2421.    scroll_horizontal(-em_always());
  2422. }
  2423.  
  2424. global function em_scroll_left()
  2425. {
  2426.    scroll_horizontal(em_always());
  2427. }
  2428.  
  2429. global function em_one_window()
  2430. {
  2431.    em_always();
  2432.    if(mdi_mode)
  2433.       toggle_window_mode(0);
  2434. }
  2435.  
  2436. global function em_delete_window()
  2437. {
  2438.    em_always();
  2439.  
  2440.    if(mdi_mode && current_window)
  2441.       delete_window();
  2442. }
  2443.  
  2444. ###############################################################################
  2445. # pre:  There is at least one window open.
  2446. # post: mdi_mode = TRUE.  current_window' is split horizontally
  2447. ###############################################################################
  2448. global function em_horizontal_window()
  2449. {
  2450.    em_always();
  2451.    if(!mdi_mode)
  2452.       toggle_window_mode(1);
  2453.    split_window_horizontal();
  2454. }
  2455.  
  2456. ###############################################################################
  2457. # pre:  There is at least one window open.
  2458. # post: mdi_mode = TRUE.  current_window' is split vertically
  2459. ###############################################################################
  2460. global function em_vertical_window()
  2461. {
  2462.    em_always();
  2463.    if(!mdi_mode)
  2464.       toggle_window_mode(1);
  2465.    split_window_vertical();
  2466. }
  2467.  
  2468. global function em_start_kbd_macro()
  2469. {
  2470.    em_always();
  2471.    record(1);
  2472.    message("Recording");
  2473. }
  2474.  
  2475. global function em_start_process()
  2476. {
  2477.    em_always();
  2478.    system();
  2479. }
  2480.  
  2481. global function em_transpose_lines()
  2482. {
  2483.    em_always();
  2484.  
  2485.    up(1);
  2486.    goto_bol();
  2487.    begin_selection(NORMAL_SELECTION);
  2488.    down(1);
  2489.    delete_to_scrap();
  2490.    end_selection();
  2491.  
  2492.    down(1);
  2493.    insert_scrap();
  2494.    up(1);
  2495. }
  2496.  
  2497. global function em_replace()
  2498. {
  2499.    local fn, old_buffer = current_buffer;
  2500.  
  2501.    em_always();
  2502.  
  2503.    fn = prompt_history("EDITFILE", "File to open: ", getcwd(), 1, 1, "em_replace_prompt" )
  2504.  
  2505.    if(fn && (fn != buffer_filename) && create_buf_and_win(fn))
  2506.       delete_buffer(old_buffer);
  2507. }
  2508.  
  2509. #global function em_visit_file()
  2510. #{
  2511. #   local name;
  2512. #  local fn;
  2513. #
  2514. #   em_always();
  2515. #  fn = prompt_history("EDITFILE","Visit file :",buffer_filename)
  2516. #
  2517. #  create_buf_and_win(fn);
  2518. #
  2519. #   if (and(buffer_flags,BUFFER_MODIFIED))
  2520. #   {
  2521. #      if (toupper(prompt("Write changes to disk first?"))=="Y")
  2522. #         write_buffer();
  2523. #      else
  2524. #      {
  2525. #         name = buffer_filename;
  2526. #         buffer_flags = xor(buffer_flags,BUFFER_MODIFIED);
  2527. #         delete_buffer();
  2528. #         edit_file(name);
  2529. #      }
  2530. #   }
  2531. #}
  2532.  
  2533. global function em_write_file(file)
  2534. {
  2535.    local msg;
  2536.  
  2537.    em_always();
  2538.  
  2539.    if(!file)
  2540.       file = prompt("Write to file: ", getcwd(), "write_buffer_as_dialog");
  2541.  
  2542.    if(file)
  2543.    {
  2544.       change_output_name(file);
  2545.       if(write_buffer())
  2546.          message("File written.");
  2547.       else
  2548.       {
  2549.          msg = sprintf("Zero bytes written to '%s'", file);
  2550.          warning(msg);
  2551.       }
  2552.    }
  2553. }
  2554.  
  2555. global function em_write_region()
  2556. {
  2557.    local file;
  2558.  
  2559.    save_position();
  2560.  
  2561.    if(!selection_type())
  2562.       em_mark_buffer();
  2563.  
  2564.    file = prompt("Write region to file: ", getcwd());
  2565.  
  2566.    if(file)
  2567.       write_marked_block(file);
  2568.  
  2569.    remove_selection();
  2570.  
  2571. #     raise_anchor();
  2572.    restore_position(TRUE);
  2573. }
  2574.  
  2575. local function isblank(s)
  2576. {
  2577.    local i;
  2578.  
  2579.    if (s == "")
  2580.       return TRUE;
  2581.  
  2582.    for (i=1; i<=length(s); i++)
  2583.    {
  2584.       if (substr(s,i,1) !~ "[ \t]")
  2585.          return FALSE;
  2586.    }
  2587.  
  2588.    return TRUE;
  2589. }
  2590.  
  2591. global function indent_region()
  2592. {
  2593.    local oldcurrent, swapt = FALSE;
  2594.  
  2595.    em_always();
  2596.  
  2597.    if (current_line < marky)
  2598.    {
  2599.       em_exchange_point_and_mark();
  2600.       swapt = TRUE;
  2601.    }
  2602.    save_position();
  2603.  
  2604.    oldcurrent = current_line;
  2605.  
  2606.    for (current_line=marky; current_line<=oldcurrent; current_line++)
  2607.    {
  2608.       goto_bol();
  2609.       em_indent();
  2610.    }
  2611.    restore_position(TRUE);
  2612.  
  2613.    if (swapt)
  2614.       em_exchange_point_and_mark();
  2615. }
  2616.  
  2617. global function em_write_state()
  2618. {
  2619.    local i;
  2620.  
  2621.    em_always();
  2622.  
  2623.    em_sta_file = fopen(em_sta_name,1)
  2624.    if (!em_sta_file)
  2625.    {
  2626.       message("Cannot open state file");
  2627.       return;
  2628.    }
  2629.  
  2630.    if (search_strings[search_string_count] != "")
  2631.       fprintf(em_sta_file,"lastsearch="search_strings[search_string_count]"\n");
  2632.  
  2633.  
  2634.    if (keymac != "")
  2635.    {
  2636.       fprintf(em_sta_file,"keymac="keymac"\n");
  2637.       # !! this doesn't always work right
  2638.    }
  2639.  
  2640.    for (i in savedmacs)
  2641.    {
  2642.       fprintf(em_sta_file,"savedmacs["i"]="i"\n");
  2643.       # !! this also doesn't always work right
  2644.    }
  2645.    # !! fprintf(em_sta_file,"push_keymap ctrlx_keymap\n");
  2646.    # !! save ctrlx keymap here as a set of assign_key commands
  2647.    # !! fprintf(em_sta_file,"pop_keymap\n");
  2648.    # !! save normal keymap here as a set of assign_key commands
  2649.    fclose(em_sta_file);
  2650.    message("State file written.");
  2651. }
  2652.  
  2653. global function em_read_state()
  2654. {
  2655.    local oldbuffer = current_buffer,cf,cmd;
  2656.  
  2657.    cf = create_buffer("",em_sta_name, BUFFER_SYSTEM+BUFFER_NO_UNDO);
  2658.  
  2659.    # !! create the ctrlx keymap (should be put in when keymaps are saved)
  2660.    # !!
  2661.    # !! ctrlx_keymap=create_keymap(empty_keymap);
  2662.    # !!
  2663.  
  2664.    # !! create and activate the main keymap (should be put in when
  2665.    # !! keymaps are saved)
  2666.    # !!
  2667.    # !! push_keymap(create_keymap(empty_keymap));
  2668.  
  2669.    if (cf)
  2670.    {
  2671.       current_buffer = cf;
  2672.       goto_buffer_top();
  2673.       do
  2674.       {
  2675.          cmd = read_buffer();
  2676.          if (cmd)
  2677.             execute_function(cmd);
  2678.  
  2679.          next_line();
  2680.       } while (cmd);
  2681.       delete_buffer(cf);
  2682.       current_buffer = oldbuffer;
  2683.    }
  2684.    else
  2685.       return FALSE;
  2686.  
  2687.    return FALSE; # !! this should return true when the keymap stuff is
  2688.                  # !! built. My problem is saving all the maps including
  2689.                  # !! multiple keystroke sequences
  2690. }
  2691.  
  2692.  
  2693. local em_tab_distance;
  2694. local em_tab_string;
  2695.  
  2696. ## first_tab_distance()
  2697. #
  2698. # Determine the column where the first Tab in a row would be positioned.
  2699. #
  2700. global function first_tab_distance()
  2701. {
  2702.    if (em_tab_string != buffer_tabs)
  2703.    {
  2704.       em_tab_string = buffer_tabs;
  2705.       buffer_flags = and(buffer_flags, not(BUFFER_REAL_SPACE_ONLY))
  2706.       save_position()
  2707.       goto_bol()
  2708.       goto_next_tab();
  2709.       em_tab_distance = current_column - 1;
  2710.       restore_position(1);
  2711.       buffer_flags = or(buffer_flags, BUFFER_REAL_SPACE_ONLY)
  2712.    }
  2713.    return em_tab_distance;
  2714. }
  2715.  
  2716. global function emacs_exit()
  2717. {
  2718.    local item, name, menu, tbhand;
  2719.  
  2720.    search_flags         = old_search_flags;
  2721.  
  2722.    #  Reset the functions called by the menu items
  2723.  
  2724.    menu = menu_info(0, MI_MENUHANDLE);
  2725.  
  2726.    for(item in fid)
  2727.    {
  2728.       if ( menu )
  2729.          menu_functions[item] = fid[item];
  2730.    }
  2731.  
  2732.    #  Reset the functions called by the toolbar buttons
  2733.  
  2734.    tbhand = toolbar_info(0);
  2735.  
  2736.    for(item in tid)
  2737.    {
  2738.       if ( tbhand )
  2739.          modify_toolbaritem(tbhand, item, TI_FUNCTIONID, tid[item]);
  2740.    }
  2741.  
  2742.    delete_event(EVENT.EMULATION_CHANGED, function_id("emacs_exit"));
  2743.    delete_event(EVENT.MOUSE_LEFT_DOWN, function_id("em_mouse_set_mark"));
  2744. }
  2745.