Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8056013082 | ||
|
|
8e90545c4b | ||
|
|
426ddbacbd | ||
|
|
7e1f8a551f | ||
|
|
e169af0447 | ||
|
|
a2cb3fafee | ||
|
|
166710f14a | ||
|
|
c1a9b7726f | ||
|
|
afb339e9d8 | ||
|
|
64c23f498f | ||
|
|
1dc92b2a12 | ||
|
|
990a957383 | ||
|
|
7bb64d724c | ||
|
|
4609dd71c6 | ||
|
|
8d00f22d4c |
@@ -5,16 +5,16 @@ android {
|
|||||||
buildToolsVersion "24.0.1"
|
buildToolsVersion "24.0.1"
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile 'com.android.support:support-annotations:24.1.1'
|
compile 'com.android.support:support-annotations:24.2.0'
|
||||||
compile "com.android.support:support-v4:24.1.1"
|
compile "com.android.support:support-v4:24.2.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.termux"
|
applicationId "com.termux"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 24
|
targetSdkVersion 24
|
||||||
versionCode 39
|
versionCode 42
|
||||||
versionName "0.39"
|
versionName "0.42"
|
||||||
|
|
||||||
ndk {
|
ndk {
|
||||||
moduleName "libtermux"
|
moduleName "libtermux"
|
||||||
|
|||||||
@@ -26,9 +26,7 @@ import java.net.MalformedURLException;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.termux.app;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
import android.support.v4.widget.DrawerLayout;
|
import android.support.v4.widget.DrawerLayout;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.InputDevice;
|
import android.view.InputDevice;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
@@ -62,7 +61,7 @@ public final class TermuxKeyListener implements TerminalKeyListener {
|
|||||||
if (keyCode == KeyEvent.KEYCODE_ENTER && !currentSession.isRunning()) {
|
if (keyCode == KeyEvent.KEYCODE_ENTER && !currentSession.isRunning()) {
|
||||||
mActivity.removeFinishedSession(currentSession);
|
mActivity.removeFinishedSession(currentSession);
|
||||||
return true;
|
return true;
|
||||||
} else if (e.isCtrlPressed() && e.isShiftPressed()) {
|
} else if (e.isCtrlPressed() && e.isAltPressed()) {
|
||||||
// Get the unmodified code point:
|
// Get the unmodified code point:
|
||||||
int unicodeChar = e.getUnicodeChar(0);
|
int unicodeChar = e.getUnicodeChar(0);
|
||||||
|
|
||||||
@@ -161,7 +160,7 @@ public final class TermuxKeyListener implements TerminalKeyListener {
|
|||||||
resultingKeyCode = KeyEvent.KEYCODE_INSERT;
|
resultingKeyCode = KeyEvent.KEYCODE_INSERT;
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
resultingKeyCode = KeyEvent.KEYCODE_MOVE_HOME;
|
resultingCodePoint = '~';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Special characters to input.
|
// Special characters to input.
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ import static android.view.KeyEvent.KEYCODE_F7;
|
|||||||
import static android.view.KeyEvent.KEYCODE_F8;
|
import static android.view.KeyEvent.KEYCODE_F8;
|
||||||
import static android.view.KeyEvent.KEYCODE_F9;
|
import static android.view.KeyEvent.KEYCODE_F9;
|
||||||
import static android.view.KeyEvent.KEYCODE_FORWARD_DEL;
|
import static android.view.KeyEvent.KEYCODE_FORWARD_DEL;
|
||||||
import static android.view.KeyEvent.KEYCODE_HOME;
|
|
||||||
import static android.view.KeyEvent.KEYCODE_INSERT;
|
import static android.view.KeyEvent.KEYCODE_INSERT;
|
||||||
import static android.view.KeyEvent.KEYCODE_MOVE_END;
|
import static android.view.KeyEvent.KEYCODE_MOVE_END;
|
||||||
|
import static android.view.KeyEvent.KEYCODE_MOVE_HOME;
|
||||||
import static android.view.KeyEvent.KEYCODE_NUMPAD_0;
|
import static android.view.KeyEvent.KEYCODE_NUMPAD_0;
|
||||||
import static android.view.KeyEvent.KEYCODE_NUMPAD_1;
|
import static android.view.KeyEvent.KEYCODE_NUMPAD_1;
|
||||||
import static android.view.KeyEvent.KEYCODE_NUMPAD_2;
|
import static android.view.KeyEvent.KEYCODE_NUMPAD_2;
|
||||||
@@ -66,7 +66,7 @@ public final class KeyHandler {
|
|||||||
// terminfo: http://pubs.opengroup.org/onlinepubs/7990989799/xcurses/terminfo.html
|
// terminfo: http://pubs.opengroup.org/onlinepubs/7990989799/xcurses/terminfo.html
|
||||||
// termcap: http://man7.org/linux/man-pages/man5/termcap.5.html
|
// termcap: http://man7.org/linux/man-pages/man5/termcap.5.html
|
||||||
TERMCAP_TO_KEYCODE.put("%i", KEYMOD_SHIFT | KEYCODE_DPAD_RIGHT);
|
TERMCAP_TO_KEYCODE.put("%i", KEYMOD_SHIFT | KEYCODE_DPAD_RIGHT);
|
||||||
TERMCAP_TO_KEYCODE.put("#2", KEYMOD_SHIFT | KEYCODE_HOME); // Shifted home
|
TERMCAP_TO_KEYCODE.put("#2", KEYMOD_SHIFT | KEYCODE_MOVE_HOME); // Shifted home
|
||||||
TERMCAP_TO_KEYCODE.put("#4", KEYMOD_SHIFT | KEYCODE_DPAD_LEFT);
|
TERMCAP_TO_KEYCODE.put("#4", KEYMOD_SHIFT | KEYCODE_DPAD_LEFT);
|
||||||
TERMCAP_TO_KEYCODE.put("*7", KEYMOD_SHIFT | KEYCODE_MOVE_END); // Shifted end key
|
TERMCAP_TO_KEYCODE.put("*7", KEYMOD_SHIFT | KEYCODE_MOVE_END); // Shifted end key
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ public final class KeyHandler {
|
|||||||
TERMCAP_TO_KEYCODE.put("kb", KEYCODE_DEL); // backspace key
|
TERMCAP_TO_KEYCODE.put("kb", KEYCODE_DEL); // backspace key
|
||||||
|
|
||||||
TERMCAP_TO_KEYCODE.put("kd", KEYCODE_DPAD_DOWN); // terminfo=kcud1, down-arrow key
|
TERMCAP_TO_KEYCODE.put("kd", KEYCODE_DPAD_DOWN); // terminfo=kcud1, down-arrow key
|
||||||
TERMCAP_TO_KEYCODE.put("kh", KEYCODE_HOME);
|
TERMCAP_TO_KEYCODE.put("kh", KEYCODE_MOVE_HOME);
|
||||||
TERMCAP_TO_KEYCODE.put("kl", KEYCODE_DPAD_LEFT);
|
TERMCAP_TO_KEYCODE.put("kl", KEYCODE_DPAD_LEFT);
|
||||||
TERMCAP_TO_KEYCODE.put("kr", KEYCODE_DPAD_RIGHT);
|
TERMCAP_TO_KEYCODE.put("kr", KEYCODE_DPAD_RIGHT);
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ public final class KeyHandler {
|
|||||||
// t_K3 <kPageUp> keypad page-up key
|
// t_K3 <kPageUp> keypad page-up key
|
||||||
// t_K4 <kEnd> keypad end key
|
// t_K4 <kEnd> keypad end key
|
||||||
// t_K5 <kPageDown> keypad page-down key
|
// t_K5 <kPageDown> keypad page-down key
|
||||||
TERMCAP_TO_KEYCODE.put("K1", KEYCODE_HOME);
|
TERMCAP_TO_KEYCODE.put("K1", KEYCODE_MOVE_HOME);
|
||||||
TERMCAP_TO_KEYCODE.put("K3", KEYCODE_PAGE_UP);
|
TERMCAP_TO_KEYCODE.put("K3", KEYCODE_PAGE_UP);
|
||||||
TERMCAP_TO_KEYCODE.put("K4", KEYCODE_MOVE_END);
|
TERMCAP_TO_KEYCODE.put("K4", KEYCODE_MOVE_END);
|
||||||
TERMCAP_TO_KEYCODE.put("K5", KEYCODE_PAGE_DOWN);
|
TERMCAP_TO_KEYCODE.put("K5", KEYCODE_PAGE_DOWN);
|
||||||
@@ -162,7 +162,9 @@ public final class KeyHandler {
|
|||||||
case KEYCODE_DPAD_LEFT:
|
case KEYCODE_DPAD_LEFT:
|
||||||
return (keyMode == 0) ? (cursorApp ? "\033OD" : "\033[D") : transformForModifiers("\033[1", keyMode, 'D');
|
return (keyMode == 0) ? (cursorApp ? "\033OD" : "\033[D") : transformForModifiers("\033[1", keyMode, 'D');
|
||||||
|
|
||||||
case KEYCODE_HOME:
|
case KEYCODE_MOVE_HOME:
|
||||||
|
// Note that KEYCODE_HOME is handled by the system and never delivered to applications.
|
||||||
|
// On a Logitech k810 keyboard KEYCODE_MOVE_HOME is sent by FN+LeftArrow.
|
||||||
return (keyMode == 0) ? (cursorApp ? "\033OH" : "\033[H") : transformForModifiers("\033[1", keyMode, 'H');
|
return (keyMode == 0) ? (cursorApp ? "\033OH" : "\033[H") : transformForModifiers("\033[1", keyMode, 'H');
|
||||||
case KEYCODE_MOVE_END:
|
case KEYCODE_MOVE_END:
|
||||||
return (keyMode == 0) ? (cursorApp ? "\033OF" : "\033[F") : transformForModifiers("\033[1", keyMode, 'F');
|
return (keyMode == 0) ? (cursorApp ? "\033OF" : "\033[F") : transformForModifiers("\033[1", keyMode, 'F');
|
||||||
@@ -217,9 +219,6 @@ public final class KeyHandler {
|
|||||||
case KEYCODE_FORWARD_DEL:
|
case KEYCODE_FORWARD_DEL:
|
||||||
return transformForModifiers("\033[3", keyMode, '~');
|
return transformForModifiers("\033[3", keyMode, '~');
|
||||||
|
|
||||||
case KEYCODE_NUMPAD_DOT:
|
|
||||||
return keypadApplication ? "\033On" : "\033[3~";
|
|
||||||
|
|
||||||
case KEYCODE_PAGE_UP:
|
case KEYCODE_PAGE_UP:
|
||||||
return "\033[5~";
|
return "\033[5~";
|
||||||
case KEYCODE_PAGE_DOWN:
|
case KEYCODE_PAGE_DOWN:
|
||||||
@@ -249,12 +248,14 @@ public final class KeyHandler {
|
|||||||
return keypadApplication ? transformForModifiers("\033O", keyMode, 'k') : "+";
|
return keypadApplication ? transformForModifiers("\033O", keyMode, 'k') : "+";
|
||||||
case KEYCODE_NUMPAD_COMMA:
|
case KEYCODE_NUMPAD_COMMA:
|
||||||
return ",";
|
return ",";
|
||||||
|
case KEYCODE_NUMPAD_DOT:
|
||||||
|
return keypadApplication ? "\033On" : ".";
|
||||||
case KEYCODE_NUMPAD_SUBTRACT:
|
case KEYCODE_NUMPAD_SUBTRACT:
|
||||||
return keypadApplication ? transformForModifiers("\033O", keyMode, 'm') : "-";
|
return keypadApplication ? transformForModifiers("\033O", keyMode, 'm') : "-";
|
||||||
case KEYCODE_NUMPAD_DIVIDE:
|
case KEYCODE_NUMPAD_DIVIDE:
|
||||||
return keypadApplication ? transformForModifiers("\033O", keyMode, 'o') : "/";
|
return keypadApplication ? transformForModifiers("\033O", keyMode, 'o') : "/";
|
||||||
case KEYCODE_NUMPAD_0:
|
case KEYCODE_NUMPAD_0:
|
||||||
return keypadApplication ? transformForModifiers("\033O", keyMode, 'p') : "1";
|
return keypadApplication ? transformForModifiers("\033O", keyMode, 'p') : "0";
|
||||||
case KEYCODE_NUMPAD_1:
|
case KEYCODE_NUMPAD_1:
|
||||||
return keypadApplication ? transformForModifiers("\033O", keyMode, 'q') : "1";
|
return keypadApplication ? transformForModifiers("\033O", keyMode, 'q') : "1";
|
||||||
case KEYCODE_NUMPAD_2:
|
case KEYCODE_NUMPAD_2:
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ public final class TerminalBuffer {
|
|||||||
* @param newRows The number of rows the screen should have.
|
* @param newRows The number of rows the screen should have.
|
||||||
* @param cursor An int[2] containing the (column, row) cursor location.
|
* @param cursor An int[2] containing the (column, row) cursor location.
|
||||||
*/
|
*/
|
||||||
public void resize(int newColumns, int newRows, int newTotalRows, int[] cursor, int currentStyle, boolean altScreen) {
|
public void resize(int newColumns, int newRows, int newTotalRows, int[] cursor, long currentStyle, boolean altScreen) {
|
||||||
// newRows > mTotalRows should not normally happen since mTotalRows is TRANSCRIPT_ROWS (10000):
|
// newRows > mTotalRows should not normally happen since mTotalRows is TRANSCRIPT_ROWS (10000):
|
||||||
if (newColumns == mColumns && newRows <= mTotalRows) {
|
if (newColumns == mColumns && newRows <= mTotalRows) {
|
||||||
// Fast resize where just the rows changed.
|
// Fast resize where just the rows changed.
|
||||||
@@ -237,7 +237,7 @@ public final class TerminalBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int currentOldCol = 0;
|
int currentOldCol = 0;
|
||||||
int styleAtCol = 0;
|
long styleAtCol = 0;
|
||||||
for (int i = 0; i < lastNonSpaceIndex; i++) {
|
for (int i = 0; i < lastNonSpaceIndex; i++) {
|
||||||
// Note that looping over java character, not cells.
|
// Note that looping over java character, not cells.
|
||||||
char c = oldLine.mText[i];
|
char c = oldLine.mText[i];
|
||||||
@@ -321,7 +321,7 @@ public final class TerminalBuffer {
|
|||||||
* @param bottomMargin One line after the last line that is scrolled.
|
* @param bottomMargin One line after the last line that is scrolled.
|
||||||
* @param style the style for the newly exposed line.
|
* @param style the style for the newly exposed line.
|
||||||
*/
|
*/
|
||||||
public void scrollDownOneLine(int topMargin, int bottomMargin, int style) {
|
public void scrollDownOneLine(int topMargin, int bottomMargin, long style) {
|
||||||
if (topMargin > bottomMargin - 1 || topMargin < 0 || bottomMargin > mScreenRows)
|
if (topMargin > bottomMargin - 1 || topMargin < 0 || bottomMargin > mScreenRows)
|
||||||
throw new IllegalArgumentException("topMargin=" + topMargin + ", bottomMargin=" + bottomMargin + ", mScreenRows=" + mScreenRows);
|
throw new IllegalArgumentException("topMargin=" + topMargin + ", bottomMargin=" + bottomMargin + ", mScreenRows=" + mScreenRows);
|
||||||
|
|
||||||
@@ -374,7 +374,7 @@ public final class TerminalBuffer {
|
|||||||
* InvalidParemeterException will be thrown. Typically this is called with a "val" argument of 32 to clear a block
|
* InvalidParemeterException will be thrown. Typically this is called with a "val" argument of 32 to clear a block
|
||||||
* of characters.
|
* of characters.
|
||||||
*/
|
*/
|
||||||
public void blockSet(int sx, int sy, int w, int h, int val, int style) {
|
public void blockSet(int sx, int sy, int w, int h, int val, long style) {
|
||||||
if (sx < 0 || sx + w > mColumns || sy < 0 || sy + h > mScreenRows) {
|
if (sx < 0 || sx + w > mColumns || sy < 0 || sy + h > mScreenRows) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Illegal arguments! blockSet(" + sx + ", " + sy + ", " + w + ", " + h + ", " + val + ", " + mColumns + ", " + mScreenRows + ")");
|
"Illegal arguments! blockSet(" + sx + ", " + sy + ", " + w + ", " + h + ", " + val + ", " + mColumns + ", " + mScreenRows + ")");
|
||||||
@@ -388,14 +388,14 @@ public final class TerminalBuffer {
|
|||||||
return (mLines[row] == null) ? (mLines[row] = new TerminalRow(mColumns, 0)) : mLines[row];
|
return (mLines[row] == null) ? (mLines[row] = new TerminalRow(mColumns, 0)) : mLines[row];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setChar(int column, int row, int codePoint, int style) {
|
public void setChar(int column, int row, int codePoint, long style) {
|
||||||
if (row >= mScreenRows || column >= mColumns)
|
if (row >= mScreenRows || column >= mColumns)
|
||||||
throw new IllegalArgumentException("row=" + row + ", column=" + column + ", mScreenRows=" + mScreenRows + ", mColumns=" + mColumns);
|
throw new IllegalArgumentException("row=" + row + ", column=" + column + ", mScreenRows=" + mScreenRows + ", mColumns=" + mColumns);
|
||||||
row = externalToInternalRow(row);
|
row = externalToInternalRow(row);
|
||||||
allocateFullLineIfNecessary(row).setChar(column, codePoint, style);
|
allocateFullLineIfNecessary(row).setChar(column, codePoint, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getStyleAt(int externalRow, int column) {
|
public long getStyleAt(int externalRow, int column) {
|
||||||
return allocateFullLineIfNecessary(externalToInternalRow(externalRow)).getStyle(column);
|
return allocateFullLineIfNecessary(externalToInternalRow(externalRow)).getStyle(column);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,7 +407,7 @@ public final class TerminalBuffer {
|
|||||||
int startOfLine = (rectangular || y == top) ? left : leftMargin;
|
int startOfLine = (rectangular || y == top) ? left : leftMargin;
|
||||||
int endOfLine = (rectangular || y + 1 == bottom) ? right : rightMargin;
|
int endOfLine = (rectangular || y + 1 == bottom) ? right : rightMargin;
|
||||||
for (int x = startOfLine; x < endOfLine; x++) {
|
for (int x = startOfLine; x < endOfLine; x++) {
|
||||||
int currentStyle = line.getStyle(x);
|
long currentStyle = line.getStyle(x);
|
||||||
int foreColor = TextStyle.decodeForeColor(currentStyle);
|
int foreColor = TextStyle.decodeForeColor(currentStyle);
|
||||||
int backColor = TextStyle.decodeBackColor(currentStyle);
|
int backColor = TextStyle.decodeBackColor(currentStyle);
|
||||||
int effect = TextStyle.decodeEffect(currentStyle);
|
int effect = TextStyle.decodeEffect(currentStyle);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import java.util.Stack;
|
|||||||
/**
|
/**
|
||||||
* Renders text into a screen. Contains all the terminal-specific knowledge and state. Emulates a subset of the X Window
|
* Renders text into a screen. Contains all the terminal-specific knowledge and state. Emulates a subset of the X Window
|
||||||
* System xterm terminal, which in turn is an emulator for a subset of the Digital Equipment Corporation vt100 terminal.
|
* System xterm terminal, which in turn is an emulator for a subset of the Digital Equipment Corporation vt100 terminal.
|
||||||
* <p/>
|
* <p>
|
||||||
* References:
|
* References:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>http://invisible-island.net/xterm/ctlseqs/ctlseqs.html</li>
|
* <li>http://invisible-island.net/xterm/ctlseqs/ctlseqs.html</li>
|
||||||
@@ -145,7 +145,7 @@ public final class TerminalEmulator {
|
|||||||
/**
|
/**
|
||||||
* The alternate screen buffer, exactly as large as the display and contains no additional saved lines (so that when
|
* The alternate screen buffer, exactly as large as the display and contains no additional saved lines (so that when
|
||||||
* the alternate screen buffer is active, you cannot scroll back to view saved lines).
|
* the alternate screen buffer is active, you cannot scroll back to view saved lines).
|
||||||
* <p/>
|
* <p>
|
||||||
* See http://www.xfree86.org/current/ctlseqs.html#The%20Alternate%20Screen%20Buffer
|
* See http://www.xfree86.org/current/ctlseqs.html#The%20Alternate%20Screen%20Buffer
|
||||||
*/
|
*/
|
||||||
final TerminalBuffer mAltBuffer;
|
final TerminalBuffer mAltBuffer;
|
||||||
@@ -206,10 +206,15 @@ public final class TerminalEmulator {
|
|||||||
*/
|
*/
|
||||||
private boolean mAboutToAutoWrap;
|
private boolean mAboutToAutoWrap;
|
||||||
|
|
||||||
/** Foreground and background color indices, 0..255. */
|
/**
|
||||||
|
* Current foreground and background colors. Can either be a color index in [0,259] or a truecolor (24-bit) value.
|
||||||
|
* For a 24-bit value the top byte (0xff000000) is set.
|
||||||
|
*
|
||||||
|
* @see TextStyle
|
||||||
|
*/
|
||||||
int mForeColor, mBackColor;
|
int mForeColor, mBackColor;
|
||||||
|
|
||||||
/** Current TextStyle effect */
|
/** Current {@link TextStyle} effect. */
|
||||||
private int mEffect;
|
private int mEffect;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -611,7 +616,7 @@ public final class TerminalEmulator {
|
|||||||
int left = Math.min(getArg(argIndex++, 1, true) + effectiveLeftMargin, effectiveRightMargin + 1);
|
int left = Math.min(getArg(argIndex++, 1, true) + effectiveLeftMargin, effectiveRightMargin + 1);
|
||||||
int bottom = Math.min(getArg(argIndex++, mRows, true) + effectiveTopMargin, effectiveBottomMargin);
|
int bottom = Math.min(getArg(argIndex++, mRows, true) + effectiveTopMargin, effectiveBottomMargin);
|
||||||
int right = Math.min(getArg(argIndex, mColumns, true) + effectiveLeftMargin, effectiveRightMargin);
|
int right = Math.min(getArg(argIndex, mColumns, true) + effectiveLeftMargin, effectiveRightMargin);
|
||||||
int style = getStyle();
|
long style = getStyle();
|
||||||
for (int row = top - 1; row < bottom; row++)
|
for (int row = top - 1; row < bottom; row++)
|
||||||
for (int col = left - 1; col < right; col++)
|
for (int col = left - 1; col < right; col++)
|
||||||
if (!selective || (TextStyle.decodeEffect(mScreen.getStyleAt(row, col)) & TextStyle.CHARACTER_ATTRIBUTE_PROTECTED) == 0)
|
if (!selective || (TextStyle.decodeEffect(mScreen.getStyleAt(row, col)) & TextStyle.CHARACTER_ATTRIBUTE_PROTECTED) == 0)
|
||||||
@@ -623,7 +628,7 @@ public final class TerminalEmulator {
|
|||||||
case 't': // "${CSI}${TOP}${LEFT}${BOTTOM}${RIGHT}${ATTRIBUTES}$t"
|
case 't': // "${CSI}${TOP}${LEFT}${BOTTOM}${RIGHT}${ATTRIBUTES}$t"
|
||||||
// Reverse attributes in rectangular area (DECRARA - http://www.vt100.net/docs/vt510-rm/DECRARA).
|
// Reverse attributes in rectangular area (DECRARA - http://www.vt100.net/docs/vt510-rm/DECRARA).
|
||||||
boolean reverse = b == 't';
|
boolean reverse = b == 't';
|
||||||
// FIXME: "coordinates of the rectangular area are affected by the setting of origin mode (DECOM)".s
|
// FIXME: "coordinates of the rectangular area are affected by the setting of origin mode (DECOM)".
|
||||||
int top = Math.min(getArg(0, 1, true) - 1, effectiveBottomMargin) + effectiveTopMargin;
|
int top = Math.min(getArg(0, 1, true) - 1, effectiveBottomMargin) + effectiveTopMargin;
|
||||||
int left = Math.min(getArg(1, 1, true) - 1, effectiveRightMargin) + effectiveLeftMargin;
|
int left = Math.min(getArg(1, 1, true) - 1, effectiveRightMargin) + effectiveLeftMargin;
|
||||||
int bottom = Math.min(getArg(2, mRows, true) + 1, effectiveBottomMargin - 1) + effectiveTopMargin;
|
int bottom = Math.min(getArg(2, mRows, true) + 1, effectiveBottomMargin - 1) + effectiveTopMargin;
|
||||||
@@ -953,7 +958,7 @@ public final class TerminalEmulator {
|
|||||||
unknownSequence(b);
|
unknownSequence(b);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
int style = getStyle();
|
long style = getStyle();
|
||||||
for (int row = startRow; row < endRow; row++) {
|
for (int row = startRow; row < endRow; row++) {
|
||||||
for (int col = startCol; col < endCol; col++) {
|
for (int col = startCol; col < endCol; col++) {
|
||||||
if ((TextStyle.decodeEffect(mScreen.getStyleAt(row, col)) & TextStyle.CHARACTER_ATTRIBUTE_PROTECTED) == 0)
|
if ((TextStyle.decodeEffect(mScreen.getStyleAt(row, col)) & TextStyle.CHARACTER_ATTRIBUTE_PROTECTED) == 0)
|
||||||
@@ -1687,43 +1692,42 @@ public final class TerminalEmulator {
|
|||||||
} else if (code >= 30 && code <= 37) {
|
} else if (code >= 30 && code <= 37) {
|
||||||
mForeColor = code - 30;
|
mForeColor = code - 30;
|
||||||
} else if (code == 38 || code == 48) {
|
} else if (code == 38 || code == 48) {
|
||||||
// ISO-8613-3 controls to set foreground (38) or background (48) colors.
|
// Extended set foreground(38)/background (48) color.
|
||||||
// P_s = (38|48) ; 2 ; P_r ; P_g ; P_b => Set to RGB value in range (0-255).
|
// This is followed by either "2;$R;$G;$B" to set a 24-bit color or
|
||||||
// P_s = (38|48) ; 5 ; P_s => Set to indexed color.
|
// "5;$INDEX" to set an indexed color.
|
||||||
if (i + 2 <= mArgIndex) {
|
if (i + 2 > mArgIndex) continue;
|
||||||
int color = -1;
|
int firstArg = mArgs[i + 1];
|
||||||
int firstArg = mArgs[i + 1];
|
if (firstArg == 2) {
|
||||||
if (firstArg == 2) {
|
if (i + 4 > mArgIndex) {
|
||||||
if (i + 4 > mArgIndex) {
|
Log.w(EmulatorDebug.LOG_TAG, "Too few CSI" + code + ";2 RGB arguments");
|
||||||
Log.w(EmulatorDebug.LOG_TAG, "Too few CSI" + code + ";2 RGB arguments");
|
|
||||||
} else {
|
|
||||||
int red = mArgs[i + 2], green = mArgs[i + 3], blue = mArgs[i + 4];
|
|
||||||
if (red < 0 || green < 0 || blue < 0 || red > 255 || green > 255 || blue > 255) {
|
|
||||||
finishSequenceAndLogError("Invalid RGB: " + red + "," + green + "," + blue);
|
|
||||||
} else {
|
|
||||||
// TODO: Implement 24 bit color.
|
|
||||||
finishSequenceAndLogError("Unimplemented RGB: " + red + "," + green + "," + blue);
|
|
||||||
}
|
|
||||||
i += 4; // "2;P_r;P_g;P_r"
|
|
||||||
}
|
|
||||||
} else if (firstArg == 5) {
|
|
||||||
color = mArgs[i + 2];
|
|
||||||
i += 2; // "5;P_s"
|
|
||||||
} else {
|
} else {
|
||||||
finishSequenceAndLogError("Invalid ISO-8613-3 SGR first argument: " + firstArg);
|
int red = mArgs[i + 2], green = mArgs[i + 3], blue = mArgs[i + 4];
|
||||||
}
|
if (red < 0 || green < 0 || blue < 0 || red > 255 || green > 255 || blue > 255) {
|
||||||
if (i != -1) {
|
finishSequenceAndLogError("Invalid RGB: " + red + "," + green + "," + blue);
|
||||||
if (color >= 0 && color < TextStyle.NUM_INDEXED_COLORS) {
|
|
||||||
if (code == 38) {
|
|
||||||
mForeColor = color;
|
|
||||||
} else {
|
|
||||||
mBackColor = color;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (LOG_ESCAPE_SEQUENCES)
|
int argbColor = 0xff000000 | (red << 16) | (green << 8) | blue;
|
||||||
Log.w(EmulatorDebug.LOG_TAG, "Invalid color index: " + color);
|
if (code == 38) {
|
||||||
|
mForeColor = argbColor;
|
||||||
|
} else {
|
||||||
|
mBackColor = argbColor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
i += 4; // "2;P_r;P_g;P_r"
|
||||||
}
|
}
|
||||||
|
} else if (firstArg == 5) {
|
||||||
|
int color = mArgs[i + 2];
|
||||||
|
i += 2; // "5;P_s"
|
||||||
|
if (color >= 0 && color < TextStyle.NUM_INDEXED_COLORS) {
|
||||||
|
if (code == 38) {
|
||||||
|
mForeColor = color;
|
||||||
|
} else {
|
||||||
|
mBackColor = color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (LOG_ESCAPE_SEQUENCES) Log.w(EmulatorDebug.LOG_TAG, "Invalid color index: " + color);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
finishSequenceAndLogError("Invalid ISO-8613-3 SGR first argument: " + firstArg);
|
||||||
}
|
}
|
||||||
} else if (code == 39) { // Set default foreground color.
|
} else if (code == 39) { // Set default foreground color.
|
||||||
mForeColor = TextStyle.COLOR_INDEX_FOREGROUND;
|
mForeColor = TextStyle.COLOR_INDEX_FOREGROUND;
|
||||||
@@ -1924,7 +1928,7 @@ public final class TerminalEmulator {
|
|||||||
mScreen.blockSet(sx, sy, w, h, ' ', getStyle());
|
mScreen.blockSet(sx, sy, w, h, ' ', getStyle());
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getStyle() {
|
private long getStyle() {
|
||||||
return TextStyle.encode(mForeColor, mBackColor, mEffect);
|
return TextStyle.encode(mForeColor, mBackColor, mEffect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ public final class TerminalRow {
|
|||||||
/** If this row has been line wrapped due to text output at the end of line. */
|
/** If this row has been line wrapped due to text output at the end of line. */
|
||||||
boolean mLineWrap;
|
boolean mLineWrap;
|
||||||
/** The style bits of each cell in the row. See {@link TextStyle}. */
|
/** The style bits of each cell in the row. See {@link TextStyle}. */
|
||||||
final int[] mStyle;
|
final long[] mStyle;
|
||||||
|
|
||||||
/** Construct a blank row (containing only whitespace, ' ') with a specified style. */
|
/** Construct a blank row (containing only whitespace, ' ') with a specified style. */
|
||||||
public TerminalRow(int columns, int style) {
|
public TerminalRow(int columns, long style) {
|
||||||
mColumns = columns;
|
mColumns = columns;
|
||||||
mText = new char[(int) (SPARE_CAPACITY_FACTOR * columns)];
|
mText = new char[(int) (SPARE_CAPACITY_FACTOR * columns)];
|
||||||
mStyle = new int[columns];
|
mStyle = new long[columns];
|
||||||
clear(style);
|
clear(style);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,14 +112,14 @@ public final class TerminalRow {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear(int style) {
|
public void clear(long style) {
|
||||||
Arrays.fill(mText, ' ');
|
Arrays.fill(mText, ' ');
|
||||||
Arrays.fill(mStyle, style);
|
Arrays.fill(mStyle, style);
|
||||||
mSpaceUsed = (short) mColumns;
|
mSpaceUsed = (short) mColumns;
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/steven676/Android-Terminal-Emulator/commit/9a47042620bec87617f0b4f5d50568535668fe26
|
// https://github.com/steven676/Android-Terminal-Emulator/commit/9a47042620bec87617f0b4f5d50568535668fe26
|
||||||
public void setChar(int columnToSet, int codePoint, int style) {
|
public void setChar(int columnToSet, int codePoint, long style) {
|
||||||
mStyle[columnToSet] = style;
|
mStyle[columnToSet] = style;
|
||||||
|
|
||||||
final int newCodePointDisplayWidth = WcWidth.width(codePoint);
|
final int newCodePointDisplayWidth = WcWidth.width(codePoint);
|
||||||
@@ -225,7 +225,7 @@ public final class TerminalRow {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int getStyle(int column) {
|
public final long getStyle(int column) {
|
||||||
return mStyle[column];
|
return mStyle[column];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ public final class TerminalSession extends TerminalOutput {
|
|||||||
* @param rows The number of rows in the terminal window.
|
* @param rows The number of rows in the terminal window.
|
||||||
*/
|
*/
|
||||||
public void initializeEmulator(int columns, int rows) {
|
public void initializeEmulator(int columns, int rows) {
|
||||||
mEmulator = new TerminalEmulator(this, columns, rows, /* transcript= */5000);
|
mEmulator = new TerminalEmulator(this, columns, rows, /* transcript= */2000);
|
||||||
|
|
||||||
int[] processId = new int[1];
|
int[] processId = new int[1];
|
||||||
mTerminalFileDescriptor = JNI.createSubprocess(mShellPath, mCwd, mArgs, mEnv, processId, rows, columns);
|
mTerminalFileDescriptor = JNI.createSubprocess(mShellPath, mCwd, mArgs, mEnv, processId, rows, columns);
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package com.termux.terminal;
|
package com.termux.terminal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes effects, foreground and background colors into a 32 bit integer, which are stored for each cell in a terminal
|
* Encodes effects, foreground and background colors into a 64 bit long, which are stored for each cell in a terminal
|
||||||
* row in {@link TerminalRow#mStyle}.
|
* row in {@link TerminalRow#mStyle}.
|
||||||
* <p/>
|
* <p/>
|
||||||
* The foreground and background colors take 9 bits each, leaving (32-9-9)=14 bits for effect flags. Using 9 for now
|
* The bit layout is:
|
||||||
* (the different CHARACTER_ATTRIBUTE_* bits).
|
* - 16 flags (11 currently used).
|
||||||
|
* - 24 for foreground color (only 9 first bits if a color index).
|
||||||
|
* - 24 for background color (only 9 first bits if a color index).
|
||||||
*/
|
*/
|
||||||
public final class TextStyle {
|
public final class TextStyle {
|
||||||
|
|
||||||
@@ -25,6 +27,10 @@ public final class TextStyle {
|
|||||||
public final static int CHARACTER_ATTRIBUTE_PROTECTED = 1 << 7;
|
public final static int CHARACTER_ATTRIBUTE_PROTECTED = 1 << 7;
|
||||||
/** Dim colors. Also known as faint or half intensity. */
|
/** Dim colors. Also known as faint or half intensity. */
|
||||||
public final static int CHARACTER_ATTRIBUTE_DIM = 1 << 8;
|
public final static int CHARACTER_ATTRIBUTE_DIM = 1 << 8;
|
||||||
|
/** If true (24-bit) color is used for the cell for foreground. */
|
||||||
|
private final static int CHARACTER_ATTRIBUTE_TRUECOLOR_FOREGROUND = 1 << 9;
|
||||||
|
/** If true (24-bit) color is used for the cell for foreground. */
|
||||||
|
private final static int CHARACTER_ATTRIBUTE_TRUECOLOR_BACKGROUND= 1 << 10;
|
||||||
|
|
||||||
public final static int COLOR_INDEX_FOREGROUND = 256;
|
public final static int COLOR_INDEX_FOREGROUND = 256;
|
||||||
public final static int COLOR_INDEX_BACKGROUND = 257;
|
public final static int COLOR_INDEX_BACKGROUND = 257;
|
||||||
@@ -34,22 +40,47 @@ public final class TextStyle {
|
|||||||
public final static int NUM_INDEXED_COLORS = 259;
|
public final static int NUM_INDEXED_COLORS = 259;
|
||||||
|
|
||||||
/** Normal foreground and background colors and no effects. */
|
/** Normal foreground and background colors and no effects. */
|
||||||
final static int NORMAL = encode(COLOR_INDEX_FOREGROUND, COLOR_INDEX_BACKGROUND, 0);
|
final static long NORMAL = encode(COLOR_INDEX_FOREGROUND, COLOR_INDEX_BACKGROUND, 0);
|
||||||
|
|
||||||
static int encode(int foreColor, int backColor, int effect) {
|
static long encode(int foreColor, int backColor, int effect) {
|
||||||
return ((effect & 0b111111111) << 18) | ((foreColor & 0b111111111) << 9) | (backColor & 0b111111111);
|
long result = effect & 0b111111111;
|
||||||
|
if ((0xff000000 & foreColor) == 0xff000000) {
|
||||||
|
// 24-bit color.
|
||||||
|
result |= CHARACTER_ATTRIBUTE_TRUECOLOR_FOREGROUND | ((foreColor & 0x00ffffffL) << 40L);
|
||||||
|
} else {
|
||||||
|
// Indexed color.
|
||||||
|
result |= (foreColor & 0b111111111L) << 40;
|
||||||
|
}
|
||||||
|
if ((0xff000000 & backColor) == 0xff000000) {
|
||||||
|
// 24-bit color.
|
||||||
|
result |= CHARACTER_ATTRIBUTE_TRUECOLOR_BACKGROUND | ((backColor & 0x00ffffffL) << 16L);
|
||||||
|
} else {
|
||||||
|
// Indexed color.
|
||||||
|
result |= (backColor & 0b111111111L) << 16L;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int decodeForeColor(int encodedColor) {
|
public static int decodeForeColor(long style) {
|
||||||
return (encodedColor >> 9) & 0b111111111;
|
if ((style & CHARACTER_ATTRIBUTE_TRUECOLOR_FOREGROUND) == 0) {
|
||||||
|
return (int) ((style >>> 40) & 0b111111111L);
|
||||||
|
} else {
|
||||||
|
return 0xff000000 | (int) ((style >>> 40) & 0x00ffffffL);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int decodeBackColor(int encodedColor) {
|
public static int decodeBackColor(long style) {
|
||||||
return encodedColor & 0b111111111;
|
if ((style & CHARACTER_ATTRIBUTE_TRUECOLOR_BACKGROUND) == 0) {
|
||||||
|
return (int) ((style >>> 16) & 0b111111111L);
|
||||||
|
} else {
|
||||||
|
return 0xff000000 | (int) ((style >>> 16) & 0x00ffffffL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int decodeEffect(int encodedColor) {
|
public static int decodeEffect(long style) {
|
||||||
return (encodedColor >> 18) & 0b111111111;
|
return (int) (style & 0b11111111111);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ final class TerminalRenderer {
|
|||||||
final char[] line = lineObject.mText;
|
final char[] line = lineObject.mText;
|
||||||
final int charsUsedInLine = lineObject.getSpaceUsed();
|
final int charsUsedInLine = lineObject.getSpaceUsed();
|
||||||
|
|
||||||
int lastRunStyle = 0;
|
long lastRunStyle = 0;
|
||||||
boolean lastRunInsideCursor = false;
|
boolean lastRunInsideCursor = false;
|
||||||
int lastRunStartColumn = -1;
|
int lastRunStartColumn = -1;
|
||||||
int lastRunStartIndex = 0;
|
int lastRunStartIndex = 0;
|
||||||
@@ -97,7 +97,7 @@ final class TerminalRenderer {
|
|||||||
final int codePoint = charIsHighsurrogate ? Character.toCodePoint(charAtIndex, line[currentCharIndex + 1]) : charAtIndex;
|
final int codePoint = charIsHighsurrogate ? Character.toCodePoint(charAtIndex, line[currentCharIndex + 1]) : charAtIndex;
|
||||||
final int codePointWcWidth = WcWidth.width(codePoint);
|
final int codePointWcWidth = WcWidth.width(codePoint);
|
||||||
final boolean insideCursor = (column >= selx1 && column <= selx2) || (cursorX == column || (codePointWcWidth == 2 && cursorX == column + 1));
|
final boolean insideCursor = (column >= selx1 && column <= selx2) || (cursorX == column || (codePointWcWidth == 2 && cursorX == column + 1));
|
||||||
final int style = lineObject.getStyle(column);
|
final long style = lineObject.getStyle(column);
|
||||||
|
|
||||||
// Check if the measured text width for this code point is not the same as that expected by wcwidth().
|
// Check if the measured text width for this code point is not the same as that expected by wcwidth().
|
||||||
// This could happen for some fonts which are not truly monospace, or for more exotic characters such as
|
// This could happen for some fonts which are not truly monospace, or for more exotic characters such as
|
||||||
@@ -154,9 +154,17 @@ final class TerminalRenderer {
|
|||||||
* @param reverseVideo if the screen is rendered with the global reverse video flag set
|
* @param reverseVideo if the screen is rendered with the global reverse video flag set
|
||||||
*/
|
*/
|
||||||
private void drawTextRun(Canvas canvas, char[] text, int[] palette, float y, int startColumn, int runWidthColumns, int startCharIndex, int runWidthChars,
|
private void drawTextRun(Canvas canvas, char[] text, int[] palette, float y, int startColumn, int runWidthColumns, int startCharIndex, int runWidthChars,
|
||||||
float mes, boolean cursor, int textStyle, boolean reverseVideo) {
|
float mes, boolean cursor, long textStyle, boolean reverseVideo) {
|
||||||
int foreColor = TextStyle.decodeForeColor(textStyle);
|
int foreColor = TextStyle.decodeForeColor(textStyle);
|
||||||
int backColor = TextStyle.decodeBackColor(textStyle);
|
int backColor = TextStyle.decodeBackColor(textStyle);
|
||||||
|
|
||||||
|
int foreColorIndex = -1;
|
||||||
|
if ((foreColor & 0xff000000) != 0xff000000) {
|
||||||
|
foreColorIndex = foreColor;
|
||||||
|
foreColor = palette[foreColor];
|
||||||
|
}
|
||||||
|
if ((backColor & 0xff000000) != 0xff000000) backColor = palette[backColor];
|
||||||
|
|
||||||
final int effect = TextStyle.decodeEffect(textStyle);
|
final int effect = TextStyle.decodeEffect(textStyle);
|
||||||
float left = startColumn * mFontWidth;
|
float left = startColumn * mFontWidth;
|
||||||
float right = left + runWidthColumns * mFontWidth;
|
float right = left + runWidthColumns * mFontWidth;
|
||||||
@@ -180,9 +188,9 @@ final class TerminalRenderer {
|
|||||||
backColor = tmp;
|
backColor = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backColor != TextStyle.COLOR_INDEX_BACKGROUND) {
|
if (backColor != palette[TextStyle.COLOR_INDEX_BACKGROUND]) {
|
||||||
// Only draw non-default background.
|
// Only draw non-default background.
|
||||||
mTextPaint.setColor(palette[backColor]);
|
mTextPaint.setColor(backColor);
|
||||||
canvas.drawRect(left, y - mFontLineSpacingAndAscent + mFontAscent, right, y, mTextPaint);
|
canvas.drawRect(left, y - mFontLineSpacingAndAscent + mFontAscent, right, y, mTextPaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,26 +203,25 @@ final class TerminalRenderer {
|
|||||||
final boolean dim = (effect & TextStyle.CHARACTER_ATTRIBUTE_DIM) != 0;
|
final boolean dim = (effect & TextStyle.CHARACTER_ATTRIBUTE_DIM) != 0;
|
||||||
|
|
||||||
// Let bold have bright colors if applicable (one of the first 8):
|
// Let bold have bright colors if applicable (one of the first 8):
|
||||||
final int actualForeColor = foreColor + (bold && foreColor < 8 ? 8 : 0);
|
if (bold && foreColorIndex >= 0 && foreColorIndex < 8) foreColor = palette[foreColorIndex + 8];
|
||||||
|
|
||||||
int foreColorARGB = palette[actualForeColor];
|
|
||||||
if (dim) {
|
if (dim) {
|
||||||
int red = (0xFF & (foreColorARGB >> 16));
|
int red = (0xFF & (foreColor >> 16));
|
||||||
int green = (0xFF & (foreColorARGB >> 8));
|
int green = (0xFF & (foreColor >> 8));
|
||||||
int blue = (0xFF & foreColorARGB);
|
int blue = (0xFF & foreColor);
|
||||||
// Dim color handling used by libvte which in turn took it from xterm
|
// Dim color handling used by libvte which in turn took it from xterm
|
||||||
// (https://bug735245.bugzilla-attachments.gnome.org/attachment.cgi?id=284267):
|
// (https://bug735245.bugzilla-attachments.gnome.org/attachment.cgi?id=284267):
|
||||||
red = red * 2 / 3;
|
red = red * 2 / 3;
|
||||||
green = green * 2 / 3;
|
green = green * 2 / 3;
|
||||||
blue = blue * 2 / 3;
|
blue = blue * 2 / 3;
|
||||||
foreColorARGB = 0xFF000000 + (red << 16) + (green << 8) + blue;
|
foreColor = 0xFF000000 + (red << 16) + (green << 8) + blue;
|
||||||
}
|
}
|
||||||
|
|
||||||
mTextPaint.setFakeBoldText(bold);
|
mTextPaint.setFakeBoldText(bold);
|
||||||
mTextPaint.setUnderlineText(underline);
|
mTextPaint.setUnderlineText(underline);
|
||||||
mTextPaint.setTextSkewX(italic ? -0.35f : 0.f);
|
mTextPaint.setTextSkewX(italic ? -0.35f : 0.f);
|
||||||
mTextPaint.setStrikeThruText(strikeThrough);
|
mTextPaint.setStrikeThruText(strikeThrough);
|
||||||
mTextPaint.setColor(foreColorARGB);
|
mTextPaint.setColor(foreColor);
|
||||||
|
|
||||||
// The text alignment is the default Paint.Align.LEFT.
|
// The text alignment is the default Paint.Align.LEFT.
|
||||||
canvas.drawText(text, startCharIndex, runWidthChars, left, y - mFontLineSpacingAndAscent, mTextPaint);
|
canvas.drawText(text, startCharIndex, runWidthChars, left, y - mFontLineSpacingAndAscent, mTextPaint);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import android.graphics.Rect;
|
|||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.text.Editable;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
@@ -233,7 +234,8 @@ public final class TerminalView extends View {
|
|||||||
// Previous keyboard issues:
|
// Previous keyboard issues:
|
||||||
// https://github.com/termux/termux-packages/issues/25
|
// https://github.com/termux/termux-packages/issues/25
|
||||||
// https://github.com/termux/termux-app/issues/87.
|
// https://github.com/termux/termux-app/issues/87.
|
||||||
// https://github.com/termux/termux-app/issues/126 for breakage from that.
|
// https://github.com/termux/termux-app/issues/126.
|
||||||
|
// https://github.com/termux/termux-app/issues/137 (japanese chars and TYPE_NULL).
|
||||||
outAttrs.inputType = InputType.TYPE_NULL;
|
outAttrs.inputType = InputType.TYPE_NULL;
|
||||||
|
|
||||||
// Let part of the application show behind when in landscape:
|
// Let part of the application show behind when in landscape:
|
||||||
@@ -244,19 +246,41 @@ public final class TerminalView extends View {
|
|||||||
@Override
|
@Override
|
||||||
public boolean finishComposingText() {
|
public boolean finishComposingText() {
|
||||||
if (LOG_KEY_EVENTS) Log.i(EmulatorDebug.LOG_TAG, "IME: finishComposingText()");
|
if (LOG_KEY_EVENTS) Log.i(EmulatorDebug.LOG_TAG, "IME: finishComposingText()");
|
||||||
commitText(getEditable(), 0);
|
super.finishComposingText();
|
||||||
|
|
||||||
// Clear the editable.
|
sendTextToTerminal(getEditable());
|
||||||
getEditable().clear();
|
getEditable().clear();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean commitText(CharSequence text, int newCursorPosition) {
|
public boolean commitText(CharSequence text, int newCursorPosition) {
|
||||||
if (LOG_KEY_EVENTS)
|
if (LOG_KEY_EVENTS) {
|
||||||
Log.i(EmulatorDebug.LOG_TAG, "IME: commitText(\"" + text + "\", " + newCursorPosition + ")");
|
Log.i(EmulatorDebug.LOG_TAG, "IME: commitText(\"" + text + "\", " + newCursorPosition + ")");
|
||||||
|
}
|
||||||
|
super.commitText(text, newCursorPosition);
|
||||||
|
|
||||||
if (mEmulator == null) return true;
|
if (mEmulator == null) return true;
|
||||||
|
|
||||||
|
Editable content = getEditable();
|
||||||
|
sendTextToTerminal(content);
|
||||||
|
content.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteSurroundingText(int leftLength, int rightLength) {
|
||||||
|
if (LOG_KEY_EVENTS)
|
||||||
|
Log.i(EmulatorDebug.LOG_TAG, "IME: deleteSurroundingText(" + leftLength + ", " + rightLength + ")");
|
||||||
|
// If leftLength=2 it may be due to a UTF-16 surrogate pair. So we cannot send
|
||||||
|
// multiple key events for that. Let's just hope that keyboards don't use
|
||||||
|
// leftLength > 1 for other purposes (such as holding down backspace for repeat).
|
||||||
|
sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
|
||||||
|
return super.deleteSurroundingText(leftLength, rightLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sendTextToTerminal(CharSequence text) {
|
||||||
final int textLengthInChars = text.length();
|
final int textLengthInChars = text.length();
|
||||||
for (int i = 0; i < textLengthInChars; i++) {
|
for (int i = 0; i < textLengthInChars; i++) {
|
||||||
char firstChar = text.charAt(i);
|
char firstChar = text.charAt(i);
|
||||||
@@ -297,35 +321,8 @@ public final class TerminalView extends View {
|
|||||||
|
|
||||||
inputCodePoint(codePoint, ctrlHeld, false);
|
inputCodePoint(codePoint, ctrlHeld, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean deleteSurroundingText(int leftLength, int rightLength) {
|
|
||||||
if (LOG_KEY_EVENTS)
|
|
||||||
Log.i(EmulatorDebug.LOG_TAG, "IME: deleteSurroundingText(" + leftLength + ", " + rightLength + ")");
|
|
||||||
// If leftLength=2 it may be due to a UTF-16 surrogate pair. So we cannot send
|
|
||||||
// multiple key events for that. Let's just hope that keyboards don't use
|
|
||||||
// leftLength > 1 for other purposes (such as holding down backspace for repeat).
|
|
||||||
sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean setComposingText(CharSequence text, int newCursorPosition) {
|
|
||||||
if (LOG_KEY_EVENTS)
|
|
||||||
Log.i(EmulatorDebug.LOG_TAG, "IME: setComposingText(\"" + text + "\", " + newCursorPosition + ")");
|
|
||||||
|
|
||||||
if (text.length() == 0) {
|
|
||||||
// Avoid log spam "SpannableStringBuilder: SPAN_EXCLUSIVE_EXCLUSIVE spans cannot
|
|
||||||
// have a zero length" when backspacing with the Google keyboard.
|
|
||||||
getEditable().clear();
|
|
||||||
} else {
|
|
||||||
super.setComposingText(text, newCursorPosition);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public class CursorAndScreenTest extends TerminalTestCase {
|
|||||||
assertLinesAre("ABCDE", "FGHIJ", "KLMNO", "PQRST", "UVWXY");
|
assertLinesAre("ABCDE", "FGHIJ", "KLMNO", "PQRST", "UVWXY");
|
||||||
for (int row = 0; row < 5; row++) {
|
for (int row = 0; row < 5; row++) {
|
||||||
for (int col = 0; col < 5; col++) {
|
for (int col = 0; col < 5; col++) {
|
||||||
int s = getStyleAt(row, col);
|
long s = getStyleAt(row, col);
|
||||||
Assert.assertEquals(col, TextStyle.decodeForeColor(s));
|
Assert.assertEquals(col, TextStyle.decodeForeColor(s));
|
||||||
Assert.assertEquals(row, TextStyle.decodeBackColor(s));
|
Assert.assertEquals(row, TextStyle.decodeBackColor(s));
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,7 @@ public class CursorAndScreenTest extends TerminalTestCase {
|
|||||||
assertLinesAre("KLMNO", "PQRST", "UVWXY", " ", " ");
|
assertLinesAre("KLMNO", "PQRST", "UVWXY", " ", " ");
|
||||||
for (int row = 0; row < 3; row++) {
|
for (int row = 0; row < 3; row++) {
|
||||||
for (int col = 0; col < 5; col++) {
|
for (int col = 0; col < 5; col++) {
|
||||||
int s = getStyleAt(row, col);
|
long s = getStyleAt(row, col);
|
||||||
Assert.assertEquals(col, TextStyle.decodeForeColor(s));
|
Assert.assertEquals(col, TextStyle.decodeForeColor(s));
|
||||||
Assert.assertEquals(row + 2, TextStyle.decodeBackColor(s));
|
Assert.assertEquals(row + 2, TextStyle.decodeBackColor(s));
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ public class CursorAndScreenTest extends TerminalTestCase {
|
|||||||
for (int col = 0; col < 5; col++) {
|
for (int col = 0; col < 5; col++) {
|
||||||
int wantedForeground = (row == 1 || row == 2) ? 98 : col;
|
int wantedForeground = (row == 1 || row == 2) ? 98 : col;
|
||||||
int wantedBackground = (row == 1 || row == 2) ? 99 : (row == 0 ? 2 : row);
|
int wantedBackground = (row == 1 || row == 2) ? 99 : (row == 0 ? 2 : row);
|
||||||
int s = getStyleAt(row, col);
|
long s = getStyleAt(row, col);
|
||||||
Assert.assertEquals(wantedForeground, TextStyle.decodeForeColor(s));
|
Assert.assertEquals(wantedForeground, TextStyle.decodeForeColor(s));
|
||||||
Assert.assertEquals(wantedBackground, TextStyle.decodeBackColor(s));
|
Assert.assertEquals(wantedBackground, TextStyle.decodeBackColor(s));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,10 +141,10 @@ public class KeyHandlerTest extends TestCase {
|
|||||||
assertKeysEquals("\033[1;6D", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_LEFT, mod, false, false));
|
assertKeysEquals("\033[1;6D", KeyHandler.getCode(KeyEvent.KEYCODE_DPAD_LEFT, mod, false, false));
|
||||||
|
|
||||||
// Home/end keys:
|
// Home/end keys:
|
||||||
assertKeysEquals("\033[H", KeyHandler.getCode(KeyEvent.KEYCODE_HOME, 0, false, false));
|
assertKeysEquals("\033[H", KeyHandler.getCode(KeyEvent.KEYCODE_MOVE_HOME, 0, false, false));
|
||||||
assertKeysEquals("\033[F", KeyHandler.getCode(KeyEvent.KEYCODE_MOVE_END, 0, false, false));
|
assertKeysEquals("\033[F", KeyHandler.getCode(KeyEvent.KEYCODE_MOVE_END, 0, false, false));
|
||||||
// ... shifted:
|
// ... shifted:
|
||||||
assertKeysEquals("\033[1;2H", KeyHandler.getCode(KeyEvent.KEYCODE_HOME, KeyHandler.KEYMOD_SHIFT, false, false));
|
assertKeysEquals("\033[1;2H", KeyHandler.getCode(KeyEvent.KEYCODE_MOVE_HOME, KeyHandler.KEYMOD_SHIFT, false, false));
|
||||||
assertKeysEquals("\033[1;2F", KeyHandler.getCode(KeyEvent.KEYCODE_MOVE_END, KeyHandler.KEYMOD_SHIFT, false, false));
|
assertKeysEquals("\033[1;2F", KeyHandler.getCode(KeyEvent.KEYCODE_MOVE_END, KeyHandler.KEYMOD_SHIFT, false, false));
|
||||||
|
|
||||||
// Function keys F1-F12:
|
// Function keys F1-F12:
|
||||||
@@ -173,5 +173,19 @@ public class KeyHandlerTest extends TestCase {
|
|||||||
assertKeysEquals("\033[21;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F10, KeyHandler.KEYMOD_SHIFT, false, false));
|
assertKeysEquals("\033[21;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F10, KeyHandler.KEYMOD_SHIFT, false, false));
|
||||||
assertKeysEquals("\033[23;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F11, KeyHandler.KEYMOD_SHIFT, false, false));
|
assertKeysEquals("\033[23;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F11, KeyHandler.KEYMOD_SHIFT, false, false));
|
||||||
assertKeysEquals("\033[24;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F12, KeyHandler.KEYMOD_SHIFT, false, false));
|
assertKeysEquals("\033[24;2~", KeyHandler.getCode(KeyEvent.KEYCODE_F12, KeyHandler.KEYMOD_SHIFT, false, false));
|
||||||
}
|
|
||||||
|
assertKeysEquals("0", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_0, 0, false, false));
|
||||||
|
assertKeysEquals("1", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_1, 0, false, false));
|
||||||
|
assertKeysEquals("2", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_2, 0, false, false));
|
||||||
|
assertKeysEquals("3", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_3, 0, false, false));
|
||||||
|
assertKeysEquals("4", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_4, 0, false, false));
|
||||||
|
assertKeysEquals("5", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_5, 0, false, false));
|
||||||
|
assertKeysEquals("6", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_6, 0, false, false));
|
||||||
|
assertKeysEquals("7", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_7, 0, false, false));
|
||||||
|
assertKeysEquals("8", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_8, 0, false, false));
|
||||||
|
assertKeysEquals("9", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_9, 0, false, false));
|
||||||
|
assertKeysEquals(",", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_COMMA, 0, false, false));
|
||||||
|
assertKeysEquals(".", KeyHandler.getCode(KeyEvent.KEYCODE_NUMPAD_DOT, 0, false, false));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public class ResizeTest extends TerminalTestCase {
|
|||||||
enterString("\033[2J");
|
enterString("\033[2J");
|
||||||
for (int r = 0; r < rows; r++) {
|
for (int r = 0; r < rows; r++) {
|
||||||
for (int c = 0; c < cols; c++) {
|
for (int c = 0; c < cols; c++) {
|
||||||
int style = getStyleAt(r, c);
|
long style = getStyleAt(r, c);
|
||||||
assertEquals(119, TextStyle.decodeForeColor(style));
|
assertEquals(119, TextStyle.decodeForeColor(style));
|
||||||
assertEquals(129, TextStyle.decodeBackColor(style));
|
assertEquals(129, TextStyle.decodeBackColor(style));
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ public class ResizeTest extends TerminalTestCase {
|
|||||||
// After resize, screen should still be same color:
|
// After resize, screen should still be same color:
|
||||||
for (int r = 0; r < rows - 2; r++) {
|
for (int r = 0; r < rows - 2; r++) {
|
||||||
for (int c = 0; c < cols; c++) {
|
for (int c = 0; c < cols; c++) {
|
||||||
int style = getStyleAt(r, c);
|
long style = getStyleAt(r, c);
|
||||||
assertEquals(119, TextStyle.decodeForeColor(style));
|
assertEquals(119, TextStyle.decodeForeColor(style));
|
||||||
assertEquals(129, TextStyle.decodeBackColor(style));
|
assertEquals(129, TextStyle.decodeBackColor(style));
|
||||||
}
|
}
|
||||||
@@ -116,7 +116,7 @@ public class ResizeTest extends TerminalTestCase {
|
|||||||
resize(cols, rows);
|
resize(cols, rows);
|
||||||
for (int r = 0; r < rows; r++) {
|
for (int r = 0; r < rows; r++) {
|
||||||
for (int c = 0; c < cols; c++) {
|
for (int c = 0; c < cols; c++) {
|
||||||
int style = getStyleAt(r, c);
|
long style = getStyleAt(r, c);
|
||||||
assertEquals(119, TextStyle.decodeForeColor(style));
|
assertEquals(119, TextStyle.decodeForeColor(style));
|
||||||
assertEquals("wrong at row=" + r, r >= 3 ? 200 : 129, TextStyle.decodeBackColor(style));
|
assertEquals("wrong at row=" + r, r >= 3 ? 200 : 129, TextStyle.decodeBackColor(style));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.termux.terminal;
|
package com.termux.terminal;
|
||||||
|
|
||||||
public class ScreenBufferTest extends TerminalTest {
|
public class ScreenBufferTest extends TerminalTestCase {
|
||||||
|
|
||||||
public void testBasics() {
|
public void testBasics() {
|
||||||
TerminalBuffer screen = new TerminalBuffer(5, 3, 3);
|
TerminalBuffer screen = new TerminalBuffer(5, 3, 3);
|
||||||
|
|||||||
@@ -147,12 +147,11 @@ public class TerminalTest extends TerminalTestCase {
|
|||||||
enterString("\033[38;5;119m");
|
enterString("\033[38;5;119m");
|
||||||
assertEquals(119, mTerminal.mForeColor);
|
assertEquals(119, mTerminal.mForeColor);
|
||||||
assertEquals(TextStyle.COLOR_INDEX_BACKGROUND, mTerminal.mBackColor);
|
assertEquals(TextStyle.COLOR_INDEX_BACKGROUND, mTerminal.mBackColor);
|
||||||
|
|
||||||
enterString("\033[48;5;129m");
|
enterString("\033[48;5;129m");
|
||||||
assertEquals(119, mTerminal.mForeColor);
|
assertEquals(119, mTerminal.mForeColor);
|
||||||
assertEquals(129, mTerminal.mBackColor);
|
assertEquals(129, mTerminal.mBackColor);
|
||||||
|
|
||||||
// Invalid parameter:
|
// Invalid parameter:
|
||||||
enterString("\033[48;8;129m");
|
enterString("\033[48;8;129m");
|
||||||
assertEquals(119, mTerminal.mForeColor);
|
assertEquals(119, mTerminal.mForeColor);
|
||||||
assertEquals(129, mTerminal.mBackColor);
|
assertEquals(129, mTerminal.mBackColor);
|
||||||
@@ -161,7 +160,31 @@ public class TerminalTest extends TerminalTestCase {
|
|||||||
enterString("\033[38;5;178;48;5;179;m");
|
enterString("\033[38;5;178;48;5;179;m");
|
||||||
assertEquals(178, mTerminal.mForeColor);
|
assertEquals(178, mTerminal.mForeColor);
|
||||||
assertEquals(179, mTerminal.mBackColor);
|
assertEquals(179, mTerminal.mBackColor);
|
||||||
}
|
|
||||||
|
// 24 bit colors:
|
||||||
|
enterString(("\033[0m")); // Reset fg and bg colors.
|
||||||
|
enterString("\033[38;2;255;127;2m");
|
||||||
|
int expectedForeground = 0xff000000 | (255 << 16) | (127 << 8) | 2;
|
||||||
|
assertEquals(expectedForeground, mTerminal.mForeColor);
|
||||||
|
assertEquals(TextStyle.COLOR_INDEX_BACKGROUND, mTerminal.mBackColor);
|
||||||
|
enterString("\033[48;2;1;2;254m");
|
||||||
|
int expectedBackground = 0xff000000 | (1 << 16) | (2 << 8) | 254;
|
||||||
|
assertEquals(expectedForeground, mTerminal.mForeColor);
|
||||||
|
assertEquals(expectedBackground, mTerminal.mBackColor);
|
||||||
|
|
||||||
|
// 24 bit colors, set fg and bg at once:
|
||||||
|
enterString(("\033[0m")); // Reset fg and bg colors.
|
||||||
|
assertEquals(TextStyle.COLOR_INDEX_FOREGROUND, mTerminal.mForeColor);
|
||||||
|
assertEquals(TextStyle.COLOR_INDEX_BACKGROUND, mTerminal.mBackColor);
|
||||||
|
enterString("\033[38;2;255;127;2;48;2;1;2;254m");
|
||||||
|
assertEquals(expectedForeground, mTerminal.mForeColor);
|
||||||
|
assertEquals(expectedBackground, mTerminal.mBackColor);
|
||||||
|
|
||||||
|
// 24 bit colors, invalid input:
|
||||||
|
enterString("\033[38;2;300;127;2;48;2;1;300;254m");
|
||||||
|
assertEquals(expectedForeground, mTerminal.mForeColor);
|
||||||
|
assertEquals(expectedBackground, mTerminal.mBackColor);
|
||||||
|
}
|
||||||
|
|
||||||
public void testBackgroundColorErase() {
|
public void testBackgroundColorErase() {
|
||||||
final int rows = 3;
|
final int rows = 3;
|
||||||
@@ -169,7 +192,7 @@ public class TerminalTest extends TerminalTestCase {
|
|||||||
withTerminalSized(cols, rows);
|
withTerminalSized(cols, rows);
|
||||||
for (int r = 0; r < rows; r++) {
|
for (int r = 0; r < rows; r++) {
|
||||||
for (int c = 0; c < cols; c++) {
|
for (int c = 0; c < cols; c++) {
|
||||||
int style = getStyleAt(r, c);
|
long style = getStyleAt(r, c);
|
||||||
assertEquals(TextStyle.COLOR_INDEX_FOREGROUND, TextStyle.decodeForeColor(style));
|
assertEquals(TextStyle.COLOR_INDEX_FOREGROUND, TextStyle.decodeForeColor(style));
|
||||||
assertEquals(TextStyle.COLOR_INDEX_BACKGROUND, TextStyle.decodeBackColor(style));
|
assertEquals(TextStyle.COLOR_INDEX_BACKGROUND, TextStyle.decodeBackColor(style));
|
||||||
}
|
}
|
||||||
@@ -182,7 +205,7 @@ public class TerminalTest extends TerminalTestCase {
|
|||||||
enterString("\033[2J");
|
enterString("\033[2J");
|
||||||
for (int r = 0; r < rows; r++) {
|
for (int r = 0; r < rows; r++) {
|
||||||
for (int c = 0; c < cols; c++) {
|
for (int c = 0; c < cols; c++) {
|
||||||
int style = getStyleAt(r, c);
|
long style = getStyleAt(r, c);
|
||||||
assertEquals(119, TextStyle.decodeForeColor(style));
|
assertEquals(119, TextStyle.decodeForeColor(style));
|
||||||
assertEquals(129, TextStyle.decodeBackColor(style));
|
assertEquals(129, TextStyle.decodeBackColor(style));
|
||||||
}
|
}
|
||||||
@@ -193,7 +216,7 @@ public class TerminalTest extends TerminalTestCase {
|
|||||||
enterString("\033[2L");
|
enterString("\033[2L");
|
||||||
for (int r = 0; r < rows; r++) {
|
for (int r = 0; r < rows; r++) {
|
||||||
for (int c = 0; c < cols; c++) {
|
for (int c = 0; c < cols; c++) {
|
||||||
int style = getStyleAt(r, c);
|
long style = getStyleAt(r, c);
|
||||||
assertEquals((r == 0 || r == 1) ? 139 : 129, TextStyle.decodeBackColor(style));
|
assertEquals((r == 0 || r == 1) ? 139 : 129, TextStyle.decodeBackColor(style));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ public abstract class TerminalTestCase extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** For testing only. Encoded style according to {@link TextStyle}. */
|
/** For testing only. Encoded style according to {@link TextStyle}. */
|
||||||
public int getStyleAt(int externalRow, int column) {
|
public long getStyleAt(int externalRow, int column) {
|
||||||
return mTerminal.getScreen().getStyleAt(externalRow, column);
|
return mTerminal.getScreen().getStyleAt(externalRow, column);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,7 +296,7 @@ public abstract class TerminalTestCase extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void assertForegroundColorAt(int externalRow, int column, int color) {
|
public void assertForegroundColorAt(int externalRow, int column, int color) {
|
||||||
int style = mTerminal.getScreen().mLines[mTerminal.getScreen().externalToInternalRow(externalRow)].getStyle(column);
|
long style = mTerminal.getScreen().mLines[mTerminal.getScreen().externalToInternalRow(externalRow)].getStyle(column);
|
||||||
assertEquals(color, TextStyle.decodeForeColor(style));
|
assertEquals(color, TextStyle.decodeForeColor(style));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class TextStyleTest extends TestCase {
|
|||||||
for (int fx : ALL_EFFECTS) {
|
for (int fx : ALL_EFFECTS) {
|
||||||
for (int fg = 0; fg < TextStyle.NUM_INDEXED_COLORS; fg++) {
|
for (int fg = 0; fg < TextStyle.NUM_INDEXED_COLORS; fg++) {
|
||||||
for (int bg = 0; bg < TextStyle.NUM_INDEXED_COLORS; bg++) {
|
for (int bg = 0; bg < TextStyle.NUM_INDEXED_COLORS; bg++) {
|
||||||
int encoded = TextStyle.encode(fg, bg, fx);
|
long encoded = TextStyle.encode(fg, bg, fx);
|
||||||
assertEquals(fg, TextStyle.decodeForeColor(encoded));
|
assertEquals(fg, TextStyle.decodeForeColor(encoded));
|
||||||
assertEquals(bg, TextStyle.decodeBackColor(encoded));
|
assertEquals(bg, TextStyle.decodeBackColor(encoded));
|
||||||
assertEquals(fx, TextStyle.decodeEffect(encoded));
|
assertEquals(fx, TextStyle.decodeEffect(encoded));
|
||||||
@@ -22,7 +22,23 @@ public class TextStyleTest extends TestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testEncodingCombinations() {
|
public void testEncoding24Bit() {
|
||||||
|
int[] values = {255, 240, 127, 1, 0};
|
||||||
|
for (int red : values) {
|
||||||
|
for (int green : values) {
|
||||||
|
for (int blue : values) {
|
||||||
|
int argb = 0xFF000000 | (red << 16) | (green << 8) | blue;
|
||||||
|
long encoded = TextStyle.encode(argb, 0, 0);
|
||||||
|
assertEquals(argb, TextStyle.decodeForeColor(encoded));
|
||||||
|
encoded = TextStyle.encode(0, argb, 0);
|
||||||
|
assertEquals(argb, TextStyle.decodeBackColor(encoded));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testEncodingCombinations() {
|
||||||
for (int f1 : ALL_EFFECTS) {
|
for (int f1 : ALL_EFFECTS) {
|
||||||
for (int f2 : ALL_EFFECTS) {
|
for (int f2 : ALL_EFFECTS) {
|
||||||
int combined = f1 | f2;
|
int combined = f1 | f2;
|
||||||
@@ -32,13 +48,13 @@ public class TextStyleTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testEncodingStrikeThrough() {
|
public void testEncodingStrikeThrough() {
|
||||||
int encoded = TextStyle.encode(TextStyle.COLOR_INDEX_FOREGROUND, TextStyle.COLOR_INDEX_BACKGROUND,
|
long encoded = TextStyle.encode(TextStyle.COLOR_INDEX_FOREGROUND, TextStyle.COLOR_INDEX_BACKGROUND,
|
||||||
TextStyle.CHARACTER_ATTRIBUTE_STRIKETHROUGH);
|
TextStyle.CHARACTER_ATTRIBUTE_STRIKETHROUGH);
|
||||||
assertTrue((TextStyle.decodeEffect(encoded) & TextStyle.CHARACTER_ATTRIBUTE_STRIKETHROUGH) != 0);
|
assertTrue((TextStyle.decodeEffect(encoded) & TextStyle.CHARACTER_ATTRIBUTE_STRIKETHROUGH) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testEncodingProtected() {
|
public void testEncodingProtected() {
|
||||||
int encoded = TextStyle.encode(TextStyle.COLOR_INDEX_FOREGROUND, TextStyle.COLOR_INDEX_BACKGROUND,
|
long encoded = TextStyle.encode(TextStyle.COLOR_INDEX_FOREGROUND, TextStyle.COLOR_INDEX_BACKGROUND,
|
||||||
TextStyle.CHARACTER_ATTRIBUTE_STRIKETHROUGH);
|
TextStyle.CHARACTER_ATTRIBUTE_STRIKETHROUGH);
|
||||||
assertTrue((TextStyle.decodeEffect(encoded) & TextStyle.CHARACTER_ATTRIBUTE_PROTECTED) == 0);
|
assertTrue((TextStyle.decodeEffect(encoded) & TextStyle.CHARACTER_ATTRIBUTE_PROTECTED) == 0);
|
||||||
encoded = TextStyle.encode(TextStyle.COLOR_INDEX_FOREGROUND, TextStyle.COLOR_INDEX_BACKGROUND,
|
encoded = TextStyle.encode(TextStyle.COLOR_INDEX_FOREGROUND, TextStyle.COLOR_INDEX_BACKGROUND,
|
||||||
|
|||||||
@@ -5,10 +5,7 @@ buildscript {
|
|||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:2.1.2'
|
classpath 'com.android.tools.build:gradle:2.1.3'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
|
||||||
// in the individual module build.gradle files
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user