home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume1 / 8710 / vms-vi / 5 < prev    next >
Encoding:
Internet Message Format  |  1990-07-13  |  45.3 KB

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