1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-09 18:56:02 +02:00

Bug 458402 - [terminal] Add support for scroll up/down and scroll region

Change-Id: If3c955663f664d34d01ada0763de2eec7b36b7d4
Signed-off-by: Anton Leherbauer <anton.leherbauer@windriver.com>
This commit is contained in:
Anton Leherbauer 2015-01-27 16:09:11 +01:00
parent 7ff9715a55
commit 53c5808e00
5 changed files with 257 additions and 12 deletions

View file

@ -10,6 +10,7 @@
* Martin Oberhuber (Wind River) - [168197] Fix Terminal for CDC-1.1/Foundation-1.1
* Anton Leherbauer (Wind River) - [453393] Add support for copying wrapped lines without line break
* Anton Leherbauer (Wind River) - [458218] Add support for ANSI insert mode
* Anton Leherbauer (Wind River) - [458402] Add support for scroll up/down and scroll region
*******************************************************************************/
package org.eclipse.tm.internal.terminal.emulator;
@ -1307,4 +1308,74 @@ public class VT100EmulatorBackendTest extends TestCase {
assertEquals("abc123", new String(term.getChars(0)));
}
public void testScrollRegion() {
ITerminalTextData term=makeITerminalTextData();
IVT100EmulatorBackend vt100=makeBakend(term);
term.setMaxHeight(10);
vt100.setDimensions(8, 6);
vt100.appendString("123");
vt100.setCursorColumn(0);
vt100.processNewline();
vt100.appendString("456");
vt100.setCursorColumn(0);
vt100.processNewline();
vt100.appendString("789");
vt100.setCursorColumn(0);
vt100.processNewline();
vt100.appendString("abc");
vt100.setCursorColumn(0);
vt100.processNewline();
vt100.appendString("def");
vt100.setCursorColumn(0);
vt100.processNewline();
vt100.appendString("ghi");
// test scroll within region
vt100.setCursorLine(1);
vt100.setScrollRegion(1, 4);
vt100.scrollUp(1);
assertEquals("123", new String(term.getChars(0)));
assertEquals("789", new String(term.getChars(1)));
assertEquals("abc", new String(term.getChars(2)));
assertEquals("def", new String(term.getChars(3)));
assertNull(term.getChars(4));
assertEquals("ghi", new String(term.getChars(5)));
vt100.scrollDown(1);
assertEquals("123", new String(term.getChars(0)));
assertNull(term.getChars(1));
assertEquals("789", new String(term.getChars(2)));
assertEquals("abc", new String(term.getChars(3)));
assertEquals("def", new String(term.getChars(4)));
assertEquals("ghi", new String(term.getChars(5)));
// test scroll without region
vt100.setScrollRegion(-1, -1);
vt100.scrollDown(1);
assertNull(term.getChars(0));
assertEquals("123", new String(term.getChars(1)));
assertNull(term.getChars(2));
assertEquals("789", new String(term.getChars(3)));
assertEquals("abc", new String(term.getChars(4)));
assertEquals("def", new String(term.getChars(5)));
assertEquals("ghi", new String(term.getChars(6)));
vt100.scrollUp(1);
assertEquals("123", new String(term.getChars(0)));
assertNull(term.getChars(1));
assertEquals("789", new String(term.getChars(2)));
assertEquals("abc", new String(term.getChars(3)));
assertEquals("def", new String(term.getChars(4)));
assertEquals("ghi", new String(term.getChars(5)));
// test scroll by newline
vt100.setScrollRegion(1, 4);
vt100.setCursorLine(4);
vt100.processNewline();
assertEquals("123", new String(term.getChars(0)));
assertEquals("789", new String(term.getChars(1)));
assertEquals("abc", new String(term.getChars(2)));
assertEquals("def", new String(term.getChars(3)));
assertNull(term.getChars(4));
assertEquals("ghi", new String(term.getChars(5)));
}
}

View file

@ -9,13 +9,13 @@
* Michael Scharf (Wind River) - initial API and implementation
* Anton Leherbauer (Wind River) - [433751] Add option to enable VT100 line wrapping mode
* Anton Leherbauer (Wind River) - [458218] Add support for ANSI insert mode
* Anton Leherbauer (Wind River) - [458402] Add support for scroll up/down and scroll region
*******************************************************************************/
package org.eclipse.tm.internal.terminal.emulator;
import org.eclipse.tm.terminal.model.Style;
/**
* @author toni
*
*/
public interface IVT100EmulatorBackend {
@ -197,4 +197,26 @@ public interface IVT100EmulatorBackend {
* @param enable whether to enable insert mode
*/
void setInsertMode(boolean enable);
/**
* Set scrolling region. Negative values reset the scroll region.
*
* @param top top line of scroll region
* @param bottom bottom line of scroll region
*/
void setScrollRegion(int top, int bottom);
/**
* Scroll text upwards.
*
* @param lines number of lines to scroll
*/
void scrollUp(int lines);
/**
* Scroll text downwards.
*
* @param lines number of lines to scroll
*/
void scrollDown(int lines);
}

View file

@ -9,6 +9,7 @@
* Michael Scharf (Wind River) - initial API and implementation
* Anton Leherbauer (Wind River) - [433751] Add option to enable VT100 line wrapping mode
* Anton Leherbauer (Wind River) - [458218] Add support for ANSI insert mode
* Anton Leherbauer (Wind River) - [458402] Add support for scroll up/down and scroll region
*******************************************************************************/
package org.eclipse.tm.internal.terminal.emulator;
@ -157,4 +158,19 @@ public class VT100BackendTraceDecorator implements IVT100EmulatorBackend {
fBackend.setInsertMode(enable);
}
public void setScrollRegion(int top, int bottom) {
fWriter.println("setScrollRegion("+top+','+bottom+")"); //$NON-NLS-1$ //$NON-NLS-2$
fBackend.setScrollRegion(top, bottom);
}
public void scrollUp(int lines) {
fWriter.println("scrollUp("+lines+")"); //$NON-NLS-1$ //$NON-NLS-2$
fBackend.scrollUp(lines);
}
public void scrollDown(int lines) {
fWriter.println("scrollDown("+lines+")"); //$NON-NLS-1$ //$NON-NLS-2$
fBackend.scrollDown(lines);
}
}

View file

@ -23,6 +23,7 @@
* Anton Leherbauer (Wind River) - [433751] Add option to enable VT100 line wrapping mode
* Anton Leherbauer (Wind River) - [458218] Add support for ANSI insert mode
* Anton Leherbauer (Wind River) - [458398] Add support for normal/application cursor keys mode
* Anton Leherbauer (Wind River) - [458402] Add support for scroll up/down and scroll region
*******************************************************************************/
package org.eclipse.tm.internal.terminal.emulator;
@ -77,6 +78,12 @@ public class VT100Emulator implements ControlListener {
*/
private static final int ANSISTATE_EXPECTING_DEC_PRIVATE_COMMAND = 4;
/**
* This is a character processing state: We've seen one of ()*+-./ after an escape
* character. Expecting a character set designation character.
*/
private static final int ANSISTATE_EXPECTING_CHARSET_DESIGNATION = 5;
/**
* This field holds the current state of the Finite TerminalState Automaton (FSA)
@ -341,6 +348,16 @@ public class VT100Emulator implements ControlListener {
ansiOsCommand.delete(0, ansiOsCommand.length());
break;
case ')':
case '(':
case '*':
case '+':
case '-':
case '.':
case '/':
ansiState = ANSISTATE_EXPECTING_CHARSET_DESIGNATION;
break;
case '7':
// Save cursor position and character attributes
@ -413,6 +430,12 @@ public class VT100Emulator implements ControlListener {
}
break;
case ANSISTATE_EXPECTING_CHARSET_DESIGNATION:
if (character != '%')
ansiState = ANSISTATE_INITIAL;
// Character set designation commands are ignored
break;
default:
// This should never happen! If it does happen, it means there is a
// bug in the FSA. For robustness, we return to the initial
@ -483,6 +506,11 @@ public class VT100Emulator implements ControlListener {
processAnsiCommand_D();
break;
case 'd':
// Line Position Absolute [row] (default = [1,column]) (VPA).
processAnsiCommand_d();
break;
case 'E':
// Move cursor to first column of Nth next line (default 1).
processAnsiCommand_E();
@ -548,16 +576,19 @@ public class VT100Emulator implements ControlListener {
processAnsiCommand_P();
break;
case 'r':
// Set Scrolling Region.
processAnsiCommand_r();
break;
case 'S':
// Scroll up.
// Emacs, vi, and GNU readline don't seem to use this command, so we ignore
// it for now.
processAnsiCommand_S();
break;
case 'T':
// Scroll down.
// Emacs, vi, and GNU readline don't seem to use this command, so we ignore
// it for now.
processAnsiCommand_T();
break;
case 'X':
@ -646,6 +677,14 @@ public class VT100Emulator implements ControlListener {
moveCursorBackward(getAnsiParameter(0));
}
/**
* This method moves the cursor to a specific row.
*/
private void processAnsiCommand_d() {
// Line Position Absolute [row] (default = [1,column]) (VPA).
text.setCursorLine(getAnsiParameter(0) - 1);
}
/**
* This method moves the cursor to the first column of the Nth next line,
* where N is specified by the ANSI parameter (default 1).
@ -967,17 +1006,63 @@ public class VT100Emulator implements ControlListener {
text.deleteCharacters(getAnsiParameter(0));
}
/**
* Set Scrolling Region [top;bottom] (default = full size of window) (DECSTBM).
*/
private void processAnsiCommand_r() {
int top = 0;
int bottom = 0;
if (ansiParameters[0].length() > 0 && ansiParameters[1].length() > 0) {
top = getAnsiParameter(0);
bottom = getAnsiParameter(1);
}
text.setScrollRegion(top-1, bottom-1);
}
/**
* Scroll up n lines (default = 1 line).
*/
private void processAnsiCommand_S() {
text.scrollUp(getAnsiParameter(0));
}
/**
* Scroll down n lines (default = 1 line).
*/
private void processAnsiCommand_T() {
text.scrollDown(getAnsiParameter(0));
}
private void processDecPrivateCommand_h() {
if (getAnsiParameter(0) == 1) {
int param = getAnsiParameter(0);
switch (param) {
case 1:
// Enable Application Cursor Keys (DECCKM)
terminal.enableApplicationCursorKeys(true);
break;
case 47:
// Use Alternate Screen Buffer (ignored).
break;
default:
Logger.log("Unsupported command parameter: CSI ?" + param + 'h'); //$NON-NLS-1$
break;
}
}
private void processDecPrivateCommand_l() {
if (getAnsiParameter(0) == 1) {
int param = getAnsiParameter(0);
switch (param) {
case 1:
// Enable Normal Cursor Keys (DECCKM)
terminal.enableApplicationCursorKeys(false);
break;
case 47:
// Use Normal Screen Buffer (ignored, but reset scroll region).
text.setScrollRegion(-1, -1);
break;
default:
Logger.log("Unsupported command parameter: CSI ?" + param + 'l'); //$NON-NLS-1$
break;
}
}

View file

@ -10,6 +10,7 @@
* Anton Leherbauer (Wind River) - [206329] Changing terminal size right after connect does not scroll properly
* Anton Leherbauer (Wind River) - [433751] Add option to enable VT100 line wrapping mode
* Anton Leherbauer (Wind River) - [458218] Add support for ANSI insert mode
* Anton Leherbauer (Wind River) - [458402] Add support for scroll up/down and scroll region
*******************************************************************************/
package org.eclipse.tm.internal.terminal.emulator;
@ -21,6 +22,28 @@ import org.eclipse.tm.terminal.model.Style;
*/
public class VT100EmulatorBackend implements IVT100EmulatorBackend {
private static class ScrollRegion {
static final ScrollRegion FULL_WINDOW = new ScrollRegion(0, Integer.MAX_VALUE-1);
private final int fTop;
private final int fBottom;
ScrollRegion(int top, int bottom) {
fTop = top;
fBottom = bottom;
}
boolean contains(int line) {
return line >= fTop && line <= fBottom;
}
int getTopLine() {
return fTop;
}
int getBottomLine() {
return fBottom;
}
int getHeight() {
return fBottom - fTop + 1;
}
}
/**
* This field holds the number of the column in which the cursor is
* logically positioned. The leftmost column on the screen is column 0, and
@ -62,6 +85,8 @@ public class VT100EmulatorBackend implements IVT100EmulatorBackend {
int fColumns;
final private ITerminalTextData fTerminal;
private boolean fVT100LineWrapping;
private ScrollRegion fScrollRegion = ScrollRegion.FULL_WINDOW;
public VT100EmulatorBackend(ITerminalTextData terminal) {
fTerminal=terminal;
}
@ -210,7 +235,7 @@ public class VT100EmulatorBackend implements IVT100EmulatorBackend {
return;
assert n>0;
int line=toAbsoluteLine(fCursorLine);
int nLines=fTerminal.getHeight()-line;
int nLines=Math.min(fTerminal.getHeight()-line, fScrollRegion.getBottomLine()-fCursorLine+1);
fTerminal.scroll(line, nLines, n);
}
}
@ -240,13 +265,12 @@ public class VT100EmulatorBackend implements IVT100EmulatorBackend {
return;
assert n>0;
int line=toAbsoluteLine(fCursorLine);
int nLines=fTerminal.getHeight()-line;
int nLines=Math.min(fTerminal.getHeight()-line, fScrollRegion.getBottomLine()-fCursorLine+1);
fTerminal.scroll(line, nLines, -n);
}
}
private boolean isCusorInScrollingRegion() {
// TODO Auto-generated method stub
return true;
return fScrollRegion.contains(fCursorLine);
}
/* (non-Javadoc)
@ -333,7 +357,9 @@ public class VT100EmulatorBackend implements IVT100EmulatorBackend {
* MUST be called from a synchronized block!
*/
private void doNewline() {
if(fCursorLine+1>=fLines) {
if (fCursorLine == fScrollRegion.getBottomLine())
scrollUp(1);
else if (fCursorLine+1>=fLines) {
int h=fTerminal.getHeight();
fTerminal.addLine();
if(h!=fTerminal.getHeight())
@ -440,4 +466,29 @@ public class VT100EmulatorBackend implements IVT100EmulatorBackend {
public void setInsertMode(boolean enable) {
fInsertMode = enable;
}
public void setScrollRegion(int top, int bottom) {
if (top < 0 || bottom < 0)
fScrollRegion = ScrollRegion.FULL_WINDOW;
else if (top < bottom)
fScrollRegion = new ScrollRegion(top, bottom);
}
public void scrollUp(int n) {
assert n>0;
synchronized (fTerminal) {
int line = toAbsoluteLine(fScrollRegion.getTopLine());
int nLines = Math.min(fTerminal.getHeight()-line, fScrollRegion.getHeight());
fTerminal.scroll(line, nLines, -n);
}
}
public void scrollDown(int n) {
assert n>0;
synchronized (fTerminal) {
int line = toAbsoluteLine(fScrollRegion.getTopLine());
int nLines = Math.min(fTerminal.getHeight()-line, fScrollRegion.getHeight());
fTerminal.scroll(line, nLines, n);
}
}
}