Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e52cd2dd41 | ||
|
|
54857d5fd4 | ||
|
|
38dd99e827 | ||
|
|
7256b04317 | ||
|
|
01a1c6de0f | ||
|
|
497fc3ecd0 | ||
|
|
b2b39abacd | ||
|
|
bee305e53f | ||
|
|
c8d2f28ed8 |
@@ -18,8 +18,8 @@ android {
|
|||||||
applicationId "com.termux"
|
applicationId "com.termux"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
versionCode 26
|
versionCode 27
|
||||||
versionName "0.26"
|
versionName "0.27"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
android:sharedUserId="com.termux"
|
android:sharedUserId="com.termux"
|
||||||
android:sharedUserLabel="@string/shared_user_label" >
|
android:sharedUserLabel="@string/shared_user_label" >
|
||||||
|
|
||||||
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
|
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
|
||||||
<uses-feature android:name="android.software.leanback" android:required="false" />
|
<uses-feature android:name="android.software.leanback" android:required="false" />
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
@@ -30,10 +30,10 @@
|
|||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ final class TermuxPreferences {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mBackIsEscape = "escape".equals(props.getProperty("back-key", "escape"));
|
mBackIsEscape = "escape".equals(props.getProperty("back-key", "back"));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Toast.makeText(context, "Error loading properties: " + e.getMessage(), Toast.LENGTH_LONG).show();
|
Toast.makeText(context, "Error loading properties: " + e.getMessage(), Toast.LENGTH_LONG).show();
|
||||||
Log.e("termux", "Error loading props", e);
|
Log.e("termux", "Error loading props", e);
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ public final class TerminalEmulator {
|
|||||||
*/
|
*/
|
||||||
private int mScrollCounter = 0;
|
private int mScrollCounter = 0;
|
||||||
|
|
||||||
private int mUtf8ToFollow, mUtf8Index;
|
private byte mUtf8ToFollow, mUtf8Index;
|
||||||
private final byte[] mUtf8InputBuffer = new byte[4];
|
private final byte[] mUtf8InputBuffer = new byte[4];
|
||||||
|
|
||||||
public final TerminalColors mColors = new TerminalColors();
|
public final TerminalColors mColors = new TerminalColors();
|
||||||
@@ -424,7 +424,11 @@ public final class TerminalEmulator {
|
|||||||
processCodePoint(/* escape (hexadecimal=0x1B, octal=033): */27);
|
processCodePoint(/* escape (hexadecimal=0x1B, octal=033): */27);
|
||||||
processCodePoint((codePoint & 0x7F) + 0x40);
|
processCodePoint((codePoint & 0x7F) + 0x40);
|
||||||
} else {
|
} else {
|
||||||
if (Character.UNASSIGNED == Character.getType(codePoint)) codePoint = UNICODE_REPLACEMENT_CHAR;
|
switch (Character.getType(codePoint)) {
|
||||||
|
case Character.UNASSIGNED:
|
||||||
|
case Character.SURROGATE:
|
||||||
|
codePoint = UNICODE_REPLACEMENT_CHAR;
|
||||||
|
}
|
||||||
processCodePoint(codePoint);
|
processCodePoint(codePoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -907,8 +911,9 @@ public final class TerminalEmulator {
|
|||||||
/** Process byte while in the {@link #ESC_CSI_QUESTIONMARK} escape state. */
|
/** Process byte while in the {@link #ESC_CSI_QUESTIONMARK} escape state. */
|
||||||
private void doCsiQuestionMark(int b) {
|
private void doCsiQuestionMark(int b) {
|
||||||
switch (b) {
|
switch (b) {
|
||||||
case 'J': // Selective erase in display (DECSED - http://www.vt100.net/docs/vt510-rm/DECSED).
|
case 'J': // Selective erase in display (DECSED) - http://www.vt100.net/docs/vt510-rm/DECSED.
|
||||||
case 'K': // Selective erase in line (DECSEL - http://vt100.net/docs/vt510-rm/DECSEL).
|
case 'K': // Selective erase in line (DECSEL) - http://vt100.net/docs/vt510-rm/DECSEL.
|
||||||
|
mAboutToAutoWrap = false;
|
||||||
int fillChar = ' ';
|
int fillChar = ' ';
|
||||||
int startCol = -1;
|
int startCol = -1;
|
||||||
int startRow = -1;
|
int startRow = -1;
|
||||||
@@ -1229,6 +1234,11 @@ public final class TerminalEmulator {
|
|||||||
mScreen.blockSet(mRightMargin - 1, mTopMargin, 1, rows, ' ', TextStyle.encode(mForeColor, mBackColor, 0));
|
mScreen.blockSet(mRightMargin - 1, mTopMargin, 1, rows, ' ', TextStyle.encode(mForeColor, mBackColor, 0));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'c': // RIS - Reset to Initial State (http://vt100.net/docs/vt510-rm/RIS).
|
||||||
|
reset();
|
||||||
|
blockClear(0, 0, mColumns, mRows);
|
||||||
|
setCursorPosition(0, 0);
|
||||||
|
break;
|
||||||
case 'D': // INDEX
|
case 'D': // INDEX
|
||||||
doLinefeed();
|
doLinefeed();
|
||||||
break;
|
break;
|
||||||
@@ -1321,9 +1331,8 @@ public final class TerminalEmulator {
|
|||||||
continueSequence(ESC_CSI_ARGS_ASTERIX);
|
continueSequence(ESC_CSI_ARGS_ASTERIX);
|
||||||
break;
|
break;
|
||||||
case '@': {
|
case '@': {
|
||||||
// ESC [ Pn @ - ICH Insert Characters.
|
// "CSI{n}@" - Insert ${n} space characters (ICH) - http://www.vt100.net/docs/vt510-rm/ICH.
|
||||||
// "This control function inserts one or more space (SP) characters starting at the cursor position."
|
mAboutToAutoWrap = false;
|
||||||
// http://www.vt100.net/docs/vt510-rm/ICH
|
|
||||||
int columnsAfterCursor = mColumns - mCursorCol;
|
int columnsAfterCursor = mColumns - mCursorCol;
|
||||||
int spacesToInsert = Math.min(getArg0(1), columnsAfterCursor);
|
int spacesToInsert = Math.min(getArg0(1), columnsAfterCursor);
|
||||||
int charsToMove = columnsAfterCursor - spacesToInsert;
|
int charsToMove = columnsAfterCursor - spacesToInsert;
|
||||||
@@ -1360,7 +1369,7 @@ public final class TerminalEmulator {
|
|||||||
case 'I': // Cursor Horizontal Forward Tabulation (CHT). Move the active position n tabs forward.
|
case 'I': // Cursor Horizontal Forward Tabulation (CHT). Move the active position n tabs forward.
|
||||||
setCursorCol(nextTabStop(getArg0(1)));
|
setCursorCol(nextTabStop(getArg0(1)));
|
||||||
break;
|
break;
|
||||||
case 'J': // ESC [ Pn J - ED - Erase in Display
|
case 'J': // "${CSI}${0,1,2}J" - Erase in Display (ED)
|
||||||
// ED ignores the scrolling margins.
|
// ED ignores the scrolling margins.
|
||||||
switch (getArg0(0)) {
|
switch (getArg0(0)) {
|
||||||
case 0: // Erase from the active position to the end of the screen, inclusive (default).
|
case 0: // Erase from the active position to the end of the screen, inclusive (default).
|
||||||
@@ -1377,8 +1386,9 @@ public final class TerminalEmulator {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
unknownSequence(b);
|
unknownSequence(b);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
mAboutToAutoWrap = false;
|
||||||
break;
|
break;
|
||||||
case 'K': // "CSI{n}K" - Erase in line (EL).
|
case 'K': // "CSI{n}K" - Erase in line (EL).
|
||||||
switch (getArg0(0)) {
|
switch (getArg0(0)) {
|
||||||
@@ -1393,8 +1403,9 @@ public final class TerminalEmulator {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
unknownSequence(b);
|
unknownSequence(b);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
mAboutToAutoWrap = false;
|
||||||
break;
|
break;
|
||||||
case 'L': // "${CSI}{N}L" - insert ${N} lines (IL).
|
case 'L': // "${CSI}{N}L" - insert ${N} lines (IL).
|
||||||
{
|
{
|
||||||
@@ -1407,6 +1418,7 @@ public final class TerminalEmulator {
|
|||||||
break;
|
break;
|
||||||
case 'M': // "${CSI}${N}M" - delete N lines (DL).
|
case 'M': // "${CSI}${N}M" - delete N lines (DL).
|
||||||
{
|
{
|
||||||
|
mAboutToAutoWrap = false;
|
||||||
int linesAfterCursor = mBottomMargin - mCursorRow;
|
int linesAfterCursor = mBottomMargin - mCursorRow;
|
||||||
int linesToDelete = Math.min(getArg0(1), linesAfterCursor);
|
int linesToDelete = Math.min(getArg0(1), linesAfterCursor);
|
||||||
int linesToMove = linesAfterCursor - linesToDelete;
|
int linesToMove = linesAfterCursor - linesToDelete;
|
||||||
@@ -1421,6 +1433,7 @@ public final class TerminalEmulator {
|
|||||||
// As characters are deleted, the remaining characters between the cursor and right margin move to the left.
|
// As characters are deleted, the remaining characters between the cursor and right margin move to the left.
|
||||||
// Character attributes move with the characters. The terminal adds blank spaces with no visual character
|
// Character attributes move with the characters. The terminal adds blank spaces with no visual character
|
||||||
// attributes at the right margin. DCH has no effect outside the scrolling margins."
|
// attributes at the right margin. DCH has no effect outside the scrolling margins."
|
||||||
|
mAboutToAutoWrap = false;
|
||||||
int cellsAfterCursor = mColumns - mCursorCol;
|
int cellsAfterCursor = mColumns - mCursorCol;
|
||||||
int cellsToDelete = Math.min(getArg0(1), cellsAfterCursor);
|
int cellsToDelete = Math.min(getArg0(1), cellsAfterCursor);
|
||||||
int cellsToMove = cellsAfterCursor - cellsToDelete;
|
int cellsToMove = cellsAfterCursor - cellsToDelete;
|
||||||
@@ -1451,6 +1464,7 @@ public final class TerminalEmulator {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'X': // "${CSI}${N}X" - Erase ${N:=1} character(s) (ECH). FIXME: Clears character attributes?
|
case 'X': // "${CSI}${N}X" - Erase ${N:=1} character(s) (ECH). FIXME: Clears character attributes?
|
||||||
|
mAboutToAutoWrap = false;
|
||||||
mScreen.blockSet(mCursorCol, mCursorRow, Math.min(getArg0(1), mColumns - mCursorCol), 1, ' ', getStyle());
|
mScreen.blockSet(mCursorCol, mCursorRow, Math.min(getArg0(1), mColumns - mCursorCol), 1, ' ', getStyle());
|
||||||
break;
|
break;
|
||||||
case 'Z': // Cursor Backward Tabulation (CBT). Move the active position n tabs backward.
|
case 'Z': // Cursor Backward Tabulation (CBT). Move the active position n tabs backward.
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import android.graphics.Canvas;
|
|||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.media.AudioManager;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@@ -692,6 +693,10 @@ public final class TerminalView extends View {
|
|||||||
// As left alt+b, jumping forward in readline:
|
// As left alt+b, jumping forward in readline:
|
||||||
codePoint = 'b';
|
codePoint = 'b';
|
||||||
leftAltDownFromEvent = true;
|
leftAltDownFromEvent = true;
|
||||||
|
} else if (codePoint == 'v' || codePoint == 'V') {
|
||||||
|
codePoint = -1;
|
||||||
|
AudioManager audio = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
|
||||||
|
audio.adjustSuggestedStreamVolume(AudioManager.ADJUST_SAME, AudioManager.USE_DEFAULT_STREAM_TYPE, AudioManager.FLAG_SHOW_UI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,4 +20,13 @@ public class ControlSequenceIntroducerTest extends TerminalTestCase {
|
|||||||
withTerminalSized(3, 4).enterString("1\r\n2\r\n3\r\nhi\033[Sy").assertLinesAre("2 ", "3 ", "hi ", " y");
|
withTerminalSized(3, 4).enterString("1\r\n2\r\n3\r\nhi\033[Sy").assertLinesAre("2 ", "3 ", "hi ", " y");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** CSI Ps X Erase Ps Character(s) (default = 1) (ECH). */
|
||||||
|
public void testCsiX() {
|
||||||
|
// See https://code.google.com/p/chromium/issues/detail?id=212712 where test was extraced from.
|
||||||
|
withTerminalSized(13, 2).enterString("abcdefghijkl\b\b\b\b\b\033[X").assertLinesAre("abcdefg ijkl ", " ");
|
||||||
|
withTerminalSized(13, 2).enterString("abcdefghijkl\b\b\b\b\b\033[1X").assertLinesAre("abcdefg ijkl ", " ");
|
||||||
|
withTerminalSized(13, 2).enterString("abcdefghijkl\b\b\b\b\b\033[2X").assertLinesAre("abcdefg jkl ", " ");
|
||||||
|
withTerminalSized(13, 2).enterString("abcdefghijkl\b\b\b\b\b\033[20X").assertLinesAre("abcdefg ", " ");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -172,4 +172,45 @@ public class CursorAndScreenTest extends TerminalTestCase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test interactions between the cursor overflow bit and various escape sequences.
|
||||||
|
* <p/>
|
||||||
|
* Adapted from hterm:
|
||||||
|
* https://chromium.googlesource.com/chromiumos/platform/assets/+/2337afa5c063127d5ce40ec7fec9b602d096df86%5E%21/#F2
|
||||||
|
*/
|
||||||
|
public void testClearingOfAutowrap() {
|
||||||
|
// Fill a row with the last hyphen wrong, then run a command that
|
||||||
|
// modifies the screen, then add a hyphen. The wrap bit should be
|
||||||
|
// cleared, so the extra hyphen can fix the row.
|
||||||
|
withTerminalSized(15, 6);
|
||||||
|
|
||||||
|
enterString("----- 1 ----X");
|
||||||
|
enterString("\033[K-"); // EL
|
||||||
|
|
||||||
|
enterString("----- 2 ----X");
|
||||||
|
enterString("\033[J-"); // ED
|
||||||
|
|
||||||
|
enterString("----- 3 ----X");
|
||||||
|
enterString("\033[@-"); // ICH
|
||||||
|
|
||||||
|
enterString("----- 4 ----X");
|
||||||
|
enterString("\033[P-"); // DCH
|
||||||
|
|
||||||
|
enterString("----- 5 ----X");
|
||||||
|
enterString("\033[X-"); // ECH
|
||||||
|
|
||||||
|
// DL will delete the entire line but clear the wrap bit, so we
|
||||||
|
// expect a hyphen at the end and nothing else.
|
||||||
|
enterString("XXXXXXXXXXXXXXX");
|
||||||
|
enterString("\033[M-"); // DL
|
||||||
|
|
||||||
|
assertLinesAre(
|
||||||
|
"----- 1 -----",
|
||||||
|
"----- 2 -----",
|
||||||
|
"----- 3 -----",
|
||||||
|
"----- 4 -----",
|
||||||
|
"----- 5 -----",
|
||||||
|
" -");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ public class DecSetTest extends TerminalTestCase {
|
|||||||
assertFalse(mTerminal.isShowingCursor());
|
assertFalse(mTerminal.isShowingCursor());
|
||||||
mTerminal.reset();
|
mTerminal.reset();
|
||||||
assertTrue("Resetting the terminal should show the cursor", mTerminal.isShowingCursor());
|
assertTrue("Resetting the terminal should show the cursor", mTerminal.isShowingCursor());
|
||||||
|
|
||||||
|
enterString("\033[?25l");
|
||||||
|
assertFalse(mTerminal.isShowingCursor());
|
||||||
|
enterString("\033c"); // RIS resetting should reveal cursor.
|
||||||
|
assertTrue(mTerminal.isShowingCursor());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** DECSET 2004, controls bracketed paste mode. */
|
/** DECSET 2004, controls bracketed paste mode. */
|
||||||
|
|||||||
@@ -12,6 +12,47 @@ public class UnicodeInputTest extends TerminalTestCase {
|
|||||||
withTerminalSized(5, 5);
|
withTerminalSized(5, 5);
|
||||||
mTerminal.append(new byte[]{(byte) 0b11101111, (byte) 'a'}, 2);
|
mTerminal.append(new byte[]{(byte) 0b11101111, (byte) 'a'}, 2);
|
||||||
assertLineIs(0, ((char) TerminalEmulator.UNICODE_REPLACEMENT_CHAR) + "a ");
|
assertLineIs(0, ((char) TerminalEmulator.UNICODE_REPLACEMENT_CHAR) + "a ");
|
||||||
|
|
||||||
|
// https://code.google.com/p/chromium/issues/detail?id=212704
|
||||||
|
byte[] input = new byte[]{
|
||||||
|
(byte) 0x61, (byte) 0xF1,
|
||||||
|
(byte) 0x80, (byte) 0x80,
|
||||||
|
(byte) 0xe1, (byte) 0x80,
|
||||||
|
(byte) 0xc2, (byte) 0x62,
|
||||||
|
(byte) 0x80, (byte) 0x63,
|
||||||
|
(byte) 0x80, (byte) 0xbf,
|
||||||
|
(byte) 0x64
|
||||||
|
};
|
||||||
|
withTerminalSized(10, 2);
|
||||||
|
mTerminal.append(input, input.length);
|
||||||
|
assertLinesAre("a\uFFFD\uFFFD\uFFFDb\uFFFDc\uFFFD\uFFFDd", " ");
|
||||||
|
|
||||||
|
// Surrogate pairs.
|
||||||
|
withTerminalSized(5, 2);
|
||||||
|
input = new byte[]{
|
||||||
|
(byte) 0xed, (byte) 0xa0,
|
||||||
|
(byte) 0x80, (byte) 0xed,
|
||||||
|
(byte) 0xad, (byte) 0xbf,
|
||||||
|
(byte) 0xed, (byte) 0xae,
|
||||||
|
(byte) 0x80, (byte) 0xed,
|
||||||
|
(byte) 0xbf, (byte) 0xbf
|
||||||
|
};
|
||||||
|
mTerminal.append(input, input.length);
|
||||||
|
assertLinesAre("\uFFFD\uFFFD\uFFFD\uFFFD ", " ");
|
||||||
|
|
||||||
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=746900: "with this patch 0xe0 0x80 is decoded as two U+FFFDs,
|
||||||
|
// but 0xe0 0xa0 is decoded as a single U+FFFD, and this is correct according to the "Best Practices", but IE
|
||||||
|
// and Chrome (Version 22.0.1229.94) decode both of them as two U+FFFDs. Opera 12.11 decodes both of them as
|
||||||
|
// one U+FFFD".
|
||||||
|
withTerminalSized(5, 2);
|
||||||
|
input = new byte[]{(byte) 0xe0, (byte) 0xa0, ' '};
|
||||||
|
mTerminal.append(input, input.length);
|
||||||
|
assertLinesAre("\uFFFD ", " ");
|
||||||
|
|
||||||
|
// withTerminalSized(5, 2);
|
||||||
|
// input = new byte[]{(byte) 0xe0, (byte) 0x80, 'a'};
|
||||||
|
// mTerminal.append(input, input.length);
|
||||||
|
// assertLinesAre("\uFFFD\uFFFDa ", " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testUnassignedCodePoint() throws UnsupportedEncodingException {
|
public void testUnassignedCodePoint() throws UnsupportedEncodingException {
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ public class WcWidthTest extends TestCase {
|
|||||||
public void testCombining() {
|
public void testCombining() {
|
||||||
assertWidthIs(0, 0x0302);
|
assertWidthIs(0, 0x0302);
|
||||||
assertWidthIs(0, 0x0308);
|
assertWidthIs(0, 0x0308);
|
||||||
|
assertWidthIs(0, 0x2060);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testWatch() {
|
public void testWatch() {
|
||||||
|
|||||||
Reference in New Issue
Block a user