gregg@a.cs.okstate.edu (Gregg Wonderly) (10/21/87)
$!=============================================================================
$! VAX/VMS archive file created by VMS_SHAR V-4.03 05-Aug-1987
$! which was written by Michael Bednarek (U3369429@ucsvc.dn.mu.oz.au)
$! To unpack, simply save and execute (@) this file.
$!
$! This archive was created by GREGG
$! on Tuesday 20-OCT-1987 22:45:39.68
$!
$! It contains the following 1 file:
$! VI.9
$!=============================================================================
$ Set Symbol/Scope=(NoLocal,NoGlobal)
$ Version=F$GetSYI("VERSION") ! See what VMS version we have here:
$ If Version.ges."V4.4" then goto Version_OK
$ Write SYS$Output "Sorry, you are running VMS ",Version, -
", but this procedure requires V4.4 or higher."
$ Exit 44
$Version_OK: CR[0,8]=13
$ Pass_or_Failed="failed!,passed."
$ Goto Start
$Convert_File:
$ Read/Time_Out=0/Error=No_Error1/Prompt="creating ''File_is'" SYS$Command ddd
$No_Error1: Define/User_Mode SYS$Output NL:
$ Edit/TPU/NoSection/NoDisplay/Command=SYS$Input/Output='File_is' -
VMS_SHAR_DUMMY.DUMMY
f:=Get_Info(Command_Line,"File_Name");b:=Create_Buffer("",f);
o:=Get_Info(Command_Line,"Output_File");Set (Output_File,b,o);
Position (Beginning_of(b));Loop x:=Erase_Character(1); Loop ExitIf x<>"V";
Move_Vertical(1);x:=Erase_Character(1);Append_Line;Move_Horizontal
(-Current_Offset);EndLoop;Move_Vertical(1);ExitIf Mark(None)=End_of(b)
EndLoop;Exit;
$ Delete VMS_SHAR_DUMMY.DUMMY;*
$ Checksum 'File_is
$ Success=F$Element(Check_Sum_is.eq.CHECKSUM$CHECKSUM,",",Pass_or_Failed)+CR
$ Read/Time_Out=0/Error=No_Error2/Prompt=" CHECKSUM ''Success'" SYS$Command ddd
$No_Error2: Return
$Start:
$ File_is="VI.9"
$ Check_Sum_is=290560531
$ Copy SYS$Input VMS_SHAR_DUMMY.DUMMY
X vi$active_count := 0;
XENDPROCEDURE;
X
X!
X! Move to line in file. vi$active_count holds the line number to GO TO.
X! If VI$ACTIVE_COUNT is zero, we move to the end of the file.
X!
XPROCEDURE vi$to_line (cnt)
X
X LOCAL
X this_pos, ! Saved position in case of botch
X last_line, ! Last line in the buffer
X win_len; ! Length of CURRENT_WINDOW
X
X ON_ERROR
X vi$message (FAO ("No such line: !SL", VI$ACTIVE_COUNT));
X POSITION (this_pos);
X cnt := 0;
X RETURN;
X ENDON_ERROR;
X
X this_pos := MARK(NONE);
X MOVE_HORIZONTAL (-CURRENT_OFFSET);
X vi$start_pos := MARK (NONE);
X
X IF cnt = 0 THEN
X POSITION (END_OF (CURRENT_BUFFER));
X ELSE
X last_line := GET_INFO (CURRENT_BUFFER, "RECORD_COUNT");
X
X IF cnt > last_line THEN
X IF last_line > 0 THEN
X vi$message ("Not that many lines in buffer");
X POSITION (this_pos);
X RETURN (0);
X ENDIF;
X ELSE
X POSITION (BEGINNING_OF (CURRENT_BUFFER));
X win_len := GET_INFO (CURRENT_WINDOW, "VISIBLE_LENGTH");
X MOVE_VERTICAL (cnt - 1);
X cnt := 0;
X ENDIF;
X ENDIF;
X
X IF (MARK (NONE) <> END_OF (CURRENT_BUFFER)) THEN
X MOVE_VERTICAL (1);
X MOVE_HORIZONTAL (-1);
X vi$new_endpos := MARK (NONE);
X MOVE_HORIZONTAL (-CURRENT_OFFSET);
X ENDIF;
X
X vi$yank_mode := VI$LINE_MODE;
X RETURN (vi$retpos (this_pos));
XENDPROCEDURE;
X
X!
X! Set a marker in the current buffer.
X!
XPROCEDURE vi$_set_mark
X
X LOCAL
X mark_char,
X mark_name,
X key_pressed;
X
X key_pressed := vi$read_a_key;
X
X mark_char := ASCII (key_pressed);
X IF (INDEX (vi$_lower_chars, mark_char) <> 0) THEN
X mark_name := "vi$mark_" + mark_char;
X EXECUTE (COMPILE (mark_name + " := MARK(NONE);"));
X ELSE
X vi$MESSAGE ("Invalid marker key!");
X ENDIF;
X
XENDPROCEDURE;
X
X!
X! Function mapped to "'" and "`".
X!
XPROCEDURE vi$_go_to_marker
X IF (vi$position (vi$to_marker, 1) <> 0) THEN
X vi$pos_in_middle (MARK (NONE));
X ENDIF;
XENDPROCEDURE;
X
X!
X! Function to move the marker indicated by the next keystroke.
X!
XPROCEDURE vi$to_marker
X
X LOCAL
X mode_key,
X pos,
X mark_name,
X mark_char,
X key_pressed;
X
X ON_ERROR;
X vi$message ("Mark not set!");
X RETURN (0);
X ENDON_ERROR;
X
X pos := MARK (NONE);
X mode_key := vi$last_key;
X key_pressed := vi$read_a_key;
X
X mark_char := ASCII (key_pressed);
X IF (INDEX (vi$_lower_chars+"'`", mark_char) = 0) THEN
X vi$MESSAGE ("Invalid marker key!");
X RETURN (0);
X ENDIF;
X
X IF (key_pressed <> F11) THEN
X IF (mark_char = "'") OR (mark_char = "`") THEN
X IF (vi$old_place <> 0) THEN
X IF (GET_INFO (vi$old_place, "BUFFER") = CURRENT_BUFFER) THEN
X POSITION (vi$old_place);
X ELSE
X MESSAGE ("Previous place not in this buffer!");
X RETURN (0);
X ENDIF;
X ELSE
X MESSAGE ("No previous mark to return to!");
X RETURN (0);
X ENDIF;
X ELSE
X mark_name := "vi$mark_" + mark_char;
X EXECUTE (COMPILE ("vi$global_mark := "+mark_name+";"));
X
V IF (vi$global_mark <> 0) AND (GET_INFO (vi$global_mark, "BUFFER")
X=
V CURRENT_BUFFER) TH
XEN
X POSITION (vi$global_mark);
X vi$yank_mode := VI$LINE_MODE;
X ELSE
X vi$message ("Invalid mark for this buffer!");
X RETURN (0);
X ENDIF;
X ENDIF;
X
X IF ASCII (mode_key) = "'" THEN
X MOVE_HORIZONTAL (-CURRENT_OFFSET);
X POSITION (vi$first_no_space);
X ENDIF;
X
X IF (MARK (NONE) <> END_OF (CURRENT_BUFFER)) THEN
X MOVE_VERTICAL (1);
X vi$new_endpos := MARK (NONE);
X MOVE_VERTICAL (-1);
X ENDIF;
X
X RETURN (vi$retpos (pos));
X ENDIF;
X
X POSITION (pos);
X RETURN (0);
XENDPROCEDURE;
X
X!
X! Maintain the repeat count in vi$active_count. If VI$ACTIVE_COUNT is ZERO,
X! and '0' is typed, this means move to beginning of the line.
X!
XPROCEDURE vi$repeat_count
X
X IF VI$ACTIVE_COUNT = 0 THEN
X vi$active_count := INT (ASCII (KEY_NAME (vi$last_key)));
X IF vi$active_count = 0 THEN
X vi$position (vi$fol, 0);
X ENDIF;
X ELSE
X vi$active_count := vi$active_count * 10 +
X INT (ASCII (KEY_NAME (vi$last_key)));
X ENDIF;
X
XENDPROCEDURE;
X
X!
X! The function mapped to <CR>.
X!
XPROCEDURE vi$_next_line
X POSITION (vi$beg_next);
XENDPROCEDURE;
X
X!
X! Move the cursor to the beginning of the next line
X!
XPROCEDURE vi$beg_next
X LOCAL
X pos;
X
X ON_ERROR
X RETURN (MARK (NONE));
X ENDON_ERROR;
X
X pos := MARK (NONE);
X MOVE_VERTICAL (vi$cur_active_count);
X MOVE_HORIZONTAL (-CURRENT_OFFSET);
X POSITION (vi$first_no_space);
X vi$yank_mode := VI$LINE_MODE;
X vi$new_offset := 1;
X RETURN (vi$retpos (pos));
X
XENDPROCEDURE;
X
X!
X! This function moves to the first non-blank character of a line
X!
XPROCEDURE vi$first_no_space
X
X LOCAL
X pos,
X t_range;
X
X ON_ERROR
X ! Ignore string not found messages.
X ENDON_ERROR;
X
X pos := MARK (NONE);
X MOVE_HORIZONTAL (- CURRENT_OFFSET);
X
X IF (LENGTH (CURRENT_LINE) > 0) THEN
X IF t_range = 0 THEN
X t_range :=
X SEARCH (ANCHOR & SPAN (vi$no_space) &
X NOTANY(vi$no_space), FORWARD);
X ENDIF;
X
X IF t_range <> 0 THEN
X POSITION (END_OF (t_range));
X ELSE
X ! If that fails, then search for a blank line with extra white
X ! space, and move to the end of the white space.
X
X t_range := SEARCH (ANCHOR & SPAN (vi$no_space), FORWARD);
X
X IF t_range <> 0 THEN
X POSITION (END_OF (t_range));
X ENDIF;
X ENDIF;
X ENDIF;
X
X vi$yank_mode := VI$IN_LINE_MODE;
X RETURN (vi$retpos (pos));
XENDPROCEDURE;
X
X!
X! Move by a section in the indicated direction
X!
XPROCEDURE vi$_section (dir)
X LOCAL
X ch;
X
X ch := vi$read_a_key;
X IF ((ASCII(ch) = "]") AND (dir = 1)) OR
X ((ASCII(ch) = "[") AND (dir = -1)) THEN
X vi$position (vi$section (dir), 1);
X ELSE
X vi$beep;
X ENDIF;
XENDPROCEDURE;
X
X!
X! Sound a bell.
X!
XPROCEDURE vi$beep
X LOCAL
X pos;
X
X IF (vi$error_bells = 0) THEN
X RETURN;
X ENDIF;
X
X pos := CURRENT_WINDOW;
X SET (BELL, ALL, ON);
X MESSAGE ("");
X SET (BELL, ALL, OFF);
X SET (BELL, BROADCAST, ON);
X POSITION (pos);
XENDPROCEDURE;
X
X!
X! Mapped to '}' and '{', moves by a paragraph in the indicated direction.
X!
XPROCEDURE vi$_paragraph(dir)
X vi$position (vi$paragraph(dir), 1);
XENDPROCEDURE;
X
X!
X! Mapped to ( moves backward a sentence
X!
XPROCEDURE vi$_begin_sentence
X vi$position (vi$begin_sentence, 1);
XENDPROCEDURE;
X
X!
X! Mapped to ) moves forward a sentence
X!
XPROCEDURE vi$_end_sentence
X vi$position (vi$end_sentence, 1);
XENDPROCEDURE;
X
X!
X! Move backward a sentence.
X!
XPROCEDURE vi$begin_sentence
X LOCAL
X rng,
X spos,
X pos;
X
X ON_ERROR;
X ENDON_ERROR;
X
X pos := MARK (NONE);
X
X MOVE_HORIZONTAL (-1);
X
X LOOP;
X rng := SEARCH (
X (("" | " " | " ") & ANY (vi$_upper_chars)),
X REVERSE, EXACT);
X
X EXITIF rng = 0;
X
X POSITION (BEGINNING_OF (rng));
X IF INDEX (" ", CURRENT_CHARACTER) = 0 THEN
X MOVE_HORIZONTAL (-1);
X ENDIF;
X IF INDEX (" ", CURRENT_CHARACTER) <> 0 THEN
X IF (CURRENT_CHARACTER = " ") THEN
X MOVE_HORIZONTAL (-1);
X IF INDEX (" ", CURRENT_CHARACTER) <> 0 THEN
X MOVE_HORIZONTAL (-1);
X IF INDEX ("?.!", CURRENT_CHARACTER) <> 0 THEN
X MOVE_HORIZONTAL (3);
X RETURN (vi$retpos (pos));
X ENDIF;
X ENDIF;
X ELSE
X MOVE_HORIZONTAL (1);
X RETURN (vi$retpos (pos));
X ENDIF;
X ENDIF;
X POSITION (BEGINNING_OF (rng));
X MOVE_HORIZONTAL (-1);
X ENDLOOP;
X
X RETURN (0);
XENDPROCEDURE;
X
X!
X! Move to next paragraph
X!
XPROCEDURE vi$paragraph (dir)
X RETURN (vi$para_sect (dir, vi$para_pat));
XENDPROCEDURE;
X
X!
X! Find next paragraph or section.
X!
XPROCEDURE vi$para_sect (dir, pat)
X LOCAL
X loc,
X direct,
X pos;
X
X pos := MARK (NONE);
X
X IF (dir < 0) THEN
X direct := REVERSE;
X MOVE_VERTICAL (-1);
X ELSE
X direct := FORWARD;
X MOVE_VERTICAL (1);
X ENDIF;
X
X SET (TIMER, ON, "Searching...");
X loc := SEARCH (pat, direct, NO_EXACT);
X SET (TIMER, OFF);
X
X IF (loc <> 0) THEN
X RETURN (BEGINNING_OF (loc));
X ELSE
X SET (TIMER, ON, "Searching...");
X loc := SEARCH (vi$next_blank, direct, NO_EXACT);
X SET (TIMER, OFF);
X IF (loc <> 0) THEN
X RETURN (BEGINNING_OF (loc));
X ENDIF;
X ENDIF;
X
X POSITION (pos);
X RETURN (0);
XENDPROCEDURE;
X
X!
X! Move to next section
X!
XPROCEDURE vi$section (dir)
X RETURN (vi$para_sect (dir, vi$sect_pat));
XENDPROCEDURE;
X
X!
X! Move forward a sentence.
X!
XPROCEDURE vi$end_sentence
X LOCAL
X rng,
X spos,
X pos;
X
X ON_ERROR;
X ENDON_ERROR;
X
X pos := MARK (NONE);
X
X MOVE_HORIZONTAL (1);
X
X LOOP;
X rng := SEARCH (ANY (vi$_upper_chars), FORWARD, EXACT);
X
X EXITIF rng = 0;
X
X POSITION (BEGINNING_OF (rng));
X IF INDEX (" ", CURRENT_CHARACTER) = 0 THEN
X MOVE_HORIZONTAL (-1);
X ENDIF;
X IF INDEX (" ", CURRENT_CHARACTER) <> 0 THEN
X IF (CURRENT_CHARACTER = " ") THEN
X MOVE_HORIZONTAL (-1);
X IF INDEX (" ", CURRENT_CHARACTER) <> 0 THEN
X MOVE_HORIZONTAL (-1);
X IF INDEX ("?.!", CURRENT_CHARACTER) <> 0 THEN
X MOVE_HORIZONTAL (3);
X RETURN (vi$retpos (pos));
X ENDIF;
X ENDIF;
X ELSE
X MOVE_HORIZONTAL (1);
X RETURN (vi$retpos (pos));
X ENDIF;
X ENDIF;
X POSITION (BEGINNING_OF (rng));
X MOVE_HORIZONTAL (1);
X ENDLOOP;
X
X RETURN (0);
XENDPROCEDURE;
X
X!
X! This function returns the value in vi$active count. It takes into
X! account that when vi$active_count is zero, it should really be
X! one.
X!
XPROCEDURE vi$cur_active_count
X LOCAL
X resp,
X old_cnt;
X
X old_cnt := vi$active_count;
X vi$active_count := 0;
X IF old_cnt <= 0 THEN
X old_cnt := 1;
X ENDIF;
X
X RETURN (old_cnt);
XENDPROCEDURE;
X
X!
X! The function mapped to 'p'.
X!
XPROCEDURE vi$put_after (dest_buf)
X
X LOCAL
X source,
X pos;
X
X source := vi$cur_text;
X
X IF (GET_INFO (dest_buf, "TYPE") = BUFFER) THEN
X source := dest_buf;
X ENDIF;
X
X IF (GET_INFO (source, "TYPE") = BUFFER) THEN
X pos := MARK (NONE);
X POSITION (BEGINNING_OF (source));
X vi$yank_mode := INT (vi$current_line);
X POSITION (pos);
X ENDIF;
X
X IF (source = "") THEN
X RETURN;
X ENDIF;
X
X IF (vi$yank_mode = VI$LINE_MODE) THEN
X IF (MARK(NONE) <> END_OF (CURRENT_BUFFER)) THEN
X MOVE_VERTICAL (1);
X ENDIF;
X ELSE
X IF (LENGTH (CURRENT_LINE) > 0) THEN
X MOVE_HORIZONTAL (1);
X ENDIF;
X ENDIF;
X
X vi$put_here (VI$AFTER, source);
XENDPROCEDURE;
X
X!
X! The function mapped to 'P'.
X!
XPROCEDURE vi$put_here (here_or_below, dest_buf)
X LOCAL
X olen,
X source,
X pos;
X
X source := vi$cur_text;
X olen := GET_INFO (CURRENT_BUFFER, "RECORD_COUNT");
X
X IF (GET_INFO (dest_buf, "TYPE") = BUFFER) THEN
X source := dest_buf;
X ENDIF;
X
X IF (GET_INFO (source, "TYPE") = BUFFER) THEN
X pos := MARK (NONE);
X POSITION (BEGINNING_OF (source));
X IF (MARK (NONE) = END_OF (source)) THEN
X RETURN;
X ENDIF;
X vi$yank_mode := INT (vi$current_line);
X ERASE_LINE;
X POSITION (pos);
X ELSE
X IF (source = "") THEN
X RETURN;
X ENDIF;
X ENDIF;
X
X IF source = 0 THEN
X vi$message ("Bad buffer for put!");
X RETURN;
X ENDIF;
X
X IF (vi$yank_mode = VI$LINE_MODE) THEN
X MOVE_HORIZONTAL (-CURRENT_OFFSET);
X ENDIF;
X
X pos := vi$get_undo_start;
X
X COPY_TEXT (source);
X APPEND_LINE;
X MOVE_HORIZONTAL (-1);
X vi$undo_end := MARK (NONE);
X MOVE_HORIZONTAL (1);
X
X vi$kill_undo;
X
X IF (here_or_below = VI$AFTER) AND (vi$yank_mode = VI$LINE_MODE) THEN
X MOVE_HORIZONTAL (-CURRENT_OFFSET);
X ENDIF;
X
X vi$undo_start := vi$set_undo_start (pos);
X
X ! Put the mode back into the buffer.
X
X IF (GET_INFO (source, "TYPE") = BUFFER) THEN
X POSITION (BEGINNING_OF (source));
X COPY_TEXT (STR (vi$yank_mode));
X SPLIT_LINE;
X POSITION (vi$undo_start);
X ENDIF;
X
X IF (here_or_below = VI$AFTER) AND (vi$yank_mode = VI$IN_LINE_MODE) THEN
X POSITION (vi$undo_end);
X ENDIF;
X
X vi$check_length (olen);
XENDPROCEDURE;
X
X!
X! Function mapped to 'o'. Note that this makes undo NOT place
X! the cursor where is really should be.
X!
XPROCEDURE vi$open_below
X LOCAL
X uline;
X
X ON_ERROR
X ! Ignore attempt to move past EOB errors
X ENDON_ERROR;
X
X uline := vi$cur_line_no;
X MOVE_VERTICAL (1);
X vi$open_here;
X vi$undo_line := uline;
X
XENDPROCEDURE;
X
X!
X! Function mapped to 'O'
X!
XPROCEDURE vi$open_here
X
X LOCAL
X uline,
X offs,
X cnt,
X epos,
X spos;
X
X uline := vi$cur_line_no;
X offs := CURRENT_OFFSET;
X
X MOVE_HORIZONTAL (- CURRENT_OFFSET);
X
X IF (MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER)) THEN
X MOVE_HORIZONTAL (-1);
X spos := MARK (NONE);
X MOVE_HORIZONTAL (1);
X ELSE
X spos := 0;
X ENDIF;
X
X SPLIT_LINE;
X
X MOVE_VERTICAL (-1);
X
X cnt := vi$while_not_esc;
X epos := MARK (NONE);
X
X IF (cnt <> 0) THEN
X IF (LENGTH (vi$current_line) > 0) THEN
X MOVE_HORIZONTAL (1);
X ENDIF;
X ENDIF;
X
X vi$undo_end := MARK (NONE);
X
X IF spos <> 0 THEN
X POSITION (spos);
X MOVE_HORIZONTAL (1);
X ELSE
X POSITION (BEGINNING_OF (CURRENT_BUFFER));
X ENDIF;
X
X vi$undo_start := MARK (NONE);
X POSITION (epos);
X
X vi$kill_undo;
X
X vi$undo_line := uline;
X vi$undo_offset := offs;
XENDPROCEDURE;
X
X!
X! This function guards the right margin, and the end of the buffer so
X! that the cursor never is displayed past those boundries.
X!
XPROCEDURE vi$check_rmarg
X
X ON_ERROR;
X ! ignore "Can't return line and end of buffer" messages
X RETURN;
X ENDON_ERROR;
X
X IF (LENGTH (vi$current_line) > 0) THEN
X IF (CURRENT_OFFSET = LENGTH (vi$current_line)) THEN
X MOVE_HORIZONTAL (-1);
X ENDIF;
X ENDIF;
X
X IF (MARK (NONE) = END_OF (CURRENT_BUFFER)) THEN
X MOVE_VERTICAL (-1);
X ENDIF;
XENDPROCEDURE;
X
X!
X! The function mapped to 'h'.
X!
XPROCEDURE vi$move_left
X vi$position (vi$left, 0);
XENDPROCEDURE;
X
X!
X! The function mapped to 'l'.
X!
XPROCEDURE vi$move_right
X vi$position (vi$right, 0);
XENDPROCEDURE;
X
X!
X! The function mapped to 'j'
X!
XPROCEDURE vi$move_down
X LOCAL
X save_mark;
X
X save_mark := 0;
X
X IF (vi$active_count >= vi$report) THEN
X save_mark := 1;
X ENDIF;
X
X vi$position (vi$downline (0), save_mark);
XENDPROCEDURE;
X
X!
X! The function mapped to 'k'.
X!
XPROCEDURE vi$move_up
X LOCAL
X save_mark;
X
X save_mark := 0;
X
X IF (vi$active_count >= vi$report) THEN
X save_mark := 1;
X ENDIF;
X
X vi$position (vi$upline, save_mark);
XENDPROCEDURE;
X
X!
X! The function mapped to 'i'.
X!
XPROCEDURE vi$insert_here
X LOCAL
X act_cnt,
X rnge,
X ccnt,
X epos,
X spos;
X
X vi$kill_undo;
X
X IF (MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER)) THEN
X MOVE_HORIZONTAL (-1);
X spos := MARK (NONE);
X MOVE_HORIZONTAL (1);
X ELSE
X spos := 0;
X ENDIF;
X
X vi$undo_start := MARK (NONE);
X
X ccnt := vi$while_not_esc;
X
X vi$undo_end := 0;
X
X IF (ccnt > 0) THEN
X IF (CURRENT_OFFSET = 0) AND
X ((ccnt > 1) OR (LENGTH (CURRENT_LINE) = 0)) AND
X (MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER)) THEN
X MOVE_HORIZONTAL (-1);
X epos := MARK (NONE);
X MOVE_HORIZONTAL (1);
X ELSE
X epos := MARK (NONE);
X ENDIF;
X ELSE
X epos := 0;
X ENDIF;
X
X IF epos <> 0 THEN
X act_cnt := vi$cur_active_count;
X
X IF spos <> 0 THEN
X POSITION (spos);
X MOVE_HORIZONTAL (1);
X ELSE
X POSITION (BEGINNING_OF (CURRENT_BUFFER));
X ENDIF;
X vi$undo_start := MARK (NONE);
X
X POSITION (epos);
X
X IF (vi$undo_start = 0) OR (epos = 0) THEN
X vi$message ("Ooops, bad markers in vi$insert_here");
X RETURN ;
X ENDIF;
X
X rnge := CREATE_RANGE (vi$undo_start, epos, NONE);
X
X LOOP
X EXITIF act_cnt < 2;
X MOVE_HORIZONTAL (1);
X
X IF rnge = 0 THEN
X vi$message ("Ooops, generated a bad range in vi$insert_here");
X RETURN ;
X ENDIF;
X
X COPY_TEXT (rnge);
X act_cnt := act_cnt - 1;
X MOVE_HORIZONTAL (-1);
X ENDLOOP;
X
X vi$undo_end := MARK (NONE);
X IF (CURRENT_OFFSET = LENGTH (vi$current_line)) THEN
X MOVE_HORIZONTAL (1);
X ENDIF;
X ENDIF;
XENDPROCEDURE;
X
X!
X! The function mapped to 'I'
X!
XPROCEDURE vi$insert_at_begin
X
X MOVE_HORIZONTAL (- CURRENT_OFFSET);
X vi$_bol;
X vi$insert_here;
X
XENDPROCEDURE;
X
X!
X! The function mapped to 'a'
X!
XPROCEDURE vi$insert_after
X
X IF (LENGTH (vi$current_line) > 0) THEN
X IF (CURRENT_OFFSET < LENGTH(vi$current_line)) THEN
X MOVE_HORIZONTAL (1);
X ENDIF;
X ENDIF;
X vi$insert_here;
X
XENDPROCEDURE;
X
X!
X! A do nothing function
X!
XPROCEDURE vi$_dummy
XENDPROCEDURE;
X
X!
X! Do the command line input processing
X!
XPROCEDURE vi$while_not_esc
X
X LOCAL
X max_mark,
X start_pos,
X max_col;
X
X max_col := CURRENT_OFFSET;
X start_pos := max_col;
X max_mark := MARK(NONE);
X vi$update (CURRENT_WINDOW);
X
X RETURN (vi$line_edit (max_col, start_pos, max_mark, 0));
XENDPROCEDURE;
X
X!
X! Insert text into the buffer using standard VI insertion.
X! Used by CHANGE, APPEND, INSERT, and REPLACE functions.
X!
XPROCEDURE vi$line_edit (max_col, start_pos, max_mark, replace)
X
X LOCAL
X chcnt,
X offset,
X seen_eol,
X col,
X cnt,
X tabstops,
X current_mark,
X desc,
X start_ins,
X ins_text,
X should_wrap,
X abbrs,
X rchar,
X abbrlen,
X cabbr,
X pos,
X in_char;
X
X ON_ERROR
X ENDON_ERROR;
X
X IF (vi$show_mode) THEN
X vi$mess_select (BOLD);
X MESSAGE (FAO ("!7* INSERT"));
X vi$mess_select (REVERSE);
X ENDIF;
X chcnt := 0;
X seen_eol := 0;
X
X abbrs := EXPAND_NAME ("vi$abbr_", VARIABLES) + " ";
X
X cabbr := "";
X abbrlen := 0;
X
X SET (INSERT, CURRENT_BUFFER);
X IF (max_col > CURRENT_OFFSET) OR (replace <> 0) THEN
X SET (OVERSTRIKE, CURRENT_BUFFER);
X ENDIF;
X
X start_ins := MARK (NONE);
X
X LOOP
X LOOP
X in_char := vi$read_a_key;
X desc := LOOKUP_KEY (KEY_NAME (in_char), COMMENT, vi$edit_keys);
X EXITIF (desc <> "reinsert");
X
X IF max_mark <> MARK (NONE) THEN
X current_mark := MARK (NONE);
X POSITION (max_mark);
X MOVE_HORIZONTAL (-1);
X
X ERASE (CREATE_RANGE (MARK (NONE), current_mark, NONE));
X ENDIF;
X
X SET (INSERT, CURRENT_BUFFER);
X COPY_TEXT (vi$last_insert);
X APPEND_LINE;
X
X max_col := CURRENT_OFFSET;
X start_pos := CURRENT_OFFSET;
X max_mark := MARK(NONE);
X chcnt := chcnt + 1;
X ENDLOOP;
X
X IF (desc = "active_macro") THEN
X EXECUTE (LOOKUP_KEY (KEY_NAME (in_char), PROGRAM, vi$edit_keys));
X ELSE
X EXITIF desc = "escape";
X
X should_wrap := (vi$wrap_margin <> 0) AND
V ((CURRENT_OFFSET + vi$wrap_margin) > vi$scr_width)
X;
X
X IF (desc <> "eol") AND (desc <> "bword") AND (desc <> "bs") THEN
X IF (should_wrap) THEN
X
X offset := 0;
X MOVE_HORIZONTAL (-1);
X
X LOOP
X EXITIF (CURRENT_OFFSET = 0);
X EXITIF (INDEX (" ", CURRENT_CHARACTER) <> 0);
X MOVE_HORIZONTAL (-1);
X offset := offset + 1;
X ENDLOOP;
X
X IF (offset <> 0) THEN
X ERASE_CHARACTER (1);
X LOOP
X EXITIF (CURRENT_OFFSET = 0);
X MOVE_HORIZONTAL (-1);
X EXITIF (
X INDEX (" ", CURRENT_CHARACTER) = 0);
X ERASE_CHARACTER (1);
X ENDLOOP;
X ENDIF;
X
X IF (CURRENT_OFFSET <> 0) THEN
X MOVE_HORIZONTAL (1);
X SPLIT_LINE;
X max_col := CURRENT_OFFSET;
X start_pos := CURRENT_OFFSET;
X max_mark := MARK(NONE);
X MOVE_HORIZONTAL (offset);
X ELSE
X MOVE_HORIZONTAL (offset);
X SPLIT_LINE;
X max_col := CURRENT_OFFSET;
X start_pos := CURRENT_OFFSET;
X max_mark := MARK(NONE);
X ENDIF;
X ENDIF;
X
X vi$update (CURRENT_WINDOW);
X
X IF desc = "vquote" THEN
X in_char := vi$read_a_key;
X ENDIF;
X
X IF in_char = TAB_KEY THEN
X vi$abbr (abbrs, 0, cabbr, abbrlen);
X IF (vi$use_tabs = 1) THEN
X COPY_TEXT (ASCII (9));
X ELSE
X cnt := 0;
X col := GET_INFO (SCREEN, "CURRENT_COLUMN");
X tabstops := GET_INFO (CURRENT_BUFFER, "TAB_STOPS");
X
X IF (GET_INFO (tabstops, "TYPE") <> STRING) THEN
X LOOP
X EXITIF (col - ((col / tabstops) *
V tabstops) = 0)
X;
X cnt := cnt + 1;
X col := col + 1;
X ENDLOOP;
X
X chcnt := chcnt + cnt;
X LOOP
X EXITIF (cnt < 0);
X IF (CURRENT_OFFSET = max_col) AND
V ((replace = 0) OR seen_eol) TH
XEN
X SET (INSERT, CURRENT_BUFFER);
X ELSE
X IF CURRENT_OFFSET > max_col THEN
X max_col := CURRENT_OFFSET;
X max_mark := MARK (NONE);;
X ENDIF;
X ENDIF;
X COPY_TEXT (" ");
X cnt := cnt - 1;
X ENDLOOP
X ELSE
X
X ! Give up on windows with weird tab stops.
X
X COPY_TEXT (ASCII (9));
X ENDIF;
X ENDIF;
X chcnt := chcnt + 1;
X ELSE
V IF (in_char <= CTRL_Z_KEY) AND (in_char >= CTRL_A_KEY) THE
XN
X in_char := (in_char - CTRL_A_KEY) /
X (CTRL_B_KEY - CTRL_A_KEY) + 1;
X ENDIF;
X
X rchar := vi$ascii(in_char);
X
X IF (INDEX (vi$_ws, rchar) <> 0) THEN
V chcnt := chcnt + vi$abbr (abbrs, rchar, cabbr, abbrlen
X);
X ELSE
X COPY_TEXT (rchar);
X IF (INDEX(vi$_upper_chars, rchar) <> 0) THEN
X cabbr := cabbr + "_";
X ENDIF;
X cabbr := cabbr + rchar;
X abbrlen := abbrlen + 1;
X chcnt := chcnt + 1;
X ENDIF;
X ENDIF;
X
X IF (CURRENT_OFFSET = max_col) AND
X ((replace = 0) OR seen_eol) THEN
X SET (INSERT, CURRENT_BUFFER);
X ELSE
X IF CURRENT_OFFSET > max_col THEN
X max_col := CURRENT_OFFSET;
X max_mark := MARK (NONE);
X ENDIF;
X ENDIF;
X ELSE
X IF desc = "bs" THEN
X IF start_pos < CURRENT_OFFSET THEN
X ! Delete backspace and the character before it.
X vi$del_a_key;
X vi$del_a_key;
X SET (OVERSTRIKE, CURRENT_BUFFER);
X MOVE_HORIZONTAL (-1);
X chcnt := chcnt - 1;
X ENDIF;
X ELSE
X IF desc = "eol" THEN
X IF (max_mark <> MARK (NONE)) AND (replace = 0) THEN
X current_mark := MARK (NONE);
X POSITION (max_mark);
X MOVE_HORIZONTAL (-1);
X ERASE (CREATE_RANGE (MARK (NONE),
X current_mark, NONE));
X ENDIF;
X vi$abbr (abbrs, 0, cabbr, abbrlen);
X SPLIT_LINE;
X chcnt := chcnt + 1;
X seen_eol := 1;
V IF (CURRENT_BUFFER = vi$dcl_buf) AND (vi$send_dcl) THE
XN
X MOVE_VERTICAL (-1);
X vi$send_to_dcl (CURRENT_LINE);
X MOVE_VERTICAL (1);
X ENDIF;
X max_col := CURRENT_OFFSET;
X start_pos := CURRENT_OFFSET;
X SET (INSERT, CURRENT_BUFFER);
X max_mark := MARK(NONE);
V IF (CURRENT_BUFFER = vi$dcl_buf) AND (vi$send_dcl) THE
XN
X EXITIF (1);
X ENDIF;
X ELSE
X IF (desc = "bword") THEN
X
X ! Backup over whitespace.
X
X LOOP
X EXITIF start_pos = CURRENT_OFFSET;
X MOVE_HORIZONTAL (-1);
X chcnt := chcnt - 1;
V EXITIF (INDEX (" ", CURRENT_CHARACTER) = 0)
X;
X SET (OVERSTRIKE, CURRENT_BUFFER);
X ENDLOOP;
X
X ! Backup over noblank words.
X
X LOOP
X EXITIF start_pos = CURRENT_OFFSET;
X SET (OVERSTRIKE, CURRENT_BUFFER);
V IF (INDEX (" ", CURRENT_CHARACTER) <> 0) TH
XEN
X chcnt := chcnt + 1;
X MOVE_HORIZONTAL (1);
X EXITIF (1);
X ENDIF;
X MOVE_HORIZONTAL (-1);
X chcnt := chcnt - 1;
X ENDLOOP;
X ENDIF;
X ENDIF;
X ENDIF;
X ENDIF;
X ENDIF;
X
X vi$update (CURRENT_WINDOW);
X ENDLOOP;
X
X IF max_mark <> MARK (NONE) THEN
X current_mark := MARK (NONE);
X IF (NOT seen_eol) AND (replace <> 0) THEN
X SET (OVERSTRIKE, CURRENT_BUFFER);
X COPY_TEXT (SUBSTR (replace, CURRENT_OFFSET + 1,
X max_col - CURRENT_OFFSET));
X POSITION (current_mark);
X ELSE
X POSITION (max_mark);
X IF (MARK(NONE) <> BEGINNING_OF (CURRENT_BUFFER)) THEN
X MOVE_HORIZONTAL (-1);
X ENDIF;
X ERASE (CREATE_RANGE (MARK (NONE), current_mark, NONE));
X ENDIF;
X ENDIF;
X
X IF (CURRENT_OFFSET > 0) AND
X (MARK(NONE) <> BEGINNING_OF (CURRENT_BUFFER)) THEN
X MOVE_HORIZONTAL (-1);
X ENDIF;
X
X ins_text := CREATE_RANGE (start_ins, MARK (NONE), NONE);
X
X ! Save last inserted text to buffer.
X
X ERASE (vi$last_insert);
X pos := MARK (NONE);
X
X POSITION (vi$last_insert);
X COPY_TEXT (ins_text);
X SPLIT_LINE;
X POSITION (BEGINNING_OF (vi$last_insert));
X
X POSITION (pos);
X
X SET (INSERT, CURRENT_BUFFER);
X
X IF (vi$show_mode) THEN
X MESSAGE ("");
X ENDIF;
X RETURN (chcnt);
XENDPROCEDURE;
X
X!
X! Check to see if 'cabbr' is a known abbreviation, and substitute the
X! proper text if it is.
X!
XPROCEDURE vi$abbr (abbrs, rchar, cabbr, abbrlen)
X LOCAL
X strg;
X
X strg := "";
X
X IF (abbrlen > 0) THEN
X EDIT (cabbr, UPPER);
X IF (INDEX (abbrs, "VI$ABBR_"+cabbr+" ") <> 0) THEN
X vi$global_var := 0;
X EXECUTE (COMPILE ("vi$global_var := vi$abbr_"+cabbr+";"));
X IF (vi$global_var <> 0) THEN
X ERASE_CHARACTER (-abbrlen);
X strg := vi$global_var;
X COPY_TEXT (strg);
X ENDIF;
X ENDIF;
X cabbr := "";
X abbrlen := 0;
X ENDIF;
X IF (rchar <> 0) THEN
X COPY_TEXT (rchar);
X ENDIF;
X RETURN (LENGTH (strg) + (rchar <> 0));
XENDPROCEDURE;
X
X!
X! Return a string describing the KEY_NAME passed. For control characters,
X! it is "^?" where the '?' is A-Z. Otherwise, the value returned by the
X! ASCII() builtin is used.
X!
XPROCEDURE vi$ascii_name (key_n)
X LOCAL
X key;
X
X key := (key_n - CTRL_A_KEY) / (CTRL_B_KEY - CTRL_A_KEY);
X IF (key > 31) OR (key < 0) THEN
X key := ASCII (key_n);
X ELSE
X key := "^" + ASCII(key+65);
X ENDIF;
X
X RETURN (key);
XENDPROCEDURE;
X
X!
X! Perform some mapping of keys to different ASCII values.
X!
XPROCEDURE vi$ascii (key_n)
X IF key_n = F12 THEN
X RETURN (ASCII (8));
X ENDIF;
X IF key_n = F11 THEN
X RETURN (ASCII (27));
X ENDIF;
X IF key_n = PF1 THEN
X RETURN (ASCII (27));
X ENDIF;
X IF key_n = RET_KEY THEN
X RETURN (ASCII (13));
X ENDIF;
X IF key_n = TAB_KEY THEN
X RETURN (ASCII (9));
X ENDIF;
X RETURN (ASCII (key_n));
XENDPROCEDURE;
X
X!
X! Move up by screens
X!
XPROCEDURE vi$prev_screen
X ON_ERROR
X ENDON_ERROR;
X
X MOVE_VERTICAL (-vi$cur_active_count *
X GET_INFO (CURRENT_WINDOW, "VISIBLE_LENGTH"));
X
X vi$position (vi$first_no_space, 0);
XENDPROCEDURE;
X
X!
X! Move down by screens
X!
XPROCEDURE vi$next_screen
X ON_ERROR
X ENDON_ERROR;
X
X MOVE_VERTICAL (vi$cur_active_count *
X (GET_INFO (CURRENT_WINDOW, "VISIBLE_LENGTH") + 2));
X
X vi$position (vi$first_no_space, 0);
XENDPROCEDURE;
X
X!
X! Scroll forward one screen
X!
XPROCEDURE vi$screen_forward
X
X vi$scroll_screen (1);
X
XENDPROCEDURE;
X
X!
X! Scroll back one screen
X!
XPROCEDURE vi$screen_backward
X
X vi$scroll_screen (-1);
X
XENDPROCEDURE;
X
X!
X! Scroll the screen up or down depending on the sign of "how_many_screens"
X! The magnitude actually has effect as well, but is never greater than 1
X! in this use.
X!
XPROCEDURE vi$scroll_screen (how_many_screens)
X
X LOCAL
X scroll_window, ! Window to be scrolled
X this_window, ! Current window
X this_column, ! Current column in scroll_window
X this_row, ! Current row in scroll_window
X old_scroll_top, ! Original value of scroll_top
X old_scroll_bottom, ! Original value of scroll_bottom
X old_scroll_amount; ! Original value of scroll_amount
X
X ! Trap and ignore messages about move beyond buffer boundaries -
X ! just move to top or bottom line of buffer
X
X ON_ERROR
X ENDON_ERROR;
X
X this_window := CURRENT_WINDOW;
X
X scroll_window := this_window;
X
X IF vi$active_count <> 0 THEN
X vi$how_much_scroll := vi$cur_active_count;
X ENDIF;
X
X this_row := GET_INFO (scroll_window, "CURRENT_ROW");
X
X IF this_row = 0 THEN
X this_row := GET_INFO (scroll_window, "VISIBLE_TOP");
X ENDIF;
X
X this_column := GET_INFO (scroll_window, "CURRENT_COLUMN");
X MOVE_HORIZONTAL (-CURRENT_OFFSET);
X
X old_scroll_top := GET_INFO (scroll_window, "SCROLL_TOP");
X old_scroll_bottom := GET_INFO (scroll_window, "SCROLL_BOTTOM");
X old_scroll_amount := GET_INFO (scroll_window, "SCROLL_AMOUNT");
X
X SET (SCROLLING, scroll_window, ON,
X this_row - GET_INFO (scroll_window, "VISIBLE_TOP"),
X GET_INFO (scroll_window, "VISIBLE_BOTTOM") - this_row, 0);
X
X MOVE_VERTICAL (how_many_screens * vi$how_much_scroll);
X vi$update (scroll_window);
X
X IF this_window <> CURRENT_WINDOW THEN
X POSITION (this_window);
X ENDIF;
X
X SET (SCROLLING, scroll_window, ON, old_scroll_top, old_scroll_bottom,
V old_scroll_amount)
X;
XENDPROCEDURE;
X
X!
X! Move forward logical words
X!
XPROCEDURE vi$_word_forward
X vi$position (vi$word_move (1), 0);
XENDPROCEDURE;
X
X!
X! Move backward logical words
X!
XPROCEDURE vi$_word_back
X vi$position (vi$word_move(-1), 0);
XENDPROCEDURE;
X
X!
X! Move by logical word taking into account the repeat count
X!
XPROCEDURE vi$word_move(dir)
X LOCAL
X old_pos,
X pos;
X
X old_pos := MARK (NONE);
X
X IF vi$active_count <= 0 THEN
X vi$active_count := 1;
X ENDIF;
X
X LOOP
X pos := vi$move_logical_word (dir);
X EXITIF pos = 0;
X POSITION (pos);
X vi$active_count := vi$active_count - 1;
X EXITIF vi$active_count = 0;
X ENDLOOP;
X
X vi$yank_mode := VI$IN_LINE_MODE;
X RETURN (vi$retpos (old_pos));
XENDPROCEDURE;
X
X!
X! Move to end of logical word
X!
XPROCEDURE vi$_word_end
X vi$position (vi$word_end, 0);
XENDPROCEDURE;
X
X!
X! Move to end of physical word
X!
XPROCEDURE vi$_full_word_end
X vi$position (vi$full_word_end, 0);
XENDPROCEDURE;
X
X!
X! Move to the end of the current word.
X!
XPROCEDURE vi$word_end
X LOCAL
X old_pos,
X pos;
X
X old_pos := MARK (NONE);
X
X IF vi$active_count <= 0 THEN
X vi$active_count := 1;
X ENDIF;
X
X LOOP
X pos := vi$move_logical_end;
X EXITIF pos = 0;
X POSITION (pos);
X vi$active_count := vi$active_count - 1;
X EXITIF vi$active_count = 0;
X ENDLOOP;
X
X vi$yank_mode := VI$IN_LINE_MODE;
X RETURN (vi$retpos (old_pos));
XENDPROCEDURE;
X
X!
X! Move to the end of a blank (eol is also considered blank) terminated word.
X!
XPROCEDURE vi$full_word_end
X
X LOCAL
X old_pos,
X pos;
X
X old_pos := MARK (NONE);
X
X IF vi$active_count <= 0 THEN
X vi$active_count := 1;
X ENDIF;
X
X LOOP
X pos := vi$move_full_end;
X EXITIF pos = 0;
X POSITION (pos);
X vi$active_count := vi$active_count - 1;
X EXITIF vi$active_count = 0;
X ENDLOOP;
X
X vi$yank_mode := VI$IN_LINE_MODE;
X RETURN (vi$retpos (old_pos));
XENDPROCEDURE;
X
X!
X! Move forward by ONE white-space delimited word
X!
XPROCEDURE vi$_full_word_forward
X vi$position (vi$full_word_move (1), 0);
XENDPROCEDURE;
X
X!
X!
X! Move backward by ONE white-space delimited word
X!
XPROCEDURE vi$_full_word_back
X vi$position (vi$full_word_move (-1), 0);
XENDPROCEDURE;
X
X!
X! Move by physical word taking the repeat count into account
X!
XPROCEDURE vi$full_word_move (dir)
X
X LOCAL
X old_pos,
X pos;
X
X old_pos := MARK (NONE);
X
X IF vi$active_count <= 0 THEN
X vi$active_count := 1;
X ENDIF;
X
X LOOP
X pos := vi$move_full_word (dir);
X EXITIF pos = 0;
X POSITION (pos);
X vi$active_count := vi$active_count - 1;
X EXITIF vi$active_count = 0;
X ENDLOOP;
X
X vi$yank_mode := VI$IN_LINE_MODE;
X RETURN (vi$retpos (old_pos));
XENDPROCEDURE;
X
X!
X! Move the cursor by BLANK separated words. DIRECTION is either
X! +1, or -1 to indicate the direction (forward, or backword respectfully)
X! to move
X!
XPROCEDURE vi$move_full_word (direction)
X
X LOCAL
X pos;
X
X pos := MARK (NONE);
X
$ GoSub Convert_Filemark);
n