home *** CD-ROM | disk | FTP | other *** search
- Path: uunet!husc6!necntc!ncoast!allbery
- From: gregg@a.cs.okstate.edu@mandrill.CWRU.Edu (Gregg Wonderly)
- Newsgroups: comp.sources.misc
- Subject: VI in TPU part 6/13
- Message-ID: <4855@ncoast.UUCP>
- Date: 13 Oct 87 02:51:59 GMT
- Sender: allbery@ncoast.UUCP
- Organization: Oklahoma State Univ., Stillwater
- Lines: 1503
- Approved: allbery@ncoast.UUCP
- X-Archive: comp.sources.misc/8710/vms-vi/6
-
- $ WRITE SYS$OUTPUT "Creating ""VI.5"""
- $ CREATE VI.5
- $ DECK/DOLLARS=$$EOD$$
- ENDIF;
- RETURN;
- ENDIF;
-
- IF (key = TAB_KEY) THEN
- key := ASCII (9);
- ELSE
- IF (key = RET_KEY) THEN
- key := ASCII (13);
- ELSE
- IF (key = DEL_KEY) THEN
- key := ASCII (8);
- ELSE
- key := ASCII (key);
- ENDIF;
- ENDIF;
- ENDIF;
-
- IF ((CURRENT_OFFSET + act_cnt) <= LENGTH (vi$current_line)) THEN
- IF (key = ASCII (13)) THEN
- MOVE_HORIZONTAL (act_cnt);
- ELSE
- MOVE_HORIZONTAL (act_cnt - 1);
- ENDIF;
- vi$save_for_undo (CREATE_RANGE (pos, MARK(NONE), NONE),
- VI$IN_LINE_MODE, 1);
- IF (key = ASCII (13)) THEN
- MOVE_HORIZONTAL (-act_cnt);
- ELSE
- MOVE_HORIZONTAL (-(act_cnt-1));
- ENDIF;
- IF (MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER)) THEN
- MOVE_HORIZONTAL (-1);
- vi$undo_start := MARK (NONE);
- MOVE_HORIZONTAL (1);
- ELSE
- vi$undo_start := 0;
- ENDIF;
-
- SET (OVERSTRIKE, CURRENT_BUFFER);
- LOOP
- IF (key = ASCII (13)) THEN
- SPLIT_LINE;
- ERASE_CHARACTER (1);
- ELSE
- COPY_TEXT (key);
- ENDIF;
- act_cnt := act_cnt - 1;
- EXITIF act_cnt = 0;
- ENDLOOP;
-
- IF (key = ASCII (13)) THEN
- MOVE_HORIZONTAL (1);
- ENDIF;
-
- MOVE_HORIZONTAL (-1);
- vi$undo_end := MARK (NONE);
-
- SET (INSERT, CURRENT_BUFFER);
- IF (vi$undo_start = 0) THEN
- vi$undo_start := BEGINNING_OF (CURRENT_BUFFER);
- ELSE
- pos := MARK (NONE);
- POSITION (vi$undo_start);
- MOVE_HORIZONTAL (1);
- vi$undo_start := MARK (NONE);
- POSITION (pos);
- ENDIF;
- ELSE
- POSITION (pos);
- ENDIF;
-
- IF (vi$show_mode) THEN
- MESSAGE ("");
- ENDIF;
- RETURN;
- ENDPROCEDURE
-
- !
- ! Perform the 'R' command
- !
- PROCEDURE vi$_replace_str
-
- LOCAL
- replace,
- max_mark,
- start_pos,
- spos,
- pos,
- max_col;
-
- pos := MARK (NONE);
- max_col := CURRENT_OFFSET;
- start_pos := max_col;
- MOVE_HORIZONTAL (LENGTH (CURRENT_LINE) - CURRENT_OFFSET);
- max_mark := MARK(NONE);
- vi$undo_end := MARK (NONE);
- POSITION (pos);
- vi$update (CURRENT_WINDOW);
- replace := CURRENT_LINE;
- spos := vi$get_undo_start;
- vi$save_for_undo (CREATE_RANGE (pos, max_mark, NONE), VI$IN_LINE_MODE, 1);
-
- vi$line_edit (max_col, start_pos, max_mark, replace);
- pos := MARK (NONE);
- vi$undo_start := vi$set_undo_start (spos);
- POSITION (pos);
- ENDPROCEDURE;
-
- !
- ! As in REAL vi, this procedure does not recognize a repeat count.
- ! A simple loop would make it possible to use the repeat count contained
- ! in "vi$active_count". A macro is used so that all of the crap for undo
- ! need not be placed here.
- !
- PROCEDURE vi$_change_case
- LOCAL
- pos;
-
- vi$active_count := 0;
- pos := INDEX (vi$_lower_chars, CURRENT_CHARACTER);
- IF pos <> 0 THEN
- vi$do_macro ("r"+SUBSTR (vi$_upper_chars, pos, 1)+"l", 0);
- ELSE
- pos := INDEX (vi$_upper_chars, CURRENT_CHARACTER);
- IF pos <> 0 THEN
- vi$do_macro ("r"+SUBSTR (vi$_lower_chars, pos, 1)+"l", 0);
- ELSE
- vi$kill_undo;
- vi$undo_end := 0;
- MOVE_HORIZONTAL (1);
- ENDIF;
- ENDIF;
-
- ENDPROCEDURE;
-
- !
- !
- !
- PROCEDURE vi$init_action (olen)
- LOCAL
- nchar;
-
- olen := GET_INFO (CURRENT_BUFFER, "RECORD_COUNT");
-
- IF (vi$select_pos = 0) THEN
- nchar := vi$read_a_key;
- IF (INDEX ("123456789", ASCII(nchar)) <> 0) THEN
- vi$active_count := INDEX (vi$_numeric_chars, ASCII(nchar)) - 1;
- LOOP
- nchar := vi$read_a_key;
- EXITIF (INDEX (vi$_numeric_chars, ASCII(nchar)) = 0);
- vi$active_count := vi$active_count *
- 10 + (INDEX (vi$_numeric_chars, ASCII (nchar)) - 1);
- ENDLOOP;
- ENDIF;
- ELSE
- nchar := KEY_NAME (".");
- ENDIF;
- RETURN (nchar);
- ENDPROCEDURE;
-
- !
- !
- !
- PROCEDURE vi$get_prog (nchar)
- IF (vi$select_pos = 0) THEN
- RETURN (LOOKUP_KEY (KEY_NAME (nchar), COMMENT, vi$move_keys));
- ELSE
- RETURN ("vi$get_select_pos");
- ENDIF;
- ENDPROCEDURE;
-
- !
- !
- !
- PROCEDURE vi$do_movement (prog, mtype)
-
- vi$endpos := 0;
- vi$new_endpos := 0;
- vi$command_type := mtype;
-
- EXECUTE (COMPILE ("vi$endpos := " + prog));
- IF vi$new_endpos <> 0 THEN
- vi$endpos := vi$new_endpos;
- ENDIF;
- ENDPROCEDURE;
-
- !
- ! Perform the operations associated with the 'c' command.
- !
- PROCEDURE vi$_change
-
- LOCAL
- max_mark,
- max_col,
- start_col,
- start_offset,
- end_offset,
- start_line,
- end_line,
- cha_range,
- pos,
- olen,
- prog,
- do_back,
- nchar;
-
- ON_ERROR;
- vi$message ("Error occured during change, at line: "+STR(ERROR_LINE));
- POSITION (vi$start_pos);
- RETURN;
- ENDON_ERROR;
-
- vi$new_offset := 1;
- nchar := vi$init_action (olen);
-
- IF (nchar = KEY_NAME ('c')) THEN
- vi$_big_s;
- RETURN;
- ENDIF;
-
- ! If the movement will be backwards, then the region must not include
- ! the current character.
-
- do_back := vi$get_direction (nchar);
-
- IF do_back THEN
- vi$move_horizontal (-1);
- vi$start_pos := MARK (NONE);
- vi$move_horizontal (1);
- ELSE
- vi$start_pos := MARK (NONE);
- ENDIF;
-
- prog := vi$get_prog (nchar);
-
- IF prog <> "" THEN
- vi$do_movement (prog, VI$CHANGE_TYPE);
-
- POSITION (vi$start_pos);
- start_offset := CURRENT_OFFSET;
- MOVE_HORIZONTAL (-CURRENT_OFFSET);
- start_line := MARK (NONE);
- POSITION (vi$start_pos);
-
- IF (vi$endpos <> 0) THEN
- POSITION (vi$endpos);
- MOVE_HORIZONTAL (-CURRENT_OFFSET);
- end_line := MARK (NONE);
- POSITION (vi$endpos);
-
- IF (MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER)) AND
- (NOT do_back) AND
- (INDEX (vi$weird_moves, ASCII (nchar)) = 0) THEN
- vi$move_horizontal (-1);
- ENDIF;
- end_offset := CURRENT_OFFSET + 1;
-
- cha_range := CREATE_RANGE (vi$start_pos, MARK (NONE), NONE);
-
- IF (start_line <> end_line) THEN
- IF (cha_range <> 0) THEN
- POSITION (vi$start_pos);
-
- vi$undo_start := vi$get_undo_start;
-
- vi$save_for_undo (cha_range, vi$yank_mode, 0);
- ERASE (cha_range);
-
- IF (vi$while_not_esc = 0) THEN
- vi$undo_end := 0;
- ELSE
- vi$undo_end := MARK (NONE);
- vi$undo_start := vi$set_undo_start (vi$undo_start);
- POSITION (vi$undo_end);
- ENDIF;
- ELSE
- vi$message ("Internal error while changing!");
- ENDIF;
- ELSE
- IF (cha_range <> 0) THEN
- IF (start_offset < end_offset) THEN
- max_col := end_offset;
- MOVE_HORIZONTAL (1);
- max_mark := MARK (NONE);
- MOVE_HORIZONTAL (-1);
- start_col := start_offset;
- ELSE
- POSITION (vi$start_pos);
- MOVE_HORIZONTAL (1);
- max_col := CURRENT_OFFSET;
- max_mark := MARK (NONE);
- POSITION (vi$start_pos);
- start_col := end_offset - 1;
- ENDIF;
-
- vi$save_for_undo (SUBSTR (vi$current_line, start_col + 1,
- max_col - start_col), vi$yank_mode, 0);
-
- SET (OVERSTRIKE, CURRENT_BUFFER);
- COPY_TEXT ("$");
- SET (INSERT, CURRENT_BUFFER);
-
- IF (start_offset < end_offset) THEN
- POSITION (vi$start_pos);
- ELSE
- POSITION (vi$endpos);
- ENDIF;
-
- vi$update (CURRENT_WINDOW);
-
- vi$undo_start := vi$get_undo_start;
-
- if (vi$line_edit (max_col, start_col, max_mark, 0) = 0) THE
- N
- vi$undo_end := 0;
- IF (start_col <> 0) THEN
- MOVE_HORIZONTAL (1);
- ENDIF;
- ELSE
- IF (CURRENT_OFFSET = 0) THEN
- MOVE_HORIZONTAL (-1);
- vi$undo_end := MARK (NONE);
- MOVE_HORIZONTAL (1);
- ELSE
- vi$undo_end := MARK (NONE);
- ENDIF;
- ENDIF;
-
- pos := MARK (NONE);
-
- vi$undo_start := vi$set_undo_start (vi$undo_start);
- POSITION (pos);
- ELSE
- vi$message ("Internal error while changing!");
- ENDIF;
- ENDIF;
- ELSE
- vi$abort (0);
- ENDIF;
- ELSE
- vi$abort (0);
- ENDIF;
-
- vi$check_length (olen);
- ENDPROCEDURE;
-
- !
- ! Decide which direction the movement will be based on whether or not
- ! the last movement was a t, T, f, F, or other backward movement.
- !
- PROCEDURE vi$get_direction (nchar)
- LOCAL
- do_back;
-
- do_back := 0;
-
- IF ((ASCII (nchar) = ",") AND ((vi$last_s_func = "vi$find_char") OR
- (vi$last_s_func = "vi$to_char"))) OR
- ((ASCII (nchar) = ";") AND ((vi$last_s_func = "vi$back_find_char") OR
- (vi$last_s_func = "vi$back_to_char"))) THEN
- do_back := 1;
- ENDIF;
-
- IF (INDEX (vi$back_moves + vi$weird2_moves, ASCII(nchar)) <> 0) THEN
- do_back := 1;
- ENDIF;
-
- RETURN (do_back);
- ENDPROCEDURE;
-
- !
- ! Given the fact that a select range is active, modify vi$start_pos
- ! to be the start of that range, and return the end of the select
- ! range.
- !
- PROCEDURE vi$get_select_pos
- LOCAL
- pos,
- rng;
-
- rng := SELECT_RANGE;
- IF (rng <> 0) THEN
- pos := MARK (NONE);
- vi$select_pos := 0;
- vi$start_pos := BEGINNING_OF (rng);
- POSITION (END_OF (rng));
- MOVE_HORIZONTAL (1);
- RETURN (vi$retpos (pos));
- ELSE
- vi$select_pos := 0;
- vi$message ("No region selected!");
- ENDIF;
- RETURN (0);
- ENDPROCEDURE;
-
- !
- ! Perform the operations associated with the 'S' command.
- !
- PROCEDURE vi$_big_s
- LOCAL
- max_mark,
- start_pos,
- max_col,
- rng,
- start,
- end,
- pos;
-
- MOVE_HORIZONTAL (-CURRENT_OFFSET);
- MOVE_HORIZONTAL (-1);
- vi$undo_start := MARK (NONE);
- MOVE_HORIZONTAL (1);
-
- IF (MARK (NONE) = BEGINNING_OF (CURRENT_BUFFER)) THEN
- vi$undo_end := 0;
- ENDIF;
-
- start := MARK (NONE);
- IF (LENGTH (vi$current_line) > 0) THEN
- MOVE_VERTICAL (vi$cur_active_count - 1);
- MOVE_HORIZONTAL (LENGTH (vi$current_line) - 1);
- ENDIF;
-
- end := MARK (NONE);
- rng := CREATE_RANGE (start, end, NONE);
- POSITION (start);
- vi$save_for_undo (rng, VI$IN_LINE_MODE, 1);
-
- ERASE (rng);
-
- max_col := CURRENT_OFFSET;
- start_pos := max_col;
- max_mark := MARK(NONE);
-
- vi$update (CURRENT_WINDOW);
-
- IF (vi$line_edit (max_col, start_pos, max_mark, 0) <> 0) THEN
- vi$undo_end := MARK (NONE);
- ELSE
- vi$undo_end := 0;
- ENDIF;
- pos := MARK (NONE);
- vi$undo_start := vi$set_undo_start (vi$undo_start);
- POSITION (pos);
- ENDPROCEDURE;
-
- !
- ! This function performs the operations associated with the '"' command
- ! that allows one of the 26 named buffers, or one of the 10 delete
- ! buffers to be the target of a 'd', 'D', 'x', 'X', 'y', 'Y', 'p' or 'P'
- ! command.
- !
- PROCEDURE vi$select_buffer
- LOCAL
- numeric,
- asc_action,
- action,
- prog,
- buf_name,
- nchar;
-
- ON_ERROR;
- RETURN;
- ENDON_ERROR;
-
- nchar := vi$read_a_key;
- action := vi$read_a_key;
- asc_action := ASCII (action);
- numeric := (INDEX (vi$_numeric_chars, asc_action) <> 0);
-
- IF numeric THEN
- vi$active_count := INDEX (vi$_numeric_chars, asc_action) - 1;
- LOOP
- action := vi$read_a_key;
- asc_action := ASCII (action);
- EXITIF (INDEX (vi$_numeric_chars, asc_action) = 0);
- vi$active_count := (vi$active_count * 10) +
- (INDEX (vi$_numeric_chars, asc_action) - 1)
- ;
- ENDLOOP;
- ENDIF;
-
- IF (asc_action <> 'P') AND (asc_action <> 'p') AND (asc_action <> 'd') AND
- (asc_action <> 'D') AND (asc_action <> 'y') AND (asc_action <> 'Y') AND
- (asc_action <> 'x') AND (asc_action <> 'X') AND (NOT numeric) THEN
-
- vi$message ("Unrecognized buffer action, ignoring: '"+asc_action+"'");
-
- RETURN;
- ENDIF;
-
- IF (INDEX ("123456789", ASCII(nchar)) <> 0) THEN
-
- IF (asc_action <> 'P') AND (asc_action <> 'p') THEN
- RETURN;
- ENDIF;
-
- ! Selected a deletion buffer.
-
- buf_name := "vi$del_buf_"+ASCII(nchar);
-
- ELSE
- IF (INDEX (vi$_letter_chars, ASCII(nchar)) <> 0) THEN
-
- ! Selected a named buffer.
-
- IF (INDEX (vi$_upper_chars, ASCII(nchar)) <> 0) THEN
- nchar := SUBSTR (vi$_lower_chars,
- INDEX (vi$_upper_chars, ASCII(nchar)), 1);
- ENDIF;
-
- buf_name := "vi$ins_buf_"+ASCII(nchar);
-
- ! Only create a buffer if we are going to put something into it.
-
- IF (asc_action <> 'P') AND (asc_action <> 'p') THEN
- EXECUTE (COMPILE ('vi$get_ins_buf(' +
- buf_name + ', "'+buf_name+'");'));
- ELSE
- vi$global_var := 0;
- EXECUTE (COMPILE ("vi$global_var:="+buf_name));
- IF (vi$global_var = 0) THEN
- MESSAGE ("There is nothing in that buffer!");
- RETURN;
- ENDIF;
- ENDIF;
- ELSE
- vi$message ("Invalid buffer!");
- RETURN;
- ENDIF;
- ENDIF;
-
- ! We now have a buffer, and the next command key, so envoke the
- ! proper code.
-
- vi$do_buf_act (asc_action, 'P', "vi$put_here (VI$HERE, "+buf_name+");");
- vi$do_buf_act (asc_action, 'p', "vi$put_after ("+buf_name+");");
- vi$do_buf_act (asc_action, 'd', "vi$_delete (0, "+buf_name+");");
- vi$do_buf_act (asc_action, 'D',
- "vi$_delete (KEY_NAME('$'), "+buf_name+");");
- vi$do_buf_act (asc_action, 'x', "vi$_delete ('l', "+buf_name+");");
- vi$do_buf_act (asc_action, 'X', "vi$_delete ('h', "+buf_name+");");
- vi$do_buf_act (asc_action, 'y', "vi$_yank (0, "+buf_name+");");
- vi$do_buf_act (asc_action, 'Y', "vi$_yank ('y', "+buf_name+");");
- vi$do_buf_act (asc_action, 'Y', "vi$_yank (KEY_NAME('y'), "+buf_name+");")
- ;
- ENDPROCEDURE;
-
- !
- ! Perform action based on key typed and passed data
- !
- PROCEDURE vi$do_buf_act (act_type, look_for, what_to_do)
-
- IF (act_type = look_for) THEN
- EXECUTE (COMPILE (what_to_do));
- ENDIF;
- ENDPROCEDURE;
-
- !
- ! Create a buffer named 'bname' providing that there is not already a
- ! buffer by that name.
- !
- PROCEDURE vi$get_ins_buf (buf, bname)
-
- IF (buf = 0) THEN
- buf := vi$init_buffer (bname, "");
- ENDIF;
-
- IF buf = 0 THEN
- vi$message ("Error creating named buffer!");
- ENDIF;
- ENDPROCEDURE;
-
- !
- ! Perform the delete command tied to the 'd' key.
- !
- PROCEDURE vi$_delete (opchar, dest_buf)
-
- LOCAL
- olen,
- old_offset,
- new_offset,
- era_range,
- opos,
- prog,
- do_back,
- nchar;
-
- ON_ERROR;
- vi$message ("Error occured during delete, at line: "+STR(ERROR_LINE));
- POSITION (vi$start_pos);
- RETURN;
- ENDON_ERROR;
-
- vi$new_offset := 1;
- nchar := opchar;
-
- opos := MARK (NONE);
- IF (nchar = 0) THEN
- nchar := vi$init_action (olen);
- ELSE
- olen := GET_INFO (CURRENT_BUFFER, "RECORD_COUNT");
- ENDIF;
-
- ! If the movement will be backwards, then the region must not include
- ! the current character.
-
- old_offset := -1;
- new_offset := -1;
-
- do_back := vi$get_direction (nchar);
-
- IF do_back THEN
- old_offset := CURRENT_OFFSET;
- vi$move_horizontal (-1);
- new_offset := CURRENT_OFFSET;
- ENDIF;
-
- vi$start_pos := MARK (NONE);
-
- ! For "dh" or "X" (a macro of "dh"), we must let vi$left do the movement.
-
- IF (INDEX (vi$weird2_moves, ASCII(nchar)) <> 0) AND
- (old_offset <> new_offset) THEN
- MOVE_HORIZONTAL (1);
- ENDIF;
-
- prog := vi$get_prog (nchar);
-
- IF prog <> "" THEN
- vi$do_movement (prog, VI$DELETE_TYPE);
-
- IF (vi$endpos <> 0) THEN
- POSITION (vi$endpos);
-
- IF (MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER)) AND
- (NOT do_back) AND
- (INDEX (vi$weird_moves, ASCII (nchar)) = 0) THEN
- MOVE_HORIZONTAL (-1);
- ENDIF;
-
- era_range := CREATE_RANGE (vi$start_pos, MARK (NONE), NONE);
-
- IF (era_range <> 0) THEN
- IF (GET_INFO (dest_buf, "TYPE") = INTEGER) THEN
- vi$cur_text := vi$put2del_buf (vi$yank_mode, era_range);
- ELSE
- vi$type2buf (STR (vi$yank_mode), dest_buf);
- vi$cur_text := vi$cp2buf (era_range, dest_buf);
- ENDIF;
-
- vi$undo_end := 0;
- vi$undo_start := vi$start_pos;
- POSITION (BEGINNING_OF (era_range));
- vi$save_for_undo (era_range, vi$yank_mode, 1);
- ERASE (era_range);
- ELSE
- vi$message ("Internal error while deleting!");
- ENDIF;
- POSITION (vi$start_pos);
- ELSE
- vi$abort (0);
- POSITION (opos);
- ENDIF;
- ELSE
- POSITION (opos);
- vi$abort (0);
- ENDIF;
-
- vi$check_length (olen);
- ENDPROCEDURE;
-
- !
- ! This procedure checks a change in the size of the buffer, and reports
- ! the change if it is greater than the number set with ":set report"
- !
- PROCEDURE vi$check_length (olen)
- LOCAL
- nlen;
-
- nlen := GET_INFO (CURRENT_BUFFER, "RECORD_COUNT");
-
- IF (nlen - vi$report) >= olen THEN
- vi$message (STR (nlen - olen) + " more lines!");
- ELSE
- IF (nlen + vi$report <= olen) THEN
- vi$message (STR (olen - nlen) + " fewer lines!");
- ENDIF;
- ENDIF;
- ENDPROCEDURE;
-
- !
- ! Perform the yank command tied to the 'y' key.
- !
- PROCEDURE vi$_yank (opchar, dest_buf)
-
- LOCAL
- old_offset,
- new_offset,
- pos,
- oline,
- nline,
- yank_range,
- prog,
- do_back,
- nchar;
-
- ON_ERROR;
- vi$message ("Error occured during yank, at line: "+STR(ERROR_LINE));
- POSITION (vi$start_pos);
- RETURN;
- ENDON_ERROR;
-
- nchar := opchar;
- pos := MARK (NONE);
-
- IF nchar = 0 THEN
- nchar := vi$init_action (oline);
- ENDIF;
-
- old_offset := -1;
- new_offset := -1;
-
- ! If the movement will be backwards, then the region must not include
- ! the current character.
-
- do_back := vi$get_direction (nchar);
-
- IF do_back THEN
- old_offset := CURRENT_OFFSET;
- vi$move_horizontal (-1);
- new_offset := CURRENT_OFFSET;
- ENDIF;
-
- vi$start_pos := MARK (NONE);
-
- ! For "yl" and similar moves, we must let vi$left to the movement.
-
- IF (INDEX (vi$weird2_moves, ASCII(nchar)) <> 0) AND
- (old_offset <> new_offset) THEN
- MOVE_HORIZONTAL (1);
- ENDIF;
-
- prog := vi$get_prog (nchar);
-
- IF prog <> "" THEN
- vi$do_movement (prog, VI$YANK_TYPE);
-
- oline := vi$cur_line_no;
- IF (vi$endpos <> 0) THEN
- POSITION (vi$endpos);
- nline := vi$abs (vi$cur_line_no - oline);
- IF (nline >= vi$report) THEN
- vi$message (STR (nline) + " lines yanked");
- ENDIF;
- IF (MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER)) AND
- (NOT do_back) AND
- (INDEX (vi$weird_moves, ASCII (nchar)) = 0) THEN
- MOVE_HORIZONTAL (-1);
- ENDIF;
-
- yank_range := CREATE_RANGE (vi$start_pos, MARK (NONE), NONE);
-
- IF (yank_range <> 0) THEN
- IF (GET_INFO (dest_buf, "TYPE") = INTEGER) THEN
- vi$cur_text := vi$put2yank_buf (yank_range, vi$temp_buf);
- ELSE
- vi$cur_text := vi$put2yank_buf (yank_range, dest_buf);
- ENDIF;
- ELSE
- vi$message ("Internal error while yanking!");
- ENDIF;
- ELSE
- vi$abort (0);
- ENDIF;
-
- POSITION (pos);
- ELSE
- vi$abort (0);
- ENDIF;
-
- ENDPROCEDURE;
-
- !
- ! Return the absolute value of the value passed.
- !
- PROCEDURE vi$abs (val)
- IF val < 0 THEN
- RETURN (-val);
- ENDIF;
- RETURN (val);
- ENDPROCEDURE;
-
- !
- ! Given a range of a buffer, or a string, place it into the "kill-ring"
- ! sliding the text back one slot that is already there.
- !
- PROCEDURE vi$put2del_buf (mode, string_parm)
-
- LOCAL
- local_str,
- pos;
-
- pos := MARK (NONE);
-
- IF (mode = VI$LINE_MODE) THEN
-
- ! Slide each range back one slot, throwing away the last.
-
- vi$mv2buf (vi$del_buf_8, vi$del_buf_9);
- vi$mv2buf (vi$del_buf_7, vi$del_buf_8);
- vi$mv2buf (vi$del_buf_6, vi$del_buf_7);
- vi$mv2buf (vi$del_buf_5, vi$del_buf_6);
- vi$mv2buf (vi$del_buf_4, vi$del_buf_5);
- vi$mv2buf (vi$del_buf_3, vi$del_buf_4);
- vi$mv2buf (vi$del_buf_2, vi$del_buf_3);
- vi$mv2buf (vi$del_buf_1, vi$del_buf_2);
-
- ! Place the new text at the front.
-
- vi$type2buf (STR(mode), vi$del_buf_1);
- vi$cp2buf (string_parm, vi$del_buf_1);
- ENDIF;
-
- ! Save the text so that a normal 'p' or 'P' command also works.
-
- vi$type2buf (STR(mode), vi$temp_buf);
- vi$cp2buf (string_parm, vi$temp_buf);
-
- POSITION (pos);
- RETURN (vi$temp_buf);
- ENDPROCEDURE;
-
- !
- ! Copy the text specified by source into the delete buffer given by
- ! dest. If dest is zero, the it will be set to the value of a newly
- ! created buffer.
- !
- PROCEDURE vi$cp2buf (source, dest)
- LOCAL
- pos;
-
- pos := MARK (NONE);
-
- IF (source <> 0) THEN
- IF (dest = 0) THEN
- dest := vi$init_buffer ("TEMP_BUF_"+str(vi$temp_buf_num), "");
- vi$temp_buf_num := vi$temp_buf_num + 1;
- ENDIF;
-
- POSITION (dest);
- COPY_TEXT (source);
- ENDIF;
-
- POSITION (pos);
- ENDPROCEDURE;
-
- !
- ! vi$mv2buf is like vi$cp2buf except that vi$mv2buf erases the buffer before
- ! performing the copy.
- !
- PROCEDURE vi$mv2buf (source, dest)
- LOCAL
- pos;
-
- pos := MARK (NONE);
-
- IF (source <> 0) THEN
- IF (dest = 0) THEN
- dest := vi$init_buffer ("TEMP_BUF_"+str(vi$temp_buf_num), "");
- vi$temp_buf_num := vi$temp_buf_num + 1;
- ELSE
- ERASE (dest);
- ENDIF;
-
- POSITION (dest);
- COPY_TEXT (source);
- ENDIF;
-
- POSITION (pos);
- ENDPROCEDURE;
-
- !
- ! Given the string representation of either VI$LINE_MODE or VI$IN_LINE_MODE,
- ! place that text into the buffer given by dest.
- !
- PROCEDURE vi$type2buf (source, dest)
- LOCAL
- pos;
-
- pos := MARK (NONE);
-
- IF (source <> 0) THEN
- IF (dest = 0) THEN
- dest := vi$init_buffer ("TEMP_BUF_"+str(vi$temp_buf_num), "");
- vi$temp_buf_num := vi$temp_buf_num + 1;
- ELSE
- ERASE (dest);
- ENDIF;
-
- POSITION (BEGINNING_OF (dest));
- COPY_TEXT (source);
- SPLIT_LINE;
- ENDIF;
-
- POSITION (pos);
- ENDPROCEDURE;
-
- !
- ! Save a piece of yanked text including the mode that it was yanked.
- !
- PROCEDURE vi$put2yank_buf (string_parm, dest_buf)
-
- LOCAL
- pos;
-
- pos := MARK (NONE);
-
- ! Set type of text in buffer.
-
- vi$type2buf (STR (vi$yank_mode), dest_buf);
- vi$cp2buf (string_parm, dest_buf);
- POSITION (pos);
-
- RETURN (dest_buf);
- ENDPROCEDURE;
-
- !
- ! This is a debugging procedure used to view the contents of a buffer.
- ! It displays the buffer indicated by 'buf', and sets the status line
- ! of the window displayed to contain the text given by 'stat_line'.
- !
- PROCEDURE vi$show_buf (buf, stat_line)
- LOCAL
- this_key,
- pos,
- new_win;
-
- IF (GET_INFO (buf, "TYPE") <> BUFFER) THEN
- vi$message ("show_buf called with non_buffer, message: "+stat_line);
- RETURN;
- ENDIF;
-
- pos := MARK (NONE);
- new_win := CREATE_WINDOW (1, 23, ON);
- MAP (new_win, buf);
- POSITION (buf);
- SET (STATUS_LINE, new_win, REVERSE, stat_line +
- ", BUFFER NAME: '"+GET_INFO (buf, "NAME")+"'");
- vi$pos_in_middle (MARK (NONE));
- UPDATE (new_win);
- LOOP
- vi$message ("Press RETURN to continue editing...");
- this_key := READ_KEY;
- EXITIF (this_key = RET_KEY);
-
- IF (this_key = CTRL_D_KEY) OR
- (this_key = CTRL_U_KEY) OR
- (this_key = CTRL_F_KEY) OR
- (this_key = CTRL_B_KEY) OR
- (this_key = KEY_NAME ('h')) OR
- (this_key = KEY_NAME ('j')) OR
- (this_key = KEY_NAME ('k')) OR
- (this_key = KEY_NAME ('l')) THEN
-
- EXECUTE (LOOKUP_KEY (this_key, PROGRAM, vi$cmd_keys));
- UPDATE (new_win);
- ENDIF;
- ENDLOOP;
-
- UNMAP (new_win);
- DELETE (new_win);
- POSITION (pos);
- UPDATE (CURRENT_WINDOW);
- ENDPROCEDURE;
-
- !
- ! This procedure moves the cursor down the number of lines indicated by
- ! vi$active count. The parameter passed is used by delete and yank
- ! operations to differentiate them from normal cursor movement.
- !
- PROCEDURE vi$downline (adj)
-
- LOCAL
- pos,
- tabstops,
- cur_off,
- offset;
-
- ! Ignore error messages
-
- ON_ERROR
- vi$active_count := 0;
- POSITION (pos);
- RETURN (0);
- ENDON_ERROR;
-
- pos := MARK (NONE);
-
- MOVE_HORIZONTAL (-CURRENT_OFFSET);
- vi$start_pos := MARK (NONE);
-
- POSITION (pos);
-
- tabstops := GET_INFO (CURRENT_BUFFER, "TAB_STOPS");
-
- IF (GET_INFO (tabstops, "TYPE") <> STRING) THEN
- offset := CURRENT_OFFSET;
- cur_off := GET_INFO (SCREEN, "CURRENT_COLUMN") - 1;
- MOVE_VERTICAL (vi$cur_active_count + adj);
- MOVE_HORIZONTAL (-CURRENT_OFFSET);
- IF (vi$new_offset = 1) THEN
- vi$max_offset := cur_off;
- vi$new_offset := 0;
- ELSE
- IF (cur_off < vi$max_offset) THEN
- cur_off := vi$max_offset;
- ENDIF;
- ENDIF;
-
- ! Save the beginning of the line as the new beginning.
-
- vi$new_endpos := MARK (NONE);
- vi$to_offset (CURRENT_LINE, cur_off, tabstops);
- ELSE
- MOVE_VERTICAL (vi$cur_active_count + adj);
- ENDIF;
-
- vi$yank_mode := VI$LINE_MODE;
- RETURN (vi$retpos (pos));
- ENDPROCEDURE;
-
- !
- ! Move left one location. Do not wrap at edge of the screen.
- !
- PROCEDURE vi$left
-
- LOCAL
- pos;
-
- ! Ignore error messages
-
- ON_ERROR
- vi$active_count := 0;
- POSITION (pos);
- RETURN (0);
- ENDON_ERROR;
-
- pos := MARK (NONE);
-
- vi$new_offset := 1;
- IF (CURRENT_OFFSET < vi$active_count) OR (CURRENT_OFFSET = 0) THEN
- vi$active_count := 0;
- RETURN (0);
- ENDIF;
-
- MOVE_HORIZONTAL (-vi$cur_active_count);
- vi$yank_mode := VI$IN_LINE_MODE;
- RETURN (vi$retpos (pos));
- ENDPROCEDURE;
-
- !
- ! Move right one location. Stop at the end of the line, but, do not
- ! wrap at edge of the screen.
- !
- PROCEDURE vi$right
-
- LOCAL
- pos,
- line,
- offset;
-
- ! Ignore error messages
-
- ON_ERROR
- vi$active_count := 0;
- POSITION (pos);
- RETURN (0);
- ENDON_ERROR
-
- pos := MARK (NONE);
-
- line := CURRENT_LINE;
- offset := CURRENT_OFFSET;
-
- ! This makes it possible to use the "s" command at the end of the line.
-
- IF (vi$command_type = VI$CHANGE_TYPE) THEN
- offset := offset - 1;
- IF (LENGTH (CURRENT_LINE) = 0) THEN
- COPY_TEXT (" ");
- MOVE_HORIZONTAL (-1);
- vi$start_pos := MARK (NONE);
- ENDIF;
- ENDIF;
-
- IF (vi$active_count < (LENGTH (line) - offset -
- (vi$command_type = VI$OTHER_TYPE))) THEN
- MOVE_HORIZONTAL (vi$cur_active_count);
- ELSE
- vi$active_count := 0;
- RETURN (0);
- ENDIF;
-
- vi$new_offset := 1;
-
- vi$yank_mode := VI$IN_LINE_MODE;
- RETURN (vi$retpos (pos));
- ENDPROCEDURE;
-
- !
- ! Move up one row, staying in the same column. Scroll if necessary.
- !
- PROCEDURE vi$upline
-
- LOCAL
- pos,
- tabstops,
- offset,
- cur_off;
-
- ! Ignore error messages
-
- ON_ERROR
- vi$active_count := 0;
- POSITION (pos);
- RETURN (0);
- ENDON_ERROR;
-
- pos := MARK (NONE);
-
- tabstops := GET_INFO (CURRENT_BUFFER, "TAB_STOPS");
-
- MOVE_HORIZONTAL (-CURRENT_OFFSET);
- MOVE_HORIZONTAL (LENGTH(vi$current_line) + 1);
- vi$new_endpos := MARK(NONE);
-
- POSITION (pos);
-
- ! We must understand it (i.e. it must be an integer) inorder to process
- ! the tabs properly.
-
- IF (GET_INFO (tabstops, "TYPE") <> STRING) THEN
- offset := CURRENT_OFFSET;
-
- cur_off := GET_INFO (SCREEN, "CURRENT_COLUMN") - 1;
- MOVE_VERTICAL(-vi$cur_active_count);
- MOVE_HORIZONTAL (-CURRENT_OFFSET);
-
- IF vi$new_offset = 1 THEN
- vi$max_offset := cur_off;
- vi$new_offset := 0;
- ENDIF;
-
- IF (cur_off < vi$max_offset) THEN
- cur_off := vi$max_offset;
- ENDIF;
-
- ! Save the beginning of the line as the new beginning.
-
- vi$start_pos := MARK (NONE);
- vi$to_offset (CURRENT_LINE, cur_off, tabstops);
- ELSE
- MOVE_VERTICAL (-vi$cur_active_count);
- ENDIF;
- vi$yank_mode := VI$LINE_MODE;
- RETURN (vi$retpos (pos));
- ENDPROCEDURE;
-
- !
- ! Move the cursor to the offset given by 'offset' counting tabs as expanded
- ! spaces.
- !
- PROCEDURE vi$to_offset (line, offset, tabstops)
- LOCAL
- cur_ch,
- col,
- diff,
- len,
- tab,
- idx;
-
- idx := 1;
- col := 0;
- len := LENGTH (line);
- tab := ASCII (9);
-
- LOOP
- EXITIF (len < idx) OR (col >= offset);
- IF (SUBSTR (line, idx, 1) = tab) THEN
- diff := (((col+tabstops)/tabstops)*tabstops)-col;
- ELSE
- diff := 1;
- ENDIF;
- col := col + diff;
- idx := idx + 1;
- ENDLOOP;
-
- ! Move N characters to the right.
-
- MOVE_HORIZONTAL (idx - 1);
- ENDPROCEDURE;
-
- !
- ! Search for a text string. This procedure is activated by typing
- ! either a '/' or a '?'.
- !
- PROCEDURE vi$search (direction)
- LOCAL
- where,
- i,
- pos,
- ch,
- sstr,
- cnt,
- add_spec,
- prompt;
-
- pos := MARK (NONE);
-
- IF (direction > 0) THEN
- prompt := "/";
- ELSE
- prompt := "?";
- ENDIF;
-
- IF (vi$read_a_line (prompt, sstr) = 0) THEN
- RETURN (0);
- ENDIF;
-
- i := 1;
- LOOP
- EXITIF (i > LENGTH (sstr));
- ch := SUBSTR (sstr, i, 1);
- IF (ch = "\") THEN
- i := i + 1;
- ELSE
- EXITIF (ch = prompt);
- ENDIF;
- i := i + 1;
- ENDLOOP;
-
- add_spec := 0;
- IF (ch = prompt) THEN
- add_spec := SUBSTR (sstr, i+1, 255);
- sstr := SUBSTR (sstr, 1, i-1);
- MESSAGE("add_spec: "+add_spec);
- MESSAGE("sstr: "+sstr);
- ENDIF;
-
- IF (direction > 0) THEN
- SET (FORWARD, CURRENT_BUFFER);
- vi$last_search_dir := 1;
- MOVE_HORIZONTAL (1);
- ELSE
- SET (REVERSE, CURRENT_BUFFER);
- vi$last_search_dir := -1;
- ENDIF;
-
- IF sstr <> "" THEN
- vi$search_string := sstr;
- ELSE
- IF vi$search_string = 0 THEN
- vi$message ("No previous string to search for!");
- POSITION (pos);
- RETURN (0);
- ENDIF;
- ENDIF;
-
- ! On success then return the position we moved to.
-
- cnt := vi$cur_active_count;
- LOOP
- where := vi$find_str (vi$search_string, 0);
- EXITIF (where = 0);
- POSITION (BEGINNING_OF (where));
- IF (CURRENT_DIRECTION = FORWARD) THEN
- MOVE_HORIZONTAL (1);
- ELSE
- MOVE_HORIZONTAL (-1);
- ENDIF;
- cnt := cnt - 1;
- EXITIF cnt = 0;
- ENDLOOP;
-
- IF (where = 0) THEN
- vi$message ("String not found");
- ELSE
- IF add_spec <> 0 THEN
- POSITION (where);
- IF add_spec = "-" THEN
- add_spec := "-1";
- ELSE
- IF (SUBSTR (add_spec, 1, 1) = "+") THEN
- IF (add_spec = "+") THEN
- add_spec := "1";
- ENDIF;
- ELSE
- add_spec := SUBSTR (add_spec, 2, 255);
- ENDIF;
- ENDIF;
-
- i := INT (add_spec);
- MOVE_VERTICAL (i);
- vi$_bol;
- where := MARK (NONE);
- ENDIF;
- MESSAGE ("");
- ENDIF;
-
- POSITION (pos);
- RETURN (where);
- ENDPROCEDURE;
-
- !
- ! Search for the next occurence of the previously searched for string.
- ! The procedure is actived by typing an 'n' or 'N' keystroke.
- !
- PROCEDURE vi$search_next (direction)
- LOCAL
- prompt,
- where,
- pos,
- cnt,
- sstr;
-
- pos := MARK (NONE);
-
- IF vi$search_string = 0 THEN
- vi$message ("No previous string to search for!");
- POSITION (pos);
- RETURN (0);
- ENDIF;
-
- IF (direction > 0) THEN
- prompt := "/" + vi$search_string;
- SET (FORWARD, CURRENT_BUFFER);
- IF (MARK (NONE) <> END_OF (CURRENT_BUFFER)) THEN
- MOVE_HORIZONTAL (1);
- ELSE
- IF (vi$wrap_scan = 1) THEN
- POSITION (BEGINNING_OF (CURRENT_BUFFER));
- ENDIF;
- ENDIF;
- ELSE
- prompt := "?" + vi$search_string;
- SET (REVERSE, CURRENT_BUFFER);
- IF (MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER)) THEN
- IF (SUBSTR (prompt, 1, 3) = "?\<") THEN
- MOVE_HORIZONTAL (-2);
- ELSE
- MOVE_HORIZONTAL (-1);
- ENDIF;
- ELSE
- IF (vi$wrap_scan = 1) THEN
- POSITION (END_OF (CURRENT_BUFFER));
- ENDIF;
- ENDIF;
- ENDIF;
-
- vi$message (prompt);
-
- ! On success then return the position we moved to.
-
- cnt := vi$cur_active_count;
- LOOP
- where := vi$find_str (vi$search_string, 0);
- EXITIF (where = 0);
- POSITION (BEGINNING_OF (where));
- IF (CURRENT_DIRECTION = FORWARD) THEN
- MOVE_HORIZONTAL (1);
- ELSE
- MOVE_HORIZONTAL (-1);
- ENDIF;
- cnt := cnt - 1;
- EXITIF cnt = 0;
- ENDLOOP;
-
- IF (where = 0) THEN
- vi$message ("String not found");
- ELSE
- vi$message ("");
- ENDIF;
-
- POSITION (pos);
- RETURN (where);
- ENDPROCEDURE;
-
- !
- ! This procedure can be used to find a string of text (using RE's).
- ! The current direction of the BUFFER is used to determine which way
- ! the search goes. 'replace' is used by the replace code to indicate
- ! that wrap scan should be performed.
- !
- PROCEDURE vi$find_str (sstr, replace)
- LOCAL
- pos,
- new_pat,
- start,
- where;
-
- ON_ERROR
- ENDON_ERROR;
-
- pos := MARK (NONE);
- IF vi$magic THEN
- new_pat := vi$re_pattern_gen (sstr);
- ELSE
- new_pat := vi$pattern_gen (sstr);
- ENDIF;
-
- IF (new_pat <> 0) THEN
- EXECUTE (COMPILE ("vi$_find_pat := " + new_pat));
- where := SEARCH (vi$_find_pat, CURRENT_DIRECTION, vi$ignore_case);
- IF (where = 0) AND (vi$wrap_scan = 1) AND (replace = 0) THEN
- IF (CURRENT_DIRECTION = FORWARD) THEN
- POSITION (BEGINNING_OF (CURRENT_BUFFER));
- ELSE
- POSITION (END_OF (CURRENT_BUFFER));
- ENDIF;
- where := SEARCH (vi$_find_pat, CURRENT_DIRECTION, vi$ignore_case);
- ENDIF;
- ELSE
- where := 0;
- ENDIF;
-
- IF (where <> 0) AND (vi$in_ws) THEN
- POSITION (BEGINNING_OF (where));
- IF (CURRENT_OFFSET <> 0) OR
- (INDEX (vi$_ws, CURRENT_CHARACTER) <> 0) THEN
- MOVE_HORIZONTAL (1);
- ENDIF;
- start := MARK (NONE);
- POSITION (END_OF (where));
- IF (CURRENT_OFFSET <> LENGTH (CURRENT_LINE)) THEN
- MOVE_HORIZONTAL (-1);
- ENDIF;
- where := CREATE_RANGE (start, MARK (NONE), NONE);
- POSITION (pos);
- ENDIF;
- RETURN (where);
- ENDPROCEDURE;
-
- !
- ! Generate a TPU pattern string, not using RE's, i.e. :set nomagic is
- ! in effect when this routine is used.
- !
- PROCEDURE vi$pattern_gen (pat)
-
- LOCAL
- first, ! First pattern to be done
- part_pat,
- chno,
- startchar,
- haveany,
- regular,
- tstr,
- endchar,
- str_pat,
- cur_pat, ! The current pattern to be extracted
- cur_char, ! The current character in the regular
- ! expression being examined
- new_pat, ! The output pattern
- pos; ! The position within the regular
- ! expression string that we are examining
- ! currently
-
- IF (INDEX (pat, "$") <> 0) OR (INDEX (pat, "^") <> 0) THEN
- new_pat := "";
- ELSE
- new_pat := '"'+pat+'"';
- RETURN (new_pat);
- ENDIF;
-
- pos := 1;
-
- IF SUBSTR (pat, pos, 1) = "^" THEN
- IF LENGTH (pat > 1) THEN
- new_pat := "line_begin & '";
- ELSE
- new_pat := "line_begin";
- ENDIF;
- pos := pos + 1;
- ENDIF;
-
- LOOP
- EXITIF (pos > LENGTH (pat));
-
- regular := 0;
- cur_pat := "";
- cur_char := substr (pat, pos, 1);
-
- IF (cur_char = "$") AND (pos+1 >= LENGTH (pat)) THEN
- IF pos <> 1 THEN
- cur_pat := "' & line_end";
- ELSE
- cur_pat := "line_end";
- $$EOD$$
-