mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-06 18:55:31 +08:00
Reformat code project-wide (getting rid of tabs)
This commit is contained in:
231
.idea/codeStyleSettings.xml
generated
Normal file
231
.idea/codeStyleSettings.xml
generated
Normal file
@@ -0,0 +1,231 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectCodeStyleSettingsManager">
|
||||
<option name="PER_PROJECT_SETTINGS">
|
||||
<value>
|
||||
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
||||
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
|
||||
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
|
||||
<value />
|
||||
</option>
|
||||
<option name="IMPORT_LAYOUT_TABLE">
|
||||
<value>
|
||||
<package name="android" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="com" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="junit" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="net" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="org" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="java" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="javax" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="" withSubpackages="true" static="false" />
|
||||
<emptyLine />
|
||||
<package name="" withSubpackages="true" static="true" />
|
||||
<emptyLine />
|
||||
</value>
|
||||
</option>
|
||||
<option name="RIGHT_MARGIN" value="100" />
|
||||
<AndroidXmlCodeStyleSettings>
|
||||
<option name="USE_CUSTOM_SETTINGS" value="true" />
|
||||
</AndroidXmlCodeStyleSettings>
|
||||
<Objective-C-extensions>
|
||||
<option name="GENERATE_INSTANCE_VARIABLES_FOR_PROPERTIES" value="ASK" />
|
||||
<option name="RELEASE_STYLE" value="IVAR" />
|
||||
<option name="TYPE_QUALIFIERS_PLACEMENT" value="BEFORE" />
|
||||
<file>
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
|
||||
</file>
|
||||
<class>
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
|
||||
</class>
|
||||
<extensions>
|
||||
<pair source="cpp" header="h" />
|
||||
<pair source="c" header="h" />
|
||||
</extensions>
|
||||
</Objective-C-extensions>
|
||||
<XML>
|
||||
<option name="XML_KEEP_LINE_BREAKS" value="false" />
|
||||
<option name="XML_ALIGN_ATTRIBUTES" value="false" />
|
||||
<option name="XML_SPACE_INSIDE_EMPTY_TAG" value="true" />
|
||||
</XML>
|
||||
<codeStyleSettings language="XML">
|
||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
<arrangement>
|
||||
<rules>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:android</NAME>
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>xmlns:.*</NAME>
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:id</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:name</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>name</NAME>
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>style</NAME>
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:layout_width</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:layout_height</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:layout_.*</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:width</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*:height</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
<section>
|
||||
<rule>
|
||||
<match>
|
||||
<AND>
|
||||
<NAME>.*</NAME>
|
||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
||||
</AND>
|
||||
</match>
|
||||
<order>BY_NAME</order>
|
||||
</rule>
|
||||
</section>
|
||||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
</value>
|
||||
</option>
|
||||
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default (1)" />
|
||||
</component>
|
||||
</project>
|
@@ -21,7 +21,7 @@ public final class BackgroundJob {
|
||||
public BackgroundJob(File cwd, File fileToExecute, String[] args) throws IOException {
|
||||
String[] env = buildEnvironment(false, cwd.getAbsolutePath());
|
||||
|
||||
String[] progArray = new String[args.length+1];
|
||||
String[] progArray = new String[args.length + 1];
|
||||
|
||||
mProcess = Runtime.getRuntime().exec(progArray, env, cwd);
|
||||
|
||||
@@ -97,7 +97,7 @@ public final class BackgroundJob {
|
||||
if (failSafe) {
|
||||
// Keep the default path so that system binaries can be used in the failsafe session.
|
||||
final String pathEnv = "PATH=" + System.getenv("PATH");
|
||||
return new String[] { termEnv, homeEnv, prefixEnv, androidRootEnv, androidDataEnv, pathEnv, externalStorageEnv };
|
||||
return new String[]{termEnv, homeEnv, prefixEnv, androidRootEnv, androidDataEnv, pathEnv, externalStorageEnv};
|
||||
} else {
|
||||
final String ps1Env = "PS1=$ ";
|
||||
final String ldEnv = "LD_LIBRARY_PATH=" + TermuxService.PREFIX_PATH + "/lib";
|
||||
@@ -105,7 +105,7 @@ public final class BackgroundJob {
|
||||
final String pathEnv = "PATH=" + TermuxService.PREFIX_PATH + "/bin:" + TermuxService.PREFIX_PATH + "/bin/applets";
|
||||
final String pwdEnv = "PWD=" + cwd;
|
||||
|
||||
return new String[] { termEnv, homeEnv, prefixEnv, ps1Env, ldEnv, langEnv, pathEnv, pwdEnv, androidRootEnv, androidDataEnv, externalStorageEnv };
|
||||
return new String[]{termEnv, homeEnv, prefixEnv, ps1Env, ldEnv, langEnv, pathEnv, pwdEnv, androidRootEnv, androidDataEnv, externalStorageEnv};
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -31,14 +31,29 @@ public final class ExtraKeysView extends GridLayout {
|
||||
int keyCode = 0;
|
||||
String chars = null;
|
||||
switch (keyName) {
|
||||
case "ESC": keyCode = KeyEvent.KEYCODE_ESCAPE; break;
|
||||
case "TAB": keyCode = KeyEvent.KEYCODE_TAB; break;
|
||||
case "▲": keyCode = KeyEvent.KEYCODE_DPAD_UP; break;
|
||||
case "◀": keyCode = KeyEvent.KEYCODE_DPAD_LEFT; break;
|
||||
case "▶": keyCode = KeyEvent.KEYCODE_DPAD_RIGHT; break;
|
||||
case "▼": keyCode = KeyEvent.KEYCODE_DPAD_DOWN; break;
|
||||
case "―": chars = "-"; break;
|
||||
default: chars = keyName;
|
||||
case "ESC":
|
||||
keyCode = KeyEvent.KEYCODE_ESCAPE;
|
||||
break;
|
||||
case "TAB":
|
||||
keyCode = KeyEvent.KEYCODE_TAB;
|
||||
break;
|
||||
case "▲":
|
||||
keyCode = KeyEvent.KEYCODE_DPAD_UP;
|
||||
break;
|
||||
case "◀":
|
||||
keyCode = KeyEvent.KEYCODE_DPAD_LEFT;
|
||||
break;
|
||||
case "▶":
|
||||
keyCode = KeyEvent.KEYCODE_DPAD_RIGHT;
|
||||
break;
|
||||
case "▼":
|
||||
keyCode = KeyEvent.KEYCODE_DPAD_DOWN;
|
||||
break;
|
||||
case "―":
|
||||
chars = "-";
|
||||
break;
|
||||
default:
|
||||
chars = keyName;
|
||||
}
|
||||
|
||||
if (keyCode > 0) {
|
||||
|
@@ -79,7 +79,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A terminal emulator activity.
|
||||
*
|
||||
* <p/>
|
||||
* See
|
||||
* <ul>
|
||||
* <li>http://www.mongrel-phones.com.au/default/how_to_make_a_local_service_and_bind_to_it_in_android</li>
|
||||
@@ -105,7 +105,9 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
||||
private static final String RELOAD_STYLE_ACTION = "com.termux.app.reload_style";
|
||||
|
||||
/** The main view of the activity showing the terminal. Initialized in onCreate(). */
|
||||
@SuppressWarnings("NullableProblems") @NonNull TerminalView mTerminalView;
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NonNull
|
||||
TerminalView mTerminalView;
|
||||
|
||||
ExtraKeysView mExtraKeysView;
|
||||
|
||||
@@ -143,7 +145,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
||||
if (mIsVisible) {
|
||||
String whatToReload = intent.getStringExtra(RELOAD_STYLE_ACTION);
|
||||
if ("storage".equals(whatToReload)) {
|
||||
if (ensureStoragePermissionGranted()) TermuxInstaller.setupStorageSymlinks(TermuxActivity.this);
|
||||
if (ensureStoragePermissionGranted())
|
||||
TermuxInstaller.setupStorageSymlinks(TermuxActivity.this);
|
||||
return;
|
||||
}
|
||||
checkForFontAndColors();
|
||||
@@ -320,7 +323,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
||||
Intent serviceIntent = new Intent(this, TermuxService.class);
|
||||
// Start the service and make it run regardless of who is bound to it:
|
||||
startService(serviceIntent);
|
||||
if (!bindService(serviceIntent, this, 0)) throw new RuntimeException("bindService() failed");
|
||||
if (!bindService(serviceIntent, this, 0))
|
||||
throw new RuntimeException("bindService() failed");
|
||||
|
||||
checkForFontAndColors();
|
||||
|
||||
@@ -376,7 +380,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
||||
// Show toast for non-current sessions that exit.
|
||||
int indexOfSession = mTermService.getSessions().indexOf(finishedSession);
|
||||
// Verify that session was not removed before we got told about it finishing:
|
||||
if (indexOfSession >= 0) showToast(toToastTitle(finishedSession) + " - exited", true);
|
||||
if (indexOfSession >= 0)
|
||||
showToast(toToastTitle(finishedSession) + " - exited", true);
|
||||
}
|
||||
mListViewAdapter.notifyDataSetChanged();
|
||||
}
|
||||
@@ -386,7 +391,7 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
||||
if (!mIsVisible) return;
|
||||
showToast("Clipboard:\n\"" + text + "\"", false);
|
||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
clipboard.setPrimaryClip(new ClipData(null, new String[] { "text/plain" }, new ClipData.Item(text)));
|
||||
clipboard.setPrimaryClip(new ClipData(null, new String[]{"text/plain"}, new ClipData.Item(text)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -535,7 +540,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable TerminalSession getCurrentTermSession() {
|
||||
@Nullable
|
||||
TerminalSession getCurrentTermSession() {
|
||||
return mTerminalView.getCurrentSession();
|
||||
}
|
||||
|
||||
@@ -695,7 +701,7 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
||||
public void onClick(DialogInterface di, int which) {
|
||||
String url = (String) urls[which];
|
||||
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
clipboard.setPrimaryClip(new ClipData(null, new String[] { "text/plain" }, new ClipData.Item(url)));
|
||||
clipboard.setPrimaryClip(new ClipData(null, new String[]{"text/plain"}, new ClipData.Item(url)));
|
||||
Toast.makeText(TermuxActivity.this, R.string.select_url_copied_to_clipboard, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}).setTitle(R.string.select_url_dialog_title).create();
|
||||
@@ -819,7 +825,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
||||
ClipData clipData = clipboard.getPrimaryClip();
|
||||
if (clipData == null) return;
|
||||
CharSequence paste = clipData.getItemAt(0).coerceToText(this);
|
||||
if (!TextUtils.isEmpty(paste)) getCurrentTermSession().getEmulator().paste(paste.toString());
|
||||
if (!TextUtils.isEmpty(paste))
|
||||
getCurrentTermSession().getEmulator().paste(paste.toString());
|
||||
}
|
||||
|
||||
/** The current session as stored or the last one if that does not exist. */
|
||||
|
@@ -31,21 +31,21 @@ import java.util.zip.ZipInputStream;
|
||||
|
||||
/**
|
||||
* Install the Termux bootstrap packages if necessary by following the below steps:
|
||||
*
|
||||
* <p/>
|
||||
* (1) If $PREFIX already exist, assume that it is correct and be done. Note that this relies on that we do not create a
|
||||
* broken $PREFIX folder below.
|
||||
*
|
||||
* <p/>
|
||||
* (2) A progress dialog is shown with "Installing..." message and a spinner.
|
||||
*
|
||||
* <p/>
|
||||
* (3) A staging folder, $STAGING_PREFIX, is {@link #deleteFolder(File)} if left over from broken installation below.
|
||||
*
|
||||
* <p/>
|
||||
* (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:
|
||||
*
|
||||
* <p/>
|
||||
* (5.1) If the zip entry encountered is SYMLINKS.txt, go through it and remember all symlinks to setup.
|
||||
*
|
||||
* <p/>
|
||||
* (5.2) For every other zip entry, extract it into $STAGING_PREFIX and set execute permissions if necessary.
|
||||
*/
|
||||
final class TermuxInstaller {
|
||||
@@ -97,7 +97,8 @@ final class TermuxInstaller {
|
||||
String line;
|
||||
while ((line = symlinksReader.readLine()) != null) {
|
||||
String[] parts = line.split("←");
|
||||
if (parts.length != 2) throw new RuntimeException("Malformed symlink line: " + line);
|
||||
if (parts.length != 2)
|
||||
throw new RuntimeException("Malformed symlink line: " + line);
|
||||
String oldPath = parts[0];
|
||||
String newPath = STAGING_PREFIX_PATH + "/" + parts[1];
|
||||
symlinks.add(Pair.create(oldPath, newPath));
|
||||
@@ -106,7 +107,8 @@ final class TermuxInstaller {
|
||||
String zipEntryName = zipEntry.getName();
|
||||
File targetFile = new File(STAGING_PREFIX_PATH, zipEntryName);
|
||||
if (zipEntry.isDirectory()) {
|
||||
if (!targetFile.mkdirs()) throw new RuntimeException("Failed to create directory: " + targetFile.getAbsolutePath());
|
||||
if (!targetFile.mkdirs())
|
||||
throw new RuntimeException("Failed to create directory: " + targetFile.getAbsolutePath());
|
||||
} else {
|
||||
try (FileOutputStream outStream = new FileOutputStream(targetFile)) {
|
||||
int readBytes;
|
||||
@@ -122,7 +124,8 @@ final class TermuxInstaller {
|
||||
}
|
||||
}
|
||||
|
||||
if (symlinks.isEmpty()) throw new RuntimeException("No SYMLINKS.txt encountered");
|
||||
if (symlinks.isEmpty())
|
||||
throw new RuntimeException("No SYMLINKS.txt encountered");
|
||||
for (Pair<String, String> symlink : symlinks) {
|
||||
Os.symlink(symlink.first, symlink.second);
|
||||
}
|
||||
|
@@ -111,7 +111,8 @@ public final class TermuxKeyListener implements TerminalKeyListener {
|
||||
mActivity.changeFontSize(false);
|
||||
} else if (unicodeChar >= '1' && unicodeChar <= '9') {
|
||||
int num = unicodeChar - '1';
|
||||
if (service.getSessions().size() > num) mActivity.switchToSession(service.getSessions().get(num));
|
||||
if (service.getSessions().size() > num)
|
||||
mActivity.switchToSession(service.getSessions().get(num));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -22,7 +22,8 @@ final class TermuxPreferences {
|
||||
|
||||
@IntDef({BELL_VIBRATE, BELL_BEEP, BELL_IGNORE})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface AsciiBellBehaviour {}
|
||||
public @interface AsciiBellBehaviour {
|
||||
}
|
||||
|
||||
static final int BELL_VIBRATE = 1;
|
||||
static final int BELL_BEEP = 2;
|
||||
@@ -127,7 +128,8 @@ final class TermuxPreferences {
|
||||
public void reloadFromProperties(Context context) {
|
||||
try {
|
||||
File propsFile = new File(TermuxService.HOME_PATH + "/.termux/termux.properties");
|
||||
if (!propsFile.exists()) propsFile = new File(TermuxService.HOME_PATH + "/.config/termux/termux.properties");
|
||||
if (!propsFile.exists())
|
||||
propsFile = new File(TermuxService.HOME_PATH + "/.config/termux/termux.properties");
|
||||
|
||||
Properties props = new Properties();
|
||||
if (propsFile.isFile() && propsFile.canRead()) {
|
||||
|
@@ -1,15 +1,5 @@
|
||||
package com.termux.app;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.termux.R;
|
||||
import com.termux.terminal.EmulatorDebug;
|
||||
import com.termux.terminal.TerminalSession;
|
||||
import com.termux.terminal.TerminalSession.SessionChangedCallback;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
@@ -26,15 +16,25 @@ import android.os.PowerManager;
|
||||
import android.util.Log;
|
||||
import android.widget.ArrayAdapter;
|
||||
|
||||
import com.termux.R;
|
||||
import com.termux.terminal.EmulatorDebug;
|
||||
import com.termux.terminal.TerminalSession;
|
||||
import com.termux.terminal.TerminalSession.SessionChangedCallback;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A service holding a list of terminal sessions, {@link #mTerminalSessions}, showing a foreground notification while
|
||||
* running so that it is not terminated. The user interacts with the session through {@link TermuxActivity}, but this
|
||||
* service may outlive the activity when the user or the system disposes of the activity. In that case the user may
|
||||
* restart {@link TermuxActivity} later to yet again access the sessions.
|
||||
*
|
||||
* <p/>
|
||||
* In order to keep both terminal sessions and spawned processes (who may outlive the terminal sessions) alive as long
|
||||
* as wanted by the user this service is a foreground service, {@link Service#startForeground(int, Notification)}.
|
||||
*
|
||||
* <p/>
|
||||
* Optionally may hold a wake and a wifi lock, in which case that is shown in the notification - see
|
||||
* {@link #buildNotification()}.
|
||||
*/
|
||||
@@ -70,7 +70,7 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
||||
|
||||
/**
|
||||
* The terminal sessions which this service manages.
|
||||
*
|
||||
* <p/>
|
||||
* Note that this list is observed by {@link TermuxActivity#mListViewAdapter}, so any changes must be made on the UI
|
||||
* thread and followed by a call to {@link ArrayAdapter#notifyDataSetChanged()} }.
|
||||
*/
|
||||
@@ -248,7 +248,7 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
||||
if (failSafe) {
|
||||
// Keep the default path so that system binaries can be used in the failsafe session.
|
||||
final String pathEnv = "PATH=" + System.getenv("PATH");
|
||||
env = new String[] { termEnv, homeEnv, prefixEnv, androidRootEnv, androidDataEnv, pathEnv, externalStorageEnv };
|
||||
env = new String[]{termEnv, homeEnv, prefixEnv, androidRootEnv, androidDataEnv, pathEnv, externalStorageEnv};
|
||||
} else {
|
||||
final String ps1Env = "PS1=$ ";
|
||||
final String ldEnv = "LD_LIBRARY_PATH=" + PREFIX_PATH + "/lib";
|
||||
@@ -256,7 +256,7 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
||||
final String pathEnv = "PATH=" + PREFIX_PATH + "/bin:" + PREFIX_PATH + "/bin/applets";
|
||||
final String pwdEnv = "PWD=" + cwd;
|
||||
|
||||
env = new String[] { termEnv, homeEnv, prefixEnv, ps1Env, ldEnv, langEnv, pathEnv, pwdEnv, androidRootEnv, androidDataEnv, externalStorageEnv };
|
||||
env = new String[]{termEnv, homeEnv, prefixEnv, ps1Env, ldEnv, langEnv, pathEnv, pwdEnv, androidRootEnv, androidDataEnv, externalStorageEnv};
|
||||
}
|
||||
|
||||
String shellName;
|
||||
@@ -277,7 +277,7 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
||||
|
||||
if (executablePath == null) {
|
||||
// Try bash, zsh and ash in that order:
|
||||
for (String shellBinary : new String[] { "bash", "zsh", "ash" }) {
|
||||
for (String shellBinary : new String[]{"bash", "zsh", "ash"}) {
|
||||
File shellFile = new File(PREFIX_PATH + "/bin/" + shellBinary);
|
||||
if (shellFile.canExecute()) {
|
||||
executablePath = shellFile.getAbsolutePath();
|
||||
@@ -300,7 +300,7 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
||||
|
||||
String[] args;
|
||||
if (arguments == null) {
|
||||
args = new String[] { shellName };
|
||||
args = new String[]{shellName};
|
||||
} else {
|
||||
args = new String[arguments.length + 1];
|
||||
args[0] = shellName;
|
||||
@@ -334,7 +334,8 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
||||
|
||||
@Override
|
||||
public void onSessionFinished(final TerminalSession finishedSession) {
|
||||
if (mSessionChangeCallback != null) mSessionChangeCallback.onSessionFinished(finishedSession);
|
||||
if (mSessionChangeCallback != null)
|
||||
mSessionChangeCallback.onSessionFinished(finishedSession);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -23,9 +23,9 @@ import java.util.LinkedList;
|
||||
/**
|
||||
* A document provider for the Storage Access Framework which exposes the files in the
|
||||
* $HOME/ folder to other apps.
|
||||
* <p>
|
||||
* <p/>
|
||||
* Note that this replaces providing an activity matching the ACTION_GET_CONTENT intent:
|
||||
* <p>
|
||||
* <p/>
|
||||
* "A document provider and ACTION_GET_CONTENT should be considered mutually exclusive. If you
|
||||
* support both of them simultaneously, your app will appear twice in the system picker UI,
|
||||
* offering two different ways of accessing your stored data. This would be confusing for users."
|
||||
@@ -172,7 +172,7 @@ public class TermuxDocumentsProvider extends DocumentsProvider {
|
||||
/**
|
||||
* Get the document id given a file. This document id must be consistent across time as other
|
||||
* applications may save the ID and use it to reference documents later.
|
||||
* <p>
|
||||
* <p/>
|
||||
* The reverse of @{link #getFileForDocId}.
|
||||
*/
|
||||
private static String getDocIdForFile(File file) {
|
||||
|
@@ -53,7 +53,7 @@ final class ByteQueue {
|
||||
|
||||
/**
|
||||
* Attempt to write the specified portion of the provided buffer to the queue.
|
||||
*
|
||||
* <p/>
|
||||
* Returns whether the output was totally written, false if it was closed before.
|
||||
*/
|
||||
public boolean write(byte[] buffer, int offset, int lengthToWrite) {
|
||||
|
@@ -12,19 +12,14 @@ final class JNI {
|
||||
/**
|
||||
* Create a subprocess. Differs from {@link ProcessBuilder} in that a pseudoterminal is used to communicate with the
|
||||
* subprocess.
|
||||
*
|
||||
* <p/>
|
||||
* Callers are responsible for calling {@link #close(int)} on the returned file descriptor.
|
||||
*
|
||||
* @param cmd
|
||||
* The command to execute
|
||||
* @param cwd
|
||||
* The current working directory for the executed command
|
||||
* @param args
|
||||
* An array of arguments to the command
|
||||
* @param envVars
|
||||
* An array of strings of the form "VAR=value" to be added to the environment of the process
|
||||
* @param processId
|
||||
* A one-element array to which the process ID of the started process will be written.
|
||||
* @param cmd The command to execute
|
||||
* @param cwd The current working directory for the executed command
|
||||
* @param args An array of arguments to the command
|
||||
* @param envVars An array of strings of the form "VAR=value" to be added to the environment of the process
|
||||
* @param processId A one-element array to which the process ID of the started process will be written.
|
||||
* @return the file descriptor resulting from opening /dev/ptmx master device. The sub process will have opened the
|
||||
* slave device counterpart (/dev/pts/$N) and have it as stdint, stdout and stderr.
|
||||
*/
|
||||
|
@@ -1,5 +1,10 @@
|
||||
package com.termux.terminal;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static android.view.KeyEvent.KEYCODE_BREAK;
|
||||
import static android.view.KeyEvent.KEYCODE_DEL;
|
||||
import static android.view.KeyEvent.KEYCODE_DPAD_CENTER;
|
||||
@@ -22,6 +27,7 @@ import static android.view.KeyEvent.KEYCODE_F7;
|
||||
import static android.view.KeyEvent.KEYCODE_F8;
|
||||
import static android.view.KeyEvent.KEYCODE_F9;
|
||||
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_MOVE_END;
|
||||
import static android.view.KeyEvent.KEYCODE_NUMPAD_0;
|
||||
@@ -47,12 +53,6 @@ import static android.view.KeyEvent.KEYCODE_PAGE_DOWN;
|
||||
import static android.view.KeyEvent.KEYCODE_PAGE_UP;
|
||||
import static android.view.KeyEvent.KEYCODE_SYSRQ;
|
||||
import static android.view.KeyEvent.KEYCODE_TAB;
|
||||
import static android.view.KeyEvent.KEYCODE_HOME;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import android.view.KeyEvent;
|
||||
|
||||
public final class KeyHandler {
|
||||
|
||||
@@ -61,6 +61,7 @@ public final class KeyHandler {
|
||||
public static final int KEYMOD_SHIFT = 0x20000000;
|
||||
|
||||
private static final Map<String, Integer> TERMCAP_TO_KEYCODE = new HashMap<>();
|
||||
|
||||
static {
|
||||
// terminfo: http://pubs.opengroup.org/onlinepubs/7990989799/xcurses/terminfo.html
|
||||
// termcap: http://man7.org/linux/man-pages/man5/termcap.5.html
|
||||
|
@@ -3,7 +3,7 @@ package com.termux.terminal;
|
||||
/**
|
||||
* A circular buffer of {@link TerminalRow}:s which keeps notes about what is visible on a logical screen and the scroll
|
||||
* history.
|
||||
*
|
||||
* <p/>
|
||||
* See {@link #externalToInternalRow(int)} for how to map from logical screen rows to array indices.
|
||||
*/
|
||||
public final class TerminalBuffer {
|
||||
@@ -21,12 +21,9 @@ public final class TerminalBuffer {
|
||||
/**
|
||||
* Create a transcript screen.
|
||||
*
|
||||
* @param columns
|
||||
* the width of the screen in characters.
|
||||
* @param totalRows
|
||||
* the height of the entire text area, in rows of text.
|
||||
* @param screenRows
|
||||
* the height of just the screen, not including the transcript that holds lines that have scrolled off
|
||||
* @param columns the width of the screen in characters.
|
||||
* @param totalRows the height of the entire text area, in rows of text.
|
||||
* @param screenRows the height of just the screen, not including the transcript that holds lines that have scrolled off
|
||||
* the top of the screen.
|
||||
*/
|
||||
public TerminalBuffer(int columns, int totalRows, int screenRows) {
|
||||
@@ -63,7 +60,7 @@ public final class TerminalBuffer {
|
||||
int x2Index = (x2 < mColumns) ? lineObject.findStartOfColumn(x2) : lineObject.getSpaceUsed();
|
||||
if (x2Index == x1Index) {
|
||||
// Selected the start of a wide character.
|
||||
x2Index = lineObject.findStartOfColumn(x2+1);
|
||||
x2Index = lineObject.findStartOfColumn(x2 + 1);
|
||||
}
|
||||
char[] line = lineObject.mText;
|
||||
int lastPrintingCharIndex = -1;
|
||||
@@ -78,7 +75,8 @@ public final class TerminalBuffer {
|
||||
if (c != ' ') lastPrintingCharIndex = i;
|
||||
}
|
||||
}
|
||||
if (lastPrintingCharIndex != -1) builder.append(line, x1Index, lastPrintingCharIndex - x1Index + 1);
|
||||
if (lastPrintingCharIndex != -1)
|
||||
builder.append(line, x1Index, lastPrintingCharIndex - x1Index + 1);
|
||||
if (!rowLineWrap && row < selY2 && row < mScreenRows - 1) builder.append('\n');
|
||||
}
|
||||
return builder.toString();
|
||||
@@ -94,15 +92,15 @@ public final class TerminalBuffer {
|
||||
|
||||
/**
|
||||
* Convert a row value from the public external coordinate system to our internal private coordinate system.
|
||||
*
|
||||
* <p/>
|
||||
* <ul>
|
||||
* <li>External coordinate system: -mActiveTranscriptRows to mScreenRows-1, with the screen being 0..mScreenRows-1.
|
||||
* <li>Internal coordinate system: the mScreenRows lines starting at mScreenFirstRow comprise the screen, while the
|
||||
* mActiveTranscriptRows lines ending at mScreenFirstRow-1 form the transcript (as a circular buffer).
|
||||
* </ul>
|
||||
*
|
||||
* <p/>
|
||||
* External <---> Internal:
|
||||
*
|
||||
* <p/>
|
||||
* <pre>
|
||||
* [ ... ] [ ... ]
|
||||
* [ -mActiveTranscriptRows ] [ mScreenFirstRow - mActiveTranscriptRows ]
|
||||
@@ -112,8 +110,7 @@ public final class TerminalBuffer {
|
||||
* [ mScreenRows-1 ] [ mScreenFirstRow + mScreenRows-1 ]
|
||||
* </pre>
|
||||
*
|
||||
* @param externalRow
|
||||
* a row in the external coordinate system.
|
||||
* @param externalRow a row in the external coordinate system.
|
||||
* @return The row corresponding to the input argument in the private coordinate system.
|
||||
*/
|
||||
public int externalToInternalRow(int externalRow) {
|
||||
@@ -139,12 +136,9 @@ public final class TerminalBuffer {
|
||||
* Resize the screen which this transcript backs. Currently, this only works if the number of columns does not
|
||||
* change or the rows expand (that is, it only works when shrinking the number of rows).
|
||||
*
|
||||
* @param newColumns
|
||||
* The number of columns 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 newColumns The number of columns 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.
|
||||
*/
|
||||
public void resize(int newColumns, int newRows, int newTotalRows, int[] cursor, int currentStyle, boolean altScreen) {
|
||||
// newRows > mTotalRows should not normally happen since mTotalRows is TRANSCRIPT_ROWS (10000):
|
||||
@@ -238,7 +232,8 @@ public final class TerminalBuffer {
|
||||
} else {
|
||||
for (int i = 0; i < oldLine.getSpaceUsed(); i++)
|
||||
// NEWLY INTRODUCED BUG! Should not index oldLine.mStyle with char indices
|
||||
if (oldLine.mText[i] != ' '/* || oldLine.mStyle[i] != currentStyle */) lastNonSpaceIndex = i + 1;
|
||||
if (oldLine.mText[i] != ' '/* || oldLine.mStyle[i] != currentStyle */)
|
||||
lastNonSpaceIndex = i + 1;
|
||||
}
|
||||
|
||||
int currentOldCol = 0;
|
||||
@@ -302,10 +297,8 @@ public final class TerminalBuffer {
|
||||
* Block copy lines and associated metadata from one location to another in the circular buffer, taking wraparound
|
||||
* into account.
|
||||
*
|
||||
* @param srcInternal
|
||||
* The first line to be copied.
|
||||
* @param len
|
||||
* The number of lines to be copied.
|
||||
* @param srcInternal The first line to be copied.
|
||||
* @param len The number of lines to be copied.
|
||||
*/
|
||||
private void blockCopyLinesDown(int srcInternal, int len) {
|
||||
if (len == 0) return;
|
||||
@@ -324,12 +317,9 @@ public final class TerminalBuffer {
|
||||
/**
|
||||
* Scroll the screen down one line. To scroll the whole screen of a 24 line screen, the arguments would be (0, 24).
|
||||
*
|
||||
* @param topMargin
|
||||
* First line that is scrolled.
|
||||
* @param bottomMargin
|
||||
* One line after the last line that is scrolled.
|
||||
* @param style
|
||||
* the style for the newly exposed line.
|
||||
* @param topMargin First line that is scrolled.
|
||||
* @param bottomMargin One line after the last line that is scrolled.
|
||||
* @param style the style for the newly exposed line.
|
||||
*/
|
||||
public void scrollDownOneLine(int topMargin, int bottomMargin, int style) {
|
||||
if (topMargin > bottomMargin - 1 || topMargin < 0 || bottomMargin > mScreenRows)
|
||||
@@ -360,18 +350,12 @@ public final class TerminalBuffer {
|
||||
* of the source and destination must be within the bounds of the screen, or else an InvalidParameterException will
|
||||
* be thrown.
|
||||
*
|
||||
* @param sx
|
||||
* source X coordinate
|
||||
* @param sy
|
||||
* source Y coordinate
|
||||
* @param w
|
||||
* width
|
||||
* @param h
|
||||
* height
|
||||
* @param dx
|
||||
* destination X coordinate
|
||||
* @param dy
|
||||
* destination Y coordinate
|
||||
* @param sx source X coordinate
|
||||
* @param sy source Y coordinate
|
||||
* @param w width
|
||||
* @param h height
|
||||
* @param dx destination X coordinate
|
||||
* @param dy destination Y coordinate
|
||||
*/
|
||||
public void blockCopy(int sx, int sy, int w, int h, int dx, int dy) {
|
||||
if (w == 0) return;
|
||||
|
@@ -57,7 +57,7 @@ public final class TerminalColorScheme {
|
||||
0xff808080, 0xff8a8a8a, 0xff949494, 0xff9e9e9e, 0xffa8a8a8, 0xffb2b2b2, 0xffbcbcbc, 0xffc6c6c6, 0xffd0d0d0, 0xffdadada, 0xffe4e4e4, 0xffeeeeee,
|
||||
|
||||
// COLOR_INDEX_DEFAULT_FOREGROUND, COLOR_INDEX_DEFAULT_BACKGROUND and COLOR_INDEX_DEFAULT_CURSOR:
|
||||
0xffffffff, 0xff000000, 0xffffffff };
|
||||
0xffffffff, 0xff000000, 0xffffffff};
|
||||
|
||||
public final int[] mDefaultColors = new int[TextStyle.NUM_INDEXED_COLORS];
|
||||
|
||||
@@ -93,7 +93,8 @@ public final class TerminalColorScheme {
|
||||
}
|
||||
|
||||
int colorValue = TerminalColors.parse(value);
|
||||
if (colorValue == 0) throw new IllegalArgumentException("Property '" + key + "' has invalid color: '" + value + "'");
|
||||
if (colorValue == 0)
|
||||
throw new IllegalArgumentException("Property '" + key + "' has invalid color: '" + value + "'");
|
||||
|
||||
mDefaultColors[colorIndex] = colorValue;
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ public final class TerminalColors {
|
||||
|
||||
/**
|
||||
* Parse color according to http://manpages.ubuntu.com/manpages/intrepid/man3/XQueryColor.3.html
|
||||
*
|
||||
* <p/>
|
||||
* Highest bit is set if successful, so return value is 0xFF${R}${G}${B}. Return 0 if failed.
|
||||
*/
|
||||
static int parse(String c) {
|
||||
|
@@ -1,18 +1,18 @@
|
||||
package com.termux.terminal;
|
||||
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Stack;
|
||||
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* <p/>
|
||||
* References:
|
||||
* <ul>
|
||||
* <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 is active, you cannot scroll back to view saved lines).
|
||||
*
|
||||
* <p/>
|
||||
* See http://www.xfree86.org/current/ctlseqs.html#The%20Alternate%20Screen%20Buffer
|
||||
*/
|
||||
final TerminalBuffer mAltBuffer;
|
||||
@@ -294,8 +294,7 @@ public final class TerminalEmulator {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mouseButton
|
||||
* one of the MOUSE_* constants of this class.
|
||||
* @param mouseButton one of the MOUSE_* constants of this class.
|
||||
*/
|
||||
public void sendMouseEvent(int mouseButton, int column, int row, boolean pressed) {
|
||||
if (mouseButton == MOUSE_LEFT_BUTTON_MOVED && !isDecsetInternalBitSet(DECSET_BIT_MOUSE_TRACKING_BUTTON_EVENT)) {
|
||||
@@ -307,7 +306,7 @@ public final class TerminalEmulator {
|
||||
// Clip to screen, and clip to the limits of 8-bit data.
|
||||
boolean out_of_bounds = column < 1 || row < 1 || column > mColumns || row > mRows || column > 255 - 32 || row > 255 - 32;
|
||||
if (!out_of_bounds) {
|
||||
byte[] data = { '\033', '[', 'M', (byte) (32 + mouseButton), (byte) (32 + column), (byte) (32 + row) };
|
||||
byte[] data = {'\033', '[', 'M', (byte) (32 + mouseButton), (byte) (32 + column), (byte) (32 + row)};
|
||||
mSession.write(data, 0, data.length);
|
||||
}
|
||||
}
|
||||
@@ -341,7 +340,7 @@ public final class TerminalEmulator {
|
||||
}
|
||||
|
||||
private void resizeScreen() {
|
||||
final int[] cursor = { mCursorCol, mCursorRow };
|
||||
final int[] cursor = {mCursorCol, mCursorRow};
|
||||
int newTotalRows = (mScreen == mAltBuffer) ? mRows : mMainBuffer.mTotalRows;
|
||||
mScreen.resize(mColumns, mRows, newTotalRows, cursor, getStyle(), isAlternateBufferActive());
|
||||
mCursorCol = cursor[0];
|
||||
@@ -390,10 +389,8 @@ public final class TerminalEmulator {
|
||||
/**
|
||||
* Accept bytes (typically from the pseudo-teletype) and process them.
|
||||
*
|
||||
* @param buffer
|
||||
* a byte array containing the bytes to be processed
|
||||
* @param length
|
||||
* the number of bytes in the array to process
|
||||
* @param buffer a byte array containing the bytes to be processed
|
||||
* @param length the number of bytes in the array to process
|
||||
*/
|
||||
public void append(byte[] buffer, int length) {
|
||||
for (int i = 0; i < length; i++)
|
||||
@@ -897,7 +894,8 @@ public final class TerminalEmulator {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (LOG_ESCAPE_SEQUENCES) Log.e(EmulatorDebug.LOG_TAG, "Unrecognized device control string: " + dcs);
|
||||
if (LOG_ESCAPE_SEQUENCES)
|
||||
Log.e(EmulatorDebug.LOG_TAG, "Unrecognized device control string: " + dcs);
|
||||
}
|
||||
finishSequence();
|
||||
}
|
||||
@@ -1086,7 +1084,8 @@ public final class TerminalEmulator {
|
||||
// Check if buffer size needs to be updated:
|
||||
if (resized) resizeScreen();
|
||||
// Clear new screen if alt buffer:
|
||||
if (newScreen == mAltBuffer) newScreen.blockSet(0, 0, mColumns, mRows, ' ', getStyle());
|
||||
if (newScreen == mAltBuffer)
|
||||
newScreen.blockSet(0, 0, mColumns, mRows, ' ', getStyle());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1542,7 +1541,7 @@ public final class TerminalEmulator {
|
||||
switch (getArg0(0)) {
|
||||
case 5: // Device status report (DSR):
|
||||
// Answer is ESC [ 0 n (Terminal OK).
|
||||
byte[] dsr = { (byte) 27, (byte) '[', (byte) '0', (byte) 'n' };
|
||||
byte[] dsr = {(byte) 27, (byte) '[', (byte) '0', (byte) 'n'};
|
||||
mSession.write(dsr, 0, dsr.length);
|
||||
break;
|
||||
case 6: // Cursor position report (CPR):
|
||||
@@ -1721,7 +1720,8 @@ public final class TerminalEmulator {
|
||||
mBackColor = color;
|
||||
}
|
||||
} else {
|
||||
if (LOG_ESCAPE_SEQUENCES) Log.w(EmulatorDebug.LOG_TAG, "Invalid color index: " + color);
|
||||
if (LOG_ESCAPE_SEQUENCES)
|
||||
Log.w(EmulatorDebug.LOG_TAG, "Invalid color index: " + color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1736,7 +1736,8 @@ public final class TerminalEmulator {
|
||||
} else if (code >= 100 && code <= 107) { // Bright background color (aixterm codes).
|
||||
mBackColor = code - 100 + 8;
|
||||
} else {
|
||||
if (LOG_ESCAPE_SEQUENCES) Log.w(EmulatorDebug.LOG_TAG, String.format("SGR unknown code %d", code));
|
||||
if (LOG_ESCAPE_SEQUENCES)
|
||||
Log.w(EmulatorDebug.LOG_TAG, String.format("SGR unknown code %d", code));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1804,7 +1805,7 @@ public final class TerminalEmulator {
|
||||
// and specification can be given in one control sequence, xterm can make more than one reply.
|
||||
int colorIndex = -1;
|
||||
int parsingPairStart = -1;
|
||||
for (int i = 0;; i++) {
|
||||
for (int i = 0; ; i++) {
|
||||
boolean endOfInput = i == textParameter.length();
|
||||
char b = endOfInput ? ';' : textParameter.charAt(i);
|
||||
if (b == ';') {
|
||||
@@ -1837,7 +1838,7 @@ public final class TerminalEmulator {
|
||||
case 12: // Set cursor color.
|
||||
int specialIndex = TextStyle.COLOR_INDEX_FOREGROUND + (value - 10);
|
||||
int lastSemiIndex = 0;
|
||||
for (int charIndex = 0;; charIndex++) {
|
||||
for (int charIndex = 0; ; charIndex++) {
|
||||
boolean endOfInput = charIndex == textParameter.length();
|
||||
if (endOfInput || textParameter.charAt(charIndex) == ';') {
|
||||
try {
|
||||
@@ -1855,7 +1856,8 @@ public final class TerminalEmulator {
|
||||
mSession.onColorsChanged();
|
||||
}
|
||||
specialIndex++;
|
||||
if (endOfInput || (specialIndex > TextStyle.COLOR_INDEX_CURSOR) || ++charIndex >= textParameter.length()) break;
|
||||
if (endOfInput || (specialIndex > TextStyle.COLOR_INDEX_CURSOR) || ++charIndex >= textParameter.length())
|
||||
break;
|
||||
lastSemiIndex = charIndex;
|
||||
} catch (NumberFormatException e) {
|
||||
// Ignore.
|
||||
@@ -1882,7 +1884,7 @@ public final class TerminalEmulator {
|
||||
mSession.onColorsChanged();
|
||||
} else {
|
||||
int lastIndex = 0;
|
||||
for (int charIndex = 0;; charIndex++) {
|
||||
for (int charIndex = 0; ; charIndex++) {
|
||||
boolean endOfInput = charIndex == textParameter.length();
|
||||
if (endOfInput || textParameter.charAt(charIndex) == ';') {
|
||||
try {
|
||||
@@ -2075,8 +2077,7 @@ public final class TerminalEmulator {
|
||||
/**
|
||||
* Send a Unicode code point to the screen.
|
||||
*
|
||||
* @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) {
|
||||
if (mUseLineDrawingUsesG0 ? mUseLineDrawingG0 : mUseLineDrawingG1) {
|
||||
@@ -2207,13 +2208,15 @@ public final class TerminalEmulator {
|
||||
if (mInsertMode && displayWidth > 0) {
|
||||
// Move character to right one space.
|
||||
int destCol = mCursorCol + displayWidth;
|
||||
if (destCol < mRightMargin) mScreen.blockCopy(mCursorCol, mCursorRow, mRightMargin - destCol, 1, destCol, mCursorRow);
|
||||
if (destCol < mRightMargin)
|
||||
mScreen.blockCopy(mCursorCol, mCursorRow, mRightMargin - destCol, 1, destCol, mCursorRow);
|
||||
}
|
||||
|
||||
int offsetDueToCombiningChar = ((displayWidth <= 0 && mCursorCol > 0 && !mAboutToAutoWrap) ? 1 : 0);
|
||||
mScreen.setChar(mCursorCol - offsetDueToCombiningChar, mCursorRow, codePoint, getStyle());
|
||||
|
||||
if (autoWrap && displayWidth > 0) mAboutToAutoWrap = (mCursorCol == mRightMargin - displayWidth);
|
||||
if (autoWrap && displayWidth > 0)
|
||||
mAboutToAutoWrap = (mCursorCol == mRightMargin - displayWidth);
|
||||
|
||||
mCursorCol = Math.min(mCursorCol + displayWidth, mRightMargin - 1);
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* A row in a terminal, composed of a fixed number of cells.
|
||||
*
|
||||
* <p/>
|
||||
* The text in the row is stored in a char[] array, {@link #mText}, for quick access during rendering.
|
||||
*/
|
||||
public final class TerminalRow {
|
||||
@@ -99,7 +99,7 @@ public final class TerminalRow {
|
||||
}
|
||||
|
||||
private boolean wideDisplayCharacterStartingAt(int column) {
|
||||
for (int currentCharIndex = 0, currentColumn = 0; currentCharIndex < mSpaceUsed;) {
|
||||
for (int currentCharIndex = 0, currentColumn = 0; currentCharIndex < mSpaceUsed; ) {
|
||||
char c = mText[currentCharIndex++];
|
||||
int codePoint = Character.isHighSurrogate(c) ? Character.toCodePoint(c, mText[currentCharIndex++]) : c;
|
||||
int wcwidth = WcWidth.width(codePoint);
|
||||
|
@@ -19,13 +19,13 @@ import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A terminal session, consisting of a process coupled to a terminal interface.
|
||||
* <p>
|
||||
* <p/>
|
||||
* The subprocess will be executed by the constructor, and when the size is made known by a call to
|
||||
* {@link #updateSize(int, int)} terminal emulation will begin and threads will be spawned to handle the subprocess I/O.
|
||||
* All terminal emulation and callback methods will be performed on the main thread.
|
||||
* <p>
|
||||
* <p/>
|
||||
* The child process may be exited forcefully by using the {@link #finishIfRunning()} method.
|
||||
*
|
||||
* <p/>
|
||||
* NOTE: The terminal session may outlive the EmulatorView, so be careful with callbacks!
|
||||
*/
|
||||
public final class TerminalSession extends TerminalOutput {
|
||||
@@ -169,10 +169,8 @@ public final class TerminalSession extends TerminalOutput {
|
||||
/**
|
||||
* Set the terminal emulator's window size and start terminal emulation.
|
||||
*
|
||||
* @param columns
|
||||
* The number of columns in the terminal window.
|
||||
* @param rows
|
||||
* The number of rows in the terminal window.
|
||||
* @param columns The number of columns in the terminal window.
|
||||
* @param rows The number of rows in the terminal window.
|
||||
*/
|
||||
public void initializeEmulator(int columns, int rows) {
|
||||
mEmulator = new TerminalEmulator(this, columns, rows, /* transcript= */5000);
|
||||
@@ -337,6 +335,8 @@ public final class TerminalSession extends TerminalOutput {
|
||||
mChangeCallback.onColorsChanged(this);
|
||||
}
|
||||
|
||||
public int getPid() { return mShellPid; }
|
||||
public int getPid() {
|
||||
return mShellPid;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ package com.termux.terminal;
|
||||
/**
|
||||
* Encodes effects, foreground and background colors into a 32 bit integer, which are stored for each cell in a terminal
|
||||
* row in {@link TerminalRow#mStyle}.
|
||||
*
|
||||
* <p/>
|
||||
* The foreground and background colors take 9 bits each, leaving (32-9-9)=14 bits for effect flags. Using 9 for now
|
||||
* (the different CHARACTER_ATTRIBUTE_* bits).
|
||||
*/
|
||||
@@ -18,7 +18,7 @@ public final class TextStyle {
|
||||
public final static int CHARACTER_ATTRIBUTE_STRIKETHROUGH = 1 << 6;
|
||||
/**
|
||||
* The selective erase control functions (DECSED and DECSEL) can only erase characters defined as erasable.
|
||||
*
|
||||
* <p/>
|
||||
* This bit is set if DECSCA (Select Character Protection Attribute) has been used to define the characters that
|
||||
* come after it as erasable from the screen.
|
||||
*/
|
||||
|
@@ -2,12 +2,12 @@ package com.termux.terminal;
|
||||
|
||||
/**
|
||||
* wcwidth() implementation from http://git.musl-libc.org/cgit/musl/tree/src/ctype
|
||||
*
|
||||
* <p/>
|
||||
* Modified to return 0 instead of -1.
|
||||
*/
|
||||
public final class WcWidth {
|
||||
|
||||
private static final short table[] = { 16, 16, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 16, 32, 16, 16, 16, 33, 34, 35, 36, 37, 38,
|
||||
private static final short table[] = {16, 16, 16, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 16, 32, 16, 16, 16, 33, 34, 35, 36, 37, 38,
|
||||
39, 16, 16, 40, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 41, 42, 16, 16, 43, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
@@ -52,9 +52,9 @@ public final class WcWidth {
|
||||
0, 0, 0, 0, 120, 38, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 128, 239, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 192, 127, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 191, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 128, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 3, 248, 255, 231, 15, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
|
||||
|
||||
private static final short wtable[] = { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
private static final short wtable[] = {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 18, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
|
||||
16, 16, 16, 16, 16, 16, 19, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 21, 22, 23, 24, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 25, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
@@ -83,7 +83,7 @@ public final class WcWidth {
|
||||
255, 255, 255, 255, 255, 15, 0, 0, 255, 3, 0, 0, 255, 255, 255, 255, 247, 255, 127, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 255, 255, 255, 255, 255, 7, 255, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
|
||||
/** Return the terminal display width of a code point: 0, 1 or 2. */
|
||||
public static int width(int wc) {
|
||||
|
@@ -9,7 +9,7 @@ import com.termux.terminal.TerminalSession;
|
||||
/**
|
||||
* Input and scale listener which may be set on a {@link TerminalView} through
|
||||
* {@link TerminalView#setOnKeyListener(TerminalKeyListener)}.
|
||||
*
|
||||
* <p/>
|
||||
* TODO: Rename to TerminalViewClient.
|
||||
*/
|
||||
public interface TerminalKeyListener {
|
||||
|
@@ -13,7 +13,7 @@ import com.termux.terminal.WcWidth;
|
||||
|
||||
/**
|
||||
* Renderer of a {@link TerminalEmulator} into a {@link Canvas}.
|
||||
*
|
||||
* <p/>
|
||||
* Saves font metrics, so needs to be recreated each time the typeface or font size changes.
|
||||
*/
|
||||
final class TerminalRenderer {
|
||||
@@ -64,7 +64,8 @@ final class TerminalRenderer {
|
||||
final TerminalBuffer screen = mEmulator.getScreen();
|
||||
final int[] palette = mEmulator.mColors.mCurrentColors;
|
||||
|
||||
if (reverseVideo) canvas.drawColor(palette[TextStyle.COLOR_INDEX_FOREGROUND], PorterDuff.Mode.SRC);
|
||||
if (reverseVideo)
|
||||
canvas.drawColor(palette[TextStyle.COLOR_INDEX_FOREGROUND], PorterDuff.Mode.SRC);
|
||||
|
||||
float heightOffset = mFontLineSpacingAndAscent;
|
||||
for (int row = topRow; row < endRow; row++) {
|
||||
@@ -89,7 +90,7 @@ final class TerminalRenderer {
|
||||
int currentCharIndex = 0;
|
||||
float measuredWidthForRun = 0.f;
|
||||
|
||||
for (int column = 0; column < columns;) {
|
||||
for (int column = 0; column < columns; ) {
|
||||
final char charAtIndex = line[currentCharIndex];
|
||||
final boolean charIsHighsurrogate = Character.isHighSurrogate(charAtIndex);
|
||||
final int charsForCodePoint = charIsHighsurrogate ? 2 : 1;
|
||||
@@ -140,28 +141,17 @@ final class TerminalRenderer {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param canvas
|
||||
* the canvas to render on
|
||||
* @param palette
|
||||
* the color palette to look up colors from textStyle
|
||||
* @param y
|
||||
* height offset into the canvas where to render the line: line * {@link #mFontLineSpacing}
|
||||
* @param startColumn
|
||||
* the run offset in columns
|
||||
* @param runWidthColumns
|
||||
* the run width in columns - this is computed from wcwidth() and may not be what the font measures to
|
||||
* @param text
|
||||
* the java char array to render text from
|
||||
* @param startCharIndex
|
||||
* index into the text array where to start
|
||||
* @param runWidthChars
|
||||
* number of java characters from the text array to render
|
||||
* @param cursor
|
||||
* true if rendering a cursor or selection
|
||||
* @param textStyle
|
||||
* the background, foreground and effect encoded using {@link TextStyle}
|
||||
* @param reverseVideo
|
||||
* if the screen is rendered with the global reverse video flag set
|
||||
* @param canvas the canvas to render on
|
||||
* @param palette the color palette to look up colors from textStyle
|
||||
* @param y height offset into the canvas where to render the line: line * {@link #mFontLineSpacing}
|
||||
* @param startColumn the run offset in columns
|
||||
* @param runWidthColumns the run width in columns - this is computed from wcwidth() and may not be what the font measures to
|
||||
* @param text the java char array to render text from
|
||||
* @param startCharIndex index into the text array where to start
|
||||
* @param runWidthChars number of java characters from the text array to render
|
||||
* @param cursor true if rendering a cursor or selection
|
||||
* @param textStyle the background, foreground and effect encoded using {@link TextStyle}
|
||||
* @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,
|
||||
float mes, boolean cursor, int textStyle, boolean reverseVideo) {
|
||||
|
@@ -96,7 +96,10 @@ public final class TerminalView extends View {
|
||||
@Override
|
||||
public boolean onSingleTapUp(MotionEvent e) {
|
||||
if (mEmulator == null) return true;
|
||||
if (mIsSelectingText) { toggleSelectingText(null); return true; }
|
||||
if (mIsSelectingText) {
|
||||
toggleSelectingText(null);
|
||||
return true;
|
||||
}
|
||||
requestFocus();
|
||||
if (!mEmulator.isMouseTrackingActive()) {
|
||||
if (!e.isFromSource(InputDevice.SOURCE_MOUSE)) {
|
||||
@@ -192,8 +195,7 @@ public final class TerminalView extends View {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onKeyListener
|
||||
* Listener for all kinds of key events, both hardware and IME (which makes it different from that
|
||||
* @param onKeyListener Listener for all kinds of key events, both hardware and IME (which makes it different from that
|
||||
* available with {@link View#setOnKeyListener(OnKeyListener)}.
|
||||
*/
|
||||
public void setOnKeyListener(TerminalKeyListener onKeyListener) {
|
||||
@@ -203,8 +205,7 @@ public final class TerminalView extends View {
|
||||
/**
|
||||
* Attach a {@link TerminalSession} to this view.
|
||||
*
|
||||
* @param session
|
||||
* The {@link TerminalSession} this view will be displaying.
|
||||
* @param session The {@link TerminalSession} this view will be displaying.
|
||||
*/
|
||||
public boolean attachSession(TerminalSession session) {
|
||||
if (session == mTermSession) return false;
|
||||
@@ -258,7 +259,8 @@ public final class TerminalView extends View {
|
||||
|
||||
@Override
|
||||
public boolean commitText(CharSequence text, int newCursorPosition) {
|
||||
if (LOG_KEY_EVENTS) Log.i(EmulatorDebug.LOG_TAG, "IME: commitText(\"" + text + "\", " + newCursorPosition + ")");
|
||||
if (LOG_KEY_EVENTS)
|
||||
Log.i(EmulatorDebug.LOG_TAG, "IME: commitText(\"" + text + "\", " + newCursorPosition + ")");
|
||||
if (mEmulator == null) return true;
|
||||
final int textLengthInChars = text.length();
|
||||
for (int i = 0; i < textLengthInChars; i++) {
|
||||
@@ -280,11 +282,21 @@ public final class TerminalView extends View {
|
||||
// E.g. penti keyboard for ctrl input.
|
||||
ctrlHeld = true;
|
||||
switch (codePoint) {
|
||||
case 31: codePoint = '_'; break;
|
||||
case 30: codePoint = '^'; break;
|
||||
case 29: codePoint = ']'; break;
|
||||
case 28: codePoint = '\\'; break;
|
||||
default: codePoint += 96; break;
|
||||
case 31:
|
||||
codePoint = '_';
|
||||
break;
|
||||
case 30:
|
||||
codePoint = '^';
|
||||
break;
|
||||
case 29:
|
||||
codePoint = ']';
|
||||
break;
|
||||
case 28:
|
||||
codePoint = '\\';
|
||||
break;
|
||||
default:
|
||||
codePoint += 96;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,7 +308,8 @@ public final class TerminalView extends View {
|
||||
|
||||
@Override
|
||||
public boolean deleteSurroundingText(int leftLength, int rightLength) {
|
||||
if (LOG_KEY_EVENTS) Log.i(EmulatorDebug.LOG_TAG, "IME: deleteSurroundingText(" + leftLength + ", " + rightLength + ")");
|
||||
if (LOG_KEY_EVENTS)
|
||||
Log.i(EmulatorDebug.LOG_TAG, "IME: deleteSurroundingText(" + leftLength + ", " + rightLength + ")");
|
||||
|
||||
// Swype keyboard sometimes(?) sends this on backspace:
|
||||
if (leftLength == 0 && rightLength == 0) leftLength = 1;
|
||||
@@ -374,8 +387,7 @@ public final class TerminalView extends View {
|
||||
/**
|
||||
* Sets the text size, which in turn sets the number of rows and columns.
|
||||
*
|
||||
* @param textSize
|
||||
* the new font size, in density-independent pixels.
|
||||
* @param textSize the new font size, in density-independent pixels.
|
||||
*/
|
||||
public void setTextSize(int textSize) {
|
||||
mRenderer = new TerminalRenderer(textSize, mRenderer == null ? Typeface.MONOSPACE : mRenderer.mTypeface);
|
||||
@@ -461,8 +473,8 @@ public final class TerminalView extends View {
|
||||
mInitialTextSelection = false;
|
||||
break;
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
int distanceFromSel1 = Math.abs(cx-mSelX1) + Math.abs(cy-mSelY1);
|
||||
int distanceFromSel2 = Math.abs(cx-mSelX2) + Math.abs(cy-mSelY2);
|
||||
int distanceFromSel1 = Math.abs(cx - mSelX1) + Math.abs(cy - mSelY1);
|
||||
int distanceFromSel2 = Math.abs(cx - mSelX2) + Math.abs(cy - mSelY2);
|
||||
mIsDraggingLeftSelection = distanceFromSel1 <= distanceFromSel2;
|
||||
mSelectionDownX = ev.getX();
|
||||
mSelectionDownY = ev.getY();
|
||||
@@ -490,11 +502,14 @@ public final class TerminalView extends View {
|
||||
// Switch handles.
|
||||
mIsDraggingLeftSelection = !mIsDraggingLeftSelection;
|
||||
int tmpX1 = mSelX1, tmpY1 = mSelY1;
|
||||
mSelX1 = mSelX2; mSelY1 = mSelY2;
|
||||
mSelX2 = tmpX1; mSelY2 = tmpY1;
|
||||
mSelX1 = mSelX2;
|
||||
mSelY1 = mSelY2;
|
||||
mSelX2 = tmpX1;
|
||||
mSelY2 = tmpY1;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) mActionMode.invalidateContentRect();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
|
||||
mActionMode.invalidateContentRect();
|
||||
invalidate();
|
||||
break;
|
||||
default:
|
||||
@@ -533,7 +548,8 @@ public final class TerminalView extends View {
|
||||
|
||||
@Override
|
||||
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
|
||||
if (LOG_KEY_EVENTS) Log.i(EmulatorDebug.LOG_TAG, "onKeyPreIme(keyCode=" + keyCode + ", event=" + event + ")");
|
||||
if (LOG_KEY_EVENTS)
|
||||
Log.i(EmulatorDebug.LOG_TAG, "onKeyPreIme(keyCode=" + keyCode + ", event=" + event + ")");
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
if (mIsSelectingText) {
|
||||
toggleSelectingText(null);
|
||||
@@ -553,7 +569,8 @@ public final class TerminalView extends View {
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (LOG_KEY_EVENTS) Log.i(EmulatorDebug.LOG_TAG, "onKeyDown(keyCode=" + keyCode + ", isSystem()=" + event.isSystem() + ", event=" + event + ")");
|
||||
if (LOG_KEY_EVENTS)
|
||||
Log.i(EmulatorDebug.LOG_TAG, "onKeyDown(keyCode=" + keyCode + ", isSystem()=" + event.isSystem() + ", event=" + event + ")");
|
||||
if (mEmulator == null) return true;
|
||||
|
||||
if (mOnKeyListener.onKeyDown(keyCode, event, mTermSession)) {
|
||||
@@ -591,7 +608,8 @@ public final class TerminalView extends View {
|
||||
int effectiveMetaState = event.getMetaState() & ~bitsToClear;
|
||||
|
||||
int result = event.getUnicodeChar(effectiveMetaState);
|
||||
if (LOG_KEY_EVENTS) Log.i(EmulatorDebug.LOG_TAG, "KeyEvent#getUnicodeChar(" + effectiveMetaState + ") returned: " + result);
|
||||
if (LOG_KEY_EVENTS)
|
||||
Log.i(EmulatorDebug.LOG_TAG, "KeyEvent#getUnicodeChar(" + effectiveMetaState + ") returned: " + result);
|
||||
if (result == 0) {
|
||||
return true;
|
||||
}
|
||||
@@ -599,7 +617,8 @@ public final class TerminalView extends View {
|
||||
int oldCombiningAccent = mCombiningAccent;
|
||||
if ((result & KeyCharacterMap.COMBINING_ACCENT) != 0) {
|
||||
// If entered combining accent previously, write it out:
|
||||
if (mCombiningAccent != 0) inputCodePoint(mCombiningAccent, controlDownFromEvent, leftAltDownFromEvent);
|
||||
if (mCombiningAccent != 0)
|
||||
inputCodePoint(mCombiningAccent, controlDownFromEvent, leftAltDownFromEvent);
|
||||
mCombiningAccent = result & KeyCharacterMap.COMBINING_ACCENT_MASK;
|
||||
} else {
|
||||
if (mCombiningAccent != 0) {
|
||||
@@ -681,15 +700,14 @@ public final class TerminalView extends View {
|
||||
/**
|
||||
* Called when a key is released in the view.
|
||||
*
|
||||
* @param keyCode
|
||||
* The keycode of the key which was released.
|
||||
* @param event
|
||||
* A {@link KeyEvent} describing the event.
|
||||
* @param keyCode The keycode of the key which was released.
|
||||
* @param event A {@link KeyEvent} describing the event.
|
||||
* @return Whether the event was handled.
|
||||
*/
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
if (LOG_KEY_EVENTS) Log.i(EmulatorDebug.LOG_TAG, "onKeyUp(keyCode=" + keyCode + ", event=" + event + ")");
|
||||
if (LOG_KEY_EVENTS)
|
||||
Log.i(EmulatorDebug.LOG_TAG, "onKeyUp(keyCode=" + keyCode + ", event=" + event + ")");
|
||||
if (mEmulator == null) return true;
|
||||
|
||||
if (mOnKeyListener.onKeyUp(keyCode, event)) {
|
||||
@@ -744,12 +762,12 @@ public final class TerminalView extends View {
|
||||
final int gripHandleMargin = gripHandleWidth / 4; // See the png.
|
||||
|
||||
int right = Math.round((mSelX1) * mRenderer.mFontWidth) + gripHandleMargin;
|
||||
int top = (mSelY1+1 - mTopRow)*mRenderer.mFontLineSpacing + mRenderer.mFontLineSpacingAndAscent;
|
||||
int top = (mSelY1 + 1 - mTopRow) * mRenderer.mFontLineSpacing + mRenderer.mFontLineSpacingAndAscent;
|
||||
mLeftSelectionHandle.setBounds(right - gripHandleWidth, top, right, top + mLeftSelectionHandle.getIntrinsicHeight());
|
||||
mLeftSelectionHandle.draw(canvas);
|
||||
|
||||
int left = Math.round((mSelX2+1)*mRenderer.mFontWidth) - gripHandleMargin;
|
||||
top = (mSelY2+1 - mTopRow) *mRenderer.mFontLineSpacing + mRenderer.mFontLineSpacingAndAscent;
|
||||
int left = Math.round((mSelX2 + 1) * mRenderer.mFontWidth) - gripHandleMargin;
|
||||
top = (mSelY2 + 1 - mTopRow) * mRenderer.mFontLineSpacing + mRenderer.mFontLineSpacingAndAscent;
|
||||
mRightSelectionHandle.setBounds(left, top, left + gripHandleWidth, top + mRightSelectionHandle.getIntrinsicHeight());
|
||||
mRightSelectionHandle.draw(canvas);
|
||||
}
|
||||
@@ -780,10 +798,10 @@ public final class TerminalView extends View {
|
||||
TerminalBuffer screen = mEmulator.getScreen();
|
||||
if (!" ".equals(screen.getSelectedText(mSelX1, mSelY1, mSelX1, mSelY1))) {
|
||||
// Selecting something other than whitespace. Expand to word.
|
||||
while (mSelX1 > 0 && !"".equals(screen.getSelectedText(mSelX1-1, mSelY1, mSelX1-1, mSelY1))) {
|
||||
while (mSelX1 > 0 && !"".equals(screen.getSelectedText(mSelX1 - 1, mSelY1, mSelX1 - 1, mSelY1))) {
|
||||
mSelX1--;
|
||||
}
|
||||
while (mSelX2 < mEmulator.mColumns-1 && !"".equals(screen.getSelectedText(mSelX2+1, mSelY1, mSelX2+1, mSelY1))) {
|
||||
while (mSelX2 < mEmulator.mColumns - 1 && !"".equals(screen.getSelectedText(mSelX2 + 1, mSelY1, mSelX2 + 1, mSelY1))) {
|
||||
mSelX2++;
|
||||
}
|
||||
}
|
||||
@@ -796,7 +814,7 @@ public final class TerminalView extends View {
|
||||
final ActionMode.Callback callback = new ActionMode.Callback() {
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
final int[] ACTION_MODE_ATTRS = { android.R.attr.actionModeCopyDrawable, android.R.attr.actionModePasteDrawable, };
|
||||
final int[] ACTION_MODE_ATTRS = {android.R.attr.actionModeCopyDrawable, android.R.attr.actionModePasteDrawable,};
|
||||
TypedArray styledAttributes = getContext().obtainStyledAttributes(ACTION_MODE_ATTRS);
|
||||
try {
|
||||
int show = MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT;
|
||||
|
Reference in New Issue
Block a user