Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.terminal.control; singleton:=true
Bundle-Version: 1.1.200.qualifier
Bundle-Version: 1.1.300.qualifier
Bundle-Activator: org.eclipse.terminal.internal.control.impl.TerminalPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,7 @@ public void insertCharacters(int charactersToInsert) {
TerminalStyle style = fTerminal.getStyle(line, col - n);
fTerminal.setChar(line, col, c, style);
}
int last = Math.min(fCursorColumn + n, fColumns);
for (int col = fCursorColumn; col < last; col++) {
fTerminal.setChar(line, col, '\000', null);
}
eraseCells(line, fCursorColumn, Math.min(fCursorColumn + n, fColumns));
}
}

Expand All @@ -177,7 +174,7 @@ public void eraseToEndOfScreen() {
synchronized (fTerminal) {
eraseLineToEnd();
for (int line = toAbsoluteLine(fCursorLine + 1); line < toAbsoluteLine(fLines); line++) {
fTerminal.cleanLine(line);
eraseLine(line);
}
}

Expand All @@ -187,7 +184,7 @@ public void eraseToEndOfScreen() {
public void eraseToCursor() {
synchronized (fTerminal) {
for (int line = toAbsoluteLine(0); line < toAbsoluteLine(fCursorLine); line++) {
fTerminal.cleanLine(line);
eraseLine(line);
}
eraseLineToCursor();
}
Expand All @@ -197,35 +194,53 @@ public void eraseToCursor() {
public void eraseAll() {
synchronized (fTerminal) {
for (int line = toAbsoluteLine(0); line < toAbsoluteLine(fLines); line++) {
fTerminal.cleanLine(line);
eraseLine(line);
}
}
}

@Override
public void eraseLine() {
synchronized (fTerminal) {
fTerminal.cleanLine(toAbsoluteLine(fCursorLine));
eraseLine(toAbsoluteLine(fCursorLine));
}
}

private void eraseLine(int line) {
fTerminal.cleanLine(line);
eraseCells(line, 0, fColumns);
}

@Override
public void eraseLineToEnd() {
synchronized (fTerminal) {
int line = toAbsoluteLine(fCursorLine);
for (int col = fCursorColumn; col < fColumns; col++) {
fTerminal.setChar(line, col, '\000', null);
}
eraseCells(toAbsoluteLine(fCursorLine), fCursorColumn, fColumns);
}
}

/**
* Erasing leaves behind the background a program is writing in, not the one the
* terminal started with (xterm's "back color erase", which every terminal that
* supports colour implements). Colouring a run of a line by setting a background
* and erasing to the end of it is how a program paints anything wider than the
* characters it has to put there, and without this such a line keeps the
* terminal's own colour from its last character on. xterm applies this to every
* erase (EL, ED, ECH) and to the cells insertion and deletion uncover (ICH, DCH).
*/
private void eraseCells(int line, int from, int to) {
fWrapPending = false; // erasing, inserting and deleting all forget a pending wrap
// Only the background carries over; what is erased is not bold or underlined.
TerminalStyle plain = getDefaultStyle();
TerminalStyle erased = plain == null || fStyle == null ? fStyle : plain.setBackground(fStyle);
for (int col = from; col < to; col++) {
fTerminal.setChar(line, col, '\000', erased);
}
}

@Override
public void eraseLineToCursor() {
synchronized (fTerminal) {
int line = toAbsoluteLine(fCursorLine);
for (int col = 0; col <= fCursorColumn; col++) {
fTerminal.setChar(line, col, '\000', null);
}
eraseCells(toAbsoluteLine(fCursorLine), 0, fCursorColumn + 1);
}
}

Expand All @@ -251,10 +266,7 @@ public void deleteCharacters(int n) {
TerminalStyle style = fTerminal.getStyle(line, col);
fTerminal.setChar(line, col - n, c, style);
}
int first = Math.max(fCursorColumn, fColumns - n);
for (int col = first; col < fColumns; col++) {
fTerminal.setChar(line, col, '\000', null);
}
eraseCells(line, Math.max(fCursorColumn, fColumns - n), fColumns);
}
}

Expand Down Expand Up @@ -353,6 +365,7 @@ private int doLineWrap() {
* MUST be called from a synchronized block!
*/
private void doNewline() {
fWrapPending = false; // DEC STD 070: any move of the cursor forgets a pending wrap
if (fCursorLine == fScrollRegion.getBottomLine()) {
scrollUp(1);
} else if (fCursorLine + 1 >= fLines) {
Expand All @@ -374,6 +387,7 @@ public void processNewline() {
}

private void doReverseLineFeed() {
fWrapPending = false;
if (fCursorLine == fScrollRegion.getTopLine()) {
scrollDown(1);
} else {
Expand Down Expand Up @@ -436,6 +450,7 @@ public void setCursorLine(int targetLine) {
targetLine = fLines - 1;
}
fCursorLine = targetLine;
fWrapPending = false;
// We make the assumption that nobody is changing the
// terminal cursor except this class!
// This assumption gives a huge performance improvement
Expand Down Expand Up @@ -505,10 +520,7 @@ public void scrollDown(int n) {
public void eraseCharacters(int n) {
synchronized (fTerminal) {
int line = toAbsoluteLine(fCursorLine);
int end = Math.min(fCursorColumn + n, fColumns);
for (int col = fCursorColumn; col < end; col++) {
fTerminal.setChar(line, col, '\000', null);
}
eraseCells(line, fCursorColumn, Math.min(fCursorColumn + n, fColumns));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.eclipse.terminal.internal.emulator;

import static org.eclipse.terminal.model.TerminalColor.BLACK;
import static org.eclipse.terminal.model.TerminalColor.GREEN;
import static org.eclipse.terminal.model.TerminalColor.WHITE;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
Expand Down Expand Up @@ -1086,4 +1087,81 @@ public void testNewlineInTopAnchoredScrollRegionCurrentlyDiscardsTopLine() {
assertNull(term.getChars(3));
assertEquals("4444", new String(term.getChars(4))); // footer below the region is untouched
}

@Test
public void testEraseKeepsBackground() {
ITerminalTextData term = makeITerminalTextData();
IVT100EmulatorBackend vt100 = makeBakend(term);
term.setMaxHeight(4);
vt100.setDimensions(4, 8);
vt100.setDefaultStyle(TerminalStyle.getStyle(WHITE, BLACK));
TerminalStyle onGreen = TerminalStyle.getStyle(WHITE, GREEN).setBold(true);
// a program paints a run wider than its text by setting a background and erasing
vt100.setStyle(onGreen);
vt100.setCursor(0, 0);
vt100.appendString("ab");
vt100.eraseLineToEnd();
assertEquals(GREEN, term.getStyle(0, 5).getBackgroundTerminalColor());
assertEquals(GREEN, term.getStyle(0, 7).getBackgroundTerminalColor());
assertFalse(term.getStyle(0, 5).isBold()); // only the background carries over
// the same for erase to cursor, whole line, ECH, and the cells ICH and DCH uncover
vt100.setCursor(1, 3);
vt100.eraseLineToCursor();
assertEquals(GREEN, term.getStyle(1, 0).getBackgroundTerminalColor());
vt100.setCursor(2, 0);
vt100.eraseLine();
assertEquals(GREEN, term.getStyle(2, 7).getBackgroundTerminalColor());
vt100.setStyle(TerminalStyle.getStyle(WHITE, BLACK));
vt100.setCursor(3, 0);
vt100.appendString("0123456"); // one short of the margin, so as not to wrap
vt100.setStyle(onGreen);
vt100.setCursor(3, 1);
vt100.eraseCharacters(2);
assertEquals(GREEN, term.getStyle(3, 2).getBackgroundTerminalColor());
assertEquals(BLACK, term.getStyle(3, 3).getBackgroundTerminalColor());
vt100.setCursor(3, 4);
vt100.insertCharacters(1);
assertEquals(GREEN, term.getStyle(3, 4).getBackgroundTerminalColor());
assertEquals('4', term.getChar(3, 5));
vt100.deleteCharacters(1);
assertEquals(GREEN, term.getStyle(3, 7).getBackgroundTerminalColor());
// erasing in the default background stays default
vt100.setStyle(TerminalStyle.getStyle(WHITE, BLACK));
vt100.setCursor(0, 0);
vt100.eraseToEndOfScreen();
assertEquals(BLACK, term.getStyle(2, 7).getBackgroundTerminalColor());
}

@Test
public void testPendingWrapForgottenByCursorMove() {
ITerminalTextData term = makeITerminalTextData();
IVT100EmulatorBackend vt100 = makeBakend(term);
term.setMaxHeight(3);
vt100.setDimensions(3, 5);
vt100.setVT100LineWrapping(true); // xterm's deferred wrap, as the process connector sets it
vt100.setCursor(0, 0);
vt100.appendString("abcde"); // fills the row: the wrap is pending, not done
// DEC STD 070: a line feed, a cursor move or an erase forgets the pending wrap
vt100.processNewline();
vt100.appendString("x");
assertEquals('x', term.getChar(1, 4));
assertFalse(term.isWrappedLine(0));
assertFalse(term.isWrappedLine(1));
vt100.setCursor(0, 4);
vt100.appendString("e");
vt100.setCursorLine(2);
vt100.appendString("y");
assertEquals('y', term.getChar(2, 4));
vt100.setCursor(0, 4);
vt100.appendString("e");
vt100.eraseCharacters(1);
vt100.appendString("z");
assertEquals('z', term.getChar(0, 4));
assertEquals(0, vt100.getCursorLine());
// only writing on is a wrap
vt100.setCursor(0, 4);
vt100.appendString("ef");
assertTrue(term.isWrappedLine(0));
assertEquals('f', term.getChar(1, 0));
}
}
Loading