gregg@a.cs.okstate.edu (Gregg Wonderly) (09/28/88)
Posting-number: Volume 4, Issue 104 Submitted-by: "Gregg Wonderly" <gregg@a.cs.okstate.edu> Archive-name: vms-vi-2/Part13 $ WRITE SYS$OUTPUT "Creating ""VI.9""" $ CREATE VI.9 $ DECK/DOLLARS=$$EOD$$ IF (token_1 = "nomagic") THEN vi$magic := 0; RETURN (0); ENDIF; IF (token_1 = "noerrorbells") OR (token_1 = "noeb") THEN vi$error_bells := 0; RETURN (0); ENDIF; IF (token_1 = "errorbells") OR (token_1 = "eb") THEN vi$error_bells := 1; RETURN (0); ENDIF; IF (token_1 = "nowrapscan") OR (token_1 = "nows") THEN vi$wrap_scan := 0; RETURN (0); ENDIF; IF (token_1 = "wrapscan") OR (token_1 = "ws") THEN vi$wrap_scan := 1; RETURN (0); ENDIF; IF (token_1 = "noupdate") THEN vi$min_update := 1; RETURN (0); ENDIF; IF (token_1 = "update") THEN vi$min_update := 0; RETURN (0); ENDIF; IF (token_1 = "noshowmode") OR (token_1 = "nosm") THEN vi$show_mode := 0; RETURN (0); ENDIF; IF (token_1 = "showmode") OR (token_1 = "sm") THEN vi$show_mode := 1; RETURN (0); ENDIF; IF (token_1 = "wrapmargin") OR (token_1 = "wm") THEN token_2 := vi$skip_separ (cmd, i, "= "+ASCII(9), separ); vi$wrap_margin := INT (token_2); RETURN (0); ENDIF; IF (token_1 = "sections") OR (token_1 = "sect") THEN pstr := "LINE_BEGIN&(("; use_fortran := 0; vi$sect_str := ""; LOOP EXITIF (SUBSTR (cmd, i, 1) = " ") OR (i >= LENGTH (cmd)); npat := SUBSTR (cmd, i, 2); vi$sect_str := vi$sect_str + npat; EDIT (npat, COLLAPSE); IF (npat = "+c") OR (npat = "+C") THEN pstr := pstr + '"{"'; ELSE IF (npat = "+f") OR (npat = "+F") THEN use_fortran := 1; npat := ""; ELSE IF (npat = "+t") OR (npat = "+T") THEN pstr := pstr + '"PROCEDURE"'; ELSE pstr := pstr + '".' + npat + '"'; ENDIF; ENDIF; ENDIF; i := i + 2; EXITIF (SUBSTR (cmd, i, 1) = " ") OR (i >= LENGTH (cmd)); IF (npat <> "") THEN pstr := pstr + "|"; ENDIF; ENDLOOP; pstr := pstr + ")"; IF (use_fortran) THEN pstr := '("FUNCTION"|"SUBROUTINE")|('+ pstr + "))|LINE_END)"; ENDIF; EXECUTE (COMPILE ("vi$sect_pat:="+pstr+";")); RETURN (0); ENDIF; IF (token_1 = "paragraphs") OR (token_1 = "para") THEN pstr := 'LINE_BEGIN&(('; vi$para_str := ""; LOOP EXITIF (SUBSTR (cmd, i, 1) = " ") OR (i >= LENGTH (cmd)); npat := SUBSTR (cmd, i, 2); vi$para_str := vi$para_str + npat; EDIT (npat, COLLAPSE); pstr := pstr + '".' + npat + '"'; i := i + 2; EXITIF (SUBSTR (cmd, i, 1) = " ") OR (i >= LENGTH (cmd)); IF (npat <> "") THEN pstr := pstr + "|"; ENDIF; ENDLOOP; pstr := pstr + ")|LINE_END)"; EXECUTE (COMPILE ("vi$para_pat:="+pstr+";")); RETURN (0); ENDIF; IF (token_1 = "number") OR (token_1 = "optimize") OR (token_1 = "noautoprint") OR (token_1 = "novice") OR (token_1 = "slowopen") OR (token_1 = "noslowopen") OR (token_1 = "beautify") OR (token_1 = "taglength") OR (token_1 = "directory") OR (token_1 = "noprompt") OR (token_1 = "edcompatible") OR (token_1 = "term") OR (token_1 = "noredraw") OR (token_1 = "redraw") OR (token_1 = "terse") OR (token_1 = "flash") OR (token_1 = "noremap") OR (token_1 = "timeout") OR (token_1 = "hardtabs") OR (token_1 = "ttytype") OR (token_1 = "warn") OR (token_1 = "nowarn") OR (token_1 = "lisp") OR (token_1 = "list") OR (token_1 = "sh") OR (token_1 = "shell") OR (token_1 = "mesg") OR (token_1 = "nomesg") OR (token_1 = "showmatch") THEN vi$not_implemented (token_1); RETURN (1); ENDIF; vi$info ("Unrecognized option ("+token_1+ "), use `set all' to see options."); RETURN (1); ENDPROCEDURE; ! ! Set the window length to the integer value passed. ! PROCEDURE vi$do_set_window (len) LOCAL buf, curwin, curbuf; curwin := CURRENT_WINDOW; curbuf := CURRENT_BUFFER; IF (vi$prev_win (curwin) = 0) AND (vi$next_win (curwin) = 0) AND (NOT vi$in_occlusion) THEN IF len < 3 THEN len := 3; ENDIF; IF len > GET_INFO (SCREEN, "VISIBLE_LENGTH") THEN len := GET_INFO (SCREEN, "VISIBLE_LENGTH"); ENDIF; oldscrlen := vi$scr_length; vi$scr_length := len; ADJUST_WINDOW (curwin, 0, vi$scr_length - oldscrlen); buf := GET_INFO (message_window, "BUFFER"); UNMAP (message_window); DELETE (message_window); message_window := CREATE_WINDOW (vi$scr_length - 1, 2, ON); MAP (message_window, buf); SET (STATUS_LINE, message_window, NONE, ""); ADJUST_WINDOW (message_window, 1, 0); DELETE (command_window); command_window := CREATE_WINDOW (vi$scr_length, 1, OFF); buf := GET_INFO (info_window, "BUFFER"); DELETE (info_window); info_window := CREATE_WINDOW (1, vi$scr_length - 1, ON); SET (STATUS_LINE, info_window, NONE, ""); SET (PROMPT_AREA, vi$scr_length, 1, REVERSE); POSITION (curbuf); POSITION (curwin); UNMAP (curwin); MAP (curwin, curbuf); ELSE vi$info ( "Can't change length of screen while multiple windows visible!"); RETURN (1); ENDIF; vi$how_much_scroll := vi$scr_length / 2; RETURN (0); ENDPROCEDURE; ! ! Show the current settings when ":set all" is issued. ! PROCEDURE vi$show_settings LOCAL bname, readonly, obuf, ic, ostat, ovid, buf; buf := vi$init_buffer ("$$vi_set_all$$", ""); ostat := GET_INFO (CURRENT_WINDOW, "STATUS_LINE"); IF (ostat = 0) THEN ostat := ""; ENDIF; ovid := GET_INFO (CURRENT_WINDOW, "STATUS_VIDEO"); IF (ovid = 0) THEN ovid := NONE; ENDIF; SET (STATUS_LINE, CURRENT_WINDOW, NONE, ""); SET (STATUS_LINE, CURRENT_WINDOW, REVERSE, " Current settings of VI options"); SET (EOB_TEXT, buf, " [Hit ENTER to continue editing]"); obuf := CURRENT_BUFFER; POSITION (buf); IF vi$ignore_case = EXACT THEN ic := 2; ELSE ic := 0; ENDIF; COPY_TEXT (FAO ( "!20<wrapmargin=!UL!>!20<tabstop=!UL!>!20<!ASmagic!>!20<!ASignorecase!>", vi$wrap_margin, vi$tab_amount, SUBSTR ("no", 1, (1-vi$magic)*2), SUBSTR ("no", 1, ic))); SPLIT_LINE; COPY_TEXT (FAO ( "!20<shiftwidth=!UL!>!20<scroll=!UL!>!20<report=!UL!>!20<!ASautowrite!>", vi$shift_width, vi$how_much_scroll, vi$report, SUBSTR ("no", 1, (1-vi$auto_write)*2))); SPLIT_LINE; COPY_TEXT (FAO ( "!20<!ASwrapscan!>!20<!ASupdate!>!20<!AStabs!>!20<!ASundomap!>", SUBSTR ("no", 1, (1-vi$wrap_scan)*2), SUBSTR ("no", 1, (vi$min_update)*2), SUBSTR ("no", 1, (1-vi$use_tabs)*2), SUBSTR ("no", 1, (1-vi$undo_map)*2) )); SPLIT_LINE; IF vi$tag_case = EXACT THEN ic := 0; ELSE ic := 2; ENDIF; COPY_TEXT (FAO ( "!20<!AStagcase!>!20<window=!UL!>!20<width=!UL!>tags=!AS", SUBSTR ("no", 1, ic), GET_INFO (CURRENT_WINDOW, "VISIBLE_LENGTH"), GET_INFO (CURRENT_WINDOW, "WIDTH"), vi$tag_files )); SPLIT_LINE; COPY_TEXT (FAO ( "!20<!ASerrorbells!>!20<paragraphs=!AS!>!20<sections=!AS!>"+ "!20<!ASsenddcl!>", SUBSTR ("no", 1, (1-vi$error_bells)*2), vi$para_str, vi$sect_str, SUBSTR ("no", 1, (1-vi$send_dcl)*2) )); SPLIT_LINE; readonly := vi$getbufmode (obuf); COPY_TEXT (FAO ( "!20<!ASshowmode!>!20<!ASautoindent!>!20<!ASempty!>!20<!ASreadonly!>", SUBSTR ("no", 1, (1-vi$show_mode)*2), SUBSTR ("no", 1, (1-vi$auto_indent)*2), SUBSTR ("no", 1, (vi$delete_empty)*2), SUBSTR ("no", 1, (1-readonly)*2) )); SPLIT_LINE; MAP (CURRENT_WINDOW, buf); UPDATE (CURRENT_WINDOW); LOOP EXITIF vi$read_a_key = RET_KEY; ENDLOOP; SET (STATUS_LINE, CURRENT_WINDOW, NONE, ""); SET (STATUS_LINE, CURRENT_WINDOW, ovid, ostat); MAP (CURRENT_WINDOW, obuf); POSITION (obuf); DELETE (buf); ENDPROCEDURE; ! ! ! PROCEDURE vi$makebufname (buf) LOCAL i, ch, bname, nname; nname := ""; bname := GET_INFO (buf, "NAME"); i := 1; LOOP EXITIF i > LENGTH (bname); ch := SUBSTR (bname, i, 1); IF INDEX (vi$_sym_chars, ch) <> 0 THEN nname := nname + ch; ENDIF; i := i + 1; ENDLOOP; RETURN (nname); ENDPROCEDURE; ! ! ! PROCEDURE vi$getbufmode (buf) LOCAL nname; ON_ERROR RETURN (1); ENDON_ERROR; IF (GET_INFO (buf, "SYSTEM")) THEN RETURN (1); ELSE nname := vi$makebufname (buf); vi$global_var := 0; EXECUTE (COMPILE ("vi$global_var := vi$bmode_"+nname)); RETURN (vi$global_var); ENDIF; ENDPROCEDURE; ! ! ! PROCEDURE vi$setbufmode (buf, bmode) LOCAL nname; nname := vi$makebufname (buf); EXECUTE (COMPILE ("vi$bmode_"+nname+":="+STR(bmode))); ENDPROCEDURE; ! ! Function to say that a particular command is not implemented. ! PROCEDURE vi$not_implemented (cmd) vi$info (cmd + " is not implemented!"); ENDPROCEDURE; ! ! The function mapped to 't'. ! PROCEDURE vi$_to_char (char_to_find) LOCAL char_val; char_val := char_to_find; vi$beep_position (vi$to_char (char_val), 0, 1); ENDPROCEDURE; ! ! Function performing task for 't'. ! PROCEDURE vi$to_char (ch_to_find) LOCAL char_to_find, act_count, pos, found; char_to_find := ch_to_find; IF char_to_find = 0 THEN char_to_find := vi$read_char_to_find; ENDIF; vi$last_s_char := char_to_find; vi$last_s_func := "vi$to_char"; pos := MARK(NONE); act_count := vi$cur_active_count; IF (MARK (NONE) = END_OF (CURRENT_BUFFER)) THEN RETURN (0); ENDIF; MOVE_HORIZONTAL (1); IF char_to_find <> ASCII(27) THEN found := 0; LOOP EXITIF (CURRENT_OFFSET >= LENGTH (vi$current_line)); MOVE_HORIZONTAL (1); found := 1; IF (CURRENT_CHARACTER = char_to_find) THEN act_count := act_count - 1; EXITIF (act_count = 0); ENDIF; found := 0; ENDLOOP; IF (NOT found) THEN POSITION (pos); RETURN (0); ELSE vi$move_horizontal (-1); ENDIF; ENDIF; vi$yank_mode := VI$IN_LINE_MODE; RETURN (vi$retpos (pos)); ENDPROCEDURE; ! ! The function mapped to 'T'. ! PROCEDURE vi$_back_to_char (char_to_find) LOCAL char_val; char_val := char_to_find; vi$beep_position (vi$back_to_char (char_val), 0, 1); ENDPROCEDURE; ! ! Function performing task for 'T'. ! PROCEDURE vi$back_to_char (ch_to_find) LOCAL char_to_find, act_count, pos, found; char_to_find := ch_to_find; IF char_to_find = 0 THEN char_to_find := vi$read_char_to_find; ENDIF; vi$last_s_char := char_to_find; vi$last_s_func := "vi$back_to_char"; pos := MARK(NONE); IF (CURRENT_OFFSET = 0) THEN RETURN (0); ENDIF; vi$move_horizontal (-1); IF (CURRENT_CHARACTER <> char_to_find) THEN vi$move_horizontal (1); ENDIF; act_count := vi$cur_active_count; IF char_to_find <> ASCII(27) THEN found := 0; LOOP EXITIF (CURRENT_OFFSET = 0); vi$move_horizontal (-1); found := 1; IF (CURRENT_CHARACTER = char_to_find) THEN act_count := act_count - 1; EXITIF (act_count = 0); ENDIF; found := 0; ENDLOOP; IF (NOT found) THEN POSITION (pos); RETURN (0); ELSE MOVE_HORIZONTAL(1); ENDIF; ENDIF; vi$yank_mode := VI$IN_LINE_MODE; RETURN (vi$retpos (pos)); ENDPROCEDURE; ! ! The function mapped to 'f'. ! PROCEDURE vi$_find_char (char_to_find) LOCAL char_val; char_val := char_to_find; vi$beep_position (vi$find_char (char_val), 0, 1); ENDPROCEDURE; ! ! Function performing task for 'f'. ! PROCEDURE vi$find_char (ch_to_find) LOCAL char_to_find, act_count, pos, found; char_to_find := ch_to_find; IF char_to_find = 0 THEN char_to_find := vi$read_char_to_find; ENDIF; vi$last_s_char := char_to_find; vi$last_s_func := "vi$find_char"; act_count := vi$cur_active_count; IF char_to_find <> ASCII(27) THEN pos := MARK(NONE); found := 0; LOOP EXITIF (CURRENT_OFFSET >= LENGTH (vi$current_line)); MOVE_HORIZONTAL (1); found := 1; IF (CURRENT_CHARACTER = char_to_find) THEN act_count := act_count - 1; EXITIF (act_count = 0); ENDIF; found := 0; ENDLOOP; IF (NOT found) THEN POSITION (pos); RETURN (0); ENDIF; ELSE RETURN (0); ENDIF; vi$yank_mode := VI$IN_LINE_MODE; RETURN (vi$retpos(pos)); ENDPROCEDURE; ! ! The function mapped to 'F'. ! PROCEDURE vi$_back_find_char (char_to_find) LOCAL char_val; char_val := char_to_find; vi$beep_position (vi$back_find_char (char_val), 0, 1); ENDPROCEDURE; ! ! Function performing task for 'F'. ! PROCEDURE vi$back_find_char (ch_to_find) LOCAL char_to_find, act_count, pos, found; char_to_find := ch_to_find; IF char_to_find = 0 THEN char_to_find := vi$read_char_to_find; ENDIF; vi$last_s_char := char_to_find; vi$last_s_func := "vi$back_find_char"; act_count := vi$cur_active_count; IF char_to_find <> ASCII(27) THEN pos := MARK(NONE); LOOP found := 0; EXITIF CURRENT_OFFSET = 0; vi$move_horizontal (-1); found := 1; IF (CURRENT_CHARACTER = char_to_find) THEN act_count := act_count - 1; EXITIF act_count = 0; ENDIF; ENDLOOP; IF (NOT found) THEN POSITION (pos); RETURN (0); ENDIF; ENDIF; vi$yank_mode := VI$IN_LINE_MODE; RETURN (vi$retpos (pos)); ENDPROCEDURE; ! ! Function to read a key, and change TAB_KEY to ASCII (9). Currently ! used by f, F, t and T commands only. ! PROCEDURE vi$read_char_to_find LOCAL rkey; rkey := vi$read_a_key; IF (rkey = TAB_KEY) THEN RETURN (ASCII (9)); ELSE IF (rkey = RET_KEY) THEN RETURN (ASCII (13)); ELSE IF (rkey = DEL_KEY) THEN RETURN (ASCII (8)); ENDIF; ENDIF; ENDIF; RETURN (ASCII (rkey)); ENDPROCEDURE; ! ! The function mapped to 'G'. ! PROCEDURE vi$go_to_line LOCAL opos, curline, pos; opos := MARK (NONE); IF (vi$beep_position (vi$to_line (vi$active_count), 1, 1) <> 0) THEN pos := MARK (NONE); POSITION (opos); vi$pos_in_middle (pos); ENDIF; vi$active_count := 0; ENDPROCEDURE; ! ! Move to line in file. vi$active_count holds the line number to GO TO. ! If VI$ACTIVE_COUNT is zero, we move to the end of the file. ! PROCEDURE vi$to_line (cnt) LOCAL this_pos, ! Saved position in case of botch last_line, ! Last line in the buffer win_len; ! Length of CURRENT_WINDOW ON_ERROR vi$info (FAO ("No such line: !SL", VI$ACTIVE_COUNT)); POSITION (this_pos); cnt := 0; RETURN; ENDON_ERROR; this_pos := MARK(NONE); POSITION (LINE_BEGIN); vi$start_pos := MARK (NONE); IF cnt = 0 THEN POSITION (END_OF (CURRENT_BUFFER)); ELSE last_line := GET_INFO (CURRENT_BUFFER, "RECORD_COUNT"); IF cnt > last_line THEN IF last_line > 0 THEN vi$info ("Not that many lines in buffer"); POSITION (this_pos); RETURN (0); ENDIF; ELSE POSITION (BEGINNING_OF (CURRENT_BUFFER)); win_len := GET_INFO (CURRENT_WINDOW, "VISIBLE_LENGTH"); MOVE_VERTICAL (cnt - 1); ENDIF; ENDIF; IF (MARK (NONE) <> END_OF (CURRENT_BUFFER)) THEN IF (MARK (NONE) = BEGINNING_OF (CURRENT_BUFFER)) THEN vi$new_endpos := MARK (NONE); ELSE MOVE_VERTICAL (1); vi$new_endpos := MARK (NONE); MOVE_VERTICAL (-1); ENDIF; ENDIF; vi$yank_mode := VI$LINE_MODE; RETURN (vi$retpos (this_pos)); ENDPROCEDURE; ! ! Set a marker in the current buffer. ! PROCEDURE vi$_set_mark LOCAL mark_char, mark_name, key_pressed; key_pressed := vi$read_a_key; mark_char := ASCII (key_pressed); IF (INDEX (vi$_lower_chars, mark_char) <> 0) THEN mark_name := "vi$mark_" + mark_char; EXECUTE (COMPILE (mark_name + " := MARK(NONE);")); ELSE vi$info ("Invalid marker key!"); ENDIF; ENDPROCEDURE; ! ! Function mapped to "'" and "`". ! PROCEDURE vi$_go_to_marker LOCAL opos, pos; opos := MARK (NONE); IF (vi$beep_position (vi$to_marker, 1, 1) <> 0) THEN pos := MARK (NONE); POSITION (opos); vi$pos_in_middle (pos); ENDIF; ENDPROCEDURE; ! ! Function to move the marker indicated by the next keystroke. ! PROCEDURE vi$to_marker LOCAL mode_key, pos, mark_name, mark_char, key_pressed; ON_ERROR; vi$info ("Mark not set!"); RETURN (0); ENDON_ERROR; mode_key := vi$last_key; key_pressed := vi$read_a_key; mark_char := ASCII (key_pressed); IF (INDEX (vi$_lower_chars+"'`", mark_char) = 0) THEN vi$info ("Invalid marker key!"); RETURN (0); ENDIF; pos := MARK (NONE); IF (key_pressed <> F11) THEN IF (mark_char = "'") OR (mark_char = "`") THEN IF (vi$old_place <> 0) THEN IF (GET_INFO (vi$old_place, "BUFFER") = CURRENT_BUFFER) THEN POSITION (vi$old_place); ELSE vi$info ("Previous place not in this buffer!"); RETURN (0); ENDIF; ELSE vi$info ("No previous mark to return to!"); RETURN (0); ENDIF; ELSE mark_name := "vi$mark_" + mark_char; EXECUTE (COMPILE ("vi$global_mark := "+mark_name+";")); IF (vi$global_mark <> 0) AND (GET_INFO (vi$global_mark, "BUFFER") = CURRENT_BUFFER) THEN POSITION (vi$global_mark); vi$yank_mode := VI$LINE_MODE; ELSE vi$info ("Invalid mark for this buffer!"); RETURN (0); ENDIF; ENDIF; IF ASCII (mode_key) = "'" THEN POSITION (LINE_BEGIN); POSITION (vi$first_no_space (0)); ENDIF; IF (MARK (NONE) <> END_OF (CURRENT_BUFFER)) THEN MOVE_VERTICAL (1); vi$new_endpos := MARK (NONE); MOVE_VERTICAL (-1); ENDIF; RETURN (vi$retpos (pos)); ENDIF; POSITION (pos); RETURN (0); ENDPROCEDURE; ! ! Maintain the repeat count in vi$active_count. If VI$ACTIVE_COUNT is ZERO, ! and '0' is typed, this means move to beginning of the line. ! PROCEDURE vi$repeat_count a IF VI$ACTIVE_COUNT = 0 THEN vi$active_count := INT (ASCII (KEY_NAME (vi$last_key))); IF vi$active_count = 0 THEN vi$beep_position (vi$fol, 0, 1); ENDIF; ELSE vi$active_count := vi$active_count * 10 + INT (ASCII (KEY_NAME (vi$last_key))); ENDIF; ENDPROCEDURE; ! ! The function mapped to <CR>. ! PROCEDURE vi$_next_line POSITION (vi$beg_next); ENDPROCEDURE; ! ! Move the cursor to the beginning of the next line ! PROCEDURE vi$beg_next LOCAL pos; ON_ERROR RETURN (MARK (NONE)); ENDON_ERROR; pos := MARK (NONE); MOVE_VERTICAL (vi$cur_active_count); POSITION (LINE_BEGIN); POSITION (vi$first_no_space (0)); vi$yank_mode := VI$LINE_MODE; vi$new_offset := 1; RETURN (vi$retpos (pos)); ENDPROCEDURE; ! ! This function moves to the first non-blank character of a line ! PROCEDURE vi$first_no_space (use_cur_active) LOCAL pos, t_range; ON_ERROR ! Ignore string not found messages. IF ERROR <> TPU$_STRNOTFOUND THEN POSITION (pos); RETURN (0); ENDIF; ENDON_ERROR; pos := MARK (NONE); IF (use_cur_active) THEN MOVE_VERTICAL (vi$cur_active_count - 1); ENDIF; POSITION (LINE_BEGIN); IF (LENGTH (CURRENT_LINE) > 0) THEN IF t_range = 0 THEN t_range := SEARCH (ANCHOR & SPAN (vi$no_space) & NOTANY(vi$no_space), FORWARD); ENDIF; IF t_range <> 0 THEN POSITION (END_OF (t_range)); ELSE ! If that fails, then search for a blank line with extra white ! space, and move to the end of the white space. t_range := SEARCH (ANCHOR & SPAN (vi$no_space), FORWARD); IF t_range <> 0 THEN POSITION (END_OF (t_range)); ENDIF; ENDIF; ENDIF; vi$yank_mode := VI$IN_LINE_MODE; RETURN (vi$retpos (pos)); ENDPROCEDURE; ! ! Move by a section in the indicated direction ! PROCEDURE vi$_section (dir) LOCAL ch; ch := vi$read_a_key; IF ((ASCII(ch) = "]") AND (dir = 1)) OR ((ASCII(ch) = "[") AND (dir = -1)) THEN vi$beep_position (vi$section (dir), 1, 1); ELSE vi$beep; ENDIF; ENDPROCEDURE; ! ! Sound a bell. ! PROCEDURE vi$beep LOCAL ln, pos; IF (vi$error_bells = 0) THEN RETURN; ENDIF; pos := MARK (NONE); POSITION (message_buffer); ln := vi$current_line; SET (BELL, ALL, ON); POSITION (pos); vi$info (ln); SET (BELL, ALL, OFF); SET (BELL, BROADCAST, ON); ENDPROCEDURE; ! ! Mapped to '}' and '{', moves by a paragraph in the indicated direction. ! PROCEDURE vi$_paragraph(dir) vi$beep_position (vi$paragraph(dir), 1, 1); ENDPROCEDURE; ! ! Mapped to ( moves backward a sentence ! PROCEDURE vi$_begin_sentence vi$beep_position (vi$begin_sentence, 1, 1); ENDPROCEDURE; ! ! Mapped to ) moves forward a sentence ! PROCEDURE vi$_end_sentence vi$beep_position (vi$end_sentence, 1, 1); ENDPROCEDURE; ! ! Move backward a sentence. ! PROCEDURE vi$begin_sentence LOCAL rng, spos, pos; ON_ERROR; ENDON_ERROR; pos := MARK (NONE); MOVE_HORIZONTAL (-1); LOOP; rng := SEARCH ( (("" | " " | ASCII (9)) & ANY (vi$_upper_chars)), REVERSE, EXACT); EXITIF rng = 0; POSITION (BEGINNING_OF (rng)); IF INDEX (vi$_space_tab, CURRENT_CHARACTER) = 0 THEN MOVE_HORIZONTAL (-1); ENDIF; IF INDEX (vi$_space_tab, CURRENT_CHARACTER) <> 0 THEN IF (CURRENT_CHARACTER = " ") THEN MOVE_HORIZONTAL (-1); IF INDEX (vi$_space_tab, CURRENT_CHARACTER) <> 0 THEN MOVE_HORIZONTAL (-1); IF INDEX ("?.!", CURRENT_CHARACTER) <> 0 THEN MOVE_HORIZONTAL (3); RETURN (vi$retpos (pos)); ENDIF; ENDIF; ELSE MOVE_HORIZONTAL (1); RETURN (vi$retpos (pos)); ENDIF; ENDIF; POSITION (BEGINNING_OF (rng)); MOVE_HORIZONTAL (-1); ENDLOOP; RETURN (0); ENDPROCEDURE; ! ! Move to next paragraph ! PROCEDURE vi$paragraph (dir) RETURN (vi$para_sect (dir, vi$para_pat)); ENDPROCEDURE; ! ! Find next paragraph or section. ! PROCEDURE vi$para_sect (dir, pat) LOCAL loc, direct, pos; pos := MARK (NONE); IF (dir < 0) THEN direct := REVERSE; MOVE_VERTICAL (-1); ELSE direct := FORWARD; MOVE_VERTICAL (1); ENDIF; loc := SEARCH (pat, direct, NO_EXACT); IF (loc <> 0) THEN RETURN (BEGINNING_OF (loc)); ENDIF; POSITION (pos); RETURN (0); ENDPROCEDURE; ! ! Move to next section ! PROCEDURE vi$section (dir) RETURN (vi$para_sect (dir, vi$sect_pat)); ENDPROCEDURE; ! ! Move forward a sentence. ! PROCEDURE vi$end_sentence LOCAL rng, spos, pos; ON_ERROR; ENDON_ERROR; pos := MARK (NONE); MOVE_HORIZONTAL (1); LOOP; rng := SEARCH (ANY (vi$_upper_chars), FORWARD, EXACT); EXITIF rng = 0; POSITION (BEGINNING_OF (rng)); IF INDEX (vi$_space_tab, CURRENT_CHARACTER) = 0 THEN MOVE_HORIZONTAL (-1); ENDIF; IF INDEX (vi$_space_tab, CURRENT_CHARACTER) <> 0 THEN IF (CURRENT_CHARACTER = " ") THEN MOVE_HORIZONTAL (-1); IF INDEX (vi$_space_tab, CURRENT_CHARACTER) <> 0 THEN MOVE_HORIZONTAL (-1); IF INDEX ("?.!", CURRENT_CHARACTER) <> 0 THEN MOVE_HORIZONTAL (3); RETURN (vi$retpos (pos)); ENDIF; ENDIF; ELSE MOVE_HORIZONTAL (1); RETURN (vi$retpos (pos)); ENDIF; ENDIF; POSITION (BEGINNING_OF (rng)); MOVE_HORIZONTAL (1); ENDLOOP; RETURN (0); ENDPROCEDURE; ! ! This function returns the value in vi$active count. It takes into ! account that when vi$active_count is zero, it should really be ! one. ! PROCEDURE vi$cur_active_count LOCAL resp, old_cnt; old_cnt := vi$active_count; vi$active_count := 0; IF old_cnt <= 0 THEN old_cnt := 1; ENDIF; RETURN (old_cnt); ENDPROCEDURE; ! ! The function mapped to 'p'. ! PROCEDURE vi$put_after (dest_buf) LOCAL source, pos; source := vi$cur_text; IF (GET_INFO (dest_buf, "TYPE") = BUFFER) THEN source := dest_buf; ENDIF; IF (GET_INFO (source, "TYPE") = BUFFER) THEN pos := MARK (NONE); POSITION (BEGINNING_OF (source)); vi$yank_mode := INT (vi$current_line); POSITION (pos); ENDIF; IF (source = "") THEN RETURN; ENDIF; IF (vi$yank_mode = VI$LINE_MODE) THEN IF (MARK(NONE) <> END_OF (CURRENT_BUFFER)) THEN MOVE_VERTICAL (1); ENDIF; ELSE IF (LENGTH (CURRENT_LINE) > 0) THEN MOVE_HORIZONTAL (1); ENDIF; ENDIF; vi$put_here (VI$AFTER, source); ENDPROCEDURE; ! ! The function mapped to 'P'. ! PROCEDURE vi$put_here (here_or_below, dest_buf) LOCAL olen, source, pos; source := vi$cur_text; olen := GET_INFO (CURRENT_BUFFER, "RECORD_COUNT"); IF (GET_INFO (dest_buf, "TYPE") = BUFFER) THEN source := dest_buf; ENDIF; IF (GET_INFO (source, "TYPE") = BUFFER) THEN pos := MARK (NONE); POSITION (BEGINNING_OF (source)); IF (MARK (NONE) = END_OF (source)) THEN RETURN; ENDIF; vi$yank_mode := INT (vi$current_line); ERASE_LINE; POSITION (pos); ELSE IF (source = "") THEN RETURN; ENDIF; ENDIF; IF source = 0 THEN vi$info ("Bad buffer for put!"); RETURN; ENDIF; IF (vi$yank_mode = VI$LINE_MODE) THEN POSITION (LINE_BEGIN); ENDIF; pos := vi$get_undo_start; COPY_TEXT (source); APPEND_LINE; MOVE_HORIZONTAL (-1); vi$undo_end := MARK (NONE); MOVE_HORIZONTAL (1); vi$kill_undo; IF (here_or_below = VI$AFTER) AND (vi$yank_mode = VI$LINE_MODE) THEN POSITION (LINE_BEGIN); ENDIF; vi$undo_start := vi$set_undo_start (pos); ! Put the mode back into the buffer. IF (GET_INFO (source, "TYPE") = BUFFER) THEN POSITION (BEGINNING_OF (source)); COPY_TEXT (STR (vi$yank_mode)); SPLIT_LINE; POSITION (vi$undo_start); ENDIF; IF (here_or_below = VI$AFTER) AND (vi$yank_mode = VI$IN_LINE_MODE) THEN POSITION (vi$undo_end); ENDIF; vi$check_length (olen); ENDPROCEDURE; ! ! Function mapped to 'o'. ! PROCEDURE vi$open_below LOCAL uline; ON_ERROR ! Ignore attempt to move past EOB errors ENDON_ERROR; uline := vi$cur_line_no; MOVE_VERTICAL (1); vi$open_here; vi$undo_line := uline; ENDPROCEDURE; ! ! Function mapped to 'O' ! PROCEDURE vi$open_here LOCAL uline, offs, cnt, epos, spos; uline := vi$cur_line_no; offs := CURRENT_OFFSET; POSITION (LINE_BEGIN); IF (MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER)) THEN MOVE_HORIZONTAL (-1); spos := MARK (NONE); MOVE_HORIZONTAL (1); ELSE spos := 0; ENDIF; SPLIT_LINE; MOVE_VERTICAL (-1); cnt := vi$while_not_esc; IF (cnt <> 0) THEN IF (LENGTH(vi$current_line) > 0) THEN MOVE_HORIZONTAL (1); ENDIF; ENDIF; epos := MARK (NONE); vi$undo_end := MARK (NONE); vi$undo_start := vi$set_undo_start (spos); POSITION (epos); vi$kill_undo; vi$undo_line := uline; vi$undo_offset := offs; ENDPROCEDURE; ! ! This function guards the right margin, and the end of the buffer so ! that the cursor never is displayed past those boundries. ! PROCEDURE vi$check_rmarg ON_ERROR; ! ignore "Can't return line and end of buffer" messages RETURN; ENDON_ERROR; IF (LENGTH (vi$current_line) > 0) THEN IF (CURRENT_OFFSET = LENGTH (vi$current_line)) THEN MOVE_HORIZONTAL (-1); ENDIF; ENDIF; IF (MARK (NONE) = END_OF (CURRENT_BUFFER)) THEN MOVE_VERTICAL (-1); ENDIF; ENDPROCEDURE; ! ! The function mapped to 'h'. ! PROCEDURE vi$move_left vi$beep_position (vi$left, 0, 1); ENDPROCEDURE; ! ! The function mapped to 'l'. ! PROCEDURE vi$move_right vi$beep_position (vi$right, 0, 1); ENDPROCEDURE; ! ! The function mapped to 'j' ! PROCEDURE vi$move_down LOCAL save_mark; save_mark := 0; IF (vi$active_count >= vi$report) THEN save_mark := 1; ENDIF; vi$beep_position (vi$downline (0), save_mark, 1); ENDPROCEDURE; ! ! The function mapped to 'k'. ! PROCEDURE vi$move_up LOCAL save_mark; save_mark := 0; IF (vi$active_count >= vi$report) THEN save_mark := 1; ENDIF; vi$beep_position (vi$upline, save_mark, 1); ENDPROCEDURE; ! ! The function mapped to 'i'. ! PROCEDURE vi$insert_here LOCAL act_cnt, rnge, ccnt, epos, spos; vi$kill_undo; IF (MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER)) THEN MOVE_HORIZONTAL (-1); spos := MARK (NONE); MOVE_HORIZONTAL (1); ELSE spos := 0; ENDIF; vi$undo_start := MARK (NONE); ccnt := vi$while_not_esc; vi$undo_end := 0; IF (ccnt > 0) THEN epos := MARK (NONE); IF (MARK (NONE) <> BEGINNING_OF (CURRENT_BUFFER)) THEN MOVE_HORIZONTAL (1); ENDIF; ELSE epos := 0; IF (CURRENT_OFFSET <> 0) THEN MOVE_HORIZONTAL (-1); ENDIF; ENDIF; act_cnt := vi$cur_active_count; IF epos <> 0 THEN IF spos <> 0 THEN POSITION (spos); MOVE_HORIZONTAL (1); ELSE POSITION (BEGINNING_OF (CURRENT_BUFFER)); ENDIF; vi$undo_start := MARK (NONE); POSITION (epos); IF (vi$undo_start = 0) OR (epos = 0) THEN vi$info ("Ooops, bad markers in vi$insert_here"); RETURN ; ENDIF; rnge := CREATE_RANGE (vi$undo_start, epos, NONE); LOOP EXITIF act_cnt < 2; MOVE_HORIZONTAL (1); IF rnge = 0 THEN vi$info ("Ooops, generated a bad range in vi$insert_here"); RETURN ; ENDIF; COPY_TEXT (rnge); act_cnt := act_cnt - 1; MOVE_HORIZONTAL (-1); ENDLOOP; vi$undo_end := MARK (NONE); IF (CURRENT_OFFSET = LENGTH (vi$current_line)) THEN MOVE_HORIZONTAL (1); ENDIF; ENDIF; ENDPROCEDURE; ! ! The function mapped to 'I' ! PROCEDURE vi$insert_at_begin POSITION (LINE_BEGIN); vi$_bol (0); vi$insert_here; ENDPROCEDURE; ! ! The function mapped to 'a' ! PROCEDURE vi$insert_after LOCAL cline, $$EOD$$