Skip to content

Commit 1c41239

Browse files
msftrncsdaxian-dbw
authored andcommitted
Correct cursor positioning (#1221)
Correct cursor positioning in cases where newline appears 1 character before last column, or a CJK character ends the line but wraps to next display line, and in cases where continuation prompt contains either CJK characters, or VT color sequences. Fixes #1216, #1217, #1188.
1 parent 725e9f1 commit 1c41239

File tree

1 file changed

+16
-31
lines changed

1 file changed

+16
-31
lines changed

PSReadLine/Render.cs

Lines changed: 16 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,7 @@ internal Point ConvertOffsetToPoint(int offset)
10351035
int y = _initialY;
10361036

10371037
int bufferWidth = _console.BufferWidth;
1038-
var continuationPromptLength = Options.ContinuationPrompt.Length;
1038+
var continuationPromptLength = LengthInBufferCells(Options.ContinuationPrompt);
10391039

10401040
for (int i = 0; i < offset; i++)
10411041
{
@@ -1052,34 +1052,26 @@ internal Point ConvertOffsetToPoint(int offset)
10521052
// Wrap? No prompt when wrapping
10531053
if (x >= bufferWidth)
10541054
{
1055-
int offsize = x - bufferWidth;
1056-
if (offsize % size == 0)
1057-
{
1058-
x -= bufferWidth;
1059-
}
1060-
else
1061-
{
1062-
x = size;
1063-
}
1055+
// If character didn't fit on current line, it will move entirely to the next line.
1056+
x = ((x == bufferWidth) ? 0 : size);
10641057

1065-
// If the next character is newline, let the next loop
1066-
// iteration increment y and adjust x.
1067-
if (!(i + 1 < offset && _buffer[i + 1] == '\n'))
1058+
// If cursor is at column 0 and the next character is newline, let the next loop
1059+
// iteration increment y.
1060+
if (x != 0 || !(i + 1 < offset && _buffer[i + 1] == '\n'))
10681061
{
10691062
y += 1;
10701063
}
10711064
}
10721065
}
10731066
}
10741067

1075-
//if the next character has bigger size than the remain space on this line,
1076-
//the cursor goes to next line where the next character is.
1077-
if (_buffer.Length > offset)
1068+
// If next character actually exists, and isn't newline, check if wider than the space left on the current line.
1069+
if (_buffer.Length > offset && _buffer[offset] != '\n')
10781070
{
10791071
int size = LengthInBufferCells(_buffer[offset]);
1080-
// next one is Wrapped to next line
1081-
if (x + size > bufferWidth && (x + size - bufferWidth) % size != 0)
1072+
if (x + size > bufferWidth)
10821073
{
1074+
// Character was wider than remaining space, so character, and cursor, appear on next line.
10831075
x = 0;
10841076
y++;
10851077
}
@@ -1095,7 +1087,7 @@ private int ConvertLineAndColumnToOffset(Point point)
10951087
int y = _initialY;
10961088

10971089
int bufferWidth = _console.BufferWidth;
1098-
var continuationPromptLength = Options.ContinuationPrompt.Length;
1090+
var continuationPromptLength = LengthInBufferCells(Options.ContinuationPrompt);
10991091
for (offset = 0; offset < _buffer.Length; offset++)
11001092
{
11011093
// If we are on the correct line, return when we find
@@ -1123,19 +1115,12 @@ private int ConvertLineAndColumnToOffset(Point point)
11231115
// Wrap? No prompt when wrapping
11241116
if (x >= bufferWidth)
11251117
{
1126-
int offsize = x - bufferWidth;
1127-
if (offsize % size == 0)
1128-
{
1129-
x -= bufferWidth;
1130-
}
1131-
else
1132-
{
1133-
x = size;
1134-
}
1118+
// If character didn't fit on current line, it will move entirely to the next line.
1119+
x = ((x == bufferWidth) ? 0 : size);
11351120

1136-
// If the next character is newline, let the next loop
1137-
// iteration increment y and adjust x.
1138-
if (!(offset + 1 < _buffer.Length && _buffer[offset + 1] == '\n'))
1121+
// If cursor is at column 0 and the next character is newline, let the next loop
1122+
// iteration increment y.
1123+
if (x != 0 || !(offset + 1 < _buffer.Length && _buffer[offset + 1] == '\n'))
11391124
{
11401125
y += 1;
11411126
}

0 commit comments

Comments
 (0)