Compare commits
37 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86bd3ca21b | ||
|
|
367398bafb | ||
|
|
dd502e55f8 | ||
|
|
798125ef7a | ||
|
|
5126f06e06 | ||
|
|
0bdbf314ef | ||
|
|
2deb9899bd | ||
|
|
694ccc38c4 | ||
|
|
c949940374 | ||
|
|
d09f70de1e | ||
|
|
ac338ce2c5 | ||
|
|
092a83a688 | ||
|
|
3533b13de8 | ||
|
|
d68a0f05be | ||
|
|
9e5293a08e | ||
|
|
3f04a0a0d5 | ||
|
|
e558f824c5 | ||
|
|
8ff72ddd8b | ||
|
|
3e05356a69 | ||
|
|
82673d3f82 | ||
|
|
f2757fdb76 | ||
|
|
81fb669d0e | ||
|
|
4a45b1b617 | ||
|
|
62b08b3cf1 | ||
|
|
1e83ea3151 | ||
|
|
9c42fdb3d6 | ||
|
|
42e3163e92 | ||
|
|
68912139f6 | ||
|
|
edc92bbcbb | ||
|
|
d7520642de | ||
|
|
adae111d5c | ||
|
|
dc9272790b | ||
|
|
05ea2ea238 | ||
|
|
ad293562bc | ||
|
|
f9a565d1e0 | ||
|
|
5b3909cb73 | ||
|
|
1be5139253 |
@@ -12,8 +12,8 @@ android:
|
||||
components:
|
||||
- platform-tools
|
||||
- tools
|
||||
- build-tools-25.0.3
|
||||
- android-25
|
||||
- build-tools-27.0.1
|
||||
- android-27
|
||||
- extra-android-m2repository
|
||||
|
||||
before_install:
|
||||
|
||||
@@ -7,8 +7,11 @@ Termux app
|
||||
|
||||
* [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 Help](http://termux.com/help/)
|
||||
* [Termux Facebook](https://facebook.com/termux/)
|
||||
* [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)
|
||||
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.3"
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion "27.0.1"
|
||||
|
||||
dependencies {
|
||||
compile 'com.android.support:support-annotations:25.3.1'
|
||||
compile "com.android.support:support-v4:25.3.1"
|
||||
compile project(":terminal-view")
|
||||
implementation 'com.android.support:support-annotations:27.0.0'
|
||||
implementation "com.android.support:support-core-ui:27.0.0"
|
||||
implementation project(":terminal-view")
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.termux"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
versionCode 52
|
||||
versionName "0.52"
|
||||
targetSdkVersion 27
|
||||
versionCode 55
|
||||
versionName "0.55"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@@ -28,5 +28,5 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile 'junit:junit:4.12'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
}
|
||||
|
||||
@@ -76,6 +76,18 @@
|
||||
</intent-filter>
|
||||
</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
|
||||
android:name=".filepicker.TermuxDocumentsProvider"
|
||||
android:authorities="com.termux.documents"
|
||||
|
||||
@@ -157,7 +157,6 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
||||
|
||||
void checkForFontAndColors() {
|
||||
try {
|
||||
// Hard-coded paths since this file is used also in Termux:Float.
|
||||
@SuppressLint("SdCardPath") File fontFile = new File("/data/data/com.termux/files/home/.termux/font.ttf");
|
||||
@SuppressLint("SdCardPath") File colorsFile = new File("/data/data/com.termux/files/home/.termux/colors.properties");
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ public final class TermuxHelpActivity extends Activity {
|
||||
mWebView.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
if (url.startsWith("https://termux.com")) {
|
||||
if (url.startsWith("https://wiki.termux.com")) {
|
||||
// Inline help.
|
||||
setContentView(progressLayout);
|
||||
return false;
|
||||
@@ -60,7 +60,7 @@ public final class TermuxHelpActivity extends Activity {
|
||||
setContentView(mWebView);
|
||||
}
|
||||
});
|
||||
mWebView.loadUrl("https://termux.com/help.html");
|
||||
mWebView.loadUrl("https://wiki.termux.com/wiki/Main_Page");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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()}.
|
||||
* <p/>
|
||||
* (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/>
|
||||
* (5.1) If the zip entry encountered is SYMLINKS.txt, go through it and remember all symlinks to setup.
|
||||
* <p/>
|
||||
|
||||
@@ -8,6 +8,7 @@ import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.annotation.NonNull;
|
||||
@@ -18,6 +19,7 @@ import com.termux.terminal.EmulatorDebug;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
|
||||
public class TermuxOpenReceiver extends BroadcastReceiver {
|
||||
|
||||
@@ -171,6 +173,16 @@ public class TermuxOpenReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode) throws FileNotFoundException {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.termux.app;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
@@ -11,10 +12,10 @@ import android.content.res.Resources;
|
||||
import android.net.Uri;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.PowerManager;
|
||||
import android.support.v4.content.WakefulBroadcastReceiver;
|
||||
import android.util.Log;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
||||
@@ -41,6 +42,8 @@ import java.util.List;
|
||||
*/
|
||||
public final class TermuxService extends Service implements SessionChangedCallback {
|
||||
|
||||
private static final String NOTIFICATION_CHANNEL_ID = "termux_notification_channel";
|
||||
|
||||
/** Note that this is a symlink on the Android M preview. */
|
||||
@SuppressLint("SdCardPath")
|
||||
public static final String FILES_PATH = "/data/data/com.termux/files";
|
||||
@@ -153,11 +156,6 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
||||
Log.e(EmulatorDebug.LOG_TAG, "Unknown TermuxService action: '" + action + "'");
|
||||
}
|
||||
|
||||
if ((flags & START_FLAG_REDELIVERY) == 0) {
|
||||
// Service is started by WBR, not restarted by system, so release the WakeLock from WBR.
|
||||
WakefulBroadcastReceiver.completeWakefulIntent(intent);
|
||||
}
|
||||
|
||||
// If this service really do get killed, there is no point restarting it automatically - let the user do on next
|
||||
// start of {@link Term):
|
||||
return Service.START_NOT_STICKY;
|
||||
@@ -170,6 +168,7 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
setupNotificationChannel();
|
||||
startForeground(NOTIFICATION_ID, buildNotification());
|
||||
}
|
||||
|
||||
@@ -208,8 +207,8 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
||||
builder.setOngoing(true);
|
||||
|
||||
// If holding a wake or wifi lock consider the notification of high priority since it's using power,
|
||||
// otherwise use a minimal priority since this is just a background service notification:
|
||||
builder.setPriority((wakeLockHeld) ? Notification.PRIORITY_HIGH : Notification.PRIORITY_MIN);
|
||||
// otherwise use a low priority
|
||||
builder.setPriority((wakeLockHeld) ? Notification.PRIORITY_HIGH : Notification.PRIORITY_LOW);
|
||||
|
||||
// No need to show a timestamp:
|
||||
builder.setShowWhen(false);
|
||||
@@ -217,6 +216,10 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
||||
// Background color for small notification icon:
|
||||
builder.setColor(0xFF000000);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
builder.setChannelId(NOTIFICATION_CHANNEL_ID);
|
||||
}
|
||||
|
||||
Resources res = getResources();
|
||||
Intent exitIntent = new Intent(this, TermuxService.class).setAction(ACTION_STOP_SERVICE);
|
||||
builder.addAction(android.R.drawable.ic_delete, res.getString(R.string.notification_action_exit), PendingIntent.getService(this, 0, exitIntent, 0));
|
||||
@@ -341,4 +344,17 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupNotificationChannel() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return;
|
||||
|
||||
String channelName = "Termux";
|
||||
String channelDescription = "Notifications from Termux";
|
||||
int importance = NotificationManager.IMPORTANCE_LOW;
|
||||
|
||||
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName,importance);
|
||||
channel.setDescription(channelDescription);
|
||||
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
manager.createNotificationChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.3.3'
|
||||
classpath 'com.android.tools.build:gradle:3.0.0'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
url "https://maven.google.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
5
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,5 @@
|
||||
#Sun Jun 11 22:47:00 CEST 2017
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.3.1-bin.zip
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
6
gradlew
vendored
6
gradlew
vendored
@@ -33,11 +33,11 @@ DEFAULT_JVM_OPTS=""
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
@@ -155,7 +155,7 @@ if $cygwin ; then
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save ( ) {
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// Start https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle
|
||||
apply plugin: 'com.github.dcendents.android-maven'
|
||||
group = publishedGroupId // Maven Group ID for the artifact
|
||||
install {
|
||||
repositories.mavenInstaller {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
plugins {
|
||||
id "com.jfrog.bintray" version "1.7"
|
||||
id "com.github.dcendents.android-maven" version "1.5"
|
||||
id "com.jfrog.bintray" version "1.7.3"
|
||||
id "com.github.dcendents.android-maven" version "2.0"
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
@@ -13,16 +13,16 @@ ext {
|
||||
libraryDescription = 'The terminal emulator used in Termux'
|
||||
siteUrl = 'https://github.com/termux/termux'
|
||||
gitUrl = 'https://github.com/termux/termux.git'
|
||||
libraryVersion = '0.50'
|
||||
libraryVersion = '0.52'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.3"
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion "27.0.1"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
targetSdkVersion 27
|
||||
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
@@ -56,7 +56,7 @@ tasks.withType(Test) {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile 'junit:junit:4.12'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
}
|
||||
|
||||
apply from: '../scripts/bintray-publish.gradle'
|
||||
|
||||
@@ -223,6 +223,7 @@ public final class TerminalEmulator {
|
||||
|
||||
private byte mUtf8ToFollow, mUtf8Index;
|
||||
private final byte[] mUtf8InputBuffer = new byte[4];
|
||||
private int mLastEmittedCodePoint = -1;
|
||||
|
||||
public final TerminalColors mColors = new TerminalColors();
|
||||
|
||||
@@ -419,10 +420,11 @@ public final class TerminalEmulator {
|
||||
mUtf8Index = mUtf8ToFollow = 0;
|
||||
|
||||
if (codePoint >= 0x80 && codePoint <= 0x9F) {
|
||||
// Sequence decoded to a C1 control character which is the same as escape followed by
|
||||
// ((code & 0x7F) + 0x40).
|
||||
processCodePoint(/* escape (hexadecimal=0x1B, octal=033): */27);
|
||||
processCodePoint((codePoint & 0x7F) + 0x40);
|
||||
// Sequence decoded to a C1 control character which we ignore. They are
|
||||
// not used nowadays and increases the risk of messing up the terminal state
|
||||
// on binary input. XTerm does not allow them in utf-8:
|
||||
// "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 {
|
||||
switch (Character.getType(codePoint)) {
|
||||
case Character.UNASSIGNED:
|
||||
@@ -1190,12 +1192,20 @@ public final class TerminalEmulator {
|
||||
}
|
||||
|
||||
private void doLinefeed() {
|
||||
boolean belowScrollingRegion = mCursorRow >= mBottomMargin;
|
||||
int newCursorRow = mCursorRow + 1;
|
||||
if (newCursorRow >= mBottomMargin) {
|
||||
scrollDownOneLine();
|
||||
newCursorRow = mBottomMargin - 1;
|
||||
if (belowScrollingRegion) {
|
||||
// Move down (but not scroll) as long as we are above the last row.
|
||||
if (mCursorRow != mRows - 1) {
|
||||
setCursorRow(newCursorRow);
|
||||
}
|
||||
} else {
|
||||
if (newCursorRow == mBottomMargin) {
|
||||
scrollDownOneLine();
|
||||
newCursorRow = mBottomMargin - 1;
|
||||
}
|
||||
setCursorRow(newCursorRow);
|
||||
}
|
||||
setCursorRow(newCursorRow);
|
||||
}
|
||||
|
||||
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).
|
||||
setCursorColRespectingOriginMode(getArg0(1) - 1);
|
||||
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.
|
||||
// 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".
|
||||
@@ -1564,7 +1579,7 @@ public final class TerminalEmulator {
|
||||
break;
|
||||
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 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
|
||||
@@ -1573,6 +1588,7 @@ public final class TerminalEmulator {
|
||||
// Also require that top + 2 <= bottom.
|
||||
mTopMargin = Math.max(0, Math.min(getArg0(1) - 1, mRows - 2));
|
||||
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.
|
||||
setCursorPosition(0, 0);
|
||||
}
|
||||
@@ -2090,6 +2106,7 @@ public final class TerminalEmulator {
|
||||
* @param codePoint The code point of the character to display
|
||||
*/
|
||||
private void emitCodePoint(int codePoint) {
|
||||
mLastEmittedCodePoint = codePoint;
|
||||
if (mUseLineDrawingUsesG0 ? mUseLineDrawingG0 : mUseLineDrawingG1) {
|
||||
// http://www.vt100.net/docs/vt102-ug/table5-15.html.
|
||||
switch (codePoint) {
|
||||
|
||||
@@ -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", " ");
|
||||
}
|
||||
|
||||
/** 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", " ");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 ");
|
||||
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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ public class TerminalRowTest extends TestCase {
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
row = new TerminalRow(COLUMNS, TextStyle.NORMAL);
|
||||
}
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ public abstract class TerminalTestCase extends TestCase {
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mOutput = new MockTerminalOutput();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
plugins {
|
||||
id "com.jfrog.bintray" version "1.7"
|
||||
id "com.github.dcendents.android-maven" version "1.5"
|
||||
id "com.jfrog.bintray" version "1.7.3"
|
||||
id "com.github.dcendents.android-maven" version "2.0"
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
@@ -13,21 +13,21 @@ ext {
|
||||
libraryDescription = 'The terminal view used in Termux'
|
||||
siteUrl = 'https://github.com/termux/termux'
|
||||
gitUrl = 'https://github.com/termux/termux.git'
|
||||
libraryVersion = '0.49'
|
||||
libraryVersion = '0.50'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.3"
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion "27.0.1"
|
||||
|
||||
dependencies {
|
||||
compile 'com.android.support:support-annotations:25.3.1'
|
||||
compile project(":terminal-emulator")
|
||||
implementation 'com.android.support:support-annotations:27.0.0'
|
||||
api project(":terminal-emulator")
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 25
|
||||
targetSdkVersion 27
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile 'junit:junit:4.12'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
}
|
||||
|
||||
apply from: '../scripts/bintray-publish.gradle'
|
||||
|
||||
@@ -834,6 +834,10 @@ public final class TerminalView extends View {
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||
if (!mIsSelectingText) {
|
||||
// Fix issue where the dialog is pressed while being dismissed.
|
||||
return true;
|
||||
}
|
||||
switch (item.getItemId()) {
|
||||
case 1:
|
||||
String selectedText = mEmulator.getSelectedText(mSelX1, mSelY1, mSelX2, mSelY2).trim();
|
||||
|
||||
Reference in New Issue
Block a user