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 * 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) - [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) - [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; package org.eclipse.tm.internal.terminal.emulator;
@ -1307,4 +1308,74 @@ public class VT100EmulatorBackendTest extends TestCase {
assertEquals("abc123", new String(term.getChars(0))); 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 * 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) - [433751] Add option to enable VT100 line wrapping mode
* Anton Leherbauer (Wind River) - [458218] Add support for ANSI insert 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; package org.eclipse.tm.internal.terminal.emulator;
import org.eclipse.tm.terminal.model.Style; import org.eclipse.tm.terminal.model.Style;
/** /**
* @author toni
* *
*/ */
public interface IVT100EmulatorBackend { public interface IVT100EmulatorBackend {
@ -197,4 +197,26 @@ public interface IVT100EmulatorBackend {
* @param enable whether to enable insert mode * @param enable whether to enable insert mode
*/ */
void setInsertMode(boolean enable); 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 * 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) - [433751] Add option to enable VT100 line wrapping mode
* Anton Leherbauer (Wind River) - [458218] Add support for ANSI insert 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; package org.eclipse.tm.internal.terminal.emulator;
@ -157,4 +158,19 @@ public class VT100BackendTraceDecorator implements IVT100EmulatorBackend {
fBackend.setInsertMode(enable); 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) - [433751] Add option to enable VT100 line wrapping mode
* Anton Leherbauer (Wind River) - [458218] Add support for ANSI insert 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) - [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; 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; 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) * 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()); ansiOsCommand.delete(0, ansiOsCommand.length());
break; break;
case ')':
case '(':
case '*':
case '+':
case '-':
case '.':
case '/':
ansiState = ANSISTATE_EXPECTING_CHARSET_DESIGNATION;
break;
case '7': case '7':
// Save cursor position and character attributes // Save cursor position and character attributes
@ -413,6 +430,12 @@ public class VT100Emulator implements ControlListener {
} }
break; break;
case ANSISTATE_EXPECTING_CHARSET_DESIGNATION:
if (character != '%')
ansiState = ANSISTATE_INITIAL;
// Character set designation commands are ignored
break;
default: default:
// This should never happen! If it does happen, it means there is a // This should never happen! If it does happen, it means there is a
// bug in the FSA. For robustness, we return to the initial // bug in the FSA. For robustness, we return to the initial
@ -483,6 +506,11 @@ public class VT100Emulator implements ControlListener {
processAnsiCommand_D(); processAnsiCommand_D();
break; break;
case 'd':
// Line Position Absolute [row] (default = [1,column]) (VPA).
processAnsiCommand_d();
break;
case 'E': case 'E':
// Move cursor to first column of Nth next line (default 1). // Move cursor to first column of Nth next line (default 1).
processAnsiCommand_E(); processAnsiCommand_E();
@ -548,16 +576,19 @@ public class VT100Emulator implements ControlListener {
processAnsiCommand_P(); processAnsiCommand_P();
break; break;
case 'r':
// Set Scrolling Region.
processAnsiCommand_r();
break;
case 'S': case 'S':
// Scroll up. // Scroll up.
// Emacs, vi, and GNU readline don't seem to use this command, so we ignore processAnsiCommand_S();
// it for now.
break; break;
case 'T': case 'T':
// Scroll down. // Scroll down.
// Emacs, vi, and GNU readline don't seem to use this command, so we ignore processAnsiCommand_T();
// it for now.
break; break;
case 'X': case 'X':
@ -646,6 +677,14 @@ public class VT100Emulator implements ControlListener {
moveCursorBackward(getAnsiParameter(0)); 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, * This method moves the cursor to the first column of the Nth next line,
* where N is specified by the ANSI parameter (default 1). * where N is specified by the ANSI parameter (default 1).
@ -967,17 +1006,63 @@ public class VT100Emulator implements ControlListener {
text.deleteCharacters(getAnsiParameter(0)); 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() { private void processDecPrivateCommand_h() {
if (getAnsiParameter(0) == 1) { int param = getAnsiParameter(0);
switch (param) {
case 1:
// Enable Application Cursor Keys (DECCKM) // Enable Application Cursor Keys (DECCKM)
terminal.enableApplicationCursorKeys(true); 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() { private void processDecPrivateCommand_l() {
if (getAnsiParameter(0) == 1) { int param = getAnsiParameter(0);
switch (param) {
case 1:
// Enable Normal Cursor Keys (DECCKM) // Enable Normal Cursor Keys (DECCKM)
terminal.enableApplicationCursorKeys(false); 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) - [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) - [433751] Add option to enable VT100 line wrapping mode
* Anton Leherbauer (Wind River) - [458218] Add support for ANSI insert 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; package org.eclipse.tm.internal.terminal.emulator;
@ -21,6 +22,28 @@ import org.eclipse.tm.terminal.model.Style;
*/ */
public class VT100EmulatorBackend implements IVT100EmulatorBackend { 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 * 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 * logically positioned. The leftmost column on the screen is column 0, and
@ -62,6 +85,8 @@ public class VT100EmulatorBackend implements IVT100EmulatorBackend {
int fColumns; int fColumns;
final private ITerminalTextData fTerminal; final private ITerminalTextData fTerminal;
private boolean fVT100LineWrapping; private boolean fVT100LineWrapping;
private ScrollRegion fScrollRegion = ScrollRegion.FULL_WINDOW;
public VT100EmulatorBackend(ITerminalTextData terminal) { public VT100EmulatorBackend(ITerminalTextData terminal) {
fTerminal=terminal; fTerminal=terminal;
} }
@ -210,7 +235,7 @@ public class VT100EmulatorBackend implements IVT100EmulatorBackend {
return; return;
assert n>0; assert n>0;
int line=toAbsoluteLine(fCursorLine); 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); fTerminal.scroll(line, nLines, n);
} }
} }
@ -240,13 +265,12 @@ public class VT100EmulatorBackend implements IVT100EmulatorBackend {
return; return;
assert n>0; assert n>0;
int line=toAbsoluteLine(fCursorLine); 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); fTerminal.scroll(line, nLines, -n);
} }
} }
private boolean isCusorInScrollingRegion() { private boolean isCusorInScrollingRegion() {
// TODO Auto-generated method stub return fScrollRegion.contains(fCursorLine);
return true;
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -333,7 +357,9 @@ public class VT100EmulatorBackend implements IVT100EmulatorBackend {
* MUST be called from a synchronized block! * MUST be called from a synchronized block!
*/ */
private void doNewline() { private void doNewline() {
if(fCursorLine+1>=fLines) { if (fCursorLine == fScrollRegion.getBottomLine())
scrollUp(1);
else if (fCursorLine+1>=fLines) {
int h=fTerminal.getHeight(); int h=fTerminal.getHeight();
fTerminal.addLine(); fTerminal.addLine();
if(h!=fTerminal.getHeight()) if(h!=fTerminal.getHeight())
@ -440,4 +466,29 @@ public class VT100EmulatorBackend implements IVT100EmulatorBackend {
public void setInsertMode(boolean enable) { public void setInsertMode(boolean enable) {
fInsertMode = 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);
}
}
} }