moar terminal fixes

This commit is contained in:
Adam D. Ruppe 2020-04-01 14:48:11 -04:00
parent 2ed6b50aa6
commit 1c119753b3
3 changed files with 174 additions and 54 deletions

View File

@ -2126,7 +2126,6 @@ class ScrollableWidget : Widget {
} else version(win32_widgets) { } else version(win32_widgets) {
recomputeChildLayout(); recomputeChildLayout();
} else static assert(0); } else static assert(0);
} }
/// ///
@ -2473,6 +2472,16 @@ abstract class ScrollbarBase : Widget {
private int step_ = 16; private int step_ = 16;
private int position_; private int position_;
///
bool atEnd() {
return position_ + viewableArea_ >= max_;
}
///
bool atStart() {
return position_ == 0;
}
/// ///
void setViewableArea(int a) { void setViewableArea(int a) {
viewableArea_ = a; viewableArea_ = a;
@ -2720,7 +2729,7 @@ class HorizontalScrollbar : ScrollbarBase {
version(win32_widgets) { version(win32_widgets) {
SCROLLINFO info; SCROLLINFO info;
info.cbSize = info.sizeof; info.cbSize = info.sizeof;
info.nPage = a; info.nPage = a + 1;
info.fMask = SIF_PAGE; info.fMask = SIF_PAGE;
SetScrollInfo(hwnd, SB_CTL, &info, true); SetScrollInfo(hwnd, SB_CTL, &info, true);
} else version(custom_widgets) { } else version(custom_widgets) {
@ -2828,7 +2837,7 @@ class VerticalScrollbar : ScrollbarBase {
version(win32_widgets) { version(win32_widgets) {
SCROLLINFO info; SCROLLINFO info;
info.cbSize = info.sizeof; info.cbSize = info.sizeof;
info.nPage = a; info.nPage = a + 1;
info.fMask = SIF_PAGE; info.fMask = SIF_PAGE;
SetScrollInfo(hwnd, SB_CTL, &info, true); SetScrollInfo(hwnd, SB_CTL, &info, true);
} else version(custom_widgets) { } else version(custom_widgets) {
@ -3493,6 +3502,11 @@ class ScrollMessageWidget : Widget {
magic = true; magic = true;
} }
///
VerticalScrollbar verticalScrollBar() { return vsb; }
///
HorizontalScrollbar horizontalScrollBar() { return hsb; }
void notify() { void notify() {
auto event = new Event("scroll", this); auto event = new Event("scroll", this);
event.dispatch(); event.dispatch();
@ -3786,18 +3800,15 @@ class Window : Widget {
event.dispatch(); event.dispatch();
break; break;
case SB_THUMBTRACK: case SB_THUMBTRACK:
auto event = new Event("scrolltrack", *widgetp); // eh kinda lying but i like the real time update display
auto event = new Event("scrolltoposition", *widgetp);
event.intValue = pos; event.intValue = pos;
event.dispatch(); event.dispatch();
/+
if(m == SB_THUMBTRACK) {
// the event loop doesn't seem to carry on with a requested redraw.. // the event loop doesn't seem to carry on with a requested redraw..
// so we request it to get our dirty bit set... // so we request it to get our dirty bit set...
redraw();
// then we need to immediately actually redraw it too for instant feedback to user // then we need to immediately actually redraw it too for instant feedback to user
if(redrawRequested)
actualRedraw(); actualRedraw();
}
+/
break; break;
default: default:
} }

View File

@ -1100,10 +1100,10 @@ struct Terminal {
if(guiThread is null) { if(guiThread is null) {
guiThread = new Thread( { guiThread = new Thread( {
auto window = new TerminalEmulatorWindow(&this); auto window = new TerminalEmulatorWindow(&this, null);
mainWindow = window; mainWindow = window;
mainWindow.win.addEventListener((NewTerminalEvent t) { mainWindow.win.addEventListener((NewTerminalEvent t) {
auto nw = new TerminalEmulatorWindow(t.t); auto nw = new TerminalEmulatorWindow(t.t, null);
t.t.tew = nw.tew; t.t.tew = nw.tew;
t.t = null; t.t = null;
nw.show(); nw.show();
@ -3582,7 +3582,6 @@ void main() {
getter.prompt = "> "; getter.prompt = "> ";
getter.history = ["abcdefghijklmnopqrstuvwzyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"]; getter.history = ["abcdefghijklmnopqrstuvwzyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"];
terminal.writeln("\n" ~ getter.getline()); terminal.writeln("\n" ~ getter.getline());
terminal.writeln("\n" ~ getter.getline()); terminal.writeln("\n" ~ getter.getline());
terminal.writeln("\n" ~ getter.getline()); terminal.writeln("\n" ~ getter.getline());
getter.dispose(); getter.dispose();
@ -5906,14 +5905,28 @@ version(TerminalDirectToEmulator) {
return tew.terminalEmulator; return tew.terminalEmulator;
} }
private this(Terminal* term) { private TerminalEmulatorWindow parent;
private TerminalEmulatorWindow[] children;
private void childClosing(TerminalEmulatorWindow t) {
foreach(idx, c; children)
if(c is t)
children = children[0 .. idx] ~ children[idx + 1 .. $];
}
private void registerChild(TerminalEmulatorWindow t) {
children ~= t;
}
private this(Terminal* term, TerminalEmulatorWindow parent) {
this.parent = parent;
scope(success) if(parent) parent.registerChild(this);
super("Terminal Application", integratedTerminalEmulatorConfiguration.initialWidth * integratedTerminalEmulatorConfiguration.fontSize / 2, integratedTerminalEmulatorConfiguration.initialHeight * integratedTerminalEmulatorConfiguration.fontSize); super("Terminal Application", integratedTerminalEmulatorConfiguration.initialWidth * integratedTerminalEmulatorConfiguration.fontSize / 2, integratedTerminalEmulatorConfiguration.initialHeight * integratedTerminalEmulatorConfiguration.fontSize);
smw = new ScrollMessageWidget(this); smw = new ScrollMessageWidget(this);
tew = new TerminalEmulatorWidget(term, smw); tew = new TerminalEmulatorWidget(term, smw);
smw.addEventListener("scroll", () { smw.addEventListener("scroll", () {
// import std.stdio; writeln(smw.position.x, " ", smw.position.y);
tew.terminalEmulator.scrollbackTo(smw.position.x, smw.position.y + tew.terminalEmulator.height); tew.terminalEmulator.scrollbackTo(smw.position.x, smw.position.y + tew.terminalEmulator.height);
redraw(); redraw();
}); });
@ -5925,6 +5938,27 @@ version(TerminalDirectToEmulator) {
integratedTerminalEmulatorConfiguration.menuExtensionsConstructor(this); integratedTerminalEmulatorConfiguration.menuExtensionsConstructor(this);
} }
TerminalEmulator.TerminalCell[] delegate(TerminalEmulator.TerminalCell[] i) parentFilter;
private void addScrollbackLineFromParent(TerminalEmulator.TerminalCell[] lineIn) {
if(parentFilter is null)
return;
auto line = parentFilter(lineIn);
if(line is null) return;
if(tew && tew.terminalEmulator) {
bool atBottom = smw.verticalScrollBar.atEnd && smw.horizontalScrollBar.atStart;
tew.terminalEmulator.addScrollbackLine(line);
tew.terminalEmulator.notifyScrollbackAdded();
if(atBottom) {
tew.terminalEmulator.notifyScrollbarPosition(0, int.max);
tew.terminalEmulator.scrollbackTo(0, int.max);
tew.redraw();
}
}
}
private TerminalEmulatorWidget tew; private TerminalEmulatorWidget tew;
private ScrollMessageWidget smw; private ScrollMessageWidget smw;
@ -5960,17 +5994,26 @@ version(TerminalDirectToEmulator) {
} }
dialog((FilterParams p) { dialog((FilterParams p) {
// FIXME: this should update in real time... somehow. auto nw = new TerminalEmulatorWindow(null, this);
auto nw = new TerminalEmulatorWindow(null);
nw.tew.terminalEmulator.toggleScrollLock(); nw.parentFilter = (TerminalEmulator.TerminalCell[] line) {
foreach(line; tew.terminalEmulator.sbb[0 .. $]) {
import std.algorithm; import std.algorithm;
import std.uni; import std.uni;
// omg autodecoding being kinda useful for once LOL // omg autodecoding being kinda useful for once LOL
if(line.map!(c => c.hasNonCharacterData ? dchar(0) : (p.caseSensitive ? c.ch : c.ch.toLower)). if(line.map!(c => c.hasNonCharacterData ? dchar(0) : (p.caseSensitive ? c.ch : c.ch.toLower)).
canFind(p.searchTerm)) canFind(p.searchTerm))
nw.tew.terminalEmulator.addScrollbackLine(line); {
// I might highlight the match too, but meh for now
return line;
} }
return null;
};
foreach(line; tew.terminalEmulator.sbb[0 .. $]) {
if(auto l = nw.parentFilter(line))
nw.tew.terminalEmulator.addScrollbackLine(l);
}
nw.tew.terminalEmulator.toggleScrollLock();
nw.tew.terminalEmulator.drawScrollback(); nw.tew.terminalEmulator.drawScrollback();
nw.title = "Filter Display"; nw.title = "Filter Display";
nw.show(); nw.show();
@ -5981,9 +6024,12 @@ version(TerminalDirectToEmulator) {
@separator @separator
void Clear() { void Clear() {
tew.terminalEmulator.clearScrollbackHistory(); tew.terminalEmulator.clearScrollbackHistory();
//tew.terminalEmulator.cls(); tew.terminalEmulator.cls();
// FIXME: move cursor back to 0,0 tew.terminalEmulator.moveCursor(0, 0);
// tell the application to redraw too (maybe signal size changed) if(tew.term) {
tew.term.windowSizeChanged = true;
tew.terminalEmulator.outgoingSignal.notify();
}
tew.redraw(); tew.redraw();
} }
@ -6040,6 +6086,11 @@ version(TerminalDirectToEmulator) {
if(term) if(term)
term.hangedUp = true; term.hangedUp = true;
if(auto wi = cast(TerminalEmulatorWindow) this.parentWindow) {
if(wi.parent)
wi.parent.childClosing(wi);
}
// try to get it to terminate slightly more forcibly too, if possible // try to get it to terminate slightly more forcibly too, if possible
if(sigIntExtension) if(sigIntExtension)
sigIntExtension(); sigIntExtension();
@ -6113,11 +6164,17 @@ version(TerminalDirectToEmulator) {
redraw(); redraw();
} }
override void addScrollbackLine(TerminalCell[] line) {
super.addScrollbackLine(line);
if(widget)
if(auto p = cast(TerminalEmulatorWindow) widget.parentWindow) {
foreach(child; p.children)
child.addScrollbackLineFromParent(line);
}
}
override void notifyScrollbackAdded() { override void notifyScrollbackAdded() {
if(this.scrollbackLength > this.height) widget.smw.setTotalArea(this.scrollbackWidth > this.width ? this.scrollbackWidth : this.width, this.scrollbackLength > this.height ? this.scrollbackLength : this.height);
widget.smw.setTotalArea(this.scrollbackWidth, this.scrollbackLength);
else
widget.smw.setTotalArea(this.width, this.height);
} }
override void notifyScrollbarPosition(int x, int y) { override void notifyScrollbarPosition(int x, int y) {

View File

@ -530,7 +530,7 @@ class TerminalEmulator {
if((!alternateScreenActive || scrollingBack) && key == TerminalKey.ScrollLock) { if((!alternateScreenActive || scrollingBack) && key == TerminalKey.ScrollLock) {
toggleScrollLock(); toggleScrollLock();
return false; return true;
} }
// scrollback controls. Unlike xterm, I only want to do this on the normal screen, since alt screen // scrollback controls. Unlike xterm, I only want to do this on the normal screen, since alt screen
@ -1233,8 +1233,7 @@ class TerminalEmulator {
private int scrollbackWidth_; private int scrollbackWidth_;
int scrollbackWidth() { int scrollbackWidth() {
return screenWidth; return scrollbackWidth_ > screenWidth ? scrollbackWidth_ : screenWidth;
//return scrollbackWidth_; // FIXME
} }
/* virtual */ void notifyScrollbackAdded() {} /* virtual */ void notifyScrollbackAdded() {}
@ -1246,8 +1245,9 @@ class TerminalEmulator {
if(alternateScreenActive && !scrollingBack) if(alternateScreenActive && !scrollingBack)
return; return;
if(!scrollingBack) if(!scrollingBack) {
startScrollback(); startScrollback();
}
if(y < 0) if(y < 0)
y = 0; y = 0;
@ -1259,10 +1259,12 @@ class TerminalEmulator {
if(currentScrollback < 0) if(currentScrollback < 0)
currentScrollback = 0; currentScrollback = 0;
if(currentScrollbackX < 0)
currentScrollbackX = 0;
if(currentScrollback == 0) if(!scrollLock && currentScrollback == 0 && currentScrollbackX == 0) {
endScrollback(); endScrollback();
else { } else {
cls(); cls();
showScrollbackOnScreen(alternateScreen, currentScrollback, false, currentScrollbackX); showScrollbackOnScreen(alternateScreen, currentScrollback, false, currentScrollbackX);
} }
@ -1273,19 +1275,20 @@ class TerminalEmulator {
return; return;
if(!scrollingBack) { if(!scrollingBack) {
if(delta <= 0) if(delta <= 0 && deltaX == 0)
return; // it does nothing to scroll down when not scrolling back return; // it does nothing to scroll down when not scrolling back
startScrollback(); startScrollback();
} }
currentScrollback += delta; currentScrollback += delta;
if(deltaX) { if(!scrollbackReflow && deltaX) {
currentScrollbackX += deltaX; currentScrollbackX += deltaX;
if(currentScrollbackX < 0) { int max = scrollbackWidth - screenWidth;
if(max < 0)
max = 0;
if(currentScrollbackX > max)
currentScrollbackX = max;
if(currentScrollbackX < 0)
currentScrollbackX = 0; currentScrollbackX = 0;
if(!scrollLock)
scrollbackReflow = true;
} else
scrollbackReflow = false;
} }
int max = cast(int) scrollbackBuffer.length - screenHeight; int max = cast(int) scrollbackBuffer.length - screenHeight;
@ -1304,8 +1307,10 @@ class TerminalEmulator {
if(currentScrollback > max) if(currentScrollback > max)
currentScrollback = max; currentScrollback = max;
if(currentScrollback < 0)
currentScrollback = 0;
if(currentScrollback <= 0) if(!scrollLock && currentScrollback <= 0 && currentScrollbackX <= 0)
endScrollback(); endScrollback();
else { else {
cls(); cls();
@ -1330,6 +1335,8 @@ class TerminalEmulator {
} }
bool endScrollback() { bool endScrollback() {
//if(scrollLock)
// return false;
if(!scrollingBack) if(!scrollingBack)
return false; return false;
scrollingBack = false; scrollingBack = false;
@ -1342,20 +1349,62 @@ class TerminalEmulator {
currentScrollback = 0; currentScrollback = 0;
currentScrollbackX = 0; currentScrollbackX = 0;
if(!scrollLock) {
scrollbackReflow = true;
recalculateScrollbackLength();
}
notifyScrollbarPosition(0, int.max); notifyScrollbarPosition(0, int.max);
return true; return true;
} }
private bool scrollbackReflow = true; private bool scrollbackReflow = true;
/* deprecated? */
public void toggleScrollbackWrap() { public void toggleScrollbackWrap() {
scrollbackReflow = !scrollbackReflow; scrollbackReflow = !scrollbackReflow;
recalculateScrollbackLength();
} }
private bool scrollLock = false; private bool scrollLock = false;
public void toggleScrollLock() { public void toggleScrollLock() {
scrollLock = !scrollLock; scrollLock = !scrollLock;
scrollbackReflow = !scrollLock; scrollbackReflow = !scrollLock;
recalculateScrollbackLength();
if(scrollLock) {
startScrollback();
cls();
currentScrollback = 0;
currentScrollbackX = 0;
showScrollbackOnScreen(alternateScreen, currentScrollback, scrollbackReflow, currentScrollbackX);
notifyScrollbarPosition(currentScrollbackX, scrollbackLength - currentScrollback - screenHeight);
} else {
endScrollback();
}
//cls();
//drawScrollback();
}
private void recalculateScrollbackLength() {
int count = cast(int) scrollbackBuffer.length;
int max;
if(scrollbackReflow) {
foreach(line; scrollbackBuffer[]) {
count += cast(int) line.length / screenWidth;
}
} else {
foreach(line; scrollbackBuffer[]) {
if(line.length > max)
max = cast(int) line.length;
}
}
scrollbackWidth_ = max;
scrollbackLength = count;
notifyScrollbackAdded();
notifyScrollbarPosition(currentScrollbackX, currentScrollback ? scrollbackLength - currentScrollback : int.max);
} }
public void writeScrollbackToFile(string filename) { public void writeScrollbackToFile(string filename) {
@ -1368,8 +1417,8 @@ class TerminalEmulator {
} }
} }
public void drawScrollback() { public void drawScrollback(bool useAltScreen = false) {
showScrollbackOnScreen(normalScreen, 0, true, 0); showScrollbackOnScreen(useAltScreen ? alternateScreen : normalScreen, 0, true, 0);
} }
private void showScrollbackOnScreen(ref TerminalCell[] screen, int howFar, bool reflow, int howFarX) { private void showScrollbackOnScreen(ref TerminalCell[] screen, int howFar, bool reflow, int howFarX) {
@ -1460,6 +1509,10 @@ class TerminalEmulator {
if(w == screenWidth && h == screenHeight) if(w == screenWidth && h == screenHeight)
return; // we're already good, do nothing to avoid wasting time and possibly losing a line (bash doesn't seem to like being told it "resized" to the same size) return; // we're already good, do nothing to avoid wasting time and possibly losing a line (bash doesn't seem to like being told it "resized" to the same size)
// do i like this?
if(scrollLock)
toggleScrollLock();
endScrollback(); // FIXME: hack endScrollback(); // FIXME: hack
screenWidth = w; screenWidth = w;
@ -1492,15 +1545,7 @@ class TerminalEmulator {
cursorY = cursorY; cursorY = cursorY;
cursorX = cursorX; cursorX = cursorX;
recalculateScrollbackLength();
int count = cast(int) scrollbackBuffer.length;
if(scrollbackReflow) {
foreach(line; scrollbackBuffer[])
count += cast(int) line.length / screenWidth;
}
scrollbackLength = count;
notifyScrollbackAdded();
notifyScrollbarPosition(currentScrollbackX, currentScrollback ? scrollbackLength - currentScrollback : int.max);
} }
private CursorPosition popSavedCursor() { private CursorPosition popSavedCursor() {
@ -1540,6 +1585,11 @@ class TerminalEmulator {
notifyScrollbackAdded(); notifyScrollbackAdded();
} }
public void moveCursor(int x, int y) {
cursorX = x;
cursorY = y;
}
/* FIXME: i want these to be private */ /* FIXME: i want these to be private */
protected { protected {
TextAttributes currentAttributes; TextAttributes currentAttributes;
@ -1853,6 +1903,8 @@ class TerminalEmulator {
public void addScrollbackLine(TerminalCell[] line) { public void addScrollbackLine(TerminalCell[] line) {
scrollbackBuffer ~= line; scrollbackBuffer ~= line;
if(!scrollbackReflow && line.length > scrollbackWidth_)
scrollbackWidth_ = cast(int) line.length;
scrollbackLength = cast(int) (scrollbackLength + 1 + (scrollbackBuffer[cast(int) scrollbackBuffer.length - 1].length) / screenWidth); scrollbackLength = cast(int) (scrollbackLength + 1 + (scrollbackBuffer[cast(int) scrollbackBuffer.length - 1].length) / screenWidth);
notifyScrollbackAdded(); notifyScrollbackAdded();
if(!alternateScreenActive) if(!alternateScreenActive)