!       ABEL_MOVE.TPU
!
!       Table of Contents as of 27-Mar-1988
!
!       Procedure name              Page    Description
!       --------------              ----    -----------
!
!       eve_move_up                    1    Move up 1 line
!       eve_move_down                  1    Move down 1 line
!       eve$move_by_screen             2    Moves by screenfuls
!       eve_move_by_character          3    Move by 1 char in current direction
!       eve_move_by_line               4    Move intelligently in current dir
!       eve_scroll                     5    Scroll in current direction
!       eve_move_by_page               6    Move by form feeds in current dir
!       eve_line                       7    Go to line or percentage of buffer
!       eve_move_window                8    Move window with arrows

!                                                                       Page 1


procedure eve_move_up                   ! Move up 1 line

! Support buffered scrolling in the eve_move_up and eve_move_down routines,
! similar to EDT.  This gets a little bit tricky.  DEC used the cursor_vertical
! command to get the free cursor motion, but that doesn't call the screen
! manager when its done, so if buffered scrolling regions are set, it will act
! like it they aren't.  And even after forcing a screen manager update, it has
! the wrong idea of where the cursor is horizontally on the line.  The solution
! is to do an update and cursor_horizontal after the cursor_vertical.
!
! Source:
!   Eve

if get_info (current_window, "current_row") =
   get_info (current_window, "visible_top") then
    scroll (current_window, -1);
else
    cursor_vertical (-1);
    update(current_window);
    cursor_horizontal(0);
endif;

endprocedure;


procedure eve_move_down                 ! Move down 1 line

! See documentation for eve_move_up

if get_info (current_window, "current_row") =
   get_info (current_window, "visible_bottom") then
    scroll (current_window, 1);
else
    cursor_vertical (1);
    update(current_window);
    cursor_horizontal(0);
endif;
endprocedure;


!                                                                       Page 2


procedure eve$move_by_screen            ! Moves by screenfuls
    (how_many_screens)

! Procedure to move by screen - used by eve_next_screen and eve_previous_screen
! Positive numbers move forward (like next screen), negative numbers backward
! Returns false if an error is encountered; otherwise returns true.
!
! Parameters:
!   how_many_screens    integer     number of screens to move
!
! Source:
!   Eve

local how_much_scroll,          ! How many lines to scroll
      scroll_window,            ! Window to be scrolled
      this_window;              ! Current window

! Trap and ignore messages about move beyond buffer boundaries -
! just move to top or bottom line of buffer

on_error
   eve$move_by_screen := 0;     ! and continue
endon_error;

eve$move_by_screen := 1;
this_window := current_window;
if this_window = eve$command_window then
    if eve$x_ambiguous_parse then
        scroll_window := eve$choice_window;
    else
        scroll_window := eve$x_pre_command_window;
    endif;
    position (scroll_window);
else
    scroll_window := this_window;
endif;
!
! Calculate how many lines a "screen-full" is
!
how_much_scroll := get_info (scroll_window, eve$kt_visible_length);
if get_info (scroll_window, "status_line") <> eve$kt_null then
    how_much_scroll := how_much_scroll - 3;
else
    how_much_scroll := how_much_scroll - 2;
endif;
if how_much_scroll <= 0 then
    how_much_scroll := 1;
endif;

move_vertical (how_many_screens * how_much_scroll);
update (scroll_window);
if this_window <> current_window then
    position (this_window);
endif;

endprocedure;




!                                                                       Page 3


procedure eve_move_by_character         ! Move by 1 char in current direction

! Move one character in the current direction...this routine is stick to the
! text (won't go to non-character places)
!
! Source:
!   Eva

if current_direction=forward then move_horizontal(1)
else move_horizontal(-1)
endif

endprocedure


!                                                                       Page 4


procedure eve_move_by_line              ! Move intelligently in current dir

! Moves by lines
!
! Qualifiers:
!   /end            boolean     always stick to end of line
!
! Source:
!   Eve

local
    beyond_eol;     ! True if cursor beyond end of current line

on_error
    return;
endon_error;

beyond_eol := get_info (current_window, eve$kt_beyond_eol);

if current_direction = reverse then
    if abl$q_end then
        move_horizontal(-current_offset);
        if mark(none)<>beginning_of(current_buffer) then
            move_vertical(-1)
        endif;
        position(search(line_end,forward));
    else
        if not beyond_eol then
            if current_offset = 0 then move_vertical (-1) endif;
        endif;
        position (search (line_begin, reverse));
    endif;

    ! In command buffer, don't back up beyond prompt

    if current_buffer = eve$command_buffer then
        if substr (current_line, 1, eve$x_command_prompt_length) =
            eve$x_command_prompt then
            move_horizontal (eve$x_command_prompt_length);
        endif;
    endif;

else
    if beyond_eol then
        position (search (line_begin, reverse));
        update (current_window);
        move_vertical (1);
    else
        if current_character = eve$x_null then
            move_vertical (1);
        endif;
    endif;
    position (search (line_end, forward));
endif;

endprocedure;


!                                                                       Page 5


procedure eve_scroll                    ! Scroll in current direction

! Combination of eve_next_screen and eve_previous_screen (to save a key when
! defining VT100 keypads)
!
! Source:
!   Eva

local
    cur_buf,
    cur_dir;

cur_buf:=current_buffer;
cur_dir:=current_direction;
move_horizontal(-current_offset);
update(current_window);
if (mark(none)=end_of(cur_buf))  then
        set(reverse,cur_buf);
    eve$update_status_lines;
else
    if (mark(none)=beginning_of(cur_buf)) then
        set(forward,cur_buf);
        eve$update_status_lines;
    endif;
endif;
if current_direction=forward then eve$move_by_screen(1)
else eve$move_by_screen(-1)
endif;
endprocedure


!                                                                       Page 6


procedure eve_move_by_page              ! Move by form feeds in current dir

! Moves by form feeds in the current direction
!
! Source:
!   Eva

local move,there;
on_error
    if (error=tpu$_endofbuf) or (error=tpu$_begofbuf) then return endif;
    if current_direction=forward then position(end_of(current_buffer))
    else position(beginning_of(current_buffer))
    endif;
endon_error;
if current_direction=forward then move_horizontal(1) else move_horizontal(-1)
endif;
there:=search(ascii(12),current_direction);
if there<>0 then position(there) endif;
endprocedure


!                                                                       Page 7


procedure eve_line (line_parameter)     ! Go to line or percentage of buffer

! Go to start of a certain line in the current buffer or percentage
!
! Parameters:
!   line_parameter  integer     line number to move to or percentage - input

local line_number,          ! Local copy of line_parameter
      this_position,        ! Marker for current cursor position
      last_line,            ! Number of lines in buffer, including eob_text
      line_string;          ! Intermediate string for line_number

on_error
    message (fao ("Cannot move to line !SL", line_number));
    position (this_position);
    return;
endon_error;

this_position := mark (none);
if not (eve$prompt_string (line_parameter, line_string,
    "Line number or percentage: ", "No line number or % given")) then return;
endif;

if not abl$extract_integer(line_string,line_number) then
    message ("Must supply line number or percentage");
    return;
endif;

if index(line_string,"%") then
    line_number := get_info(current_buffer,"record_count") * line_number/100
endif;

if line_number <= 0 then
    message (fao ("Cannot move to line !SL", line_number));
    return;
endif;

last_line := get_info (current_buffer, eve$kt_record_count) + 1;
                            ! include eob_text

if line_number > last_line then
    if last_line > 0 then
        message (fao ("Buffer has only !SL line!%S", last_line));
    else
        message ("Buffer is empty");
    endif;
else
    position (beginning_of (current_buffer));
    move_vertical (line_number - 1);    ! already at line 1
    eve$position_in_middle (mark (none));
endif;

endprocedure;


!                                                                       Page 8


procedure eve_move_window               ! Move window with arrows

! Move screen window around the buffer
!
! Source:
!   Abel

local
    key_read;
loop
    key_read :=
        eve$prompt_key("Move screen with arrow keys; <Return> when done");
    if key_read = ret_key   then exitif 1                   else
    if key_read = up        then eve$move_by_screen(-1)     else
    if key_read = down      then eve$move_by_screen(1)      else
    if key_read = left      then eve_shift_left(60)         else
    if key_read = right     then eve_shift_right(60)
    endif; endif; endif; endif; endif;
    update(current_window);
endloop;
endprocedure
