Improve cursor tracking.

This commit is contained in:
james 2023-02-19 23:56:53 +02:00
parent 1793d8e43b
commit 3eb0a64df3
1 changed files with 88 additions and 39 deletions

View File

@ -2158,7 +2158,10 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
void writeln(T...)(T t) { void writeln(T...)(T t) {
write(t, "\n"); write(t, "\n");
} }
import std.uni;
int[Grapheme] graphemeWidth;
bool willInsertFollowingLine = false;
bool uncertainIfAtEndOfLine = false;
/+ /+
/// A combined moveTo and writef that puts the cursor back where it was before when it finishes the write. /// A combined moveTo and writef that puts the cursor back where it was before when it finishes the write.
/// Only works in cellular mode. /// Only works in cellular mode.
@ -2180,18 +2183,30 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
writeStringRaw(toWrite, ForceOption.alwaysSend); writeStringRaw(toWrite, ForceOption.alwaysSend);
} }
+/ +/
void writePrintableString(const(char)[] s, ForceOption force = ForceOption.automatic) { void writePrintableString(const(char)[] s, ForceOption force = ForceOption.automatic) {
// an escape character is going to mess things up. Actually any non-printable character could, but meh while(s.length > 0) {
// assert(s.indexOf("\033") == -1); size_t index = 0;
import std.utf;
if(s.length == 0) import std.uni;
return; import std.range;
bool written=false;
// tracking cursor position loop:
// FIXME: by grapheme? foreach(g; s.byDchar.byGrapheme) {
foreach(dchar ch; s) { index += g[].byChar.walkLength;
switch(ch) { if(uncertainIfAtEndOfLine) {
uncertainIfAtEndOfLine = false;
writePrintableString_(s[0..index],force);
written = true;
updateCursorPosition();
break;
}
if(willInsertFollowingLine) {
willInsertFollowingLine = false;
_cursorX = 0;
_cursorY++;
if(_cursorY >= height) { _cursorY--; }
}
switch(g[0]) {
case '\n': case '\n':
_cursorX = 0; _cursorX = 0;
_cursorY++; _cursorY++;
@ -2207,24 +2222,54 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
_cursorX += diff; _cursorX += diff;
break; break;
default: default:
_cursorX++; if(auto ptr = g in graphemeWidth) {
} _cursorX += *ptr;
if(_wrapAround && _cursorX > width) { if(_wrapAround) {
_cursorX = 0; if(_cursorX == width) {
_cursorX--;
willInsertFollowingLine = true;
}
else if(cursorX > width) {
_cursorX = *ptr;
_cursorY++; _cursorY++;
}
if(_cursorY == height) if(_cursorY == height)
_cursorY--; _cursorY--;
}
}
/+
auto index = getIndex(_cursorX, _cursorY);
if(data[index] != ch) {
data[index] = ch;
} }
+/ else {
int x = _cursorX;
int y = _cursorY;
writePrintableString_(s[0..index],force);
written = true;
updateCursorPosition();
//FIXME: At some point it might be worthwhile to check if the next wrtie will wrap on those terminals that support it
//Note that: tmux (and screen?) seem to signal that the next write will wrap by reporting cursorX==width
if (_cursorX+1< width || _cursorX == width) {
graphemeWidth[g] = _cursorY > y
? _cursorX
: _cursorX - x;
if(_cursorX == width) { willInsertFollowingLine = true; }
} }
else { uncertainIfAtEndOfLine = true; }
break loop;
}
}
}
if(!written) { writePrintableString_(s[0..index],force); }
s = s[index..$];
}
}
void writePrintableString_(const(char)[] s, ForceOption force = ForceOption.automatic) {
// an escape character is going to mess things up. Actually any non-printable character could, but meh
// assert(s.indexOf("\033") == -1);
if(s.length == 0)
return;
version(TerminalDirectToEmulator) { version(TerminalDirectToEmulator) {
// this breaks up extremely long output a little as an aid to the // this breaks up extremely long output a little as an aid to the
@ -2454,6 +2499,10 @@ http://msdn.microsoft.com/en-us/library/windows/desktop/ms683193%28v=vs.85%29.as
terminal._cursorY = terminal.tew.terminalEmulator.cursorY; terminal._cursorY = terminal.tew.terminalEmulator.cursorY;
} else } else
updateCursorPosition_impl(); updateCursorPosition_impl();
if(_cursorX == width) {
willInsertFollowingLine = true;
_cursorX--;
}
} }
private void updateCursorPosition_impl() { private void updateCursorPosition_impl() {
auto terminal = &this; auto terminal = &this;