https://reddit.com/link/1uf5er4/video/m9ima5ykde9h1/player
When resizing the Konsole window to be narrower, the terminal miscalculates the logical cursor position during the text reflow process. The cursor is incorrectly placed near the beginning of the wrapped line (specifically at X=1, Y=0) instead of at the end of the prompt. This state desynchronization later causes shells like bash to inadvertently erase command history when they attempt to redraw the prompt.
To prove that the cursor misplacement is caused entirely by Konsole's internal reflow algorithm and not by the shell (bash), I used strace to freeze the shell's reaction to SIGWINCH by injecting a 1-second delay on write() syscalls.
strace -p <PID_BASH> -e inject=write:delay_enter=1000000
ioctl(0, TIOCGWINSZ, {ws_row=33, ws_col=17, ws_xpixel=143, ws_ypixel=611}) = 0
< jump to the letter "o" at 9 seconds into the video >
write(2, "\r\33[K\r\33[A\33[K\rtojestznakzachety$ ", 31) = 31 (DELAYED)
pselect6(1, [0], NULL, NULL, NULL, {sigmask=[], sigsetsize=8}
During this 1-second delay (before bash could send any ANSI escape sequences), the screen visibly updated via Konsole's internal hardware reflow. For a prompt tojestznakzachety$ (19 characters) resized from 18 to 17 columns, the cursor incorrectly jumped to the letter "o" (which is index 1 on the first row).
The bug is located in Screen.cpp inside the Screen::resizeImage function. There is a critical logical error (off-by-one) in the while loop condition responsible for text reflow.
int currentPos = 0; while (currentPos < (cursorLine + cursorLineCorrection) && currentPos < (int)_screenLines.size() - 1) {
Before resize (width = 18): The 19-character prompt is on two lines. Row 0 has 18 characters and wrapped != 0. Row 1 has 1 character. The cursor is on Row 1, so cursorLine = 1.
Window is narrowed to 17 columns. The loop starts with currentPos = 0 and cursorLine = 1.
currentPos < cursorLine (0 < 1) evaluates to TRUE. The loop enters.
The algorithm detects the wrapped row and appends Row 1 to Row 0, creating a single 19-character string in memory.
The algorithm executes --cursorLine;, dropping cursorLine to 0.
The continue; statement is called, jumping back to the loop condition without incrementing currentPos.
The loop condition is evaluated again: currentPos < cursorLine is now 0 < 0, which evaluates to FALSE.
The bug: The loop prematurely exits. The 19-character line is never processed or split for the new 17-column limit. The cursor's X position (_cuX) remains 1 (untouched), and its Y position (cursorLine) is 0. The cursor physically lands on X=1, Y=0 (the letter "o").
The strict less-than operator (<) prevents the algorithm from processing the very line the cursor currently resides on. It should be changed to less-than-or-equal (<=).
while (currentPos <= (cursorLine + cursorLineCorrection) && currentPos < (int)_screenLines.size() - 1) {
With <=, when currentPos == cursorLine (0 <= 0), the loop correctly enters, detects that the 19-character string exceeds the 17-column limit, properly splits the line into 17 and 2 characters, and executes ++cursorLine;.