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