blob: 31e6d62590171eb2008d5bb3a19b410ba0e45e2a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2018 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* Michael Scharf (Wind River) - initial API and implementation
* Anton Leherbauer (Wind River) - [453393] Add support for copying wrapped lines without line break
*******************************************************************************/
package org.eclipse.tm.internal.terminal.model;
import org.eclipse.tm.terminal.model.ITerminalTextData;
import org.eclipse.tm.terminal.model.ITerminalTextDataSnapshot;
import org.eclipse.tm.terminal.model.LineSegment;
import org.eclipse.tm.terminal.model.TerminalStyle;
/**
* This class stores the data only within a window {@link #setWindow(int, int)} and
* {@link #getWindowStartLine()} and {@link #getWindowSize()}. Everything outside
* the is <code>char=='\000'</code> and <code>style=null</code>.
*
*/
public class TerminalTextDataWindow implements ITerminalTextData {
final ITerminalTextData fData;
int fWindowStartLine;
int fWindowSize;
int fHeight;
int fMaxHeight;
public TerminalTextDataWindow(ITerminalTextData data) {
fData = data;
}
public TerminalTextDataWindow() {
this(new TerminalTextDataStore());
}
/**
* This is used in asserts to throw an {@link RuntimeException}.
* This is useful for tests.
* @return never -- throws an exception
*/
private boolean throwRuntimeException() {
throw new RuntimeException();
}
/**
* @param line
* @return true if the line is within the window
*/
boolean isInWindow(int line) {
return line >= fWindowStartLine && line < fWindowStartLine + fWindowSize;
}
@Override
public char getChar(int line, int column) {
if (!isInWindow(line))
return 0;
return fData.getChar(line - fWindowStartLine, column);
}
@Override
public char[] getChars(int line) {
if (!isInWindow(line))
return null;
return fData.getChars(line - fWindowStartLine);
}
@Override
public int getHeight() {
return fHeight;
}
@Override
public LineSegment[] getLineSegments(int line, int startCol, int numberOfCols) {
if (!isInWindow(line))
return new LineSegment[] { new LineSegment(startCol, new String(new char[numberOfCols]), null) };
return fData.getLineSegments(line - fWindowStartLine, startCol, numberOfCols);
}
@Override
public int getMaxHeight() {
return fMaxHeight;
}
@Override
public TerminalStyle getStyle(int line, int column) {
if (!isInWindow(line))
return null;
return fData.getStyle(line - fWindowStartLine, column);
}
@Override
public TerminalStyle[] getStyles(int line) {
if (!isInWindow(line))
return null;
return fData.getStyles(line - fWindowStartLine);
}
@Override
public int getWidth() {
return fData.getWidth();
}
@Override
public ITerminalTextDataSnapshot makeSnapshot() {
throw new UnsupportedOperationException();
}
@Override
public void addLine() {
if (fMaxHeight > 0 && getHeight() < fMaxHeight) {
setDimensions(getHeight() + 1, getWidth());
} else {
scroll(0, getHeight(), -1);
}
}
@Override
public void copy(ITerminalTextData source) {
// we inherit the dimensions of the source
setDimensions(source.getHeight(), source.getWidth());
int n = Math.min(fWindowSize, source.getHeight() - fWindowStartLine);
if (n > 0)
fData.copyRange(source, fWindowStartLine, 0, n);
}
@Override
public void copyRange(ITerminalTextData source, int sourceStartLine, int destStartLine, int length) {
int n = length;
int dStart = destStartLine - fWindowStartLine;
int sStart = sourceStartLine;
// if start outside our range, cut the length to copy
if (dStart < 0) {
n += dStart;
sStart -= dStart;
dStart = 0;
}
// do not exceed the window size
n = Math.min(n, fWindowSize);
if (n > 0)
fData.copyRange(source, sStart, dStart, n);
}
@Override
public void copyLine(ITerminalTextData source, int sourceLine, int destLine) {
if (isInWindow(destLine))
fData.copyLine(source, sourceLine, destLine - fWindowStartLine);
}
@Override
public void scroll(int startLine, int size, int shift) {
assert (startLine >= 0 && startLine + size <= fHeight) || throwRuntimeException();
int n = size;
int start = startLine - fWindowStartLine;
// if start outside our range, cut the length to copy
if (start < 0) {
n += start;
start = 0;
}
n = Math.min(n, fWindowSize - start);
// do not exceed the window size
if (n > 0)
fData.scroll(start, n, shift);
}
@Override
public void setChar(int line, int column, char c, TerminalStyle style) {
if (!isInWindow(line))
return;
fData.setChar(line - fWindowStartLine, column, c, style);
}
@Override
public void setChars(int line, int column, char[] chars, int start, int len, TerminalStyle style) {
if (!isInWindow(line))
return;
fData.setChars(line - fWindowStartLine, column, chars, start, len, style);
}
@Override
public void setChars(int line, int column, char[] chars, TerminalStyle style) {
if (!isInWindow(line))
return;
fData.setChars(line - fWindowStartLine, column, chars, style);
}
@Override
public void setDimensions(int height, int width) {
assert height >= 0 || throwRuntimeException();
fData.setDimensions(fWindowSize, width);
fHeight = height;
}
@Override
public void setMaxHeight(int height) {
fMaxHeight = height;
}
public void setWindow(int startLine, int size) {
fWindowStartLine = startLine;
fWindowSize = size;
fData.setDimensions(fWindowSize, getWidth());
}
public int getWindowStartLine() {
return fWindowStartLine;
}
public int getWindowSize() {
return fWindowSize;
}
public void setHeight(int height) {
fHeight = height;
}
@Override
public void cleanLine(int line) {
if (isInWindow(line))
fData.cleanLine(line - fWindowStartLine);
}
@Override
public int getCursorColumn() {
return fData.getCursorColumn();
}
@Override
public int getCursorLine() {
return fData.getCursorLine();
}
@Override
public void setCursorColumn(int column) {
fData.setCursorColumn(column);
}
@Override
public void setCursorLine(int line) {
fData.setCursorLine(line);
}
@Override
public boolean isWrappedLine(int line) {
if (isInWindow(line))
return fData.isWrappedLine(line - fWindowStartLine);
return false;
}
@Override
public void setWrappedLine(int line) {
if (isInWindow(line))
fData.setWrappedLine(line - fWindowStartLine);
}
}