v04i099: TPUVI for VMS part 8 of 17

Gregg Wonderly gregg at a.cs.okstate.edu
Tue Sep 27 11:52:38 AEST 1988


Posting-number: Volume 4, Issue 99
Submitted-by: "Gregg Wonderly" <gregg at a.cs.okstate.edu>
Archive-name: vms-vi-2/Part08

$ WRITE SYS$OUTPUT "Creating ""VI.4"""
$ CREATE VI.4
$ DECK/DOLLARS=$$EOD$$
!
!
!                   The VI EDITOR written in VAXTPU
!
!   Written by Gregg Wonderly
!   Mathematics Department
!   Oklahoma State University
!   Stillwater Oklahoma, 74078
!
!   internet: gregg at nemo.math.okstate.edu
!   uucp: okstate!nemo.math.okstate.edu!gregg
!
!   Version number 2, edit 631, 28-AUG-1988 19:09:47.00
!
!   This program is the property of the author, and you should refrain
!   from trying to make a profit from it (that's not nice).
!
!   You can pass it around freely, as you should have gotten it for free.
!   All I ask is that you give credit where credit is due.
!
!
!
!   Initialize TPU for VI emulation.
!
PROCEDURE vi$init_vars
    LOCAL
        i;

    vi$find_rng := 0;
    vi$_version := "VAX/TPU -- VI Version 2, Edit 631";
    message_buffer := 0;
    message_window := 0;
    vi$did_mess := 0;
    vi$readonly := 0;

    command_buffer := 0;
    command_window := 0;

    show_buffer := 0;
    info_window := 0;

    choice_buffer := 0;
    choice_window := 0;

    vi$last_mapped := 0;
    vi$delete_empty := 0;

    vi$last_insert := 0;

    vi$bracket_chars := "{}()[]";       ! The recognized brackets.

    ! interline movement that is backwards, or different than the others

    vi$paren_cnt := 0;
    vi$abbr_ := "";
    vi$back_moves := "bB0FT^(";
    vi$weird_moves := "ft$DeE%?";
    vi$weird2_moves := "h";
    vi$dot_keys := "iIdpPDxXaAcCoOrRSs<>~&";

    vi$_lower_chars := "abcdefghijklmnopqrstuvwxyz";
    vi$_upper_chars := "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    vi$_letter_chars := vi$_lower_chars + vi$_upper_chars;
    vi$_numeric_chars := "0123456789";
    vi$_alpha_chars := vi$_letter_chars + "_" + vi$_numeric_chars;
    vi$_sym_chars := vi$_alpha_chars + "$";
    vi$_ctl_chars := "";
    i := 0;
    LOOP
        EXITIF (i = 32);
        vi$_ctl_chars := vi$_ctl_chars + ASCII (i);
        i := i + 1;
    ENDLOOP;

    vi$_space_chars := " " + ASCII(9) + vi$_ctl_chars;
    vi$_space_tab := " " + ASCII(9);
    vi$_punct_chars := "!@`~#$%^&*()-=+{}[];:'""\|,.?/><";
    vi$_ex_separs := ", " + ASCII(9);
    vi$_ascii_chars := "";
    vi$_ws := ",./?;:'""\|[]{}-=+)(*&^%$#@!~`" + vi$_space_chars;
    vi$no_space := " " + ASCII(9) + ASCII (10) + ASCII(11) + ASCII(13);
    i := 0;
    LOOP
        EXITIF (i = 256);
        vi$_ascii_chars := vi$_ascii_chars + ASCII (i);
        i := i + 1;
    ENDLOOP;

    vi$pch := ASCII(9);
    i := 32;
    LOOP
        EXITIF (i = 256);
        vi$pch := vi$pch + ASCII (i);
        i := i + 1;
    ENDLOOP;

    vi$m_level := 0;
    vi$in_learn := 0;
    vi$playing_back := 0;

    vi$dcl_buf := 0;
    vi$dcl_process := 0;
    vi$send_dcl := 1;

    vi$tag_buf := 0;
    vi$tag_files := "tags";
    vi$tag_case := EXACT;
    vi$in_ws := 0;
    vi$in_global := 0;
    vi$in_occlusion := 0;
    vi$old_occ_win := 0;
    vi$occluding_win := 0;
    vi$error_bells := 1;
    vi$show_mode := 0;
    vi$auto_indent := 0;

    vi$tmp_key_buf := 0;

    vi$last_mess := "";

    vi$max_offset := 0;
    vi$new_offset := 1;

    vi$append_it := 0;
    vi$old_place := 0;
    vi$select_pos := 0;

    vi$term_vt200 := 0;
    vi$scr_width := 0;
    vi$scr_length := 0;

    vi$para_str := "P ";
    vi$para_pat := LINE_BEGIN & ((".P")|LINE_END);
    vi$sect_str := "CHHLPG+c";
    vi$sect_pat := LINE_BEGIN & ((".CH"| ".HL"| ".PG"| "{")|LINE_END);
    vi$last_cmd := 0;
    vi$last_filter := 0;

    vi$replace_separ := 0;
    vi$replace_source := 0;
    vi$replace_dest := 0;

    VI$DELETE_TYPE  := 1;
    VI$CHANGE_TYPE  := 2;
    VI$OTHER_TYPE   := 3;
    VI$YANK_TYPE    := 4;
    VI$FILTER_TYPE  := 5;
    VI$SHIFT_TYPE   := 6;
    vi$command_type := VI$OTHER_TYPE;

    vi$cu_cwd           := 1;
    vi$cu_trnlnm_job    := 2;
    vi$cu_trnlnm_proc   := 3;
    vi$cu_trnlnm_sys    := 4;
    vi$cu_trnlnm_group  := 5;
    vi$cu_getmsg        := 6;
    vi$cu_set_sysdisk   := 7;
    vi$cu_sleep         := 8;
    vi$cu_pasthru_on    := 9;
    vi$cu_pasthru_off   := 10;
    vi$cu_spawn         := 11;

    vi$filter_proc := 0;
    vi$filter_buf := 0;

    vi$push_key_buf := 0;

    o1 := 0; o2 := 0; o3 := 0; o4 := 0; o5 := 0;
    o6 := 0; o7 := 0; o8 := 0; o9 := 0;

    p1 := 0; p2 := 0; p3 := 0; p4 := 0; p5 := 0;
    p6 := 0; p7 := 0; p8 := 0; p9 := 0;

    vi$ex_mode_buffer := 0;
    vi$global_var := 0;
    vi$macro_active := "$$active_macro$$";
    vi$_find_pat := 0;
    vi$wrap_scan := 1;

    vi$last_key := 0;
    vi$last_keys := 0;
    vi$cur_keys := 0;
    vi$key_buf := 0;
    vi$min_update := 1;
    vi$tab_amount := 8;
    vi$shift_width := 8;
    vi$spaces := "                                                    ";
    vi$use_tabs := 1;
    vi$in_show_match := 0;
    vi$report := 5;
    vi$auto_write := 0;
    vi$ignore_case := EXACT;
    vi$wrap_margin := 0;
    vi$magic := 1;
    vi$undo_map := 1;

    vi$undo_line_str := 0;
    vi$undo_line_mark := 0;
    vi$undo_line := 0;
    vi$undo_offset := 0;

    vi$how_much_scroll := 12;

    vi$search_string := 0;
    vi$last_search_dir := 1;

    vi$undo_start := 0;
    vi$undo_end := 0;
    vi$undo_buffer := 0;
    vi$undo_valid := 0;

    VI$HERE := 0;
    VI$AFTER := 1;

    VI$LINE_MODE := 1;
    VI$IN_LINE_MODE := 2;

    vi$cur_level := 0;

    vi$global_mark := 0;
    vi$yank_mode := 0;
    vi$temp_buf := 0;
    vi$cur_text := "";      ! Where text to PUT comes from.

    ! The ten deletion buffers.

    vi$del_buf_1 := 0; vi$del_buf_2 := 0; vi$del_buf_3 := 0;
    vi$del_buf_4 := 0; vi$del_buf_5 := 0; vi$del_buf_6 := 0;
    vi$del_buf_7 := 0; vi$del_buf_8 := 0; vi$del_buf_9 := 0;

    ! Named buffers accessible from the keyboard characters.

    vi$ins_buf_a := 0; vi$ins_buf_b := 0; vi$ins_buf_c := 0;
    vi$ins_buf_d := 0; vi$ins_buf_e := 0; vi$ins_buf_f := 0;
    vi$ins_buf_g := 0; vi$ins_buf_h := 0; vi$ins_buf_i := 0;
    vi$ins_buf_j := 0; vi$ins_buf_k := 0; vi$ins_buf_l := 0;
    vi$ins_buf_m := 0; vi$ins_buf_n := 0; vi$ins_buf_o := 0;
    vi$ins_buf_p := 0; vi$ins_buf_q := 0; vi$ins_buf_r := 0;
    vi$ins_buf_s := 0; vi$ins_buf_t := 0; vi$ins_buf_u := 0;
    vi$ins_buf_v := 0; vi$ins_buf_w := 0; vi$ins_buf_x := 0;
    vi$ins_buf_y := 0; vi$ins_buf_z := 0;

    ! The 26 marks available

    vi$mark_a := 0; vi$mark_b := 0; vi$mark_c := 0; vi$mark_d := 0;
    vi$mark_e := 0; vi$mark_f := 0; vi$mark_g := 0; vi$mark_h := 0;
    vi$mark_i := 0; vi$mark_j := 0; vi$mark_k := 0; vi$mark_l := 0;
    vi$mark_m := 0; vi$mark_n := 0; vi$mark_o := 0; vi$mark_p := 0;
    vi$mark_q := 0; vi$mark_r := 0; vi$mark_s := 0; vi$mark_t := 0;
    vi$mark_u := 0; vi$mark_v := 0; vi$mark_w := 0; vi$mark_x := 0;
    vi$mark_y := 0; vi$mark_z := 0;

    vi$endpos := 0;
    vi$new_endpos := 0;
    vi$start_pos := 0;

    VI$ALPHA_TYPE := 1;
    VI$PUNCT_TYPE := 2;
    VI$SPACE_TYPE := 3;
    VI$EOL_TYPE := 4;

    vi$temp_buf_num := 1;
    vi$last_s_func := 0;
    vi$last_s_char := 0;

    vi$active_count := 0;
    vi$cmd_keys := "c_keys";
    vi$move_keys := "m_keys";
    vi$edit_keys := "e_keys";

ENDPROCEDURE;

!
!   Map all of the key bindings into the proper key maps.
!
!       The "c_keys" map is used for command mode key processing.
!       The "e_keys" map is used during line editing.
!       The "m_keys" map is used to determine movement associated with
!                    a particular key.
!
PROCEDURE vi$init_keys

    ! Define all of the command mode keys.

    vi$cmd_keys := CREATE_KEY_MAP ("c_keys");

    DEFINE_KEY ("vi$make_full_screen", KP0, "", vi$cmd_keys);
    DEFINE_KEY ("vi$delete_window", KP1, "", vi$cmd_keys);
    DEFINE_KEY ("vi$split_here", KP2, "", vi$cmd_keys);
    DEFINE_KEY ("vi$next_window", KP3, "", vi$cmd_keys);
    DEFINE_KEY ("vi$shrink_window(vi$cur_active_count)", KP4,
            "", vi$cmd_keys);
    DEFINE_KEY ("vi$enlarge_window(vi$cur_active_count)", KP5,
            "", vi$cmd_keys);
    DEFINE_KEY ("vi$previous_window", KP6, "", vi$cmd_keys);

    DEFINE_KEY ("vi$prev_screen", CTRL_B_KEY, "vi$prev_screen", vi$cmd_keys);
    DEFINE_KEY ("vi$screen_forward", CTRL_D_KEY,
        "vi$screen_forward", vi$cmd_keys);
    DEFINE_KEY ("vi$pull_push_line (1)", CTRL_E_KEY,
        "vi$pull_push_line (1)", vi$cmd_keys);
    DEFINE_KEY ("vi$next_screen", CTRL_F_KEY, "vi$next_screen", vi$cmd_keys);
    DEFINE_KEY ("vi$what_line", CTRL_G_KEY, "vi$what_line", vi$cmd_keys);
    DEFINE_KEY ("vi$move_left", CTRL_H_KEY, "vi$move_left", vi$cmd_keys);
    DEFINE_KEY ("vi$move_down", CTRL_J_KEY, "vi$move_down", vi$cmd_keys);
    DEFINE_KEY ("refresh", CTRL_L_KEY, "refresh", vi$cmd_keys);
    DEFINE_KEY ("vi$move_down", CTRL_N_KEY, "vi$move_down", vi$cmd_keys);
    DEFINE_KEY ("vi$move_up", CTRL_P_KEY, "vi$move_up", vi$cmd_keys);
    DEFINE_KEY ("vi$remember", CTRL_R_KEY, "vi$remember", vi$cmd_keys);
    DEFINE_KEY ("vi$screen_backward", CTRL_U_KEY,
        "vi$screen_backward", vi$cmd_keys);
    DEFINE_KEY ("vi$send_to_dcl (CURRENT_LINE)", CTRL_X_KEY,
        "vi$send_to_dcl (CURRENT_LINE)", vi$cmd_keys);
    DEFINE_KEY ("vi$pull_push_line (-1)", CTRL_Y_KEY,
        "vi$pull_push_line (-1)", vi$cmd_keys);
    DEFINE_KEY ("vi$to_tag(0, 0)", KEY_NAME(ASCII(29)),
        "vi$to_tag(0, 0)", vi$cmd_keys);
    DEFINE_KEY ("vi$move_prev_buf (0)", KEY_NAME(ASCII(30)),
        "vi$move_prev_buf (0)", vi$cmd_keys);
    DEFINE_KEY ("vi$do_help('')", PF2, "vi$do_help('')", vi$cmd_keys);
    DEFINE_KEY ("vi$on_escape", PF1, "vi$on_escape", vi$cmd_keys);
    DEFINE_KEY ("vi$on_escape", F11, "vi$on_escape", vi$cmd_keys);
    DEFINE_KEY ("vi$_go_to_marker", KEY_NAME ("'"),
        "vi$_go_to_marker", vi$cmd_keys);
    DEFINE_KEY ("vi$_go_to_marker", KEY_NAME ("`"),
        "vi$_go_to_marker", vi$cmd_keys);
    DEFINE_KEY ("vi$select_buffer", KEY_NAME ('"'),
        "vi$select_buffer", vi$cmd_keys);
    DEFINE_KEY ("vi$_match_brackets", KEY_NAME ('%'),
        "vi$_match_brackets", vi$cmd_keys);
    DEFINE_KEY ("vi$_change_case", KEY_NAME ('~'),
        "vi$_change_case", vi$cmd_keys);
    DEFINE_KEY ("vi$region_left", KEY_NAME ('<'),
        "vi$region_left", vi$cmd_keys);
    DEFINE_KEY ("vi$region_right", KEY_NAME ('>'),
        "vi$region_right", vi$cmd_keys);
    DEFINE_KEY ("vi$_next_line", KEY_NAME ('+'), "vi$_next_line", vi$cmd_keys);
    DEFINE_KEY ("vi$do_macro('k^', 0)", KEY_NAME ('-'),
        "vi$do_macro('k^', 0)", vi$cmd_keys);
    DEFINE_KEY ("vi$_paragraph (-1)", KEY_NAME ('{'),
        "vi$_paragraph (-1)", vi$cmd_keys);
    DEFINE_KEY ("vi$_section (-1)", KEY_NAME ('['),
        "vi$_section (-1)", vi$cmd_keys);
    DEFINE_KEY ("vi$_begin_sentence", KEY_NAME ('('),
        "vi$_begin_sentence", vi$cmd_keys);
    DEFINE_KEY ("vi$_paragraph (1)", KEY_NAME ('}'),
        "vi$_paragraph (1)", vi$cmd_keys);
    DEFINE_KEY ("vi$_section (1)", KEY_NAME (']'),
        "vi$_section (1)", vi$cmd_keys);
    DEFINE_KEY ("vi$_end_sentence", KEY_NAME (')'),
        "vi$_end_sentence", vi$cmd_keys);
    DEFINE_KEY ("vi$insert_after", KEY_NAME ('a'),
        "vi$insert_after", vi$cmd_keys);
    DEFINE_KEY ("vi$do_macro('$a', 0)", KEY_NAME ('A'),
        "vi$do_macro('$a', 0)", vi$cmd_keys);
    DEFINE_KEY ("vi$_word_back", KEY_NAME ('b'),
        "vi$_word_back", vi$cmd_keys);
    DEFINE_KEY ("vi$_full_word_back", KEY_NAME ('B'),
        "vi$_full_word_back", vi$cmd_keys);
    DEFINE_KEY ("vi$_change", KEY_NAME ('c'),
        "vi$_change", vi$cmd_keys);
    DEFINE_KEY ("vi$do_macro ('c$', 0)", KEY_NAME ('C'),
        "vi$do_macro ('c$', 0)", vi$cmd_keys);
    DEFINE_KEY ("vi$_delete (0, -1)", KEY_NAME ('d'),
        "delete", vi$cmd_keys);
    DEFINE_KEY ("vi$_delete (KEY_NAME('$'), -1)", KEY_NAME ('D'),
        "delete_eol", vi$cmd_keys);
    DEFINE_KEY ("vi$_word_end", KEY_NAME ('e'),
        "vi$_word_end", vi$cmd_keys);
    DEFINE_KEY ("vi$_full_word_end", KEY_NAME ('E'),
        "vi$_full_word_end", vi$cmd_keys);
    DEFINE_KEY ("vi$_find_char (0)", KEY_NAME ('f'),
        "vi$_find_char (0)", vi$cmd_keys);
    DEFINE_KEY ("vi$_back_find_char (0)", KEY_NAME ('F'),
        "vi$_back_find_char (0)", vi$cmd_keys);
    DEFINE_KEY ("vi$go_to_line", KEY_NAME ('G'),
        "vi$go_to_line", vi$cmd_keys);
    DEFINE_KEY ("vi$move_left", KEY_NAME ('h'),
        "vi$move_left", vi$cmd_keys);
    DEFINE_KEY ("vi$home", KEY_NAME ('H'), "vi$home", vi$cmd_keys);
    DEFINE_KEY ("vi$insert_here", KEY_NAME ('i'),
        "vi$insert_here", vi$cmd_keys);
    DEFINE_KEY ("vi$insert_at_begin", KEY_NAME ('I'),
        "vi$insert_at_begin", vi$cmd_keys);
    DEFINE_KEY ("vi$move_down", KEY_NAME ('j'),
        "vi$move_down", vi$cmd_keys);
    DEFINE_KEY ("vi$_join_lines", KEY_NAME ('J'),
        "vi$_join_lines", vi$cmd_keys);
    DEFINE_KEY ("vi$move_up", KEY_NAME ('k'), "vi$move_up", vi$cmd_keys);
    DEFINE_KEY ("vi$move_right", KEY_NAME ('l'), "vi$move_right", vi$cmd_keys);
    DEFINE_KEY ("vi$last", KEY_NAME ('L'), "vi$last", vi$cmd_keys);
    DEFINE_KEY ("vi$_set_mark", KEY_NAME ('m'), "vi$_set_mark", vi$cmd_keys);
    DEFINE_KEY ("vi$middle", KEY_NAME ('M'), "vi$middle", vi$cmd_keys);
    DEFINE_KEY ("vi$_search_next(vi$last_search_dir)", KEY_NAME('n'),
        "vi$_search_next(vi$last_search_dir)", vi$cmd_keys);
    DEFINE_KEY ("vi$_search_next(-vi$last_search_dir)", KEY_NAME('N'),
        "vi$_search_next(-vi$last_search_dir)", vi$cmd_keys);
    DEFINE_KEY ("vi$open_below", KEY_NAME ('o'), "vi$open_below", vi$cmd_keys);
    DEFINE_KEY ("vi$open_here", KEY_NAME ('O'), "vi$open_here", vi$cmd_keys);
    DEFINE_KEY ("vi$put_here (VI$HERE, -1)", KEY_NAME ('P'),
        "vi$put_here (VI$HERE, -1)", vi$cmd_keys);
    DEFINE_KEY ("vi$put_after (-1)", KEY_NAME ('p'),
        "vi$put_after (-1)", vi$cmd_keys);
    DEFINE_KEY ("vi$_replace_char", KEY_NAME ('r'),
        "vi$_replace_char", vi$cmd_keys);
    DEFINE_KEY ("vi$_replace_str", KEY_NAME ('R'),
        "vi$_replace_str", vi$cmd_keys);
    DEFINE_KEY ("vi$do_macro('cl', 0)", KEY_NAME ('s'),
        "vi$do_macro('cl', 0)", vi$cmd_keys);
    DEFINE_KEY ("vi$_big_s", KEY_NAME ('S'), "vi$_big_s", vi$cmd_keys);
    DEFINE_KEY ("vi$_to_char (0)", KEY_NAME ('t'),
        "vi$_to_char (0)", vi$cmd_keys);
    DEFINE_KEY ("vi$_back_to_char (0)", KEY_NAME ('T'),
        "vi$_back_to_char (0)", vi$cmd_keys);
    DEFINE_KEY ("vi$perform_undo", KEY_NAME ('u'),
        "vi$perform_undo", vi$cmd_keys);
    DEFINE_KEY ("vi$undo_one_line", KEY_NAME ('U'),
        "vi$undo_one_line", vi$cmd_keys);
    DEFINE_KEY ("vi$_word_forward", KEY_NAME ('w'),
        "vi$_word_forward", vi$cmd_keys);
    DEFINE_KEY ("vi$_full_word_forward", KEY_NAME ('W'),
        "vi$_full_word_forward", vi$cmd_keys);
    DEFINE_KEY ("vi$do_macro ('dl', 0)", KEY_NAME ('x'),
        "vi$do_macro ('dl', 0)", vi$cmd_keys);
    DEFINE_KEY ("vi$do_macro ('dh', 0)", KEY_NAME ('X'),
        "vi$do_macro ('dh', 0)", vi$cmd_keys);
    DEFINE_KEY ("vi$_yank (0, -1)", KEY_NAME ('y'),
        "vi$_yank (0, -1)", vi$cmd_keys);
    DEFINE_KEY ("vi$_yank (KEY_NAME('y'), -1)", KEY_NAME ('Y'),
        "vi$_yank (KEY_NAME('y'), -1)", vi$cmd_keys);
    DEFINE_KEY ("vi$_ZZ (0)", KEY_NAME ('Z'), "vi$_ZZ", vi$cmd_keys);
    DEFINE_KEY ("vi$_z_move", KEY_NAME ('z'), "vi$_z_move", vi$cmd_keys);
    DEFINE_KEY ("vi$_to_column", KEY_NAME ('|'),
        "vi$_to_column", vi$cmd_keys);
    DEFINE_KEY ("vi$_next_line", RET_KEY, "vi$_next_line", vi$cmd_keys);
    DEFINE_KEY ("vi$repeat_count", KEY_NAME ('0'),
        "vi$repeat_count", vi$cmd_keys);
    DEFINE_KEY ("vi$repeat_count", KEY_NAME ('1'),
        "vi$repeat_count", vi$cmd_keys);
    DEFINE_KEY ("vi$repeat_count", KEY_NAME ('2'),
        "vi$repeat_count", vi$cmd_keys);
    DEFINE_KEY ("vi$repeat_count", KEY_NAME ('3'),
        "vi$repeat_count", vi$cmd_keys);
    DEFINE_KEY ("vi$repeat_count", KEY_NAME ('4'),
        "vi$repeat_count", vi$cmd_keys);
    DEFINE_KEY ("vi$repeat_count", KEY_NAME ('5'),
        "vi$repeat_count", vi$cmd_keys);
    DEFINE_KEY ("vi$repeat_count", KEY_NAME ('6'),
        "vi$repeat_count", vi$cmd_keys);
    DEFINE_KEY ("vi$repeat_count", KEY_NAME ('7'),
        "vi$repeat_count", vi$cmd_keys);
    DEFINE_KEY ("vi$repeat_count", KEY_NAME ('8'),
        "vi$repeat_count", vi$cmd_keys);
    DEFINE_KEY ("vi$repeat_count", KEY_NAME ('9'),
        "vi$repeat_count", vi$cmd_keys);
    DEFINE_KEY ("vi$move_left", F12, "vi$move_left", vi$cmd_keys);
    DEFINE_KEY ("vi$move_left", LEFT, "vi$move_left", vi$cmd_keys);
    DEFINE_KEY ("vi$move_right", RIGHT, "vi$move_right", vi$cmd_keys);
    DEFINE_KEY ("vi$move_up", UP, "vi$move_up", vi$cmd_keys);
    DEFINE_KEY ("vi$move_down", DOWN, "vi$move_down", vi$cmd_keys);
    DEFINE_KEY ("vi$move_left", DEL_KEY, "vi$move_left", vi$cmd_keys);
    DEFINE_KEY ("vi$move_right", KEY_NAME (' '), "vi$move_right", vi$cmd_keys);
    DEFINE_KEY ("vi$ex_mode", DO, "vi$ex_mode", vi$cmd_keys);
    DEFINE_KEY ("vi$ex_mode", KEY_NAME(':'), "vi$ex_mode", vi$cmd_keys);
    DEFINE_KEY ("vi$_repeat_torf_back", KEY_NAME(','),
        "vi$_repeat_torf_back", vi$cmd_keys);
    DEFINE_KEY ("vi$_repeat_torf", KEY_NAME(';'),
        "vi$_repeat_torf", vi$cmd_keys);
    DEFINE_KEY ("vi$_search(1)", KEY_NAME('/'),
        "vi$_search(1)", vi$cmd_keys);
    DEFINE_KEY ("vi$_search(-1)", KEY_NAME('?'),
        "vi$_search(-1)", vi$cmd_keys);
    DEFINE_KEY ("vi$_eol", KEY_NAME('$'), "vi$_eol", vi$cmd_keys);
    DEFINE_KEY ("vi$_bol (1)", KEY_NAME('^'), "vi$_bol (1)", vi$cmd_keys);
    DEFINE_KEY ("vi$do_macro(vi$last_keys, 0)", KEY_NAME('.'),
        "vi$do_macro(vi$last_keys, 0)", vi$cmd_keys);
    DEFINE_KEY ("vi$macro", KEY_NAME('@'), "vi$macro", vi$cmd_keys);
    DEFINE_KEY ("vi$repeat_subs", KEY_NAME('&'), "vi$repeat_subs", vi$cmd_keys);
    DEFINE_KEY ("vi$region_filter", KEY_NAME('!'),
        "vi$region_filter", vi$cmd_keys);

    ! Define all of the insert-mode keys

    vi$edit_keys := CREATE_KEY_MAP ("e_keys");

    ! These maps are not really active, but the comment fields are used
    ! during the execution of "vi$line_edit".

    DEFINE_KEY ("vi$_dummy", F12, "bs", vi$edit_keys);
    DEFINE_KEY ("vi$_dummy", PF1, "escape", vi$edit_keys);
    DEFINE_KEY ("vi$_dummy", F11, "escape", vi$edit_keys);
    DEFINE_KEY ("vi$_dummy", KEY_NAME (ASCII(27)), "escape", vi$edit_keys);
    DEFINE_KEY ("vi$_dummy", KEY_NAME (ASCII(0)), "reinsert", vi$edit_keys);
    DEFINE_KEY ("vi$_dummy", RET_KEY, "eol", vi$edit_keys);
    DEFINE_KEY ("vi$_dummy", TAB_KEY, "tab", vi$edit_keys);
    DEFINE_KEY ("vi$_dummy", CTRL_D_KEY, "detab", vi$edit_keys);
    DEFINE_KEY ("vi$_dummy", CTRL_H_KEY, "bs", vi$edit_keys);
    DEFINE_KEY ("vi$_dummy", CTRL_T_KEY, "entab", vi$edit_keys);
    DEFINE_KEY ("vi$_dummy", CTRL_V_KEY, "vquote", vi$edit_keys);
    DEFINE_KEY ("vi$_dummy", CTRL_W_KEY, "bword", vi$edit_keys);
    DEFINE_KEY ("vi$_dummy", DEL_KEY, "bs", vi$edit_keys);

    ! Define all of the delete mode mappings

    vi$move_keys := CREATE_KEY_MAP ("m_keys");

    DEFINE_KEY ("vi$downline(1)", RET_KEY, "vi$downline(1)", vi$move_keys);
    DEFINE_KEY ("vi$right", KEY_NAME (" "), "vi$right", vi$move_keys);
    DEFINE_KEY ("vi$eol", KEY_NAME("$"), "vi$eol", vi$move_keys);
    DEFINE_KEY ("vi$to_marker", KEY_NAME ("'"), "vi$to_marker", vi$move_keys);
    DEFINE_KEY ("vi$to_marker", KEY_NAME ("`"), "vi$to_marker", vi$move_keys);
    DEFINE_KEY ("vi$first_no_space (1)", KEY_NAME("^"),
        "vi$first_no_space (1)", vi$move_keys);
    DEFINE_KEY ("vi$fol", KEY_NAME("0"), "vi$fol", vi$move_keys);
    DEFINE_KEY ("vi$upline", KEY_NAME ("-"), "vi$upline", vi$move_keys);
    DEFINE_KEY ("vi$downline(1)", KEY_NAME ("+"),
        "vi$downline(1)", vi$move_keys);
    DEFINE_KEY ("vi$search(1)", KEY_NAME ("/"), "vi$search(1)", vi$move_keys);
    DEFINE_KEY ("vi$search(-1)", KEY_NAME ("?"), "vi$search(-1)", vi$move_keys);
    DEFINE_KEY ("vi$match_brackets", KEY_NAME ("%"),
        "vi$match_brackets", vi$move_keys);
    DEFINE_KEY ("vi$full_word_move(-1)", KEY_NAME ("B"),
        "vi$full_word_move(-1)", vi$move_keys);
    DEFINE_KEY ("vi$word_move(-1)", KEY_NAME ("b"),
        "vi$word_move(-1)", vi$move_keys);
    DEFINE_KEY ("vi$_dummy", KEY_NAME ("c"),
        "vi$_dummy", vi$move_keys);
    DEFINE_KEY ("vi$word_end", KEY_NAME ("e"), "vi$word_end", vi$move_keys);
    DEFINE_KEY ("vi$full_word_end", KEY_NAME ("E"),
        "vi$full_word_end", vi$move_keys);
    DEFINE_KEY ("vi$back_find_char(0)", KEY_NAME ("F"),
        "vi$back_find_char(0)", vi$move_keys);
    DEFINE_KEY ("vi$find_char(0)", KEY_NAME ("f"),
        "vi$find_char(0)", vi$move_keys);
    DEFINE_KEY ("vi$to_line (vi$active_count)", KEY_NAME ("G"),
            "vi$to_line (vi$active_count)", vi$move_keys);
    DEFINE_KEY ("vi$to_home", KEY_NAME ("H"), "vi$to_home", vi$move_keys);
    DEFINE_KEY ("vi$left", KEY_NAME ("h"), "vi$left", vi$move_keys);
    DEFINE_KEY ("vi$downline(1)", KEY_NAME ("j"),
        "vi$downline(1)", vi$move_keys);
    DEFINE_KEY ("vi$upline", KEY_NAME ("k"), "vi$upline", vi$move_keys);
    DEFINE_KEY ("vi$right", KEY_NAME ("l"), "vi$right", vi$move_keys);
    DEFINE_KEY ("vi$to_middle", KEY_NAME ("M"), "vi$to_middle", vi$move_keys);
    DEFINE_KEY ("vi$to_last", KEY_NAME ("L"), "vi$to_last", vi$move_keys);
    DEFINE_KEY ("vi$search_next(vi$last_search_dir)", KEY_NAME('n'),
            "vi$search_next(vi$last_search_dir)", vi$move_keys);
    DEFINE_KEY ("vi$search_next(-vi$last_search_dir)", KEY_NAME('N'),
            "vi$search_next(-vi$last_search_dir)", vi$move_keys);
    DEFINE_KEY ("vi$to_char(0)", KEY_NAME ("t"), "vi$to_char(0)", vi$move_keys);
    DEFINE_KEY ("vi$back_to_char(0)", KEY_NAME ("T"),
        "vi$back_to_char(0)", vi$move_keys);
    DEFINE_KEY ("vi$word_move(1)", KEY_NAME ("w"),
        "vi$word_move(1)", vi$move_keys);
    DEFINE_KEY ("vi$full_word_move(1)", KEY_NAME ("W"),
        "vi$full_word_move(1)", vi$move_keys);
    DEFINE_KEY ("vi$downline", KEY_NAME(">"), "vi$downline(0)", vi$move_keys);
    DEFINE_KEY ("vi$downline", KEY_NAME("<"), "vi$downline(0)", vi$move_keys);
    DEFINE_KEY ("vi$downline(0)", KEY_NAME("d"),
        "vi$downline(0)", vi$move_keys);
    DEFINE_KEY ("vi$downline(0)", KEY_NAME("y"),
        "vi$downline(0)", vi$move_keys);
    DEFINE_KEY ("vi$downline(0)", KEY_NAME("!"),
        "vi$downline(0)", vi$move_keys);
    DEFINE_KEY ("vi$to_column", KEY_NAME ('|'), "vi$to_column", vi$move_keys);
    DEFINE_KEY ("vi$repeat_torf", KEY_NAME(';'),
        "vi$repeat_torf", vi$move_keys);
    DEFINE_KEY ("vi$repeat_torf_back", KEY_NAME(','),
        "vi$repeat_torf_back", vi$move_keys);
    DEFINE_KEY ("vi$paragraph (1)", KEY_NAME ('}'),
        "vi$paragraph (1)", vi$move_keys);
    DEFINE_KEY ("vi$section (1)", KEY_NAME (']'),
        "vi$section (1)", vi$move_keys);
    DEFINE_KEY ("vi$end_sentence", KEY_NAME (')'),
        "vi$end_sentence", vi$move_keys);
    DEFINE_KEY ("vi$paragraph (-1)", KEY_NAME ('{'),
        "vi$paragraph (-1)", vi$move_keys);
    DEFINE_KEY ("vi$section (-1)", KEY_NAME ('['),
        "vi$section (-1)", vi$move_keys);
    DEFINE_KEY ("vi$begin_sentence", KEY_NAME ('('),
        "vi$begin_sentence", vi$move_keys);

ENDPROCEDURE;

!
!   This procedure is called by the CTRL-` keystroke to swap the current
!   buffer with the previous one.
!
PROCEDURE vi$move_prev_buf (bang)
    LOCAL
        outf,
        buf;

    IF (vi$last_mapped = 0) OR
                            (GET_INFO (vi$last_mapped, "TYPE") <> BUFFER) THEN
        vi$info ("No alternate buffer!");
        RETURN;
    ENDIF;
    buf := vi$last_mapped;
    IF (NOT bang) AND (vi$check_auto_write) THEN
        RETURN;
    ENDIF;
    MAP (CURRENT_WINDOW, buf);
    vi$set_status_line (CURRENT_WINDOW);
    vi$pos_in_middle (MARK (NONE));
    outf := GET_INFO (CURRENT_BUFFER, "OUTPUT_FILE");
    IF outf = 0 THEN
        outf := GET_INFO (CURRENT_BUFFER, "NAME");
    ENDIF;
    vi$info ('"'+outf+'"');
ENDPROCEDURE;

!
!   This procedure is used to return the current mark in the buffer, after
!   moving to the mark passed.  This routine is used by the majority of the
!   procedures that perform movement, and then return the location they
!   stopped at, but do not change the current location in the buffer.
!
PROCEDURE vi$retpos (pos)
    LOCAL
        endpos;

    ON_ERROR
    ENDON_ERROR

    endpos := MARK (NONE);

    ! If the marker is zero, then there is no way to position to it.

    IF (pos <> 0) THEN
        POSITION (pos);
    ENDIF;
    RETURN (endpos);
ENDPROCEDURE;

!
!   This procedure is called whenever ESCAPE is pressed while in command mode.
!   The current active count should be zeroed, and possibly other things.
!
PROCEDURE vi$on_escape
    vi$active_count := 0;
    vi$beep;
ENDPROCEDURE;

!
!
!
!
PROCEDURE vi$do_help (init_command)
    LOCAL
        buf,
        win;

    buf := CURRENT_BUFFER;
    MAP (info_window, show_buffer);
    vi$pasthru_off;
    HELP_TEXT ("vi$root:[doc]vi.hlb","VI " + init_command,ON,show_buffer);
    vi$pasthru_on;
    UNMAP (info_window);
    POSITION (buf);
ENDPROCEDURE;

!
!   This is the main processing loop, this function should never be exited.
!   This means that the TPU "ABORT" builtin can not be used anywhere.
!
PROCEDURE vi$command_mode (l_key)
    LOCAL
        key,
        last_len,
        win,
        cwin,
        bol,
        pos,
        repos,
        prog;

    IF (NOT vi$min_update) THEN
        UPDATE (CURRENT_WINDOW);
    ENDIF;

    ! Get the key to process (last key pressed).

    key := l_key;

    ! Save the key for '.' repeats.

    vi$push_a_key (key);

    ! Save the key so that vi$last_key behaves as LAST_KEY would.

    vi$last_key := key;

    ! Initialize macro level counter.

    vi$m_level := 0;

    ! Set up so that 'U' works.  Note that there is a problem with U after u
    ! when a :s or & was the last thing done.  The vi$undo_line mark is moved
    ! from the beginning of the line to the end of the line by the undo code.
    ! The fix is not obvious at this point.

    pos := MARK (NONE);
    POSITION (LINE_BEGIN);
    bol := MARK (NONE);
    repos := 0;
    IF (GET_INFO (vi$undo_line_mark, "TYPE") = MARKER) THEN
        POSITION (vi$undo_line_mark);
        POSITION (LINE_BEGIN);
        IF (bol <> MARK (NONE)) THEN
            repos := 1;
        ENDIF;
    ELSE
        repos := 1;
    ENDIF;

    IF (repos) THEN
        POSITION (bol);
        vi$move_horizontal (1);
        vi$undo_line_mark := MARK (NONE);
        vi$undo_line_str  := vi$current_line;
    ENDIF;
    POSITION (pos);

    ! Get the key's program.

    prog := LOOKUP_KEY (KEY_NAME (key), PROGRAM, vi$cmd_keys);

    ! If prog = 0 then key is undefined, so ignore it.

    IF (prog <> 0) THEN

        IF (vi$did_mess) THEN
            vi$did_mess := 0;
            MESSAGE ("");
        ENDIF;

        vi$command_type := VI$OTHER_TYPE;

        ! Otherwise, do the program for that key.

        EXECUTE (prog);

        ! If this is a key that can change the buffer, then
        ! save the sequence of keys so that '.' causes them to
        ! be repeated.

        IF (INDEX (vi$dot_keys, ASCII (key)) <> 0) THEN
            vi$copy_keys (vi$last_keys, vi$cur_keys);
        ENDIF;
    ELSE

        ! Zap the repeat count so that next command doesn't repeat.

        vi$active_count := 0;
        vi$beep;
    ENDIF;

    ! Make sure we are not past end of line or at EOB.

    vi$check_rmarg;

    IF (INDEX ("0123456789", ASCII (key)) = 0) OR (vi$active_count = 0) THEN
        ERASE (vi$cur_keys);
    ENDIF;
ENDPROCEDURE;

!
!   Perform a macro command string that is either a string, or a buffer
!   containing KEY_NAME values (as in execution of the '.' command).
!
PROCEDURE vi$do_macro (commands, save_buffer)
    LOCAL
        typ,
        old_global,
        pos,
        key,
        prog;

    IF (vi$m_level > 30) THEN
        vi$info ("Infinite loop detected in key macro sequence!");
        RETURN;
    ENDIF;
    vi$m_level := vi$m_level + 1;
    vi$new_offset := 1;

    pos := MARK (NONE);

    ! If "commands" is a string then we must generate a buffer to
    ! place the commands into so that they can be read with "vi$read_a_key".

    IF (GET_INFO (commands, "TYPE") = STRING) THEN
        IF (vi$tmp_key_buf = 0) THEN
            vi$tmp_key_buf := vi$init_buffer ("$$tmp_key_buf$$", "");
        ELSE
            ERASE (vi$tmp_key_buf);
        ENDIF;

        IF vi$tmp_key_buf = 0 THEN
            vi$info ("Can't do key macro: "+commands);
            RETURN;
        ENDIF;

        vi$str_to_keybuf (commands, vi$tmp_key_buf);
        vi$insert_macro_keys (vi$tmp_key_buf);
    ELSE
        vi$insert_macro_keys (commands);
    ENDIF;

    POSITION (pos);

    IF vi$undo_map THEN
        old_global := vi$in_global;
        vi$in_global := 0;
        IF (save_buffer AND (NOT old_global)) THEN
            vi$save_for_undo (CURRENT_BUFFER, VI$LINE_MODE, 1);
            vi$in_global := 1;
        ELSE
            IF old_global THEN
                vi$in_global := 1;
            ENDIF;
        ENDIF;
    ENDIF;

    LOOP

        ! Stop when all levels of macro are completed.

        EXITIF (vi$key_buf = 0);
        key := vi$read_a_key;

        ! Get that keys program.

        prog := LOOKUP_KEY (key, PROGRAM, vi$cmd_keys);

        ! If prog = 0 then key is undefined, so ignore it.

        IF (prog <> 0) THEN

            ! Otherwise, do the program for that key.

            EXECUTE (prog);
        ELSE
            vi$info ("Key '"+ASCII(key)+"' is undefined!");
            vi$abort (0);
        ENDIF;
    ENDLOOP;

    IF (vi$in_global) THEN
        vi$undo_start := BEGINNING_OF (CURRENT_BUFFER);
        vi$undo_end := END_OF (CURRENT_BUFFER);
        vi$in_global := old_global;
    ENDIF;
ENDPROCEDURE;

!
!   This function handles the macro capability that allows the text in
!   a named or numbered buffer to be executed as a sequence of commands
!   by type an '@' and then the letter or number indicating the buffer to
!   execute the contents of.
!
PROCEDURE vi$macro
    LOCAL
        line,
        buf_name,
        bpos,
        cnt,
        ccnt,
        pos,
        buf,
        mode,
        ch;

    IF (vi$m_level > 30) THEN
        vi$info ("Infinite loop detected in macro key sequence!");
        RETURN;
    ENDIF;
    vi$m_level := vi$m_level + 1;

    ch := vi$read_a_key;

    IF (INDEX ("123456789", ASCII(ch)) <> 0) THEN

        ! Selected a deletion buffer.

        buf_name := "vi$del_buf_"+ASCII(ch);
    ELSE
        IF (INDEX (vi$_letter_chars, ASCII(ch)) <> 0) THEN

            ! Selected a named buffer.

            IF (INDEX (vi$_upper_chars, ASCII(ch)) <> 0) THEN
                ch := SUBSTR (vi$_lower_chars,
                            INDEX (vi$_upper_chars, ASCII(ch)), 1);
            ENDIF;

            buf_name := "vi$ins_buf_"+ASCII(ch);
        ELSE
            vi$info ("Invalid buffer!");
            RETURN;
        ENDIF;
    ENDIF;

    vi$global_var := 0;
    EXECUTE (COMPILE ("vi$global_var := "+buf_name+";"));
    buf := vi$global_var;
    IF (buf = 0) THEN
        vi$info ("There is no text in that buffer!");
        RETURN;
    ENDIF;

    pos := MARK (NONE);
    POSITION (BEGINNING_OF (buf));
a    !  Get and skip the buffer mode indicator.

    mode := INT (vi$current_line);
    MOVE_VERTICAL (1);

    ! Get the number of lines to do.

    cnt := GET_INFO (CURRENT_BUFFER, "RECORD_COUNT") - 2;
    ccnt := 0;

    LOOP
        line := vi$current_line;

        IF (ccnt = cnt) THEN
            IF mode = VI$LINE_MODE THEN
                line := line + ASCII (13);
            ENDIF;
        ELSE
            line := line + ASCII (13);
        ENDIF;

        ccnt := ccnt + 1;
        bpos := MARK (NONE);
        POSITION (pos);
        vi$do_macro (line, 1);

        EXITIF (ccnt = cnt);

        pos := MARK (NONE);
        POSITION (bpos);
        MOVE_VERTICAL (1);
    ENDLOOP;
ENDPROCEDURE;

!
!   This procedure handles the operation of the U command.  U undoes all
!   changes performed on a line, providing the cursor has not left that
!   line.
!
PROCEDURE vi$undo_one_line
    LOCAL
        nstr,
        npos,
        repos,
        pos;

    pos := MARK (NONE);
    POSITION (LINE_BEGIN);
    npos := MARK (NONE);
    repos := 1;
    IF (GET_INFO (vi$undo_line_mark, "TYPE") = MARKER) THEN
        POSITION (vi$undo_line_mark);
        POSITION (LINE_BEGIN);
        IF (npos <> MARK (NONE)) THEN
            repos := 0;
        ENDIF;
    ELSE
        repos := 0;
    ENDIF;

    IF (repos) THEN
        nstr := vi$current_line;
        ERASE_LINE;
        COPY_TEXT (vi$undo_line_str);
        SPLIT_LINE;
        MOVE_VERTICAL (-1);
        vi$kill_undo;
        vi$undo_end := 0;
        vi$undo_line_str := nstr;
        vi$undo_line_mark := MARK (NONE);
    ELSE
        vi$undo_line_mark := 0;
    ENDIF;
ENDPROCEDURE;

!
!   This procedure takes a range or string of data, and squirrels it away
!   to be restored when an undo operation is performed.
!
PROCEDURE vi$save_for_undo (undo_data, btype, save_line_info)
    LOCAL
        pos;

    pos := MARK (NONE);

    IF (vi$in_global) THEN
        RETURN;
    ENDIF;

    IF (save_line_info) THEN
        vi$undo_line := vi$cur_line_no;
        vi$undo_offset := CURRENT_OFFSET;
    ELSE
        vi$undo_line := 0;
    ENDIF;

    IF vi$undo_buffer = 0 THEN
        vi$undo_buffer := vi$init_buffer ("$$vi$undo_buffer$$", "");
        IF vi$undo_buffer = 0 THEN
            vi$info ("Error creating undo buffer!");
            RETURN;
        ENDIF;
    ENDIF;

    vi$type2buf (STR (btype), vi$undo_buffer);
    vi$cp2buf (undo_data, vi$undo_buffer);

    vi$undo_valid := 1;

    POSITION (pos);
ENDPROCEDURE;

!
!   Disallow the data last saved with vi$save_for_undo() from being restored
!   during an undo operation.
!
PROCEDURE vi$kill_undo
    IF (NOT vi$in_global) THEN
        vi$undo_valid := 0;
        vi$undo_line := 0;
    ENDIF;
ENDPROCEDURE;

!
!   Perform the operation of undoing the last change.  This operation is
!   actually comprised of 3 separate operations.  The first operation is
!   to restore any text saved by vi$save_for_undo().  The next operation is
!   to vi$save_for_undo() any text delimited by vi$undo_start and vi$undo_end.
!   vi$undo_start marks the location where step 1 is performed.  vi$undo_end
!   determines whether or not there is text to save and then delete.  If
!   it has a non-zero value, then the range delimited by it and vi$undo_start
!   is saved (using vi$save_for_undo()), and then deleted.
!
PROCEDURE vi$perform_undo
    LOCAL
        done_pos,
        cbuf,
        pos,
        undo_line,
        undo_offset,
        cline,
        coff,
        btype,
        errno,
        undo_mode,
        saved_text,
        new_start,
        new_end,
        era_range;

    vi$new_offset := 1;
    new_start := 0;
    cline := vi$cur_line_no;
    coff := CURRENT_OFFSET;
    undo_line := vi$undo_line;
    undo_offset := vi$undo_offset;

    IF (GET_INFO (vi$undo_start, "BUFFER") <> CURRENT_BUFFER) OR
            ((NOT vi$undo_valid) AND (vi$undo_end = 0)) THEN
        vi$beep;
        RETURN;
    ENDIF;

    IF (vi$undo_valid) THEN
        cbuf := CURRENT_BUFFER;

        POSITION (BEGINNING_OF (vi$undo_buffer));
        undo_mode := INT (vi$current_line);
        ERASE_LINE;

        POSITION (vi$undo_start);

        IF MARK (NONE) = BEGINNING_OF (CURRENT_BUFFER) THEN
            new_start := 1;
        ELSE
            MOVE_HORIZONTAL (-1);
            new_start := MARK (NONE);
            MOVE_HORIZONTAL (1);
        ENDIF;

        SET (INSERT, CURRENT_BUFFER);
        COPY_TEXT (vi$undo_buffer);

        APPEND_LINE;
        MOVE_HORIZONTAL (-1);
        new_end := MARK (NONE);

        POSITION (BEGINNING_OF (vi$undo_buffer));
        COPY_TEXT (STR (undo_mode));
        SPLIT_LINE;

        POSITION (new_end);
    ENDIF;

    ! Use flag to determine whether or not to kill buffer contents.

    saved_text := 0;

    IF (vi$undo_start <> 0) AND (vi$undo_end <> 0) THEN
        saved_text := 1;
        pos := MARK (NONE);

        POSITION (vi$undo_end);
        IF (CURRENT_OFFSET <> 0) THEN
            btype := VI$IN_LINE_MODE;
        ELSE
            btype := VI$LINE_MODE;
        ENDIF;

        POSITION (pos);

        era_range := CREATE_RANGE (vi$undo_start, vi$undo_end, NONE);

        IF era_range <> 0 THEN
            POSITION (vi$undo_start);
            vi$save_for_undo (era_range, btype, 1);
            ERASE (era_range);
        ENDIF;
    ENDIF;

    IF (GET_INFO (new_start, "TYPE") <> INTEGER) THEN
        POSITION (new_start);
        vi$move_horizontal (1);
        vi$undo_start := MARK (NONE);
        vi$undo_end := new_end;
    ELSE
        IF new_start = 1 THEN
            vi$undo_start := BEGINNING_OF (CURRENT_BUFFER);
            vi$undo_end := new_end;
        ELSE
            vi$undo_end := 0;
        ENDIF;
    ENDIF;

    IF (saved_text = 0) THEN
        vi$kill_undo;
    ENDIF;

    IF (vi$undo_start <> 0) THEN
        POSITION (vi$undo_start);
    ENDIF;

    ! If undoing a macro then reposition to the place where we started.

    IF (undo_line <> 0) THEN
        vi$move_to_line (undo_line);
        vi$move_horizontal (undo_offset);
        vi$pos_in_middle (MARK (NONE));
        vi$undo_line := undo_line;
        vi$undo_offset := undo_offset;
    ENDIF;
ENDPROCEDURE;

!
!   This function performs the operations associated with the ^Y and ^E
!   keystrokes.
!
PROCEDURE vi$pull_push_line (direction)

    LOCAL
        currow,
        limit,
        n_lines,
        pos;

    ON_ERROR
        ! Ignore "ATTEMPT to move past TOP/BOTTOM of buffer"
    ENDON_ERROR;

    ! Get the number of lines to move.

    n_lines := vi$cur_active_count * direction;

    ! Mark the destination position for the case where we are at the top or
    ! bottom of the window.

    MOVE_VERTICAL (n_lines);
    pos := MARK (NONE);

    ! Return to the old position.

    MOVE_VERTICAL (-n_lines);

    ! Get the current screen row

    currow := GET_INFO (CURRENT_WINDOW, "CURRENT_ROW");

    ! Get the proper border value based on the direction.

    IF (n_lines < 0) THEN
        limit := GET_INFO (CURRENT_WINDOW, "VISIBLE_BOTTOM");
    ELSE
        limit := GET_INFO (CURRENT_WINDOW, "VISIBLE_TOP");
    ENDIF;

    ! If we are NOT at the top or bottom, then the current row is the dest.

    IF (n_lines > 0) THEN
        IF (currow - limit) >= n_lines THEN
            pos := MARK (NONE);
        ENDIF;
    ELSE
        IF vi$abs (currow - limit) >= vi$abs (n_lines) THEN
            pos := MARK (NONE);
        ENDIF;
    ENDIF;

    ! Scroll the window.  If the scroll fails, then move the cursor.

    POSITION (LINE_BEGIN);
    IF (SCROLL (CURRENT_WINDOW, n_lines) <> n_lines) THEN
        POSITION (pos);
        MOVE_VERTICAL (n_lines);
    ELSE

        ! Otherwise the position we wanted is visible, so move there.

        POSITION (pos);
        IF (n_lines < 0) AND ((currow - limit) > n_lines) THEN
            MOVE_VERTICAL (limit - currow);
        ENDIF;
    ENDIF;
ENDPROCEDURE;

!
!   Move to the location indicated by a '|' command.
!
PROCEDURE vi$_to_column
    vi$beep_position (vi$to_column, 0, 1);
ENDPROCEDURE;

!
!   Return the marker indicating the column selected by vi$active_count
!
PROCEDURE vi$to_column
    LOCAL
        pos,
        act_count;

    act_count := vi$cur_active_count;
    pos := MARK (NONE);

    IF (act_count <= LENGTH (vi$current_line)) THEN
        pos := MARK (NONE);
        MOVE_HORIZONTAL (act_count - CURRENT_OFFSET - 1);
        RETURN (vi$retpos (pos));
    ENDIF;
    RETURN (0);
ENDPROCEDURE;

!
!   Perform the operations associated with 'ZZ' (write and exit) command.
!
PROCEDURE vi$_ZZ (rkey)
     LOCAL
        prcnam,
        ans,
        cur_buf,
        read_z,
        buf,
        errno;

    ON_ERROR
        errno := ERROR;
        IF errno = TPU$_NOPARENT THEN

            !  Use vi$quit so that buffers not written will not be written
            !  automatically.

            vi$quit;
        ENDIF;
    ENDON_ERROR;

    read_z := rkey;

    IF (read_z <> KEY_NAME ('Z')) THEN
        read_z := vi$read_a_key;
    ENDIF;

    IF (read_z = KEY_NAME ('Z')) THEN
        cur_buf := CURRENT_BUFFER;

        IF (GET_INFO (cur_buf, "MODIFIED")) AND
                            (GET_INFO (cur_buf, "SYSTEM") = 0) THEN

            IF (vi$can_write (cur_buf)) THEN
                IF (GET_INFO (cur_buf, "NO_WRITE") = 0) THEN
                    vi$info ("Writing out """+GET_INFO (cur_buf, "NAME")+"""");
                    WRITE_FILE (cur_buf);
                ENDIF;
            ELSE
                RETURN;
            ENDIF;
        ENDIF;

        buf := GET_INFO (BUFFERS, "FIRST");
        LOOP
            EXITIF (buf = 0);
            IF (GET_INFO (buf, "MODIFIED")) AND
                                (GET_INFO (buf, "SYSTEM") = 0) THEN

                ans := vi$read_line ("Write """+GET_INFO (buf, "NAME")+"""? ");

                CHANGE_CASE (ans, LOWER);
                IF SUBSTR (ans, 1, 1) = "y" THEN
                    IF (vi$can_write (buf)) THEN
                        IF (GET_INFO (buf, "NO_WRITE") = 0) THEN
                            vi$info ("Writing out """+
                                                GET_INFO (buf, "NAME")+"""");
                            WRITE_FILE (buf);
                        ENDIF;
                    ELSE
                        RETURN;
                    ENDIF;
                ENDIF;
            ENDIF;
            buf := GET_INFO (BUFFERS, "NEXT");
        ENDLOOP;

        IF (vi$get_attach_parm ("TPU$NOSUBPROC") = " ") THEN
            prcnam := vi$get_attach_parm ("TPU$ATTACH_NAME");
            vi$pasthru_off;
            IF (prcnam = " ") THEN
                ATTACH;
            ELSE
                ATTACH (prcnam);
            ENDIF;
            vi$pasthru_on;
            vi$process_args;
        ELSE
            vi$do_quit ("q", "q");
        ENDIF;
    ENDIF;

    vi$kill_undo;
    vi$undo_end := 0;
    vi$active_count := 0;
ENDPROCEDURE;

!
!   Process the job logical names that are used to pass parameters between
!   the parent process and the editor.
!
PROCEDURE vi$process_args

    LOCAL
        buf,
        bufn,
        errno,
        startup_cmd,
        new_output,
        find_text,
        new_lineno,
        input_file;

    ON_ERROR

        errno := ERROR;

        SET (SUCCESS, ON);
        vi$system_message (errno);
        RETURN;

    ENDON_ERROR;

    startup_cmd := vi$get_attach_parm ("TPU$NEWCMD");

    IF startup_cmd = " " THEN
        input_file := vi$get_attach_parm ("TPU$ARGS");

        IF (input_file <> " ") THEN
            new_output := vi$get_attach_parm ("TPU$OUTPUT");

            !  When a file is specified, and a new output file is also
            !  specified, then we will attempt to erase any existing
            !  buffer's contents so that MAIL will actually be able to
            !  be used over and over during an editor's life.

            IF (new_output <> " ") THEN
                bufn := FILE_PARSE (input_file,"","",NAME) +
                        FILE_PARSE (input_file,"","",TYPE);
                buf := vi$find_buffer_by_name (bufn);
                IF buf <> 0 THEN
                    IF (GET_INFO (buf, "MODIFIED") = 0) OR
                                        GET_INFO (buf, "NO_WRITE") THEN
                        ERASE (buf);
                    ELSE
                        vi$info (
                "Buffer is modified, original contents not destroyed!");
                    ENDIF;
                ENDIF;
            ENDIF;

            vi$get_file (input_file);

            IF (new_output <> " ") THEN
                SET (OUTPUT_FILE, CURRENT_BUFFER, new_output);
                vi$status_lines (CURRENT_BUFFER);

                !  Set the buffer to be modified so that the file will
                !  be written on exit.

                SPLIT_LINE;
                APPEND_LINE;
            ENDIF;
        ENDIF;
    ELSE
        new_output := vi$get_attach_parm ("TPU$OUTPUT");
        IF (new_output <> " ") THEN
            SET (OUTPUT_FILE, CURRENT_BUFFER, new_output);
            vi$status_lines (CURRENT_BUFFER);

            !  Set the buffer to be modified so that the file will
            !  be written on exit.

            SPLIT_LINE;
            APPEND_LINE;
        ENDIF;

        vi$do_cmd_line (startup_cmd);
    ENDIF;

    new_lineno := vi$get_attach_parm ("TPU$LINE");

    IF (new_lineno = " ") THEN
        find_text := vi$get_attach_parm ("TPU$SEARCH");
        IF (find_text <> " ") THEN
            IF SUBSTR (find_text, 1, 1) = "/" THEN
                SET (FORWARD, CURRENT_BUFFER);
                vi$last_search_dir := 1;
            ELSE
                SET (REVERSE, CURRENT_BUFFER);
                vi$last_search_dir := -1;
            ENDIF;
            vi$search_string := SUBSTR (find_text, 2, LENGTH (find_text)-1);
            vi$beep_position (vi$find_str (vi$search_string, 0, 0), 1, 1);
        ENDIF;
    ELSE
        vi$beep_position (vi$to_line (INT (new_lineno)), 1, 1);
    ENDIF;
ENDPROCEDURE;

!
!  A special procedure to trap any errors in translating logical names, and
!  just ignore them, and return a " " string on error.
!
PROCEDURE vi$get_attach_parm (parm)
    LOCAL
        rstr,
        errno,
        blank;

    ON_ERROR
        errno := ERROR;
        RETURN (blank);
    ENDON_ERROR;

    blank := " ";

    rstr := CALL_USER (vi$cu_trnlnm_job, parm);
    RETURN (rstr);
ENDPROCEDURE;

!
!   Perform the operations associated with the 'z' key command.
!
PROCEDURE vi$_z_move

    LOCAL
        pos,
        crow,
        old_scroll,
        scrl_value,
        scroll_top,
        scroll_bottom,
        scroll_amount,
        act_count,
        done,
        next_key,
        cur_window;

    vi$active_count := 0;
    LOOP
$$EOD$$



More information about the Comp.sources.misc mailing list