mirror of https://github.com/adamdruppe/arsd.git
moar terminal fixes
This commit is contained in:
parent
2ed6b50aa6
commit
1c119753b3
35
minigui.d
35
minigui.d
|
@ -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:
|
||||
}
|
||||
|
|
91
terminal.d
91
terminal.d
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue