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

View File

@ -1100,10 +1100,10 @@ struct Terminal {
if(guiThread is null) {
guiThread = new Thread( {
auto window = new TerminalEmulatorWindow(&this);
auto window = new TerminalEmulatorWindow(&this, null);
mainWindow = window;
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 = null;
nw.show();
@ -3582,7 +3582,6 @@ void main() {
getter.prompt = "> ";
getter.history = ["abcdefghijklmnopqrstuvwzyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"];
terminal.writeln("\n" ~ getter.getline());
terminal.writeln("\n" ~ getter.getline());
terminal.writeln("\n" ~ getter.getline());
getter.dispose();
@ -5906,14 +5905,28 @@ version(TerminalDirectToEmulator) {
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);
smw = new ScrollMessageWidget(this);
tew = new TerminalEmulatorWidget(term, smw);
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);
redraw();
});
@ -5925,6 +5938,27 @@ version(TerminalDirectToEmulator) {
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 ScrollMessageWidget smw;
@ -5960,17 +5994,26 @@ version(TerminalDirectToEmulator) {
}
dialog((FilterParams p) {
// FIXME: this should update in real time... somehow.
auto nw = new TerminalEmulatorWindow(null);
nw.tew.terminalEmulator.toggleScrollLock();
foreach(line; tew.terminalEmulator.sbb[0 .. $]) {
auto nw = new TerminalEmulatorWindow(null, this);
nw.parentFilter = (TerminalEmulator.TerminalCell[] line) {
import std.algorithm;
import std.uni;
// omg autodecoding being kinda useful for once LOL
if(line.map!(c => c.hasNonCharacterData ? dchar(0) : (p.caseSensitive ? c.ch : c.ch.toLower)).
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.title = "Filter Display";
nw.show();
@ -5981,9 +6024,12 @@ version(TerminalDirectToEmulator) {
@separator
void Clear() {
tew.terminalEmulator.clearScrollbackHistory();
//tew.terminalEmulator.cls();
// FIXME: move cursor back to 0,0
// tell the application to redraw too (maybe signal size changed)
tew.terminalEmulator.cls();
tew.terminalEmulator.moveCursor(0, 0);
if(tew.term) {
tew.term.windowSizeChanged = true;
tew.terminalEmulator.outgoingSignal.notify();
}
tew.redraw();
}
@ -6040,6 +6086,11 @@ version(TerminalDirectToEmulator) {
if(term)
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
if(sigIntExtension)
sigIntExtension();
@ -6113,11 +6164,17 @@ version(TerminalDirectToEmulator) {
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() {
if(this.scrollbackLength > this.height)
widget.smw.setTotalArea(this.scrollbackWidth, this.scrollbackLength);
else
widget.smw.setTotalArea(this.width, this.height);
widget.smw.setTotalArea(this.scrollbackWidth > this.width ? this.scrollbackWidth : this.width, this.scrollbackLength > this.height ? this.scrollbackLength : this.height);
}
override void notifyScrollbarPosition(int x, int y) {

View File

@ -530,7 +530,7 @@ class TerminalEmulator {
if((!alternateScreenActive || scrollingBack) && key == TerminalKey.ScrollLock) {
toggleScrollLock();
return false;
return true;
}
// 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_;
int scrollbackWidth() {
return screenWidth;
//return scrollbackWidth_; // FIXME
return scrollbackWidth_ > screenWidth ? scrollbackWidth_ : screenWidth;
}
/* virtual */ void notifyScrollbackAdded() {}
@ -1246,8 +1245,9 @@ class TerminalEmulator {
if(alternateScreenActive && !scrollingBack)
return;
if(!scrollingBack)
if(!scrollingBack) {
startScrollback();
}
if(y < 0)
y = 0;
@ -1259,10 +1259,12 @@ class TerminalEmulator {
if(currentScrollback < 0)
currentScrollback = 0;
if(currentScrollbackX < 0)
currentScrollbackX = 0;
if(currentScrollback == 0)
if(!scrollLock && currentScrollback == 0 && currentScrollbackX == 0) {
endScrollback();
else {
} else {
cls();
showScrollbackOnScreen(alternateScreen, currentScrollback, false, currentScrollbackX);
}
@ -1273,19 +1275,20 @@ class TerminalEmulator {
return;
if(!scrollingBack) {
if(delta <= 0)
if(delta <= 0 && deltaX == 0)
return; // it does nothing to scroll down when not scrolling back
startScrollback();
}
currentScrollback += delta;
if(deltaX) {
if(!scrollbackReflow && 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;
if(!scrollLock)
scrollbackReflow = true;
} else
scrollbackReflow = false;
}
int max = cast(int) scrollbackBuffer.length - screenHeight;
@ -1304,8 +1307,10 @@ class TerminalEmulator {
if(currentScrollback > max)
currentScrollback = max;
if(currentScrollback < 0)
currentScrollback = 0;
if(currentScrollback <= 0)
if(!scrollLock && currentScrollback <= 0 && currentScrollbackX <= 0)
endScrollback();
else {
cls();
@ -1330,6 +1335,8 @@ class TerminalEmulator {
}
bool endScrollback() {
//if(scrollLock)
// return false;
if(!scrollingBack)
return false;
scrollingBack = false;
@ -1342,20 +1349,62 @@ class TerminalEmulator {
currentScrollback = 0;
currentScrollbackX = 0;
if(!scrollLock) {
scrollbackReflow = true;
recalculateScrollbackLength();
}
notifyScrollbarPosition(0, int.max);
return true;
}
private bool scrollbackReflow = true;
/* deprecated? */
public void toggleScrollbackWrap() {
scrollbackReflow = !scrollbackReflow;
recalculateScrollbackLength();
}
private bool scrollLock = false;
public void toggleScrollLock() {
scrollLock = !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) {
@ -1368,8 +1417,8 @@ class TerminalEmulator {
}
}
public void drawScrollback() {
showScrollbackOnScreen(normalScreen, 0, true, 0);
public void drawScrollback(bool useAltScreen = false) {
showScrollbackOnScreen(useAltScreen ? alternateScreen : normalScreen, 0, true, 0);
}
private void showScrollbackOnScreen(ref TerminalCell[] screen, int howFar, bool reflow, int howFarX) {
@ -1460,6 +1509,10 @@ class TerminalEmulator {
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)
// do i like this?
if(scrollLock)
toggleScrollLock();
endScrollback(); // FIXME: hack
screenWidth = w;
@ -1492,15 +1545,7 @@ class TerminalEmulator {
cursorY = cursorY;
cursorX = cursorX;
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);
recalculateScrollbackLength();
}
private CursorPosition popSavedCursor() {
@ -1540,6 +1585,11 @@ class TerminalEmulator {
notifyScrollbackAdded();
}
public void moveCursor(int x, int y) {
cursorX = x;
cursorY = y;
}
/* FIXME: i want these to be private */
protected {
TextAttributes currentAttributes;
@ -1853,6 +1903,8 @@ class TerminalEmulator {
public void addScrollbackLine(TerminalCell[] 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);
notifyScrollbackAdded();
if(!alternateScreenActive)