home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume4 / vms-vi-2 / part08 < prev    next >
Internet Message Format  |  1989-02-03  |  46KB

  1. Path: xanth!mcnc!gatech!bloom-beacon!bu-cs!mirror!necntc!ncoast!allbery
  2. From: gregg@a.cs.okstate.edu (Gregg Wonderly)
  3. Newsgroups: comp.sources.misc
  4. Subject: v04i099: TPUVI for VMS part 8 of 17
  5. Message-ID: <8809212101.AA08060@uunet.UU.NET>
  6. Date: 27 Sep 88 01:52:38 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: gregg@a.cs.okstate.edu (Gregg Wonderly)
  9. Lines: 1503
  10. Approved: allbery@ncoast.UUCP
  11.  
  12. Posting-number: Volume 4, Issue 99
  13. Submitted-by: "Gregg Wonderly" <gregg@a.cs.okstate.edu>
  14. Archive-name: vms-vi-2/Part08
  15.  
  16. $ WRITE SYS$OUTPUT "Creating ""VI.4"""
  17. $ CREATE VI.4
  18. $ DECK/DOLLARS=$$EOD$$
  19. !
  20. !
  21. !                   The VI EDITOR written in VAXTPU
  22. !
  23. !   Written by Gregg Wonderly
  24. !   Mathematics Department
  25. !   Oklahoma State University
  26. !   Stillwater Oklahoma, 74078
  27. !
  28. !   internet: gregg@nemo.math.okstate.edu
  29. !   uucp: okstate!nemo.math.okstate.edu!gregg
  30. !
  31. !   Version number 2, edit 631, 28-AUG-1988 19:09:47.00
  32. !
  33. !   This program is the property of the author, and you should refrain
  34. !   from trying to make a profit from it (that's not nice).
  35. !
  36. !   You can pass it around freely, as you should have gotten it for free.
  37. !   All I ask is that you give credit where credit is due.
  38. !
  39. !
  40. !
  41. !   Initialize TPU for VI emulation.
  42. !
  43. PROCEDURE vi$init_vars
  44.     LOCAL
  45.         i;
  46.  
  47.     vi$find_rng := 0;
  48.     vi$_version := "VAX/TPU -- VI Version 2, Edit 631";
  49.     message_buffer := 0;
  50.     message_window := 0;
  51.     vi$did_mess := 0;
  52.     vi$readonly := 0;
  53.  
  54.     command_buffer := 0;
  55.     command_window := 0;
  56.  
  57.     show_buffer := 0;
  58.     info_window := 0;
  59.  
  60.     choice_buffer := 0;
  61.     choice_window := 0;
  62.  
  63.     vi$last_mapped := 0;
  64.     vi$delete_empty := 0;
  65.  
  66.     vi$last_insert := 0;
  67.  
  68.     vi$bracket_chars := "{}()[]";       ! The recognized brackets.
  69.  
  70.     ! interline movement that is backwards, or different than the others
  71.  
  72.     vi$paren_cnt := 0;
  73.     vi$abbr_ := "";
  74.     vi$back_moves := "bB0FT^(";
  75.     vi$weird_moves := "ft$DeE%?";
  76.     vi$weird2_moves := "h";
  77.     vi$dot_keys := "iIdpPDxXaAcCoOrRSs<>~&";
  78.  
  79.     vi$_lower_chars := "abcdefghijklmnopqrstuvwxyz";
  80.     vi$_upper_chars := "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  81.     vi$_letter_chars := vi$_lower_chars + vi$_upper_chars;
  82.     vi$_numeric_chars := "0123456789";
  83.     vi$_alpha_chars := vi$_letter_chars + "_" + vi$_numeric_chars;
  84.     vi$_sym_chars := vi$_alpha_chars + "$";
  85.     vi$_ctl_chars := "";
  86.     i := 0;
  87.     LOOP
  88.         EXITIF (i = 32);
  89.         vi$_ctl_chars := vi$_ctl_chars + ASCII (i);
  90.         i := i + 1;
  91.     ENDLOOP;
  92.  
  93.     vi$_space_chars := " " + ASCII(9) + vi$_ctl_chars;
  94.     vi$_space_tab := " " + ASCII(9);
  95.     vi$_punct_chars := "!@`~#$%^&*()-=+{}[];:'""\|,.?/><";
  96.     vi$_ex_separs := ", " + ASCII(9);
  97.     vi$_ascii_chars := "";
  98.     vi$_ws := ",./?;:'""\|[]{}-=+)(*&^%$#@!~`" + vi$_space_chars;
  99.     vi$no_space := " " + ASCII(9) + ASCII (10) + ASCII(11) + ASCII(13);
  100.     i := 0;
  101.     LOOP
  102.         EXITIF (i = 256);
  103.         vi$_ascii_chars := vi$_ascii_chars + ASCII (i);
  104.         i := i + 1;
  105.     ENDLOOP;
  106.  
  107.     vi$pch := ASCII(9);
  108.     i := 32;
  109.     LOOP
  110.         EXITIF (i = 256);
  111.         vi$pch := vi$pch + ASCII (i);
  112.         i := i + 1;
  113.     ENDLOOP;
  114.  
  115.     vi$m_level := 0;
  116.     vi$in_learn := 0;
  117.     vi$playing_back := 0;
  118.  
  119.     vi$dcl_buf := 0;
  120.     vi$dcl_process := 0;
  121.     vi$send_dcl := 1;
  122.  
  123.     vi$tag_buf := 0;
  124.     vi$tag_files := "tags";
  125.     vi$tag_case := EXACT;
  126.     vi$in_ws := 0;
  127.     vi$in_global := 0;
  128.     vi$in_occlusion := 0;
  129.     vi$old_occ_win := 0;
  130.     vi$occluding_win := 0;
  131.     vi$error_bells := 1;
  132.     vi$show_mode := 0;
  133.     vi$auto_indent := 0;
  134.  
  135.     vi$tmp_key_buf := 0;
  136.  
  137.     vi$last_mess := "";
  138.  
  139.     vi$max_offset := 0;
  140.     vi$new_offset := 1;
  141.  
  142.     vi$append_it := 0;
  143.     vi$old_place := 0;
  144.     vi$select_pos := 0;
  145.  
  146.     vi$term_vt200 := 0;
  147.     vi$scr_width := 0;
  148.     vi$scr_length := 0;
  149.  
  150.     vi$para_str := "P ";
  151.     vi$para_pat := LINE_BEGIN & ((".P")|LINE_END);
  152.     vi$sect_str := "CHHLPG+c";
  153.     vi$sect_pat := LINE_BEGIN & ((".CH"| ".HL"| ".PG"| "{")|LINE_END);
  154.     vi$last_cmd := 0;
  155.     vi$last_filter := 0;
  156.  
  157.     vi$replace_separ := 0;
  158.     vi$replace_source := 0;
  159.     vi$replace_dest := 0;
  160.  
  161.     VI$DELETE_TYPE  := 1;
  162.     VI$CHANGE_TYPE  := 2;
  163.     VI$OTHER_TYPE   := 3;
  164.     VI$YANK_TYPE    := 4;
  165.     VI$FILTER_TYPE  := 5;
  166.     VI$SHIFT_TYPE   := 6;
  167.     vi$command_type := VI$OTHER_TYPE;
  168.  
  169.     vi$cu_cwd           := 1;
  170.     vi$cu_trnlnm_job    := 2;
  171.     vi$cu_trnlnm_proc   := 3;
  172.     vi$cu_trnlnm_sys    := 4;
  173.     vi$cu_trnlnm_group  := 5;
  174.     vi$cu_getmsg        := 6;
  175.     vi$cu_set_sysdisk   := 7;
  176.     vi$cu_sleep         := 8;
  177.     vi$cu_pasthru_on    := 9;
  178.     vi$cu_pasthru_off   := 10;
  179.     vi$cu_spawn         := 11;
  180.  
  181.     vi$filter_proc := 0;
  182.     vi$filter_buf := 0;
  183.  
  184.     vi$push_key_buf := 0;
  185.  
  186.     o1 := 0; o2 := 0; o3 := 0; o4 := 0; o5 := 0;
  187.     o6 := 0; o7 := 0; o8 := 0; o9 := 0;
  188.  
  189.     p1 := 0; p2 := 0; p3 := 0; p4 := 0; p5 := 0;
  190.     p6 := 0; p7 := 0; p8 := 0; p9 := 0;
  191.  
  192.     vi$ex_mode_buffer := 0;
  193.     vi$global_var := 0;
  194.     vi$macro_active := "$$active_macro$$";
  195.     vi$_find_pat := 0;
  196.     vi$wrap_scan := 1;
  197.  
  198.     vi$last_key := 0;
  199.     vi$last_keys := 0;
  200.     vi$cur_keys := 0;
  201.     vi$key_buf := 0;
  202.     vi$min_update := 1;
  203.     vi$tab_amount := 8;
  204.     vi$shift_width := 8;
  205.     vi$spaces := "                                                    ";
  206.     vi$use_tabs := 1;
  207.     vi$in_show_match := 0;
  208.     vi$report := 5;
  209.     vi$auto_write := 0;
  210.     vi$ignore_case := EXACT;
  211.     vi$wrap_margin := 0;
  212.     vi$magic := 1;
  213.     vi$undo_map := 1;
  214.  
  215.     vi$undo_line_str := 0;
  216.     vi$undo_line_mark := 0;
  217.     vi$undo_line := 0;
  218.     vi$undo_offset := 0;
  219.  
  220.     vi$how_much_scroll := 12;
  221.  
  222.     vi$search_string := 0;
  223.     vi$last_search_dir := 1;
  224.  
  225.     vi$undo_start := 0;
  226.     vi$undo_end := 0;
  227.     vi$undo_buffer := 0;
  228.     vi$undo_valid := 0;
  229.  
  230.     VI$HERE := 0;
  231.     VI$AFTER := 1;
  232.  
  233.     VI$LINE_MODE := 1;
  234.     VI$IN_LINE_MODE := 2;
  235.  
  236.     vi$cur_level := 0;
  237.  
  238.     vi$global_mark := 0;
  239.     vi$yank_mode := 0;
  240.     vi$temp_buf := 0;
  241.     vi$cur_text := "";      ! Where text to PUT comes from.
  242.  
  243.     ! The ten deletion buffers.
  244.  
  245.     vi$del_buf_1 := 0; vi$del_buf_2 := 0; vi$del_buf_3 := 0;
  246.     vi$del_buf_4 := 0; vi$del_buf_5 := 0; vi$del_buf_6 := 0;
  247.     vi$del_buf_7 := 0; vi$del_buf_8 := 0; vi$del_buf_9 := 0;
  248.  
  249.     ! Named buffers accessible from the keyboard characters.
  250.  
  251.     vi$ins_buf_a := 0; vi$ins_buf_b := 0; vi$ins_buf_c := 0;
  252.     vi$ins_buf_d := 0; vi$ins_buf_e := 0; vi$ins_buf_f := 0;
  253.     vi$ins_buf_g := 0; vi$ins_buf_h := 0; vi$ins_buf_i := 0;
  254.     vi$ins_buf_j := 0; vi$ins_buf_k := 0; vi$ins_buf_l := 0;
  255.     vi$ins_buf_m := 0; vi$ins_buf_n := 0; vi$ins_buf_o := 0;
  256.     vi$ins_buf_p := 0; vi$ins_buf_q := 0; vi$ins_buf_r := 0;
  257.     vi$ins_buf_s := 0; vi$ins_buf_t := 0; vi$ins_buf_u := 0;
  258.     vi$ins_buf_v := 0; vi$ins_buf_w := 0; vi$ins_buf_x := 0;
  259.     vi$ins_buf_y := 0; vi$ins_buf_z := 0;
  260.  
  261.     ! The 26 marks available
  262.  
  263.     vi$mark_a := 0; vi$mark_b := 0; vi$mark_c := 0; vi$mark_d := 0;
  264.     vi$mark_e := 0; vi$mark_f := 0; vi$mark_g := 0; vi$mark_h := 0;
  265.     vi$mark_i := 0; vi$mark_j := 0; vi$mark_k := 0; vi$mark_l := 0;
  266.     vi$mark_m := 0; vi$mark_n := 0; vi$mark_o := 0; vi$mark_p := 0;
  267.     vi$mark_q := 0; vi$mark_r := 0; vi$mark_s := 0; vi$mark_t := 0;
  268.     vi$mark_u := 0; vi$mark_v := 0; vi$mark_w := 0; vi$mark_x := 0;
  269.     vi$mark_y := 0; vi$mark_z := 0;
  270.  
  271.     vi$endpos := 0;
  272.     vi$new_endpos := 0;
  273.     vi$start_pos := 0;
  274.  
  275.     VI$ALPHA_TYPE := 1;
  276.     VI$PUNCT_TYPE := 2;
  277.     VI$SPACE_TYPE := 3;
  278.     VI$EOL_TYPE := 4;
  279.  
  280.     vi$temp_buf_num := 1;
  281.     vi$last_s_func := 0;
  282.     vi$last_s_char := 0;
  283.  
  284.     vi$active_count := 0;
  285.     vi$cmd_keys := "c_keys";
  286.     vi$move_keys := "m_keys";
  287.     vi$edit_keys := "e_keys";
  288.  
  289. ENDPROCEDURE;
  290.  
  291. !
  292. !   Map all of the key bindings into the proper key maps.
  293. !
  294. !       The "c_keys" map is used for command mode key processing.
  295. !       The "e_keys" map is used during line editing.
  296. !       The "m_keys" map is used to determine movement associated with
  297. !                    a particular key.
  298. !
  299. PROCEDURE vi$init_keys
  300.  
  301.     ! Define all of the command mode keys.
  302.  
  303.     vi$cmd_keys := CREATE_KEY_MAP ("c_keys");
  304.  
  305.     DEFINE_KEY ("vi$make_full_screen", KP0, "", vi$cmd_keys);
  306.     DEFINE_KEY ("vi$delete_window", KP1, "", vi$cmd_keys);
  307.     DEFINE_KEY ("vi$split_here", KP2, "", vi$cmd_keys);
  308.     DEFINE_KEY ("vi$next_window", KP3, "", vi$cmd_keys);
  309.     DEFINE_KEY ("vi$shrink_window(vi$cur_active_count)", KP4,
  310.             "", vi$cmd_keys);
  311.     DEFINE_KEY ("vi$enlarge_window(vi$cur_active_count)", KP5,
  312.             "", vi$cmd_keys);
  313.     DEFINE_KEY ("vi$previous_window", KP6, "", vi$cmd_keys);
  314.  
  315.     DEFINE_KEY ("vi$prev_screen", CTRL_B_KEY, "vi$prev_screen", vi$cmd_keys);
  316.     DEFINE_KEY ("vi$screen_forward", CTRL_D_KEY,
  317.         "vi$screen_forward", vi$cmd_keys);
  318.     DEFINE_KEY ("vi$pull_push_line (1)", CTRL_E_KEY,
  319.         "vi$pull_push_line (1)", vi$cmd_keys);
  320.     DEFINE_KEY ("vi$next_screen", CTRL_F_KEY, "vi$next_screen", vi$cmd_keys);
  321.     DEFINE_KEY ("vi$what_line", CTRL_G_KEY, "vi$what_line", vi$cmd_keys);
  322.     DEFINE_KEY ("vi$move_left", CTRL_H_KEY, "vi$move_left", vi$cmd_keys);
  323.     DEFINE_KEY ("vi$move_down", CTRL_J_KEY, "vi$move_down", vi$cmd_keys);
  324.     DEFINE_KEY ("refresh", CTRL_L_KEY, "refresh", vi$cmd_keys);
  325.     DEFINE_KEY ("vi$move_down", CTRL_N_KEY, "vi$move_down", vi$cmd_keys);
  326.     DEFINE_KEY ("vi$move_up", CTRL_P_KEY, "vi$move_up", vi$cmd_keys);
  327.     DEFINE_KEY ("vi$remember", CTRL_R_KEY, "vi$remember", vi$cmd_keys);
  328.     DEFINE_KEY ("vi$screen_backward", CTRL_U_KEY,
  329.         "vi$screen_backward", vi$cmd_keys);
  330.     DEFINE_KEY ("vi$send_to_dcl (CURRENT_LINE)", CTRL_X_KEY,
  331.         "vi$send_to_dcl (CURRENT_LINE)", vi$cmd_keys);
  332.     DEFINE_KEY ("vi$pull_push_line (-1)", CTRL_Y_KEY,
  333.         "vi$pull_push_line (-1)", vi$cmd_keys);
  334.     DEFINE_KEY ("vi$to_tag(0, 0)", KEY_NAME(ASCII(29)),
  335.         "vi$to_tag(0, 0)", vi$cmd_keys);
  336.     DEFINE_KEY ("vi$move_prev_buf (0)", KEY_NAME(ASCII(30)),
  337.         "vi$move_prev_buf (0)", vi$cmd_keys);
  338.     DEFINE_KEY ("vi$do_help('')", PF2, "vi$do_help('')", vi$cmd_keys);
  339.     DEFINE_KEY ("vi$on_escape", PF1, "vi$on_escape", vi$cmd_keys);
  340.     DEFINE_KEY ("vi$on_escape", F11, "vi$on_escape", vi$cmd_keys);
  341.     DEFINE_KEY ("vi$_go_to_marker", KEY_NAME ("'"),
  342.         "vi$_go_to_marker", vi$cmd_keys);
  343.     DEFINE_KEY ("vi$_go_to_marker", KEY_NAME ("`"),
  344.         "vi$_go_to_marker", vi$cmd_keys);
  345.     DEFINE_KEY ("vi$select_buffer", KEY_NAME ('"'),
  346.         "vi$select_buffer", vi$cmd_keys);
  347.     DEFINE_KEY ("vi$_match_brackets", KEY_NAME ('%'),
  348.         "vi$_match_brackets", vi$cmd_keys);
  349.     DEFINE_KEY ("vi$_change_case", KEY_NAME ('~'),
  350.         "vi$_change_case", vi$cmd_keys);
  351.     DEFINE_KEY ("vi$region_left", KEY_NAME ('<'),
  352.         "vi$region_left", vi$cmd_keys);
  353.     DEFINE_KEY ("vi$region_right", KEY_NAME ('>'),
  354.         "vi$region_right", vi$cmd_keys);
  355.     DEFINE_KEY ("vi$_next_line", KEY_NAME ('+'), "vi$_next_line", vi$cmd_keys);
  356.     DEFINE_KEY ("vi$do_macro('k^', 0)", KEY_NAME ('-'),
  357.         "vi$do_macro('k^', 0)", vi$cmd_keys);
  358.     DEFINE_KEY ("vi$_paragraph (-1)", KEY_NAME ('{'),
  359.         "vi$_paragraph (-1)", vi$cmd_keys);
  360.     DEFINE_KEY ("vi$_section (-1)", KEY_NAME ('['),
  361.         "vi$_section (-1)", vi$cmd_keys);
  362.     DEFINE_KEY ("vi$_begin_sentence", KEY_NAME ('('),
  363.         "vi$_begin_sentence", vi$cmd_keys);
  364.     DEFINE_KEY ("vi$_paragraph (1)", KEY_NAME ('}'),
  365.         "vi$_paragraph (1)", vi$cmd_keys);
  366.     DEFINE_KEY ("vi$_section (1)", KEY_NAME (']'),
  367.         "vi$_section (1)", vi$cmd_keys);
  368.     DEFINE_KEY ("vi$_end_sentence", KEY_NAME (')'),
  369.         "vi$_end_sentence", vi$cmd_keys);
  370.     DEFINE_KEY ("vi$insert_after", KEY_NAME ('a'),
  371.         "vi$insert_after", vi$cmd_keys);
  372.     DEFINE_KEY ("vi$do_macro('$a', 0)", KEY_NAME ('A'),
  373.         "vi$do_macro('$a', 0)", vi$cmd_keys);
  374.     DEFINE_KEY ("vi$_word_back", KEY_NAME ('b'),
  375.         "vi$_word_back", vi$cmd_keys);
  376.     DEFINE_KEY ("vi$_full_word_back", KEY_NAME ('B'),
  377.         "vi$_full_word_back", vi$cmd_keys);
  378.     DEFINE_KEY ("vi$_change", KEY_NAME ('c'),
  379.         "vi$_change", vi$cmd_keys);
  380.     DEFINE_KEY ("vi$do_macro ('c$', 0)", KEY_NAME ('C'),
  381.         "vi$do_macro ('c$', 0)", vi$cmd_keys);
  382.     DEFINE_KEY ("vi$_delete (0, -1)", KEY_NAME ('d'),
  383.         "delete", vi$cmd_keys);
  384.     DEFINE_KEY ("vi$_delete (KEY_NAME('$'), -1)", KEY_NAME ('D'),
  385.         "delete_eol", vi$cmd_keys);
  386.     DEFINE_KEY ("vi$_word_end", KEY_NAME ('e'),
  387.         "vi$_word_end", vi$cmd_keys);
  388.     DEFINE_KEY ("vi$_full_word_end", KEY_NAME ('E'),
  389.         "vi$_full_word_end", vi$cmd_keys);
  390.     DEFINE_KEY ("vi$_find_char (0)", KEY_NAME ('f'),
  391.         "vi$_find_char (0)", vi$cmd_keys);
  392.     DEFINE_KEY ("vi$_back_find_char (0)", KEY_NAME ('F'),
  393.         "vi$_back_find_char (0)", vi$cmd_keys);
  394.     DEFINE_KEY ("vi$go_to_line", KEY_NAME ('G'),
  395.         "vi$go_to_line", vi$cmd_keys);
  396.     DEFINE_KEY ("vi$move_left", KEY_NAME ('h'),
  397.         "vi$move_left", vi$cmd_keys);
  398.     DEFINE_KEY ("vi$home", KEY_NAME ('H'), "vi$home", vi$cmd_keys);
  399.     DEFINE_KEY ("vi$insert_here", KEY_NAME ('i'),
  400.         "vi$insert_here", vi$cmd_keys);
  401.     DEFINE_KEY ("vi$insert_at_begin", KEY_NAME ('I'),
  402.         "vi$insert_at_begin", vi$cmd_keys);
  403.     DEFINE_KEY ("vi$move_down", KEY_NAME ('j'),
  404.         "vi$move_down", vi$cmd_keys);
  405.     DEFINE_KEY ("vi$_join_lines", KEY_NAME ('J'),
  406.         "vi$_join_lines", vi$cmd_keys);
  407.     DEFINE_KEY ("vi$move_up", KEY_NAME ('k'), "vi$move_up", vi$cmd_keys);
  408.     DEFINE_KEY ("vi$move_right", KEY_NAME ('l'), "vi$move_right", vi$cmd_keys);
  409.     DEFINE_KEY ("vi$last", KEY_NAME ('L'), "vi$last", vi$cmd_keys);
  410.     DEFINE_KEY ("vi$_set_mark", KEY_NAME ('m'), "vi$_set_mark", vi$cmd_keys);
  411.     DEFINE_KEY ("vi$middle", KEY_NAME ('M'), "vi$middle", vi$cmd_keys);
  412.     DEFINE_KEY ("vi$_search_next(vi$last_search_dir)", KEY_NAME('n'),
  413.         "vi$_search_next(vi$last_search_dir)", vi$cmd_keys);
  414.     DEFINE_KEY ("vi$_search_next(-vi$last_search_dir)", KEY_NAME('N'),
  415.         "vi$_search_next(-vi$last_search_dir)", vi$cmd_keys);
  416.     DEFINE_KEY ("vi$open_below", KEY_NAME ('o'), "vi$open_below", vi$cmd_keys);
  417.     DEFINE_KEY ("vi$open_here", KEY_NAME ('O'), "vi$open_here", vi$cmd_keys);
  418.     DEFINE_KEY ("vi$put_here (VI$HERE, -1)", KEY_NAME ('P'),
  419.         "vi$put_here (VI$HERE, -1)", vi$cmd_keys);
  420.     DEFINE_KEY ("vi$put_after (-1)", KEY_NAME ('p'),
  421.         "vi$put_after (-1)", vi$cmd_keys);
  422.     DEFINE_KEY ("vi$_replace_char", KEY_NAME ('r'),
  423.         "vi$_replace_char", vi$cmd_keys);
  424.     DEFINE_KEY ("vi$_replace_str", KEY_NAME ('R'),
  425.         "vi$_replace_str", vi$cmd_keys);
  426.     DEFINE_KEY ("vi$do_macro('cl', 0)", KEY_NAME ('s'),
  427.         "vi$do_macro('cl', 0)", vi$cmd_keys);
  428.     DEFINE_KEY ("vi$_big_s", KEY_NAME ('S'), "vi$_big_s", vi$cmd_keys);
  429.     DEFINE_KEY ("vi$_to_char (0)", KEY_NAME ('t'),
  430.         "vi$_to_char (0)", vi$cmd_keys);
  431.     DEFINE_KEY ("vi$_back_to_char (0)", KEY_NAME ('T'),
  432.         "vi$_back_to_char (0)", vi$cmd_keys);
  433.     DEFINE_KEY ("vi$perform_undo", KEY_NAME ('u'),
  434.         "vi$perform_undo", vi$cmd_keys);
  435.     DEFINE_KEY ("vi$undo_one_line", KEY_NAME ('U'),
  436.         "vi$undo_one_line", vi$cmd_keys);
  437.     DEFINE_KEY ("vi$_word_forward", KEY_NAME ('w'),
  438.         "vi$_word_forward", vi$cmd_keys);
  439.     DEFINE_KEY ("vi$_full_word_forward", KEY_NAME ('W'),
  440.         "vi$_full_word_forward", vi$cmd_keys);
  441.     DEFINE_KEY ("vi$do_macro ('dl', 0)", KEY_NAME ('x'),
  442.         "vi$do_macro ('dl', 0)", vi$cmd_keys);
  443.     DEFINE_KEY ("vi$do_macro ('dh', 0)", KEY_NAME ('X'),
  444.         "vi$do_macro ('dh', 0)", vi$cmd_keys);
  445.     DEFINE_KEY ("vi$_yank (0, -1)", KEY_NAME ('y'),
  446.         "vi$_yank (0, -1)", vi$cmd_keys);
  447.     DEFINE_KEY ("vi$_yank (KEY_NAME('y'), -1)", KEY_NAME ('Y'),
  448.         "vi$_yank (KEY_NAME('y'), -1)", vi$cmd_keys);
  449.     DEFINE_KEY ("vi$_ZZ (0)", KEY_NAME ('Z'), "vi$_ZZ", vi$cmd_keys);
  450.     DEFINE_KEY ("vi$_z_move", KEY_NAME ('z'), "vi$_z_move", vi$cmd_keys);
  451.     DEFINE_KEY ("vi$_to_column", KEY_NAME ('|'),
  452.         "vi$_to_column", vi$cmd_keys);
  453.     DEFINE_KEY ("vi$_next_line", RET_KEY, "vi$_next_line", vi$cmd_keys);
  454.     DEFINE_KEY ("vi$repeat_count", KEY_NAME ('0'),
  455.         "vi$repeat_count", vi$cmd_keys);
  456.     DEFINE_KEY ("vi$repeat_count", KEY_NAME ('1'),
  457.         "vi$repeat_count", vi$cmd_keys);
  458.     DEFINE_KEY ("vi$repeat_count", KEY_NAME ('2'),
  459.         "vi$repeat_count", vi$cmd_keys);
  460.     DEFINE_KEY ("vi$repeat_count", KEY_NAME ('3'),
  461.         "vi$repeat_count", vi$cmd_keys);
  462.     DEFINE_KEY ("vi$repeat_count", KEY_NAME ('4'),
  463.         "vi$repeat_count", vi$cmd_keys);
  464.     DEFINE_KEY ("vi$repeat_count", KEY_NAME ('5'),
  465.         "vi$repeat_count", vi$cmd_keys);
  466.     DEFINE_KEY ("vi$repeat_count", KEY_NAME ('6'),
  467.         "vi$repeat_count", vi$cmd_keys);
  468.     DEFINE_KEY ("vi$repeat_count", KEY_NAME ('7'),
  469.         "vi$repeat_count", vi$cmd_keys);
  470.     DEFINE_KEY ("vi$repeat_count", KEY_NAME ('8'),
  471.         "vi$repeat_count", vi$cmd_keys);
  472.     DEFINE_KEY ("vi$repeat_count", KEY_NAME ('9'),
  473.         "vi$repeat_count", vi$cmd_keys);
  474.     DEFINE_KEY ("vi$move_left", F12, "vi$move_left", vi$cmd_keys);
  475.     DEFINE_KEY ("vi$move_left", LEFT, "vi$move_left", vi$cmd_keys);
  476.     DEFINE_KEY ("vi$move_right", RIGHT, "vi$move_right", vi$cmd_keys);
  477.     DEFINE_KEY ("vi$move_up", UP, "vi$move_up", vi$cmd_keys);
  478.     DEFINE_KEY ("vi$move_down", DOWN, "vi$move_down", vi$cmd_keys);
  479.     DEFINE_KEY ("vi$move_left", DEL_KEY, "vi$move_left", vi$cmd_keys);
  480.     DEFINE_KEY ("vi$move_right", KEY_NAME (' '), "vi$move_right", vi$cmd_keys);
  481.     DEFINE_KEY ("vi$ex_mode", DO, "vi$ex_mode", vi$cmd_keys);
  482.     DEFINE_KEY ("vi$ex_mode", KEY_NAME(':'), "vi$ex_mode", vi$cmd_keys);
  483.     DEFINE_KEY ("vi$_repeat_torf_back", KEY_NAME(','),
  484.         "vi$_repeat_torf_back", vi$cmd_keys);
  485.     DEFINE_KEY ("vi$_repeat_torf", KEY_NAME(';'),
  486.         "vi$_repeat_torf", vi$cmd_keys);
  487.     DEFINE_KEY ("vi$_search(1)", KEY_NAME('/'),
  488.         "vi$_search(1)", vi$cmd_keys);
  489.     DEFINE_KEY ("vi$_search(-1)", KEY_NAME('?'),
  490.         "vi$_search(-1)", vi$cmd_keys);
  491.     DEFINE_KEY ("vi$_eol", KEY_NAME('$'), "vi$_eol", vi$cmd_keys);
  492.     DEFINE_KEY ("vi$_bol (1)", KEY_NAME('^'), "vi$_bol (1)", vi$cmd_keys);
  493.     DEFINE_KEY ("vi$do_macro(vi$last_keys, 0)", KEY_NAME('.'),
  494.         "vi$do_macro(vi$last_keys, 0)", vi$cmd_keys);
  495.     DEFINE_KEY ("vi$macro", KEY_NAME('@'), "vi$macro", vi$cmd_keys);
  496.     DEFINE_KEY ("vi$repeat_subs", KEY_NAME('&'), "vi$repeat_subs", vi$cmd_keys);
  497.     DEFINE_KEY ("vi$region_filter", KEY_NAME('!'),
  498.         "vi$region_filter", vi$cmd_keys);
  499.  
  500.     ! Define all of the insert-mode keys
  501.  
  502.     vi$edit_keys := CREATE_KEY_MAP ("e_keys");
  503.  
  504.     ! These maps are not really active, but the comment fields are used
  505.     ! during the execution of "vi$line_edit".
  506.  
  507.     DEFINE_KEY ("vi$_dummy", F12, "bs", vi$edit_keys);
  508.     DEFINE_KEY ("vi$_dummy", PF1, "escape", vi$edit_keys);
  509.     DEFINE_KEY ("vi$_dummy", F11, "escape", vi$edit_keys);
  510.     DEFINE_KEY ("vi$_dummy", KEY_NAME (ASCII(27)), "escape", vi$edit_keys);
  511.     DEFINE_KEY ("vi$_dummy", KEY_NAME (ASCII(0)), "reinsert", vi$edit_keys);
  512.     DEFINE_KEY ("vi$_dummy", RET_KEY, "eol", vi$edit_keys);
  513.     DEFINE_KEY ("vi$_dummy", TAB_KEY, "tab", vi$edit_keys);
  514.     DEFINE_KEY ("vi$_dummy", CTRL_D_KEY, "detab", vi$edit_keys);
  515.     DEFINE_KEY ("vi$_dummy", CTRL_H_KEY, "bs", vi$edit_keys);
  516.     DEFINE_KEY ("vi$_dummy", CTRL_T_KEY, "entab", vi$edit_keys);
  517.     DEFINE_KEY ("vi$_dummy", CTRL_V_KEY, "vquote", vi$edit_keys);
  518.     DEFINE_KEY ("vi$_dummy", CTRL_W_KEY, "bword", vi$edit_keys);
  519.     DEFINE_KEY ("vi$_dummy", DEL_KEY, "bs", vi$edit_keys);
  520.  
  521.     ! Define all of the delete mode mappings
  522.  
  523.     vi$move_keys := CREATE_KEY_MAP ("m_keys");
  524.  
  525.     DEFINE_KEY ("vi$downline(1)", RET_KEY, "vi$downline(1)", vi$move_keys);
  526.     DEFINE_KEY ("vi$right", KEY_NAME (" "), "vi$right", vi$move_keys);
  527.     DEFINE_KEY ("vi$eol", KEY_NAME("$"), "vi$eol", vi$move_keys);
  528.     DEFINE_KEY ("vi$to_marker", KEY_NAME ("'"), "vi$to_marker", vi$move_keys);
  529.     DEFINE_KEY ("vi$to_marker", KEY_NAME ("`"), "vi$to_marker", vi$move_keys);
  530.     DEFINE_KEY ("vi$first_no_space (1)", KEY_NAME("^"),
  531.         "vi$first_no_space (1)", vi$move_keys);
  532.     DEFINE_KEY ("vi$fol", KEY_NAME("0"), "vi$fol", vi$move_keys);
  533.     DEFINE_KEY ("vi$upline", KEY_NAME ("-"), "vi$upline", vi$move_keys);
  534.     DEFINE_KEY ("vi$downline(1)", KEY_NAME ("+"),
  535.         "vi$downline(1)", vi$move_keys);
  536.     DEFINE_KEY ("vi$search(1)", KEY_NAME ("/"), "vi$search(1)", vi$move_keys);
  537.     DEFINE_KEY ("vi$search(-1)", KEY_NAME ("?"), "vi$search(-1)", vi$move_keys);
  538.     DEFINE_KEY ("vi$match_brackets", KEY_NAME ("%"),
  539.         "vi$match_brackets", vi$move_keys);
  540.     DEFINE_KEY ("vi$full_word_move(-1)", KEY_NAME ("B"),
  541.         "vi$full_word_move(-1)", vi$move_keys);
  542.     DEFINE_KEY ("vi$word_move(-1)", KEY_NAME ("b"),
  543.         "vi$word_move(-1)", vi$move_keys);
  544.     DEFINE_KEY ("vi$_dummy", KEY_NAME ("c"),
  545.         "vi$_dummy", vi$move_keys);
  546.     DEFINE_KEY ("vi$word_end", KEY_NAME ("e"), "vi$word_end", vi$move_keys);
  547.     DEFINE_KEY ("vi$full_word_end", KEY_NAME ("E"),
  548.         "vi$full_word_end", vi$move_keys);
  549.     DEFINE_KEY ("vi$back_find_char(0)", KEY_NAME ("F"),
  550.         "vi$back_find_char(0)", vi$move_keys);
  551.     DEFINE_KEY ("vi$find_char(0)", KEY_NAME ("f"),
  552.         "vi$find_char(0)", vi$move_keys);
  553.     DEFINE_KEY ("vi$to_line (vi$active_count)", KEY_NAME ("G"),
  554.             "vi$to_line (vi$active_count)", vi$move_keys);
  555.     DEFINE_KEY ("vi$to_home", KEY_NAME ("H"), "vi$to_home", vi$move_keys);
  556.     DEFINE_KEY ("vi$left", KEY_NAME ("h"), "vi$left", vi$move_keys);
  557.     DEFINE_KEY ("vi$downline(1)", KEY_NAME ("j"),
  558.         "vi$downline(1)", vi$move_keys);
  559.     DEFINE_KEY ("vi$upline", KEY_NAME ("k"), "vi$upline", vi$move_keys);
  560.     DEFINE_KEY ("vi$right", KEY_NAME ("l"), "vi$right", vi$move_keys);
  561.     DEFINE_KEY ("vi$to_middle", KEY_NAME ("M"), "vi$to_middle", vi$move_keys);
  562.     DEFINE_KEY ("vi$to_last", KEY_NAME ("L"), "vi$to_last", vi$move_keys);
  563.     DEFINE_KEY ("vi$search_next(vi$last_search_dir)", KEY_NAME('n'),
  564.             "vi$search_next(vi$last_search_dir)", vi$move_keys);
  565.     DEFINE_KEY ("vi$search_next(-vi$last_search_dir)", KEY_NAME('N'),
  566.             "vi$search_next(-vi$last_search_dir)", vi$move_keys);
  567.     DEFINE_KEY ("vi$to_char(0)", KEY_NAME ("t"), "vi$to_char(0)", vi$move_keys);
  568.     DEFINE_KEY ("vi$back_to_char(0)", KEY_NAME ("T"),
  569.         "vi$back_to_char(0)", vi$move_keys);
  570.     DEFINE_KEY ("vi$word_move(1)", KEY_NAME ("w"),
  571.         "vi$word_move(1)", vi$move_keys);
  572.     DEFINE_KEY ("vi$full_word_move(1)", KEY_NAME ("W"),
  573.         "vi$full_word_move(1)", vi$move_keys);
  574.     DEFINE_KEY ("vi$downline", KEY_NAME(">"), "vi$downline(0)", vi$move_keys);
  575.     DEFINE_KEY ("vi$downline", KEY_NAME("<"), "vi$downline(0)", vi$move_keys);
  576.     DEFINE_KEY ("vi$downline(0)", KEY_NAME("d"),
  577.         "vi$downline(0)", vi$move_keys);
  578.     DEFINE_KEY ("vi$downline(0)", KEY_NAME("y"),
  579.         "vi$downline(0)", vi$move_keys);
  580.     DEFINE_KEY ("vi$downline(0)", KEY_NAME("!"),
  581.         "vi$downline(0)", vi$move_keys);
  582.     DEFINE_KEY ("vi$to_column", KEY_NAME ('|'), "vi$to_column", vi$move_keys);
  583.     DEFINE_KEY ("vi$repeat_torf", KEY_NAME(';'),
  584.         "vi$repeat_torf", vi$move_keys);
  585.     DEFINE_KEY ("vi$repeat_torf_back", KEY_NAME(','),
  586.         "vi$repeat_torf_back", vi$move_keys);
  587.     DEFINE_KEY ("vi$paragraph (1)", KEY_NAME ('}'),
  588.         "vi$paragraph (1)", vi$move_keys);
  589.     DEFINE_KEY ("vi$section (1)", KEY_NAME (']'),
  590.         "vi$section (1)", vi$move_keys);
  591.     DEFINE_KEY ("vi$end_sentence", KEY_NAME (')'),
  592.         "vi$end_sentence", vi$move_keys);
  593.     DEFINE_KEY ("vi$paragraph (-1)", KEY_NAME ('{'),
  594.         "vi$paragraph (-1)", vi$move_keys);
  595.     DEFINE_KEY ("vi$section (-1)", KEY_NAME ('['),
  596.         "vi$section (-1)", vi$move_keys);
  597.     DEFINE_KEY ("vi$begin_sentence", KEY_NAME ('('),
  598.         "vi$begin_sentence", vi$move_keys);
  599.  
  600. ENDPROCEDURE;
  601.  
  602. !
  603. !   This procedure is called by the CTRL-` keystroke to swap the current
  604. !   buffer with the previous one.
  605. !
  606. PROCEDURE vi$move_prev_buf (bang)
  607.     LOCAL
  608.         outf,
  609.         buf;
  610.  
  611.     IF (vi$last_mapped = 0) OR
  612.                             (GET_INFO (vi$last_mapped, "TYPE") <> BUFFER) THEN
  613.         vi$info ("No alternate buffer!");
  614.         RETURN;
  615.     ENDIF;
  616.     buf := vi$last_mapped;
  617.     IF (NOT bang) AND (vi$check_auto_write) THEN
  618.         RETURN;
  619.     ENDIF;
  620.     MAP (CURRENT_WINDOW, buf);
  621.     vi$set_status_line (CURRENT_WINDOW);
  622.     vi$pos_in_middle (MARK (NONE));
  623.     outf := GET_INFO (CURRENT_BUFFER, "OUTPUT_FILE");
  624.     IF outf = 0 THEN
  625.         outf := GET_INFO (CURRENT_BUFFER, "NAME");
  626.     ENDIF;
  627.     vi$info ('"'+outf+'"');
  628. ENDPROCEDURE;
  629.  
  630. !
  631. !   This procedure is used to return the current mark in the buffer, after
  632. !   moving to the mark passed.  This routine is used by the majority of the
  633. !   procedures that perform movement, and then return the location they
  634. !   stopped at, but do not change the current location in the buffer.
  635. !
  636. PROCEDURE vi$retpos (pos)
  637.     LOCAL
  638.         endpos;
  639.  
  640.     ON_ERROR
  641.     ENDON_ERROR
  642.  
  643.     endpos := MARK (NONE);
  644.  
  645.     ! If the marker is zero, then there is no way to position to it.
  646.  
  647.     IF (pos <> 0) THEN
  648.         POSITION (pos);
  649.     ENDIF;
  650.     RETURN (endpos);
  651. ENDPROCEDURE;
  652.  
  653. !
  654. !   This procedure is called whenever ESCAPE is pressed while in command mode.
  655. !   The current active count should be zeroed, and possibly other things.
  656. !
  657. PROCEDURE vi$on_escape
  658.     vi$active_count := 0;
  659.     vi$beep;
  660. ENDPROCEDURE;
  661.  
  662. !
  663. !
  664. !
  665. !
  666. PROCEDURE vi$do_help (init_command)
  667.     LOCAL
  668.         buf,
  669.         win;
  670.  
  671.     buf := CURRENT_BUFFER;
  672.     MAP (info_window, show_buffer);
  673.     vi$pasthru_off;
  674.     HELP_TEXT ("vi$root:[doc]vi.hlb","VI " + init_command,ON,show_buffer);
  675.     vi$pasthru_on;
  676.     UNMAP (info_window);
  677.     POSITION (buf);
  678. ENDPROCEDURE;
  679.  
  680. !
  681. !   This is the main processing loop, this function should never be exited.
  682. !   This means that the TPU "ABORT" builtin can not be used anywhere.
  683. !
  684. PROCEDURE vi$command_mode (l_key)
  685.     LOCAL
  686.         key,
  687.         last_len,
  688.         win,
  689.         cwin,
  690.         bol,
  691.         pos,
  692.         repos,
  693.         prog;
  694.  
  695.     IF (NOT vi$min_update) THEN
  696.         UPDATE (CURRENT_WINDOW);
  697.     ENDIF;
  698.  
  699.     ! Get the key to process (last key pressed).
  700.  
  701.     key := l_key;
  702.  
  703.     ! Save the key for '.' repeats.
  704.  
  705.     vi$push_a_key (key);
  706.  
  707.     ! Save the key so that vi$last_key behaves as LAST_KEY would.
  708.  
  709.     vi$last_key := key;
  710.  
  711.     ! Initialize macro level counter.
  712.  
  713.     vi$m_level := 0;
  714.  
  715.     ! Set up so that 'U' works.  Note that there is a problem with U after u
  716.     ! when a :s or & was the last thing done.  The vi$undo_line mark is moved
  717.     ! from the beginning of the line to the end of the line by the undo code.
  718.     ! The fix is not obvious at this point.
  719.  
  720.     pos := MARK (NONE);
  721.     POSITION (LINE_BEGIN);
  722.     bol := MARK (NONE);
  723.     repos := 0;
  724.     IF (GET_INFO (vi$undo_line_mark, "TYPE") = MARKER) THEN
  725.         POSITION (vi$undo_line_mark);
  726.         POSITION (LINE_BEGIN);
  727.         IF (bol <> MARK (NONE)) THEN
  728.             repos := 1;
  729.         ENDIF;
  730.     ELSE
  731.         repos := 1;
  732.     ENDIF;
  733.  
  734.     IF (repos) THEN
  735.         POSITION (bol);
  736.         vi$move_horizontal (1);
  737.         vi$undo_line_mark := MARK (NONE);
  738.         vi$undo_line_str  := vi$current_line;
  739.     ENDIF;
  740.     POSITION (pos);
  741.  
  742.     ! Get the key's program.
  743.  
  744.     prog := LOOKUP_KEY (KEY_NAME (key), PROGRAM, vi$cmd_keys);
  745.  
  746.     ! If prog = 0 then key is undefined, so ignore it.
  747.  
  748.     IF (prog <> 0) THEN
  749.  
  750.         IF (vi$did_mess) THEN
  751.             vi$did_mess := 0;
  752.             MESSAGE ("");
  753.         ENDIF;
  754.  
  755.         vi$command_type := VI$OTHER_TYPE;
  756.  
  757.         ! Otherwise, do the program for that key.
  758.  
  759.         EXECUTE (prog);
  760.  
  761.         ! If this is a key that can change the buffer, then
  762.         ! save the sequence of keys so that '.' causes them to
  763.         ! be repeated.
  764.  
  765.         IF (INDEX (vi$dot_keys, ASCII (key)) <> 0) THEN
  766.             vi$copy_keys (vi$last_keys, vi$cur_keys);
  767.         ENDIF;
  768.     ELSE
  769.  
  770.         ! Zap the repeat count so that next command doesn't repeat.
  771.  
  772.         vi$active_count := 0;
  773.         vi$beep;
  774.     ENDIF;
  775.  
  776.     ! Make sure we are not past end of line or at EOB.
  777.  
  778.     vi$check_rmarg;
  779.  
  780.     IF (INDEX ("0123456789", ASCII (key)) = 0) OR (vi$active_count = 0) THEN
  781.         ERASE (vi$cur_keys);
  782.     ENDIF;
  783. ENDPROCEDURE;
  784.  
  785. !
  786. !   Perform a macro command string that is either a string, or a buffer
  787. !   containing KEY_NAME values (as in execution of the '.' command).
  788. !
  789. PROCEDURE vi$do_macro (commands, save_buffer)
  790.     LOCAL
  791.         typ,
  792.         old_global,
  793.         pos,
  794.         key,
  795.         prog;
  796.  
  797.     IF (vi$m_level > 30) THEN
  798.         vi$info ("Infinite loop detected in key macro sequence!");
  799.         RETURN;
  800.     ENDIF;
  801.     vi$m_level := vi$m_level + 1;
  802.     vi$new_offset := 1;
  803.  
  804.     pos := MARK (NONE);
  805.  
  806.     ! If "commands" is a string then we must generate a buffer to
  807.     ! place the commands into so that they can be read with "vi$read_a_key".
  808.  
  809.     IF (GET_INFO (commands, "TYPE") = STRING) THEN
  810.         IF (vi$tmp_key_buf = 0) THEN
  811.             vi$tmp_key_buf := vi$init_buffer ("$$tmp_key_buf$$", "");
  812.         ELSE
  813.             ERASE (vi$tmp_key_buf);
  814.         ENDIF;
  815.  
  816.         IF vi$tmp_key_buf = 0 THEN
  817.             vi$info ("Can't do key macro: "+commands);
  818.             RETURN;
  819.         ENDIF;
  820.  
  821.         vi$str_to_keybuf (commands, vi$tmp_key_buf);
  822.         vi$insert_macro_keys (vi$tmp_key_buf);
  823.     ELSE
  824.         vi$insert_macro_keys (commands);
  825.     ENDIF;
  826.  
  827.     POSITION (pos);
  828.  
  829.     IF vi$undo_map THEN
  830.         old_global := vi$in_global;
  831.         vi$in_global := 0;
  832.         IF (save_buffer AND (NOT old_global)) THEN
  833.             vi$save_for_undo (CURRENT_BUFFER, VI$LINE_MODE, 1);
  834.             vi$in_global := 1;
  835.         ELSE
  836.             IF old_global THEN
  837.                 vi$in_global := 1;
  838.             ENDIF;
  839.         ENDIF;
  840.     ENDIF;
  841.  
  842.     LOOP
  843.  
  844.         ! Stop when all levels of macro are completed.
  845.  
  846.         EXITIF (vi$key_buf = 0);
  847.         key := vi$read_a_key;
  848.  
  849.         ! Get that keys program.
  850.  
  851.         prog := LOOKUP_KEY (key, PROGRAM, vi$cmd_keys);
  852.  
  853.         ! If prog = 0 then key is undefined, so ignore it.
  854.  
  855.         IF (prog <> 0) THEN
  856.  
  857.             ! Otherwise, do the program for that key.
  858.  
  859.             EXECUTE (prog);
  860.         ELSE
  861.             vi$info ("Key '"+ASCII(key)+"' is undefined!");
  862.             vi$abort (0);
  863.         ENDIF;
  864.     ENDLOOP;
  865.  
  866.     IF (vi$in_global) THEN
  867.         vi$undo_start := BEGINNING_OF (CURRENT_BUFFER);
  868.         vi$undo_end := END_OF (CURRENT_BUFFER);
  869.         vi$in_global := old_global;
  870.     ENDIF;
  871. ENDPROCEDURE;
  872.  
  873. !
  874. !   This function handles the macro capability that allows the text in
  875. !   a named or numbered buffer to be executed as a sequence of commands
  876. !   by type an '@' and then the letter or number indicating the buffer to
  877. !   execute the contents of.
  878. !
  879. PROCEDURE vi$macro
  880.     LOCAL
  881.         line,
  882.         buf_name,
  883.         bpos,
  884.         cnt,
  885.         ccnt,
  886.         pos,
  887.         buf,
  888.         mode,
  889.         ch;
  890.  
  891.     IF (vi$m_level > 30) THEN
  892.         vi$info ("Infinite loop detected in macro key sequence!");
  893.         RETURN;
  894.     ENDIF;
  895.     vi$m_level := vi$m_level + 1;
  896.  
  897.     ch := vi$read_a_key;
  898.  
  899.     IF (INDEX ("123456789", ASCII(ch)) <> 0) THEN
  900.  
  901.         ! Selected a deletion buffer.
  902.  
  903.         buf_name := "vi$del_buf_"+ASCII(ch);
  904.     ELSE
  905.         IF (INDEX (vi$_letter_chars, ASCII(ch)) <> 0) THEN
  906.  
  907.             ! Selected a named buffer.
  908.  
  909.             IF (INDEX (vi$_upper_chars, ASCII(ch)) <> 0) THEN
  910.                 ch := SUBSTR (vi$_lower_chars,
  911.                             INDEX (vi$_upper_chars, ASCII(ch)), 1);
  912.             ENDIF;
  913.  
  914.             buf_name := "vi$ins_buf_"+ASCII(ch);
  915.         ELSE
  916.             vi$info ("Invalid buffer!");
  917.             RETURN;
  918.         ENDIF;
  919.     ENDIF;
  920.  
  921.     vi$global_var := 0;
  922.     EXECUTE (COMPILE ("vi$global_var := "+buf_name+";"));
  923.     buf := vi$global_var;
  924.     IF (buf = 0) THEN
  925.         vi$info ("There is no text in that buffer!");
  926.         RETURN;
  927.     ENDIF;
  928.  
  929.     pos := MARK (NONE);
  930.     POSITION (BEGINNING_OF (buf));
  931. a    !  Get and skip the buffer mode indicator.
  932.  
  933.     mode := INT (vi$current_line);
  934.     MOVE_VERTICAL (1);
  935.  
  936.     ! Get the number of lines to do.
  937.  
  938.     cnt := GET_INFO (CURRENT_BUFFER, "RECORD_COUNT") - 2;
  939.     ccnt := 0;
  940.  
  941.     LOOP
  942.         line := vi$current_line;
  943.  
  944.         IF (ccnt = cnt) THEN
  945.             IF mode = VI$LINE_MODE THEN
  946.                 line := line + ASCII (13);
  947.             ENDIF;
  948.         ELSE
  949.             line := line + ASCII (13);
  950.         ENDIF;
  951.  
  952.         ccnt := ccnt + 1;
  953.         bpos := MARK (NONE);
  954.         POSITION (pos);
  955.         vi$do_macro (line, 1);
  956.  
  957.         EXITIF (ccnt = cnt);
  958.  
  959.         pos := MARK (NONE);
  960.         POSITION (bpos);
  961.         MOVE_VERTICAL (1);
  962.     ENDLOOP;
  963. ENDPROCEDURE;
  964.  
  965. !
  966. !   This procedure handles the operation of the U command.  U undoes all
  967. !   changes performed on a line, providing the cursor has not left that
  968. !   line.
  969. !
  970. PROCEDURE vi$undo_one_line
  971.     LOCAL
  972.         nstr,
  973.         npos,
  974.         repos,
  975.         pos;
  976.  
  977.     pos := MARK (NONE);
  978.     POSITION (LINE_BEGIN);
  979.     npos := MARK (NONE);
  980.     repos := 1;
  981.     IF (GET_INFO (vi$undo_line_mark, "TYPE") = MARKER) THEN
  982.         POSITION (vi$undo_line_mark);
  983.         POSITION (LINE_BEGIN);
  984.         IF (npos <> MARK (NONE)) THEN
  985.             repos := 0;
  986.         ENDIF;
  987.     ELSE
  988.         repos := 0;
  989.     ENDIF;
  990.  
  991.     IF (repos) THEN
  992.         nstr := vi$current_line;
  993.         ERASE_LINE;
  994.         COPY_TEXT (vi$undo_line_str);
  995.         SPLIT_LINE;
  996.         MOVE_VERTICAL (-1);
  997.         vi$kill_undo;
  998.         vi$undo_end := 0;
  999.         vi$undo_line_str := nstr;
  1000.         vi$undo_line_mark := MARK (NONE);
  1001.     ELSE
  1002.         vi$undo_line_mark := 0;
  1003.     ENDIF;
  1004. ENDPROCEDURE;
  1005.  
  1006. !
  1007. !   This procedure takes a range or string of data, and squirrels it away
  1008. !   to be restored when an undo operation is performed.
  1009. !
  1010. PROCEDURE vi$save_for_undo (undo_data, btype, save_line_info)
  1011.     LOCAL
  1012.         pos;
  1013.  
  1014.     pos := MARK (NONE);
  1015.  
  1016.     IF (vi$in_global) THEN
  1017.         RETURN;
  1018.     ENDIF;
  1019.  
  1020.     IF (save_line_info) THEN
  1021.         vi$undo_line := vi$cur_line_no;
  1022.         vi$undo_offset := CURRENT_OFFSET;
  1023.     ELSE
  1024.         vi$undo_line := 0;
  1025.     ENDIF;
  1026.  
  1027.     IF vi$undo_buffer = 0 THEN
  1028.         vi$undo_buffer := vi$init_buffer ("$$vi$undo_buffer$$", "");
  1029.         IF vi$undo_buffer = 0 THEN
  1030.             vi$info ("Error creating undo buffer!");
  1031.             RETURN;
  1032.         ENDIF;
  1033.     ENDIF;
  1034.  
  1035.     vi$type2buf (STR (btype), vi$undo_buffer);
  1036.     vi$cp2buf (undo_data, vi$undo_buffer);
  1037.  
  1038.     vi$undo_valid := 1;
  1039.  
  1040.     POSITION (pos);
  1041. ENDPROCEDURE;
  1042.  
  1043. !
  1044. !   Disallow the data last saved with vi$save_for_undo() from being restored
  1045. !   during an undo operation.
  1046. !
  1047. PROCEDURE vi$kill_undo
  1048.     IF (NOT vi$in_global) THEN
  1049.         vi$undo_valid := 0;
  1050.         vi$undo_line := 0;
  1051.     ENDIF;
  1052. ENDPROCEDURE;
  1053.  
  1054. !
  1055. !   Perform the operation of undoing the last change.  This operation is
  1056. !   actually comprised of 3 separate operations.  The first operation is
  1057. !   to restore any text saved by vi$save_for_undo().  The next operation is
  1058. !   to vi$save_for_undo() any text delimited by vi$undo_start and vi$undo_end.
  1059. !   vi$undo_start marks the location where step 1 is performed.  vi$undo_end
  1060. !   determines whether or not there is text to save and then delete.  If
  1061. !   it has a non-zero value, then the range delimited by it and vi$undo_start
  1062. !   is saved (using vi$save_for_undo()), and then deleted.
  1063. !
  1064. PROCEDURE vi$perform_undo
  1065.     LOCAL
  1066.         done_pos,
  1067.         cbuf,
  1068.         pos,
  1069.         undo_line,
  1070.         undo_offset,
  1071.         cline,
  1072.         coff,
  1073.         btype,
  1074.         errno,
  1075.         undo_mode,
  1076.         saved_text,
  1077.         new_start,
  1078.         new_end,
  1079.         era_range;
  1080.  
  1081.     vi$new_offset := 1;
  1082.     new_start := 0;
  1083.     cline := vi$cur_line_no;
  1084.     coff := CURRENT_OFFSET;
  1085.     undo_line := vi$undo_line;
  1086.     undo_offset := vi$undo_offset;
  1087.  
  1088.     IF (GET_INFO (vi$undo_start, "BUFFER") <> CURRENT_BUFFER) OR
  1089.             ((NOT vi$undo_valid) AND (vi$undo_end = 0)) THEN
  1090.         vi$beep;
  1091.         RETURN;
  1092.     ENDIF;
  1093.  
  1094.     IF (vi$undo_valid) THEN
  1095.         cbuf := CURRENT_BUFFER;
  1096.  
  1097.         POSITION (BEGINNING_OF (vi$undo_buffer));
  1098.         undo_mode := INT (vi$current_line);
  1099.         ERASE_LINE;
  1100.  
  1101.         POSITION (vi$undo_start);
  1102.  
  1103.         IF MARK (NONE) = BEGINNING_OF (CURRENT_BUFFER) THEN
  1104.             new_start := 1;
  1105.         ELSE
  1106.             MOVE_HORIZONTAL (-1);
  1107.             new_start := MARK (NONE);
  1108.             MOVE_HORIZONTAL (1);
  1109.         ENDIF;
  1110.  
  1111.         SET (INSERT, CURRENT_BUFFER);
  1112.         COPY_TEXT (vi$undo_buffer);
  1113.  
  1114.         APPEND_LINE;
  1115.         MOVE_HORIZONTAL (-1);
  1116.         new_end := MARK (NONE);
  1117.  
  1118.         POSITION (BEGINNING_OF (vi$undo_buffer));
  1119.         COPY_TEXT (STR (undo_mode));
  1120.         SPLIT_LINE;
  1121.  
  1122.         POSITION (new_end);
  1123.     ENDIF;
  1124.  
  1125.     ! Use flag to determine whether or not to kill buffer contents.
  1126.  
  1127.     saved_text := 0;
  1128.  
  1129.     IF (vi$undo_start <> 0) AND (vi$undo_end <> 0) THEN
  1130.         saved_text := 1;
  1131.         pos := MARK (NONE);
  1132.  
  1133.         POSITION (vi$undo_end);
  1134.         IF (CURRENT_OFFSET <> 0) THEN
  1135.             btype := VI$IN_LINE_MODE;
  1136.         ELSE
  1137.             btype := VI$LINE_MODE;
  1138.         ENDIF;
  1139.  
  1140.         POSITION (pos);
  1141.  
  1142.         era_range := CREATE_RANGE (vi$undo_start, vi$undo_end, NONE);
  1143.  
  1144.         IF era_range <> 0 THEN
  1145.             POSITION (vi$undo_start);
  1146.             vi$save_for_undo (era_range, btype, 1);
  1147.             ERASE (era_range);
  1148.         ENDIF;
  1149.     ENDIF;
  1150.  
  1151.     IF (GET_INFO (new_start, "TYPE") <> INTEGER) THEN
  1152.         POSITION (new_start);
  1153.         vi$move_horizontal (1);
  1154.         vi$undo_start := MARK (NONE);
  1155.         vi$undo_end := new_end;
  1156.     ELSE
  1157.         IF new_start = 1 THEN
  1158.             vi$undo_start := BEGINNING_OF (CURRENT_BUFFER);
  1159.             vi$undo_end := new_end;
  1160.         ELSE
  1161.             vi$undo_end := 0;
  1162.         ENDIF;
  1163.     ENDIF;
  1164.  
  1165.     IF (saved_text = 0) THEN
  1166.         vi$kill_undo;
  1167.     ENDIF;
  1168.  
  1169.     IF (vi$undo_start <> 0) THEN
  1170.         POSITION (vi$undo_start);
  1171.     ENDIF;
  1172.  
  1173.     ! If undoing a macro then reposition to the place where we started.
  1174.  
  1175.     IF (undo_line <> 0) THEN
  1176.         vi$move_to_line (undo_line);
  1177.         vi$move_horizontal (undo_offset);
  1178.         vi$pos_in_middle (MARK (NONE));
  1179.         vi$undo_line := undo_line;
  1180.         vi$undo_offset := undo_offset;
  1181.     ENDIF;
  1182. ENDPROCEDURE;
  1183.  
  1184. !
  1185. !   This function performs the operations associated with the ^Y and ^E
  1186. !   keystrokes.
  1187. !
  1188. PROCEDURE vi$pull_push_line (direction)
  1189.  
  1190.     LOCAL
  1191.         currow,
  1192.         limit,
  1193.         n_lines,
  1194.         pos;
  1195.  
  1196.     ON_ERROR
  1197.         ! Ignore "ATTEMPT to move past TOP/BOTTOM of buffer"
  1198.     ENDON_ERROR;
  1199.  
  1200.     ! Get the number of lines to move.
  1201.  
  1202.     n_lines := vi$cur_active_count * direction;
  1203.  
  1204.     ! Mark the destination position for the case where we are at the top or
  1205.     ! bottom of the window.
  1206.  
  1207.     MOVE_VERTICAL (n_lines);
  1208.     pos := MARK (NONE);
  1209.  
  1210.     ! Return to the old position.
  1211.  
  1212.     MOVE_VERTICAL (-n_lines);
  1213.  
  1214.     ! Get the current screen row
  1215.  
  1216.     currow := GET_INFO (CURRENT_WINDOW, "CURRENT_ROW");
  1217.  
  1218.     ! Get the proper border value based on the direction.
  1219.  
  1220.     IF (n_lines < 0) THEN
  1221.         limit := GET_INFO (CURRENT_WINDOW, "VISIBLE_BOTTOM");
  1222.     ELSE
  1223.         limit := GET_INFO (CURRENT_WINDOW, "VISIBLE_TOP");
  1224.     ENDIF;
  1225.  
  1226.     ! If we are NOT at the top or bottom, then the current row is the dest.
  1227.  
  1228.     IF (n_lines > 0) THEN
  1229.         IF (currow - limit) >= n_lines THEN
  1230.             pos := MARK (NONE);
  1231.         ENDIF;
  1232.     ELSE
  1233.         IF vi$abs (currow - limit) >= vi$abs (n_lines) THEN
  1234.             pos := MARK (NONE);
  1235.         ENDIF;
  1236.     ENDIF;
  1237.  
  1238.     ! Scroll the window.  If the scroll fails, then move the cursor.
  1239.  
  1240.     POSITION (LINE_BEGIN);
  1241.     IF (SCROLL (CURRENT_WINDOW, n_lines) <> n_lines) THEN
  1242.         POSITION (pos);
  1243.         MOVE_VERTICAL (n_lines);
  1244.     ELSE
  1245.  
  1246.         ! Otherwise the position we wanted is visible, so move there.
  1247.  
  1248.         POSITION (pos);
  1249.         IF (n_lines < 0) AND ((currow - limit) > n_lines) THEN
  1250.             MOVE_VERTICAL (limit - currow);
  1251.         ENDIF;
  1252.     ENDIF;
  1253. ENDPROCEDURE;
  1254.  
  1255. !
  1256. !   Move to the location indicated by a '|' command.
  1257. !
  1258. PROCEDURE vi$_to_column
  1259.     vi$beep_position (vi$to_column, 0, 1);
  1260. ENDPROCEDURE;
  1261.  
  1262. !
  1263. !   Return the marker indicating the column selected by vi$active_count
  1264. !
  1265. PROCEDURE vi$to_column
  1266.     LOCAL
  1267.         pos,
  1268.         act_count;
  1269.  
  1270.     act_count := vi$cur_active_count;
  1271.     pos := MARK (NONE);
  1272.  
  1273.     IF (act_count <= LENGTH (vi$current_line)) THEN
  1274.         pos := MARK (NONE);
  1275.         MOVE_HORIZONTAL (act_count - CURRENT_OFFSET - 1);
  1276.         RETURN (vi$retpos (pos));
  1277.     ENDIF;
  1278.     RETURN (0);
  1279. ENDPROCEDURE;
  1280.  
  1281. !
  1282. !   Perform the operations associated with 'ZZ' (write and exit) command.
  1283. !
  1284. PROCEDURE vi$_ZZ (rkey)
  1285.      LOCAL
  1286.         prcnam,
  1287.         ans,
  1288.         cur_buf,
  1289.         read_z,
  1290.         buf,
  1291.         errno;
  1292.  
  1293.     ON_ERROR
  1294.         errno := ERROR;
  1295.         IF errno = TPU$_NOPARENT THEN
  1296.  
  1297.             !  Use vi$quit so that buffers not written will not be written
  1298.             !  automatically.
  1299.  
  1300.             vi$quit;
  1301.         ENDIF;
  1302.     ENDON_ERROR;
  1303.  
  1304.     read_z := rkey;
  1305.  
  1306.     IF (read_z <> KEY_NAME ('Z')) THEN
  1307.         read_z := vi$read_a_key;
  1308.     ENDIF;
  1309.  
  1310.     IF (read_z = KEY_NAME ('Z')) THEN
  1311.         cur_buf := CURRENT_BUFFER;
  1312.  
  1313.         IF (GET_INFO (cur_buf, "MODIFIED")) AND
  1314.                             (GET_INFO (cur_buf, "SYSTEM") = 0) THEN
  1315.  
  1316.             IF (vi$can_write (cur_buf)) THEN
  1317.                 IF (GET_INFO (cur_buf, "NO_WRITE") = 0) THEN
  1318.                     vi$info ("Writing out """+GET_INFO (cur_buf, "NAME")+"""");
  1319.                     WRITE_FILE (cur_buf);
  1320.                 ENDIF;
  1321.             ELSE
  1322.                 RETURN;
  1323.             ENDIF;
  1324.         ENDIF;
  1325.  
  1326.         buf := GET_INFO (BUFFERS, "FIRST");
  1327.         LOOP
  1328.             EXITIF (buf = 0);
  1329.             IF (GET_INFO (buf, "MODIFIED")) AND
  1330.                                 (GET_INFO (buf, "SYSTEM") = 0) THEN
  1331.  
  1332.                 ans := vi$read_line ("Write """+GET_INFO (buf, "NAME")+"""? ");
  1333.  
  1334.                 CHANGE_CASE (ans, LOWER);
  1335.                 IF SUBSTR (ans, 1, 1) = "y" THEN
  1336.                     IF (vi$can_write (buf)) THEN
  1337.                         IF (GET_INFO (buf, "NO_WRITE") = 0) THEN
  1338.                             vi$info ("Writing out """+
  1339.                                                 GET_INFO (buf, "NAME")+"""");
  1340.                             WRITE_FILE (buf);
  1341.                         ENDIF;
  1342.                     ELSE
  1343.                         RETURN;
  1344.                     ENDIF;
  1345.                 ENDIF;
  1346.             ENDIF;
  1347.             buf := GET_INFO (BUFFERS, "NEXT");
  1348.         ENDLOOP;
  1349.  
  1350.         IF (vi$get_attach_parm ("TPU$NOSUBPROC") = " ") THEN
  1351.             prcnam := vi$get_attach_parm ("TPU$ATTACH_NAME");
  1352.             vi$pasthru_off;
  1353.             IF (prcnam = " ") THEN
  1354.                 ATTACH;
  1355.             ELSE
  1356.                 ATTACH (prcnam);
  1357.             ENDIF;
  1358.             vi$pasthru_on;
  1359.             vi$process_args;
  1360.         ELSE
  1361.             vi$do_quit ("q", "q");
  1362.         ENDIF;
  1363.     ENDIF;
  1364.  
  1365.     vi$kill_undo;
  1366.     vi$undo_end := 0;
  1367.     vi$active_count := 0;
  1368. ENDPROCEDURE;
  1369.  
  1370. !
  1371. !   Process the job logical names that are used to pass parameters between
  1372. !   the parent process and the editor.
  1373. !
  1374. PROCEDURE vi$process_args
  1375.  
  1376.     LOCAL
  1377.         buf,
  1378.         bufn,
  1379.         errno,
  1380.         startup_cmd,
  1381.         new_output,
  1382.         find_text,
  1383.         new_lineno,
  1384.         input_file;
  1385.  
  1386.     ON_ERROR
  1387.  
  1388.         errno := ERROR;
  1389.  
  1390.         SET (SUCCESS, ON);
  1391.         vi$system_message (errno);
  1392.         RETURN;
  1393.  
  1394.     ENDON_ERROR;
  1395.  
  1396.     startup_cmd := vi$get_attach_parm ("TPU$NEWCMD");
  1397.  
  1398.     IF startup_cmd = " " THEN
  1399.         input_file := vi$get_attach_parm ("TPU$ARGS");
  1400.  
  1401.         IF (input_file <> " ") THEN
  1402.             new_output := vi$get_attach_parm ("TPU$OUTPUT");
  1403.  
  1404.             !  When a file is specified, and a new output file is also
  1405.             !  specified, then we will attempt to erase any existing
  1406.             !  buffer's contents so that MAIL will actually be able to
  1407.             !  be used over and over during an editor's life.
  1408.  
  1409.             IF (new_output <> " ") THEN
  1410.                 bufn := FILE_PARSE (input_file,"","",NAME) +
  1411.                         FILE_PARSE (input_file,"","",TYPE);
  1412.                 buf := vi$find_buffer_by_name (bufn);
  1413.                 IF buf <> 0 THEN
  1414.                     IF (GET_INFO (buf, "MODIFIED") = 0) OR
  1415.                                         GET_INFO (buf, "NO_WRITE") THEN
  1416.                         ERASE (buf);
  1417.                     ELSE
  1418.                         vi$info (
  1419.                 "Buffer is modified, original contents not destroyed!");
  1420.                     ENDIF;
  1421.                 ENDIF;
  1422.             ENDIF;
  1423.  
  1424.             vi$get_file (input_file);
  1425.  
  1426.             IF (new_output <> " ") THEN
  1427.                 SET (OUTPUT_FILE, CURRENT_BUFFER, new_output);
  1428.                 vi$status_lines (CURRENT_BUFFER);
  1429.  
  1430.                 !  Set the buffer to be modified so that the file will
  1431.                 !  be written on exit.
  1432.  
  1433.                 SPLIT_LINE;
  1434.                 APPEND_LINE;
  1435.             ENDIF;
  1436.         ENDIF;
  1437.     ELSE
  1438.         new_output := vi$get_attach_parm ("TPU$OUTPUT");
  1439.         IF (new_output <> " ") THEN
  1440.             SET (OUTPUT_FILE, CURRENT_BUFFER, new_output);
  1441.             vi$status_lines (CURRENT_BUFFER);
  1442.  
  1443.             !  Set the buffer to be modified so that the file will
  1444.             !  be written on exit.
  1445.  
  1446.             SPLIT_LINE;
  1447.             APPEND_LINE;
  1448.         ENDIF;
  1449.  
  1450.         vi$do_cmd_line (startup_cmd);
  1451.     ENDIF;
  1452.  
  1453.     new_lineno := vi$get_attach_parm ("TPU$LINE");
  1454.  
  1455.     IF (new_lineno = " ") THEN
  1456.         find_text := vi$get_attach_parm ("TPU$SEARCH");
  1457.         IF (find_text <> " ") THEN
  1458.             IF SUBSTR (find_text, 1, 1) = "/" THEN
  1459.                 SET (FORWARD, CURRENT_BUFFER);
  1460.                 vi$last_search_dir := 1;
  1461.             ELSE
  1462.                 SET (REVERSE, CURRENT_BUFFER);
  1463.                 vi$last_search_dir := -1;
  1464.             ENDIF;
  1465.             vi$search_string := SUBSTR (find_text, 2, LENGTH (find_text)-1);
  1466.             vi$beep_position (vi$find_str (vi$search_string, 0, 0), 1, 1);
  1467.         ENDIF;
  1468.     ELSE
  1469.         vi$beep_position (vi$to_line (INT (new_lineno)), 1, 1);
  1470.     ENDIF;
  1471. ENDPROCEDURE;
  1472.  
  1473. !
  1474. !  A special procedure to trap any errors in translating logical names, and
  1475. !  just ignore them, and return a " " string on error.
  1476. !
  1477. PROCEDURE vi$get_attach_parm (parm)
  1478.     LOCAL
  1479.         rstr,
  1480.         errno,
  1481.         blank;
  1482.  
  1483.     ON_ERROR
  1484.         errno := ERROR;
  1485.         RETURN (blank);
  1486.     ENDON_ERROR;
  1487.  
  1488.     blank := " ";
  1489.  
  1490.     rstr := CALL_USER (vi$cu_trnlnm_job, parm);
  1491.     RETURN (rstr);
  1492. ENDPROCEDURE;
  1493.  
  1494. !
  1495. !   Perform the operations associated with the 'z' key command.
  1496. !
  1497. PROCEDURE vi$_z_move
  1498.  
  1499.     LOCAL
  1500.         pos,
  1501.         crow,
  1502.         old_scroll,
  1503.         scrl_value,
  1504.         scroll_top,
  1505.         scroll_bottom,
  1506.         scroll_amount,
  1507.         act_count,
  1508.         done,
  1509.         next_key,
  1510.         cur_window;
  1511.  
  1512.     vi$active_count := 0;
  1513.     LOOP
  1514. $$EOD$$
  1515.