Merge remote-tracking branch

'origin/GP-6784_Dan_PR-9147_SetoKaiba_master' (Closes #9146,
Closes #9147)
This commit is contained in:
Ryan Kurtz
2026-05-05 04:42:31 -04:00
2 changed files with 30 additions and 6 deletions
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -129,7 +129,14 @@ public class VtBuffer {
if (c == 0) { if (c == 0) {
return; return;
} }
checkVerticalScroll(); // Only scroll if cursor is completely off-screen (beyond the display).
// Do NOT scroll when cursor is outside the scroll region but still within
// the display (e.g., on a fixed status bar line). Scroll region scrolling
// for line feeds is handled by moveCursorDown() via checkVerticalScroll().
while (curY >= rows) {
scrollViewportDown(true);
curY = Math.max(0, curY - 1);
}
// At this point, we have no choice but to wrap // At this point, we have no choice but to wrap
lines.get(curY).putChar(curX, c, curAttrs); lines.get(curY).putChar(curX, c, curAttrs);
} }
@@ -310,14 +317,30 @@ public class VtBuffer {
*/ */
public void moveCursorRight(int n, boolean wrap, boolean isCursorShowing) { public void moveCursorRight(int n, boolean wrap, boolean isCursorShowing) {
if (wrap && curX + n >= cols) { if (wrap && curX + n >= cols) {
checkVerticalScroll(); // Decide based on the pre-wrap position whether we are in the scroll region.
// If the cursor was inside the scroll region before wrapping, the wrap may
// push it past the bottom margin and should trigger scroll-region scrolling.
// If outside (e.g., on a fixed status bar line), just clamp to the display.
boolean wasInScrollRegion = (curY >= scrollStart && curY < scrollEnd);
if (wasInScrollRegion) {
checkVerticalScroll();
}
curX = 0; curX = 0;
lines.get(curY).wrappedToNext = true; if (curY < rows) {
lines.get(curY).wrappedToNext = true;
}
curY++; curY++;
bottomY = Math.max(bottomY, curY); bottomY = Math.max(bottomY, curY);
if (isCursorShowing) { if (wasInScrollRegion) {
// Always scroll when wrapping within the scroll region, regardless
// of cursor visibility. This prevents deferred scrolls from leaking
// into subsequent putChar() calls.
checkVerticalScroll(); checkVerticalScroll();
} }
else {
// Outside scroll region: clamp to display bounds
curY = Math.min(curY, rows - 1);
}
} }
else { else {
curX = Math.max(0, Math.min(curX + n, cols - 1)); curX = Math.max(0, Math.min(curX + n, cols - 1));
@@ -876,6 +876,7 @@ public interface VtHandler {
handleMoveCursorCol(n - 1); handleMoveCursorCol(n - 1);
return; return;
} }
case 'f': // Horizontal and Vertical Position (same as CUP)
case 'H': { // Cursor position case 'H': { // Cursor position
OfInt bits = parseCsiInts(csiParam); OfInt bits = parseCsiInts(csiParam);
int n = bits.hasNext() ? bits.nextInt() : 1; int n = bits.hasNext() ? bits.nextInt() : 1;