                  { --- Cursor movement --- }

procedure character_left;             { move cursor left one character }
begin
if index>TEXTSTART then
    begin
    index:=index-1;
    if eol(index) then
        begin
        if cy=SCREENTOP then scroll_down_line(1) else cy:=cy-1;
        end;
    cx:=x_to_bol(index)+1;
    end;
end; { character_left }

procedure character_right;             { move cursor right one character }
begin
if index<text_end then
    begin
    if eol(index) then
        begin
        if cy=SCREENBOTTOM then scroll_up_line(1) else cy:=cy+1;
        cx:=SCREENLEFT;
        end
    else
        cx:=cx+dx(index);
    index:=index+1;
    end;
end; { character_right }

procedure line_up;        { move cursor up one line }
begin
if (page_top_line>1) or (cy<>SCREENTOP) then
    begin
    if cy=SCREENTOP then scroll_down_line(1) else cy:=cy-1;
    find_index_above_cx(index,cx,1);
    cx:=min(cx,x_to_bol(index)+1);
    end;
end; { line_up }

procedure line_down;      { move cursor down one line }
begin
if  (page_bottom_line<n_lines) or (cy<page_bottom_line-page_top_line+SCREENTOP) then
    begin
    if cy=SCREENBOTTOM then scroll_up_line(1) else cy:=cy+1;
    find_index_below_cx(index,cx,1);
    cx:=min(cx,x_to_bol(index)+1);
    end;
end; { line_down }

procedure word_left;   { move cursor backwards to begin of word }
begin
if index>TEXTSTART then
    begin
    if (text[index] in alphanums) and (text[index-1] in alphanums) then
        while (index>1) and (text[index] in alphanums) do character_left
    else
        begin
        character_left;
        while (index>TEXTSTART) and (text[index] in separators) do
            character_left;
        while (index>TEXTSTART) and (text[index] in alphanums )
                                and not (text[index-1] in separators) do
            character_left;
        end;
    end;
end; { word_left }

procedure word_right;   { move cursor forward to next word }
begin
while (index<text_end) and (text[index] in alphanums) do character_right;
while (index<text_end) and (text[index] in separators) do character_right;
end; { word_right }

procedure to_left_on_line;
begin index:=index-ch_to_bol(index); cx:=SCREENLEFT; end;

procedure to_right_on_line;
begin index:=index+ch_to_eol(index); cx:=x_to_bol(index)+1; end;

procedure to_top_of_screen;
begin
find_index_above_cx(index,cx,cy-SCREENTOP);
cx:=x_to_bol(index)+1; cy:=SCREENTOP;
end; { to_top_of_screen }

procedure to_bottom_of_screen;
begin
i:=page_bottom_line-page_top_line+SCREENTOP-cy;
find_index_below_cx(index,cx,i);
cx:=x_to_bol(index)+1; cy:=cy+i;
end; { to_bottom_of_screen }

procedure to_top_of_file;
begin
index:=TEXTSTART;
page_top_line:=1; find_page_bottom_line;
page_top_index:=TEXTSTART; find_page_bottom_index;
cx:=SCREENLEFT; cy:=SCREENTOP; display_rest_page(index,cx,cy);
end; { to_top_of_file }

procedure to_end_of_file;
begin
index:=text_end;
i:=page_bottom_line-page_top_line;
cx:=SCREENLEFT; cy:=SCREENTOP+i;
if n_lines-page_top_line >= PAGELEN then
    begin
    page_top_line:=max(1,n_lines-PAGELEN+1);
    find_page_bottom_line;
    page_top_index:=index;
    find_index_above_cx(page_top_index,cx,i);
    find_page_bottom_index;
    display_rest_page(page_top_index,cx,SCREENTOP);
    end;
end; { to_end_of_file }

procedure to_beginning_of_block;
begin
if block_flag then
    begin index:=block_begin; find_page(index,cx,cy); end;
end; { to_beginning_of_block }

procedure to_end_of_block;
begin
if block_flag then
    begin
    index:=block_end; find_page(index,cx,cy);
    if not eol(index) then character_right;
    end;
end; { to_end_of_block }

procedure scroll_up;      { scroll page one line up}
begin
if (page_bottom_line<n_lines) then
   begin if (cy<=SCREENTOP) then line_down; cy:=cy-1; end;
scroll_up_line(1);
end; { scroll_up }

procedure scroll_down;      { scroll page one line down }
begin
if page_top_line>1 then
    begin if cy>=SCREENBOTTOM then line_up; cy:=cy+1; end;
scroll_down_line(1);
end; { scroll_down }

procedure page_up;      { back to previous page }
var d:integer;
begin
d:=min(page_top_line,PAGELEN)-1;
if d>0 then
    begin
    page_top_line:=page_top_line-d;
    find_page_bottom_line;
    find_index_above_cx(index,cx,d);
    find_index_above_cx(page_top_index,SCREENLEFT,d);
    find_page_bottom_index;
    display_rest_page(page_top_index,SCREENLEFT,SCREENTOP);
    end
else
    begin
    find_index_above_cx(index,cx,cy-SCREENTOP);
    cy:=SCREENTOP;
    end;
cx:=min(cx,x_to_bol(index)+1);
end; { page_up }

procedure page_down;      { forward to next page }
var d:integer;
begin
d:=min(n_lines-page_top_line,PAGELEN)-1;
if d>0 then
    begin
    page_top_line:=page_top_line+d;
    find_page_bottom_line;
    find_index_below_cx(index,cx,d);
    find_index_below_cx(page_top_index,SCREENLEFT,d);
    find_page_bottom_index;
    display_rest_page(page_top_index,SCREENLEFT,SCREENTOP);
    cx:=min(cx,x_to_bol(index)+1);
    cy:=min(cy,page_bottom_line-page_top_line+SCREENTOP)
    end;
end; { page_down }

