Vertical Position Relative (VPR)

Move the cursor down `n` rows without changing the column.

  1. 0x1B
    ESC
  2. 0x5B
    [
  3. ____
    y
  4. 0x65
    e

The parameter y must be an integer greater than or equal to 1. If y is less than or equal to 0, adjust y to be 1. If y is omitted, y defaults to 1.

This sequence always unsets the pending wrap state.

VPR moves the cursor y rows down from its current position. The cursor column does not change. VPR is paired with VPA the same way CUD is paired with VPA: VPA selects an absolute row, VPR selects a row relative to where the cursor is now.

If the current cursor position is at or above the bottom margin, the lowest point the cursor can move to is the bottom margin. If the current cursor position is below the bottom margin, the lowest point the cursor can move to is the final row of the screen. This sequence never triggers scrolling and never modifies cell content.

Note

In practice VPR and CUD (Cursor Down, CSI Pn B) produce identical results for the same parameter; both clamp at the bottom margin and both unset pending wrap.

Validation

VPR V-1: Normal Usage

printf "\033[1;1H" # move to top-left
printf "\033[0J" # clear screen
printf "A"
printf "\033[2e" # VPR down 2 rows
printf "X"
|A_________|
|__________|
|_Xc_______|

VPR V-2: Default Parameter

printf "\033[1;1H" # move to top-left
printf "\033[0J" # clear screen
printf "A"
printf "\033[e" # VPR with default (1)
printf "X"
|A_________|
|_Xc_______|

VPR V-3: Stops at Bottom Margin

printf "\033[1;1H" # move to top-left
printf "\033[0J" # clear screen
printf "\n\n\n\n" # screen is 4 high
printf "\033[1;3r" # scroll region rows 1..3
printf "\033[1;1H"
printf "A"
printf "\033[500e" # VPR way past the bottom
printf "X"
|A_________|
|__________|
|_Xc_______|
|__________|

VPR V-4: Pending Wrap is Unset

cols=$(tput cols)
printf "\033[${cols}G" # move to last column
printf "A" # set pending wrap state
printf "\033[1e" # VPR cancels pending wrap
printf "X"
|_________A|
|_________X|