mirror of https://github.com/adamdruppe/arsd.git
Merge pull request #362 from jamesragray/accurateCursorPos
Attempt to track cursor more accurately by caching widths of grapheme's
This commit is contained in:
commit
cc416c9848
127
terminal.d
127
terminal.d
|
@ -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,51 +2183,93 @@ 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) {
|
||||||
|
while(s.length > 0) {
|
||||||
|
size_t index = 0;
|
||||||
|
import std.utf;
|
||||||
|
import std.uni;
|
||||||
|
import std.range;
|
||||||
|
bool written=false;
|
||||||
|
loop:
|
||||||
|
foreach(g; s.byDchar.byGrapheme) {
|
||||||
|
index += g[].byChar.walkLength;
|
||||||
|
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':
|
||||||
|
_cursorX = 0;
|
||||||
|
_cursorY++;
|
||||||
|
break;
|
||||||
|
case '\r':
|
||||||
|
_cursorX = 0;
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
// FIXME: get the actual tabstop, if possible
|
||||||
|
int diff = 8 - (_cursorX % 8);
|
||||||
|
if(diff == 0)
|
||||||
|
diff = 8;
|
||||||
|
_cursorX += diff;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if(auto ptr = g in graphemeWidth) {
|
||||||
|
_cursorX += *ptr;
|
||||||
|
|
||||||
void writePrintableString(const(char)[] s, ForceOption force = ForceOption.automatic) {
|
if(_wrapAround) {
|
||||||
|
if(_cursorX == width) {
|
||||||
|
_cursorX--;
|
||||||
|
willInsertFollowingLine = true;
|
||||||
|
}
|
||||||
|
else if(cursorX > width) {
|
||||||
|
_cursorX = *ptr;
|
||||||
|
_cursorY++;
|
||||||
|
if(_cursorY == height)
|
||||||
|
_cursorY--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
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
|
// an escape character is going to mess things up. Actually any non-printable character could, but meh
|
||||||
// assert(s.indexOf("\033") == -1);
|
// assert(s.indexOf("\033") == -1);
|
||||||
|
|
||||||
if(s.length == 0)
|
if(s.length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// tracking cursor position
|
|
||||||
// FIXME: by grapheme?
|
|
||||||
foreach(dchar ch; s) {
|
|
||||||
switch(ch) {
|
|
||||||
case '\n':
|
|
||||||
_cursorX = 0;
|
|
||||||
_cursorY++;
|
|
||||||
break;
|
|
||||||
case '\r':
|
|
||||||
_cursorX = 0;
|
|
||||||
break;
|
|
||||||
case '\t':
|
|
||||||
// FIXME: get the actual tabstop, if possible
|
|
||||||
int diff = 8 - (_cursorX % 8);
|
|
||||||
if(diff == 0)
|
|
||||||
diff = 8;
|
|
||||||
_cursorX += diff;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
_cursorX++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_wrapAround && _cursorX > width) {
|
|
||||||
_cursorX = 0;
|
|
||||||
_cursorY++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_cursorY == height)
|
|
||||||
_cursorY--;
|
|
||||||
|
|
||||||
/+
|
|
||||||
auto index = getIndex(_cursorX, _cursorY);
|
|
||||||
if(data[index] != ch) {
|
|
||||||
data[index] = ch;
|
|
||||||
}
|
|
||||||
+/
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
|
|
Loading…
Reference in New Issue