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) {
|
||||
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.
|
||||
/// 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);
|
||||
}
|
||||
+/
|
||||
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
|
||||
// assert(s.indexOf("\033") == -1);
|
||||
|
||||
if(s.length == 0)
|
||||
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) {
|
||||
// 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;
|
||||
} else
|
||||
updateCursorPosition_impl();
|
||||
if(_cursorX == width) {
|
||||
willInsertFollowingLine = true;
|
||||
_cursorX--;
|
||||
}
|
||||
}
|
||||
private void updateCursorPosition_impl() {
|
||||
auto terminal = &this;
|
||||
|
|
Loading…
Reference in New Issue