diff options
author | Jack Palevich <jackpal@google.com> | 2012-09-28 22:09:57 -0700 |
---|---|---|
committer | Jack Palevich <jackpal@google.com> | 2012-09-28 22:09:57 -0700 |
commit | 54d253011a2ec02adc247d6402fce0daaeb27a9f (patch) | |
tree | 02a64806883e70a84116e7871de729694fa36aed | |
parent | 8f5212af5f2d9b2b4367d83d13fa8e663f82c7ef (diff) | |
download | AndroidTerm-54d253011a2ec02adc247d6402fce0daaeb27a9f.tar.gz |
Make blank lines track the current foreground/background color.
This fixes emulation errors related to scrolling with a non-default
background color.
5 files changed, 140 insertions, 137 deletions
diff --git a/libraries/emulatorview/src/jackpal/androidterm/emulatorview/Screen.java b/libraries/emulatorview/src/jackpal/androidterm/emulatorview/Screen.java index 0c30738..84110be 100644 --- a/libraries/emulatorview/src/jackpal/androidterm/emulatorview/Screen.java +++ b/libraries/emulatorview/src/jackpal/androidterm/emulatorview/Screen.java @@ -55,8 +55,9 @@ interface Screen { * * @param topMargin First line that is scrolled. * @param bottomMargin One line after the last line that is scrolled. + * @param style the style for the newly exposed line. */ - void scroll(int topMargin, int bottomMargin); + void scroll(int topMargin, int bottomMargin, int style); /** * Block copy characters from one position in the screen to another. The two diff --git a/libraries/emulatorview/src/jackpal/androidterm/emulatorview/StyleRow.java b/libraries/emulatorview/src/jackpal/androidterm/emulatorview/StyleRow.java new file mode 100644 index 0000000..de9484a --- /dev/null +++ b/libraries/emulatorview/src/jackpal/androidterm/emulatorview/StyleRow.java @@ -0,0 +1,97 @@ +package jackpal.androidterm.emulatorview; + +/** + * Utility class for dealing with text style lines. + * + * We pack color and formatting information for a particular character into an + * int -- see the TextStyle class for details. The simplest way of storing + * that information for a screen row would be to use an array of int -- but + * given that we only use the lower three bytes of the int to store information, + * that effectively wastes one byte per character -- nearly 8 KB per 100 lines + * with an 80-column transcript. + * + * Instead, we use an array of bytes and store the bytes of each int + * consecutively in big-endian order. + */ +final class StyleRow { + private int mStyle; + private int mColumns; + /** Initially null, will be allocated when needed. */ + private byte[] mData; + + StyleRow(int style, int columns) { + mStyle = style; + mColumns = columns; + } + + void set(int column, int style) { + if (style == mStyle && mData == null) { + return; + } + ensureData(); + setStyle(column, style); + } + + int get(int column) { + if (mData == null) { + return mStyle; + } + return getStyle(column); + } + + boolean isSolidStyle() { + return mData == null; + } + + int getSolidStyle() { + if (mData != null) { + throw new IllegalArgumentException("Not a solid style"); + } + return mStyle; + } + + void copy(int start, StyleRow dst, int offset, int len) { + // fast case + if (mData == null && dst.mData == null && start == 0 && offset == 0 + && len == mColumns) { + dst.mStyle = mStyle; + return; + } + // There are other potentially fast cases, but let's just treat them + // all the same for simplicity. + ensureData(); + dst.ensureData(); + System.arraycopy(mData, 3*start, dst.mData, 3*offset, 3*len); + + } + + void ensureData() { + if (mData == null) { + allocate(); + } + } + + private void allocate() { + mData = new byte[3*mColumns]; + for (int i = 0; i < mColumns; i++) { + setStyle(i, mStyle); + } + } + + private int getStyle(int column) { + int index = 3 * column; + byte[] line = mData; + return line[index] & 0xff | (line[index+1] & 0xff) << 8 + | (line[index+2] & 0xff) << 16; + } + + private void setStyle(int column, int value) { + int index = 3 * column; + byte[] line = mData; + line[index] = (byte) (value & 0xff); + line[index+1] = (byte) ((value >> 8) & 0xff); + line[index+2] = (byte) ((value >> 16) & 0xff); + } + + +} diff --git a/libraries/emulatorview/src/jackpal/androidterm/emulatorview/TerminalEmulator.java b/libraries/emulatorview/src/jackpal/androidterm/emulatorview/TerminalEmulator.java index ac7e904..6c39d7b 100644 --- a/libraries/emulatorview/src/jackpal/androidterm/emulatorview/TerminalEmulator.java +++ b/libraries/emulatorview/src/jackpal/androidterm/emulatorview/TerminalEmulator.java @@ -1491,7 +1491,7 @@ class TerminalEmulator { private void scroll() { //System.out.println("Scroll(): mTopMargin " + mTopMargin + " mBottomMargin " + mBottomMargin); mScrollCounter ++; - mScreen.scroll(mTopMargin, mBottomMargin); + mScreen.scroll(mTopMargin, mBottomMargin, getStyle()); } /** diff --git a/libraries/emulatorview/src/jackpal/androidterm/emulatorview/TranscriptScreen.java b/libraries/emulatorview/src/jackpal/androidterm/emulatorview/TranscriptScreen.java index 590236f..99fe829 100644 --- a/libraries/emulatorview/src/jackpal/androidterm/emulatorview/TranscriptScreen.java +++ b/libraries/emulatorview/src/jackpal/androidterm/emulatorview/TranscriptScreen.java @@ -110,9 +110,10 @@ class TranscriptScreen implements Screen { * * @param topMargin First line that is scrolled. * @param bottomMargin One line after the last line that is scrolled. + * @param style the style for the newly exposed line. */ - public void scroll(int topMargin, int bottomMargin) { - mData.scroll(topMargin, bottomMargin); + public void scroll(int topMargin, int bottomMargin, int style) { + mData.scroll(topMargin, bottomMargin, style); } /** @@ -165,7 +166,7 @@ class TranscriptScreen implements Screen { public final void drawText(int row, Canvas canvas, float x, float y, TextRenderer renderer, int cx, int selx1, int selx2, String imeText) { char[] line; - byte[] color; + StyleRow color; try { line = mData.getLine(row); color = mData.getLineColor(row); @@ -209,11 +210,7 @@ class TranscriptScreen implements Screen { while (column < columns) { int style; boolean cursorStyle = false; - if (color != null) { - style = TextStyleLine.getStyle(color, column); - } else { - style = defaultStyle; - } + style = color.get(column); int width; if (Character.isHighSurrogate(line[index])) { cHigh = line[index++]; @@ -309,7 +306,7 @@ class TranscriptScreen implements Screen { UnicodeTranscript data = mData; int columns = mColumns; char[] line; - byte[] rowColorBuffer = null; + StyleRow rowColorBuffer = null; if (selY1 < -data.getActiveTranscriptRows()) { selY1 = -data.getActiveTranscriptRows(); } @@ -353,7 +350,7 @@ class TranscriptScreen implements Screen { char c = line[i]; if (c == 0) { break; - } else if (c != ' ' || (rowColorBuffer != null && TextStyleLine.getStyle(rowColorBuffer, column) != defaultColor)) { + } else if (c != ' ' || (rowColorBuffer.get(column) != defaultColor)) { lastPrintingChar = i; } if (!Character.isLowSurrogate(c)) { @@ -369,7 +366,7 @@ class TranscriptScreen implements Screen { if (rowColorBuffer != null) { column = 0; for (int j = 0; j <= lastPrintingChar; ++j) { - colors.append(TextStyleLine.getStyle(rowColorBuffer, column)); + colors.append(rowColorBuffer.get(column)); column += UnicodeTranscript.charWidth(line, j); if (Character.isHighSurrogate(line[j])) { ++j; diff --git a/libraries/emulatorview/src/jackpal/androidterm/emulatorview/UnicodeTranscript.java b/libraries/emulatorview/src/jackpal/androidterm/emulatorview/UnicodeTranscript.java index efcba8e..584b643 100644 --- a/libraries/emulatorview/src/jackpal/androidterm/emulatorview/UnicodeTranscript.java +++ b/libraries/emulatorview/src/jackpal/androidterm/emulatorview/UnicodeTranscript.java @@ -33,8 +33,7 @@ import jackpal.androidterm.emulatorview.compat.AndroidCharacterCompat; * is used to store the "offset" at which each column starts; for example, * if column 20 starts at index 23 in the array, then mOffset[20] = 3. * - * Color/formatting information is stored in a separate circular buffer of - * int[]. See TextStyle for how to encode/decode the text style. + * Style information is stored in a separate circular buffer of StyleRows. * * Rows are allocated on demand, when a character is first stored into them. * A "basic" row is allocated unless the store which triggers the allocation @@ -46,7 +45,7 @@ class UnicodeTranscript { private static final String TAG = "UnicodeTranscript"; private Object[] mLines; - private byte[][] mColor; + private StyleRow[] mColor; private boolean[] mLineWrap; private int mTotalRows; private int mScreenRows; @@ -57,16 +56,16 @@ class UnicodeTranscript { private int mScreenFirstRow = 0; private char[] tmpLine; - private byte[] tmpColor; + private StyleRow tmpColor; public UnicodeTranscript(int columns, int totalRows, int screenRows, int defaultStyle) { mColumns = columns; mTotalRows = totalRows; mScreenRows = screenRows; mLines = new Object[totalRows]; - mColor = new byte[totalRows][]; + mColor = new StyleRow[totalRows]; mLineWrap = new boolean[totalRows]; - tmpColor = TextStyleLine.allocate(columns); + tmpColor = new StyleRow(defaultStyle, mColumns); mDefaultStyle = defaultStyle; } @@ -151,7 +150,7 @@ class UnicodeTranscript { if (shift < -activeTranscriptRows) { // We want to add blank lines at the bottom instead of at the top Object[] lines = mLines; - byte[][] color = mColor; + Object[] color = mColor; boolean[] lineWrap = mLineWrap; int screenFirstRow = mScreenFirstRow; int totalRows = mTotalRows; @@ -281,8 +280,9 @@ class UnicodeTranscript { * * @param topMargin First line that is scrolled. * @param bottomMargin One line after the last line that is scrolled. + * @param style the style for the newly exposed line. */ - public void scroll(int topMargin, int bottomMargin) { + public void scroll(int topMargin, int bottomMargin, int style) { // Separate out reasons so that stack crawls help us // figure out which condition was violated. if (topMargin > bottomMargin - 1) { @@ -310,7 +310,7 @@ class UnicodeTranscript { // Blank the bottom margin int blankRow = externalToInternalRow(bottomMargin - 1); mLines[blankRow] = null; - mColor[blankRow] = null; + mColor[blankRow] = new StyleRow(style, mColumns); mLineWrap[blankRow] = false; return; @@ -324,10 +324,10 @@ class UnicodeTranscript { one line, move the lines on screen below the bottom margin down one line, then insert the scrolled line into the transcript */ Object[] lines = mLines; - byte[][] color = mColor; + StyleRow[] color = mColor; boolean[] lineWrap = mLineWrap; Object scrollLine = lines[topMarginInt]; - byte[] scrollColor = color[topMarginInt]; + StyleRow scrollColor = color[topMarginInt]; boolean scrollLineWrap = lineWrap[topMarginInt]; blockCopyLines(screenFirstRow, topMargin, 1); blockCopyLines(bottomMarginInt, screenRows - bottomMargin, 1); @@ -344,7 +344,7 @@ class UnicodeTranscript { // Blank the bottom margin int blankRow = externalToInternalRow(bottomMargin - 1); lines[blankRow] = null; - color[blankRow] = null; + color[blankRow] = new StyleRow(style, mColumns); lineWrap[blankRow] = false; return; @@ -370,7 +370,7 @@ class UnicodeTranscript { throw new IllegalArgumentException(); } Object[] lines = mLines; - byte[][] color = mColor; + StyleRow[] color = mColor; if (sy > dy) { // Move in increasing order for (int y = 0; y < h; y++) { @@ -407,18 +407,7 @@ class UnicodeTranscript { } } } - if (color[srcRow] == null && color[dstRow] == null) { - continue; - } else if (color[srcRow] == null && color[dstRow] != null) { - int defaultColor = mDefaultStyle; - for (int x = dx; x < dx + w; ++x) { - TextStyleLine.setStyle(color[dstRow], x, defaultColor); - } - continue; - } else if (color[srcRow] != null && color[dstRow] == null) { - allocateColor(dstRow, mColumns); - } - TextStyleLine.copy(color[srcRow], sx, color[dstRow], dx, w); + color[srcRow].copy(sx, color[dstRow], dx, w); } } else { // Move in decreasing order @@ -456,18 +445,7 @@ class UnicodeTranscript { } } } - if (color[srcRow] == null && color[dstRow] == null) { - continue; - } else if (color[srcRow] == null && color[dstRow] != null) { - int defaultColor = mDefaultStyle; - for (int x = dx; x < dx + w; ++x) { - TextStyleLine.setStyle(color[dstRow], x, defaultColor); - } - continue; - } else if (color[srcRow] != null && color[dstRow] == null) { - allocateColor(dstRow, mColumns); - } - TextStyleLine.copy(color[srcRow], sx, color[dstRow], dx, w); + color[srcRow].copy(sx, color[dstRow], dx, w); } } } @@ -640,29 +618,30 @@ class UnicodeTranscript { } /** - * Get color/formatting information for a particular line. Use the - * methods in TextStyleLine to access the values. + * Get color/formatting information for a particular line. + * The returned object may be a pointer to a temporary buffer, only good + * until the next call to getLineColor. */ - public byte[] getLineColor(int row, int x1, int x2) { + public StyleRow getLineColor(int row, int x1, int x2) { if (row < -mActiveTranscriptRows || row > mScreenRows-1) { throw new IllegalArgumentException(); } row = externalToInternalRow(row); - byte[] color = mColor[row]; - byte[] tmp = tmpColor; + StyleRow color = mColor[row]; + StyleRow tmp = tmpColor; if (color != null) { if (x1 == 0 && x2 == mColumns) { return color; } - TextStyleLine.copy(color, x1, tmp, 0, x2-x1); + color.copy(x1, tmp, 0, x2-x1); return tmp; } else { return null; } } - public byte[] getLineColor(int row) { + public StyleRow getLineColor(int row) { return getLineColor(row, 0, mColumns); } @@ -679,7 +658,8 @@ class UnicodeTranscript { * * @param row The row of the character to get. * @param column The column of the character to get. - * @param charIndex The index of the character in the column to get (0 for the first character, 1 for the next, etc.) + * @param charIndex The index of the character in the column to get + * (0 for the first character, 1 for the next, etc.) * @param out The char[] array into which the character will be placed. * @param offset The offset in the array at which the character will be placed. * @return Whether or not there are characters following this one in the column. @@ -700,33 +680,7 @@ class UnicodeTranscript { FullUnicodeLine line = (FullUnicodeLine) mLines[row]; return line.getChar(column, charIndex, out, offset); } -/* - public int getForeColor(int row, int column) { - if (row < -mActiveTranscriptRows || row > mScreenRows-1) { - throw new IllegalArgumentException(); - } - row = externalToInternalRow(row); - if (mColor[row] == null) { - return mDefaultForeColor; - } else { - return (mColor[row][column] >> 4) & 0xf; - } - } - - public int getBackColor(int row, int column) { - if (row < -mActiveTranscriptRows || row > mScreenRows-1) { - throw new IllegalArgumentException(); - } - row = externalToInternalRow(row); - - if (mColor[row] == null) { - return mDefaultBackColor; - } else { - return mColor[row][column] & 0xf; - } - } -*/ private boolean isBasicChar(int codePoint) { return !(charWidth(codePoint) != 1 || Character.charCount(codePoint) != 1); } @@ -740,7 +694,9 @@ class UnicodeTranscript { } mLines[row] = line; - mColor[row] = null; + if (mColor[row] == null) { + mColor[row] = new StyleRow(0, columns); + } return line; } @@ -748,20 +704,10 @@ class UnicodeTranscript { FullUnicodeLine line = new FullUnicodeLine(columns); mLines[row] = line; - mColor[row] = null; - return line; - } - - private byte[] allocateColor(int row, int columns) { - byte[] color = TextStyleLine.allocate(columns); - - // Set all of the columns to the default colors - int defaultColor = mDefaultStyle; - for (int i = 0; i < columns; ++i) { - TextStyleLine.setStyle(color, i, defaultColor); + if (mColor[row] == null) { + mColor[row] = new StyleRow(0, columns); } - mColor[row] = color; - return color; + return line; } public boolean setChar(int column, int row, int codePoint, int style) { @@ -770,10 +716,7 @@ class UnicodeTranscript { } row = externalToInternalRow(row); - if (mColor[row] == null) { - allocateColor(row, mColumns); - } - TextStyleLine.setStyle(mColor[row], column, style); + mColor[row].set(column, style); return true; } @@ -1062,38 +1005,3 @@ class FullUnicodeLine { } } -/** - * Utility methods for dealing with text style lines. - * - * We pack color and formatting information for a particular character into an - * int -- see the TextStyle class for details. The simplest way of storing - * that information for a screen row would be to use an array of int -- but - * given that we only use the lower three bytes of the int to store information, - * that effectively wastes one byte per character -- nearly 8 KB per 100 lines - * with an 80-column transcript. - * - * Instead, we use an array of bytes and store the bytes of each int - * consecutively in big-endian order. - */ -final class TextStyleLine { - public static byte[] allocate(int columns) { - return new byte[3*columns]; - } - - public static int getStyle(byte[] line, int column) { - int index = 3 * column; - return line[index] & 0xff | (line[index+1] & 0xff) << 8 | (line[index+2] & 0xff) << 16; - } - - public static void setStyle(byte[] line, int column, int value) { - int index = 3 * column; - line[index] = (byte) (value & 0xff); - line[index+1] = (byte) ((value >> 8) & 0xff); - line[index+2] = (byte) ((value >> 16) & 0xff); - } - - public static void copy(byte[] src, int start, - byte[] dst, int offset, int len) { - System.arraycopy(src, 3*start, dst, 3*offset, 3*len); - } -} |