Compare commits

..

26 Commits
v0.52 ... v0.54

Author SHA1 Message Date
Fredrik Fornwall
092a83a688 Validate file path in TermuxOpenReceiver 2017-10-28 16:19:58 +02:00
Fredrik Fornwall
3533b13de8 Get rid of two android studio warnings 2017-10-28 11:05:43 +02:00
Fredrik Fornwall
d68a0f05be Update gradle configuration 2017-10-28 11:05:43 +02:00
Fredrik Fornwall
9e5293a08e Do not scroll when below bottom margin 2017-10-28 11:05:43 +02:00
Fredrik Fornwall
3f04a0a0d5 Bump build tools version in .travis.yml 2017-10-28 11:05:43 +02:00
Fredrik Fornwall
e558f824c5 Update gradle configuration 2017-10-28 11:05:43 +02:00
Auxilus
8ff72ddd8b replace help url with wiki url
HELP page wiki changed to https://wiki.termux.com/wiki/Main_Page as it now has more info than http://termux.com/help.html
2017-09-26 18:14:19 +02:00
Fredrik Fornwall
3e05356a69 Merge pull request #421 from sdrausty/master
Added two important links to README.md
2017-09-20 22:37:49 +02:00
Fredrik Fornwall
82673d3f82 Update gradle configuration 2017-09-17 11:47:12 +02:00
Fredrik Fornwall
f2757fdb76 Merge pull request #424 from EdwardBetts/patch-1
correct spelling mistake
2017-09-15 00:21:47 +02:00
Edward Betts
81fb669d0e correct spelling mistake 2017-09-13 16:16:08 +01:00
S D Rausty
4a45b1b617 Commit on 20170911 at 13:23:22 and at 1505150602 in Unix time. 2017-09-11 13:23:22 -04:00
S D Rausty
62b08b3cf1 Merge pull request #1 from termux/master
Hello
2017-09-10 13:24:32 -04:00
Fredrik Fornwall
1e83ea3151 Merge pull request #412 from Auxilus/patch-2
Added wiki link
2017-09-06 16:26:54 +02:00
Auxilus
9c42fdb3d6 Added wiki link 2017-09-05 10:43:30 +05:30
Fredrik Fornwall
42e3163e92 Update gradle to 4.1 2017-08-24 20:49:43 +02:00
Fredrik Fornwall
68912139f6 Additional REP test 2017-08-23 23:29:59 +02:00
Fredrik Fornwall
edc92bbcbb Start supporting the REP escape sequence 2017-08-13 16:14:31 +02:00
Fredrik Fornwall
d7520642de Update gradle 2017-07-29 03:05:48 +02:00
Fredrik Fornwall
adae111d5c Update gradle config 2017-07-09 21:07:18 +02:00
Fredrik Fornwall
dc9272790b Merge pull request #301 from kzlin129/android-things-auto-launch
[Android-things] Launch TermuxActivity automatically on boot
2017-06-26 02:04:03 +02:00
Fredrik Fornwall
05ea2ea238 Bump version to 0.53 2017-06-26 01:30:08 +02:00
Fredrik Fornwall
ad293562bc Fix possible crash in the copy/paste/more dialog 2017-06-26 01:29:05 +02:00
Fredrik Fornwall
f9a565d1e0 Ignore C1 control codes
C1 control codes are not used nowadays and just risks messing up
the terminal when they are used by accident.
2017-06-26 01:28:18 +02:00
Will Lin
5b3909cb73 Update AndroidManifest.xml with expanded comment 2017-06-17 15:39:23 +08:00
Will Lin
1be5139253 [Android-things] Launch TermuxActivity automatically on boot 2017-04-18 20:13:47 +08:00
19 changed files with 112 additions and 40 deletions

View File

@@ -12,8 +12,8 @@ android:
components: components:
- platform-tools - platform-tools
- tools - tools
- build-tools-25.0.3 - build-tools-27.0.0
- android-25 - android-26
- extra-android-m2repository - extra-android-m2repository
before_install: before_install:

View File

@@ -7,8 +7,11 @@ Termux app
* [Termux on Google Play Store](https://play.google.com/store/apps/details?id=com.termux) * [Termux on Google Play Store](https://play.google.com/store/apps/details?id=com.termux)
* [Termux on F-Droid](https://f-droid.org/repository/browse/?fdid=com.termux) * [Termux on F-Droid](https://f-droid.org/repository/browse/?fdid=com.termux)
* [Termux Help](http://termux.com/help/) * [Termux Facebook](https://facebook.com/termux/)
* [Termux Google+ community](http://termux.com/community/) * [Termux Google+ community](http://termux.com/community/)
* [Termux Help](http://termux.com/help/)
* [Termux Twitter](http://twitter.com/termux/)
* [Termux Wiki](https://wiki.termux.com/wiki/)
Note that this repository is for the app itself (the user interface and the terminal emulation). For the packages installable inside the app, see [termux/termux-packages](https://github.com/termux/termux-packages) Note that this repository is for the app itself (the user interface and the terminal emulation). For the packages installable inside the app, see [termux/termux-packages](https://github.com/termux/termux-packages)

View File

@@ -1,21 +1,22 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
android { android {
compileSdkVersion 25 compileSdkVersion 26
buildToolsVersion "25.0.3" buildToolsVersion "27.0.0"
dependencies { dependencies {
compile 'com.android.support:support-annotations:25.3.1' compile 'com.android.support:support-annotations:27.0.0'
compile "com.android.support:support-v4:25.3.1" compile "com.android.support:support-core-utils:26.1.0"
compile "com.android.support:support-core-ui:26.1.0"
compile project(":terminal-view") compile project(":terminal-view")
} }
defaultConfig { defaultConfig {
applicationId "com.termux" applicationId "com.termux"
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 25 targetSdkVersion 26
versionCode 52 versionCode 54
versionName "0.52" versionName "0.54"
} }
buildTypes { buildTypes {

View File

@@ -76,6 +76,18 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity-alias
android:name=".HomeActivity"
android:targetActivity="com.termux.app.TermuxActivity">
<!-- Launch activity automatically on boot on Android Things devices -->
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.IOT_LAUNCHER"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity-alias>
<provider <provider
android:name=".filepicker.TermuxDocumentsProvider" android:name=".filepicker.TermuxDocumentsProvider"
android:authorities="com.termux.documents" android:authorities="com.termux.documents"

View File

@@ -39,7 +39,7 @@ public final class TermuxHelpActivity extends Activity {
mWebView.setWebViewClient(new WebViewClient() { mWebView.setWebViewClient(new WebViewClient() {
@Override @Override
public boolean shouldOverrideUrlLoading(WebView view, String url) { public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("https://termux.com")) { if (url.startsWith("https://wiki.termux.com")) {
// Inline help. // Inline help.
setContentView(progressLayout); setContentView(progressLayout);
return false; return false;
@@ -60,7 +60,7 @@ public final class TermuxHelpActivity extends Activity {
setContentView(mWebView); setContentView(mWebView);
} }
}); });
mWebView.loadUrl("https://termux.com/help.html"); mWebView.loadUrl("https://wiki.termux.com/wiki/Main_Page");
} }
@Override @Override

View File

@@ -43,7 +43,7 @@ import java.util.zip.ZipInputStream;
* (4) The architecture is determined and an appropriate bootstrap zip url is determined in {@link #determineZipUrl()}. * (4) The architecture is determined and an appropriate bootstrap zip url is determined in {@link #determineZipUrl()}.
* <p/> * <p/>
* (5) The zip, containing entries relative to the $PREFIX, is is downloaded and extracted by a zip input stream * (5) The zip, containing entries relative to the $PREFIX, is is downloaded and extracted by a zip input stream
* continously encountering zip file entries: * continuously encountering zip file entries:
* <p/> * <p/>
* (5.1) If the zip entry encountered is SYMLINKS.txt, go through it and remember all symlinks to setup. * (5.1) If the zip entry encountered is SYMLINKS.txt, go through it and remember all symlinks to setup.
* <p/> * <p/>

View File

@@ -8,6 +8,7 @@ import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
import android.database.MatrixCursor; import android.database.MatrixCursor;
import android.net.Uri; import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
@@ -18,6 +19,7 @@ import com.termux.terminal.EmulatorDebug;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException;
public class TermuxOpenReceiver extends BroadcastReceiver { public class TermuxOpenReceiver extends BroadcastReceiver {
@@ -171,6 +173,16 @@ public class TermuxOpenReceiver extends BroadcastReceiver {
@Override @Override
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException { public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
File file = new File(uri.getPath()); File file = new File(uri.getPath());
try {
String path = file.getCanonicalPath();
String storagePath = Environment.getExternalStorageDirectory().getCanonicalPath();
// See https://support.google.com/faqs/answer/7496913:
if (!(path.startsWith(TermuxService.FILES_PATH) || path.startsWith(storagePath))) {
throw new IllegalArgumentException("Invalid path: " + path);
}
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
} }
} }

View File

@@ -1,17 +1,19 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
repositories { repositories {
jcenter() jcenter()
google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:2.3.3' classpath 'com.android.tools.build:gradle:3.0.0'
} }
} }
allprojects { allprojects {
repositories { repositories {
jcenter() jcenter()
maven {
url "https://maven.google.com"
}
} }
} }

Binary file not shown.

View File

@@ -1,6 +1,5 @@
#Sun Jun 11 22:47:00 CEST 2017 distributionUrl=https\://services.gradle.org/distributions/gradle-4.2.1-bin.zip
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-bin.zip zipStoreBase=GRADLE_USER_HOME

6
gradlew vendored
View File

@@ -33,11 +33,11 @@ DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD="maximum"
warn ( ) { warn () {
echo "$*" echo "$*"
} }
die ( ) { die () {
echo echo
echo "$*" echo "$*"
echo echo
@@ -155,7 +155,7 @@ if $cygwin ; then
fi fi
# Escape application args # Escape application args
save ( ) { save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " " echo " "
} }

View File

@@ -1,6 +1,6 @@
plugins { plugins {
id "com.jfrog.bintray" version "1.7" id "com.jfrog.bintray" version "1.7.3"
id "com.github.dcendents.android-maven" version "1.5" id "com.github.dcendents.android-maven" version "2.0"
} }
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
@@ -13,16 +13,16 @@ ext {
libraryDescription = 'The terminal emulator used in Termux' libraryDescription = 'The terminal emulator used in Termux'
siteUrl = 'https://github.com/termux/termux' siteUrl = 'https://github.com/termux/termux'
gitUrl = 'https://github.com/termux/termux.git' gitUrl = 'https://github.com/termux/termux.git'
libraryVersion = '0.50' libraryVersion = '0.51'
} }
android { android {
compileSdkVersion 25 compileSdkVersion 26
buildToolsVersion "25.0.3" buildToolsVersion "27.0.0"
defaultConfig { defaultConfig {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 25 targetSdkVersion 26
externalNativeBuild { externalNativeBuild {
ndkBuild { ndkBuild {

View File

@@ -223,6 +223,7 @@ public final class TerminalEmulator {
private byte mUtf8ToFollow, mUtf8Index; private byte mUtf8ToFollow, mUtf8Index;
private final byte[] mUtf8InputBuffer = new byte[4]; private final byte[] mUtf8InputBuffer = new byte[4];
private int mLastEmittedCodePoint = -1;
public final TerminalColors mColors = new TerminalColors(); public final TerminalColors mColors = new TerminalColors();
@@ -419,10 +420,11 @@ public final class TerminalEmulator {
mUtf8Index = mUtf8ToFollow = 0; mUtf8Index = mUtf8ToFollow = 0;
if (codePoint >= 0x80 && codePoint <= 0x9F) { if (codePoint >= 0x80 && codePoint <= 0x9F) {
// Sequence decoded to a C1 control character which is the same as escape followed by // Sequence decoded to a C1 control character which we ignore. They are
// ((code & 0x7F) + 0x40). // not used nowadays and increases the risk of messing up the terminal state
processCodePoint(/* escape (hexadecimal=0x1B, octal=033): */27); // on binary input. XTerm does not allow them in utf-8:
processCodePoint((codePoint & 0x7F) + 0x40); // "It is not possible to use a C1 control obtained from decoding the
// UTF-8 text" - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
} else { } else {
switch (Character.getType(codePoint)) { switch (Character.getType(codePoint)) {
case Character.UNASSIGNED: case Character.UNASSIGNED:
@@ -1190,12 +1192,20 @@ public final class TerminalEmulator {
} }
private void doLinefeed() { private void doLinefeed() {
boolean belowScrollingRegion = mCursorRow >= mBottomMargin;
int newCursorRow = mCursorRow + 1; int newCursorRow = mCursorRow + 1;
if (newCursorRow >= mBottomMargin) { if (belowScrollingRegion) {
scrollDownOneLine(); // Move down (but not scroll) as long as we are above the last row.
newCursorRow = mBottomMargin - 1; if (mCursorRow != mRows - 1) {
setCursorRow(newCursorRow);
}
} else {
if (newCursorRow == mBottomMargin) {
scrollDownOneLine();
newCursorRow = mBottomMargin - 1;
}
setCursorRow(newCursorRow);
} }
setCursorRow(newCursorRow);
} }
private void continueSequence(int state) { private void continueSequence(int state) {
@@ -1508,6 +1518,11 @@ public final class TerminalEmulator {
case '`': // Horizontal position absolute (HPA - http://www.vt100.net/docs/vt510-rm/HPA). case '`': // Horizontal position absolute (HPA - http://www.vt100.net/docs/vt510-rm/HPA).
setCursorColRespectingOriginMode(getArg0(1) - 1); setCursorColRespectingOriginMode(getArg0(1) - 1);
break; break;
case 'b': // Repeat the preceding graphic character Ps times (REP).
if (mLastEmittedCodePoint == -1) break;
final int numRepeat = getArg0(1);
for (int i = 0; i < numRepeat; i++) emitCodePoint(mLastEmittedCodePoint);
break;
case 'c': // Primary Device Attributes (http://www.vt100.net/docs/vt510-rm/DA1) if argument is missing or zero. case 'c': // Primary Device Attributes (http://www.vt100.net/docs/vt510-rm/DA1) if argument is missing or zero.
// The important part that may still be used by some (tmux stores this value but does not currently use it) // The important part that may still be used by some (tmux stores this value but does not currently use it)
// is the first response parameter identifying the terminal service class, where we send 64 for "vt420". // is the first response parameter identifying the terminal service class, where we send 64 for "vt420".
@@ -1564,7 +1579,7 @@ public final class TerminalEmulator {
break; break;
case 'r': // "CSI${top};${bottom}r" - set top and bottom Margins (DECSTBM). case 'r': // "CSI${top};${bottom}r" - set top and bottom Margins (DECSTBM).
{ {
// http://www.vt100.net/docs/vt510-rm/DECSTBM // https://vt100.net/docs/vt510-rm/DECSTBM.html
// The top margin defaults to 1, the bottom margin defaults to mRows. // The top margin defaults to 1, the bottom margin defaults to mRows.
// The escape sequence numbers top 1..23, but we number top 0..22. // The escape sequence numbers top 1..23, but we number top 0..22.
// The escape sequence numbers bottom 2..24, and so do we (because we use a zero based numbering // The escape sequence numbers bottom 2..24, and so do we (because we use a zero based numbering
@@ -1573,6 +1588,7 @@ public final class TerminalEmulator {
// Also require that top + 2 <= bottom. // Also require that top + 2 <= bottom.
mTopMargin = Math.max(0, Math.min(getArg0(1) - 1, mRows - 2)); mTopMargin = Math.max(0, Math.min(getArg0(1) - 1, mRows - 2));
mBottomMargin = Math.max(mTopMargin + 2, Math.min(getArg1(mRows), mRows)); mBottomMargin = Math.max(mTopMargin + 2, Math.min(getArg1(mRows), mRows));
// DECSTBM moves the cursor to column 1, line 1 of the page respecting origin mode. // DECSTBM moves the cursor to column 1, line 1 of the page respecting origin mode.
setCursorPosition(0, 0); setCursorPosition(0, 0);
} }
@@ -2090,6 +2106,7 @@ public final class TerminalEmulator {
* @param codePoint The code point of the character to display * @param codePoint The code point of the character to display
*/ */
private void emitCodePoint(int codePoint) { private void emitCodePoint(int codePoint) {
mLastEmittedCodePoint = codePoint;
if (mUseLineDrawingUsesG0 ? mUseLineDrawingG0 : mUseLineDrawingG1) { if (mUseLineDrawingUsesG0 ? mUseLineDrawingG0 : mUseLineDrawingG1) {
// http://www.vt100.net/docs/vt102-ug/table5-15.html. // http://www.vt100.net/docs/vt102-ug/table5-15.html.
switch (codePoint) { switch (codePoint) {

View File

@@ -35,4 +35,15 @@ public class ControlSequenceIntroducerTest extends TerminalTestCase {
withTerminalSized(3, 2).enterString("\033[0;38;2;255;255;255;48;2;0;0;0;1;2;3;4;5;7;8;9mabc").assertLinesAre("abc", " "); withTerminalSized(3, 2).enterString("\033[0;38;2;255;255;255;48;2;0;0;0;1;2;3;4;5;7;8;9mabc").assertLinesAre("abc", " ");
} }
/** CSI Ps b Repeat the preceding graphic character Ps times (REP). */
public void testRepeat() {
withTerminalSized(3, 2).enterString("a\033[b").assertLinesAre("aa ", " ");
withTerminalSized(3, 2).enterString("a\033[2b").assertLinesAre("aaa", " ");
// When no char has been output we ignore REP:
withTerminalSized(3, 2).enterString("\033[b").assertLinesAre(" ", " ");
// This shows that REP outputs the last emitted code point and not the one relative to the
// current cursor position:
withTerminalSized(5, 2).enterString("abcde\033[2G\033[2b\n").assertLinesAre("aeede", " ");
}
} }

View File

@@ -98,4 +98,13 @@ public class ScrollRegionTest extends TerminalTestCase {
withTerminalSized(2, 5).enterString("1\r\n2\r\n3\r\n4\r\n5").assertLinesAre("1 ", "2 ", "3 ", "4 ", "5 "); withTerminalSized(2, 5).enterString("1\r\n2\r\n3\r\n4\r\n5").assertLinesAre("1 ", "2 ", "3 ", "4 ", "5 ");
enterString("\033[3r").enterString("\033[2T").assertLinesAre("1 ", "2 ", " ", " ", "3 "); enterString("\033[3r").enterString("\033[2T").assertLinesAre("1 ", "2 ", " ", " ", "3 ");
} }
public void testScrollDownBelowScrollRegion() {
withTerminalSized(2, 5).enterString("1\r\n2\r\n3\r\n4\r\n5").assertLinesAre("1 ", "2 ", "3 ", "4 ", "5 ");
enterString("\033[1;3r"); // DECSTBM margins.
enterString("\033[4;1H"); // Place cursor just below bottom margin.
enterString("QQ\r\nRR\r\n\r\n\r\nYY");
assertLinesAre("1 ", "2 ", "3 ", "QQ", "YY");
}
} }

View File

@@ -27,6 +27,7 @@ public class TerminalRowTest extends TestCase {
@Override @Override
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp();
row = new TerminalRow(COLUMNS, TextStyle.NORMAL); row = new TerminalRow(COLUMNS, TextStyle.NORMAL);
} }

View File

@@ -103,6 +103,7 @@ public abstract class TerminalTestCase extends TestCase {
@Override @Override
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp();
mOutput = new MockTerminalOutput(); mOutput = new MockTerminalOutput();
} }

View File

@@ -17,8 +17,8 @@ ext {
} }
android { android {
compileSdkVersion 25 compileSdkVersion 26
buildToolsVersion "25.0.3" buildToolsVersion "27.0.0"
dependencies { dependencies {
compile 'com.android.support:support-annotations:25.3.1' compile 'com.android.support:support-annotations:25.3.1'
@@ -27,7 +27,7 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 25 targetSdkVersion 26
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
} }

View File

@@ -834,6 +834,10 @@ public final class TerminalView extends View {
@Override @Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) { public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
if (!mIsSelectingText) {
// Fix issue where the dialog is pressed while being dismissed.
return true;
}
switch (item.getItemId()) { switch (item.getItemId()) {
case 1: case 1:
String selectedText = mEmulator.getSelectedText(mSelX1, mSelY1, mSelX2, mSelY2).trim(); String selectedText = mEmulator.getSelectedText(mSelX1, mSelY1, mSelX2, mSelY2).trim();