mirror of
https://github.com/fankes/termux-app.git
synced 2025-09-07 03:05:18 +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>
|
@@ -31,14 +31,29 @@ public final class ExtraKeysView extends GridLayout {
|
|||||||
int keyCode = 0;
|
int keyCode = 0;
|
||||||
String chars = null;
|
String chars = null;
|
||||||
switch (keyName) {
|
switch (keyName) {
|
||||||
case "ESC": keyCode = KeyEvent.KEYCODE_ESCAPE; break;
|
case "ESC":
|
||||||
case "TAB": keyCode = KeyEvent.KEYCODE_TAB; break;
|
keyCode = KeyEvent.KEYCODE_ESCAPE;
|
||||||
case "▲": keyCode = KeyEvent.KEYCODE_DPAD_UP; break;
|
break;
|
||||||
case "◀": keyCode = KeyEvent.KEYCODE_DPAD_LEFT; break;
|
case "TAB":
|
||||||
case "▶": keyCode = KeyEvent.KEYCODE_DPAD_RIGHT; break;
|
keyCode = KeyEvent.KEYCODE_TAB;
|
||||||
case "▼": keyCode = KeyEvent.KEYCODE_DPAD_DOWN; break;
|
break;
|
||||||
case "―": chars = "-"; break;
|
case "▲":
|
||||||
default: chars = keyName;
|
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) {
|
if (keyCode > 0) {
|
||||||
|
@@ -79,7 +79,7 @@ import java.util.regex.Pattern;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A terminal emulator activity.
|
* A terminal emulator activity.
|
||||||
*
|
* <p/>
|
||||||
* See
|
* See
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>http://www.mongrel-phones.com.au/default/how_to_make_a_local_service_and_bind_to_it_in_android</li>
|
* <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";
|
private static final String RELOAD_STYLE_ACTION = "com.termux.app.reload_style";
|
||||||
|
|
||||||
/** The main view of the activity showing the terminal. Initialized in onCreate(). */
|
/** The main view of the activity showing the terminal. Initialized in onCreate(). */
|
||||||
@SuppressWarnings("NullableProblems") @NonNull TerminalView mTerminalView;
|
@SuppressWarnings("NullableProblems")
|
||||||
|
@NonNull
|
||||||
|
TerminalView mTerminalView;
|
||||||
|
|
||||||
ExtraKeysView mExtraKeysView;
|
ExtraKeysView mExtraKeysView;
|
||||||
|
|
||||||
@@ -143,7 +145,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
if (mIsVisible) {
|
if (mIsVisible) {
|
||||||
String whatToReload = intent.getStringExtra(RELOAD_STYLE_ACTION);
|
String whatToReload = intent.getStringExtra(RELOAD_STYLE_ACTION);
|
||||||
if ("storage".equals(whatToReload)) {
|
if ("storage".equals(whatToReload)) {
|
||||||
if (ensureStoragePermissionGranted()) TermuxInstaller.setupStorageSymlinks(TermuxActivity.this);
|
if (ensureStoragePermissionGranted())
|
||||||
|
TermuxInstaller.setupStorageSymlinks(TermuxActivity.this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
checkForFontAndColors();
|
checkForFontAndColors();
|
||||||
@@ -320,7 +323,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
Intent serviceIntent = new Intent(this, TermuxService.class);
|
Intent serviceIntent = new Intent(this, TermuxService.class);
|
||||||
// Start the service and make it run regardless of who is bound to it:
|
// Start the service and make it run regardless of who is bound to it:
|
||||||
startService(serviceIntent);
|
startService(serviceIntent);
|
||||||
if (!bindService(serviceIntent, this, 0)) throw new RuntimeException("bindService() failed");
|
if (!bindService(serviceIntent, this, 0))
|
||||||
|
throw new RuntimeException("bindService() failed");
|
||||||
|
|
||||||
checkForFontAndColors();
|
checkForFontAndColors();
|
||||||
|
|
||||||
@@ -376,7 +380,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
// Show toast for non-current sessions that exit.
|
// Show toast for non-current sessions that exit.
|
||||||
int indexOfSession = mTermService.getSessions().indexOf(finishedSession);
|
int indexOfSession = mTermService.getSessions().indexOf(finishedSession);
|
||||||
// Verify that session was not removed before we got told about it finishing:
|
// 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();
|
mListViewAdapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
@@ -535,7 +540,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable TerminalSession getCurrentTermSession() {
|
@Nullable
|
||||||
|
TerminalSession getCurrentTermSession() {
|
||||||
return mTerminalView.getCurrentSession();
|
return mTerminalView.getCurrentSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -819,7 +825,8 @@ public final class TermuxActivity extends Activity implements ServiceConnection
|
|||||||
ClipData clipData = clipboard.getPrimaryClip();
|
ClipData clipData = clipboard.getPrimaryClip();
|
||||||
if (clipData == null) return;
|
if (clipData == null) return;
|
||||||
CharSequence paste = clipData.getItemAt(0).coerceToText(this);
|
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. */
|
/** 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:
|
* 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
|
* (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.
|
* broken $PREFIX folder below.
|
||||||
*
|
* <p/>
|
||||||
* (2) A progress dialog is shown with "Installing..." message and a spinner.
|
* (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.
|
* (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()}.
|
* (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
|
* (5) The zip, containing entries relative to the $PREFIX, is is downloaded and extracted by a zip input stream
|
||||||
* continously encountering zip file entries:
|
* 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.
|
* (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.
|
* (5.2) For every other zip entry, extract it into $STAGING_PREFIX and set execute permissions if necessary.
|
||||||
*/
|
*/
|
||||||
final class TermuxInstaller {
|
final class TermuxInstaller {
|
||||||
@@ -97,7 +97,8 @@ final class TermuxInstaller {
|
|||||||
String line;
|
String line;
|
||||||
while ((line = symlinksReader.readLine()) != null) {
|
while ((line = symlinksReader.readLine()) != null) {
|
||||||
String[] parts = line.split("←");
|
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 oldPath = parts[0];
|
||||||
String newPath = STAGING_PREFIX_PATH + "/" + parts[1];
|
String newPath = STAGING_PREFIX_PATH + "/" + parts[1];
|
||||||
symlinks.add(Pair.create(oldPath, newPath));
|
symlinks.add(Pair.create(oldPath, newPath));
|
||||||
@@ -106,7 +107,8 @@ final class TermuxInstaller {
|
|||||||
String zipEntryName = zipEntry.getName();
|
String zipEntryName = zipEntry.getName();
|
||||||
File targetFile = new File(STAGING_PREFIX_PATH, zipEntryName);
|
File targetFile = new File(STAGING_PREFIX_PATH, zipEntryName);
|
||||||
if (zipEntry.isDirectory()) {
|
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 {
|
} else {
|
||||||
try (FileOutputStream outStream = new FileOutputStream(targetFile)) {
|
try (FileOutputStream outStream = new FileOutputStream(targetFile)) {
|
||||||
int readBytes;
|
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) {
|
for (Pair<String, String> symlink : symlinks) {
|
||||||
Os.symlink(symlink.first, symlink.second);
|
Os.symlink(symlink.first, symlink.second);
|
||||||
}
|
}
|
||||||
|
@@ -111,7 +111,8 @@ public final class TermuxKeyListener implements TerminalKeyListener {
|
|||||||
mActivity.changeFontSize(false);
|
mActivity.changeFontSize(false);
|
||||||
} else if (unicodeChar >= '1' && unicodeChar <= '9') {
|
} else if (unicodeChar >= '1' && unicodeChar <= '9') {
|
||||||
int num = unicodeChar - '1';
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,8 @@ final class TermuxPreferences {
|
|||||||
|
|
||||||
@IntDef({BELL_VIBRATE, BELL_BEEP, BELL_IGNORE})
|
@IntDef({BELL_VIBRATE, BELL_BEEP, BELL_IGNORE})
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
public @interface AsciiBellBehaviour {}
|
public @interface AsciiBellBehaviour {
|
||||||
|
}
|
||||||
|
|
||||||
static final int BELL_VIBRATE = 1;
|
static final int BELL_VIBRATE = 1;
|
||||||
static final int BELL_BEEP = 2;
|
static final int BELL_BEEP = 2;
|
||||||
@@ -127,7 +128,8 @@ final class TermuxPreferences {
|
|||||||
public void reloadFromProperties(Context context) {
|
public void reloadFromProperties(Context context) {
|
||||||
try {
|
try {
|
||||||
File propsFile = new File(TermuxService.HOME_PATH + "/.termux/termux.properties");
|
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();
|
Properties props = new Properties();
|
||||||
if (propsFile.isFile() && propsFile.canRead()) {
|
if (propsFile.isFile() && propsFile.canRead()) {
|
||||||
|
@@ -1,15 +1,5 @@
|
|||||||
package com.termux.app;
|
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.annotation.SuppressLint;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
@@ -26,15 +16,25 @@ import android.os.PowerManager;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.ArrayAdapter;
|
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
|
* 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
|
* 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
|
* 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.
|
* 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
|
* 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)}.
|
* 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
|
* Optionally may hold a wake and a wifi lock, in which case that is shown in the notification - see
|
||||||
* {@link #buildNotification()}.
|
* {@link #buildNotification()}.
|
||||||
*/
|
*/
|
||||||
@@ -70,7 +70,7 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The terminal sessions which this service manages.
|
* 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
|
* 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()} }.
|
* thread and followed by a call to {@link ArrayAdapter#notifyDataSetChanged()} }.
|
||||||
*/
|
*/
|
||||||
@@ -334,7 +334,8 @@ public final class TermuxService extends Service implements SessionChangedCallba
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSessionFinished(final TerminalSession finishedSession) {
|
public void onSessionFinished(final TerminalSession finishedSession) {
|
||||||
if (mSessionChangeCallback != null) mSessionChangeCallback.onSessionFinished(finishedSession);
|
if (mSessionChangeCallback != null)
|
||||||
|
mSessionChangeCallback.onSessionFinished(finishedSession);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -23,9 +23,9 @@ import java.util.LinkedList;
|
|||||||
/**
|
/**
|
||||||
* A document provider for the Storage Access Framework which exposes the files in the
|
* A document provider for the Storage Access Framework which exposes the files in the
|
||||||
* $HOME/ folder to other apps.
|
* $HOME/ folder to other apps.
|
||||||
* <p>
|
* <p/>
|
||||||
* Note that this replaces providing an activity matching the ACTION_GET_CONTENT intent:
|
* 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
|
* "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,
|
* 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."
|
* 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
|
* 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.
|
* applications may save the ID and use it to reference documents later.
|
||||||
* <p>
|
* <p/>
|
||||||
* The reverse of @{link #getFileForDocId}.
|
* The reverse of @{link #getFileForDocId}.
|
||||||
*/
|
*/
|
||||||
private static String getDocIdForFile(File file) {
|
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.
|
* 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.
|
* Returns whether the output was totally written, false if it was closed before.
|
||||||
*/
|
*/
|
||||||
public boolean write(byte[] buffer, int offset, int lengthToWrite) {
|
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
|
* Create a subprocess. Differs from {@link ProcessBuilder} in that a pseudoterminal is used to communicate with the
|
||||||
* subprocess.
|
* subprocess.
|
||||||
*
|
* <p/>
|
||||||
* Callers are responsible for calling {@link #close(int)} on the returned file descriptor.
|
* Callers are responsible for calling {@link #close(int)} on the returned file descriptor.
|
||||||
*
|
*
|
||||||
* @param cmd
|
* @param cmd The command to execute
|
||||||
* The command to execute
|
* @param cwd The current working directory for the executed command
|
||||||
* @param cwd
|
* @param args An array of arguments to the command
|
||||||
* The current working directory for the executed command
|
* @param envVars An array of strings of the form "VAR=value" to be added to the environment of the process
|
||||||
* @param args
|
* @param processId A one-element array to which the process ID of the started process will be written.
|
||||||
* 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
|
* @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.
|
* slave device counterpart (/dev/pts/$N) and have it as stdint, stdout and stderr.
|
||||||
*/
|
*/
|
||||||
|
@@ -1,5 +1,10 @@
|
|||||||
package com.termux.terminal;
|
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_BREAK;
|
||||||
import static android.view.KeyEvent.KEYCODE_DEL;
|
import static android.view.KeyEvent.KEYCODE_DEL;
|
||||||
import static android.view.KeyEvent.KEYCODE_DPAD_CENTER;
|
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_F8;
|
||||||
import static android.view.KeyEvent.KEYCODE_F9;
|
import static android.view.KeyEvent.KEYCODE_F9;
|
||||||
import static android.view.KeyEvent.KEYCODE_FORWARD_DEL;
|
import static android.view.KeyEvent.KEYCODE_FORWARD_DEL;
|
||||||
|
import static android.view.KeyEvent.KEYCODE_HOME;
|
||||||
import static android.view.KeyEvent.KEYCODE_INSERT;
|
import static android.view.KeyEvent.KEYCODE_INSERT;
|
||||||
import static android.view.KeyEvent.KEYCODE_MOVE_END;
|
import static android.view.KeyEvent.KEYCODE_MOVE_END;
|
||||||
import static android.view.KeyEvent.KEYCODE_NUMPAD_0;
|
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_PAGE_UP;
|
||||||
import static android.view.KeyEvent.KEYCODE_SYSRQ;
|
import static android.view.KeyEvent.KEYCODE_SYSRQ;
|
||||||
import static android.view.KeyEvent.KEYCODE_TAB;
|
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 {
|
public final class KeyHandler {
|
||||||
|
|
||||||
@@ -61,6 +61,7 @@ public final class KeyHandler {
|
|||||||
public static final int KEYMOD_SHIFT = 0x20000000;
|
public static final int KEYMOD_SHIFT = 0x20000000;
|
||||||
|
|
||||||
private static final Map<String, Integer> TERMCAP_TO_KEYCODE = new HashMap<>();
|
private static final Map<String, Integer> TERMCAP_TO_KEYCODE = new HashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// terminfo: http://pubs.opengroup.org/onlinepubs/7990989799/xcurses/terminfo.html
|
// terminfo: http://pubs.opengroup.org/onlinepubs/7990989799/xcurses/terminfo.html
|
||||||
// termcap: http://man7.org/linux/man-pages/man5/termcap.5.html
|
// termcap: http://man7.org/linux/man-pages/man5/termcap.5.html
|
||||||
|
@@ -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
|
* A circular buffer of {@link TerminalRow}:s which keeps notes about what is visible on a logical screen and the scroll
|
||||||
* history.
|
* history.
|
||||||
*
|
* <p/>
|
||||||
* See {@link #externalToInternalRow(int)} for how to map from logical screen rows to array indices.
|
* See {@link #externalToInternalRow(int)} for how to map from logical screen rows to array indices.
|
||||||
*/
|
*/
|
||||||
public final class TerminalBuffer {
|
public final class TerminalBuffer {
|
||||||
@@ -21,12 +21,9 @@ public final class TerminalBuffer {
|
|||||||
/**
|
/**
|
||||||
* Create a transcript screen.
|
* Create a transcript screen.
|
||||||
*
|
*
|
||||||
* @param columns
|
* @param columns the width of the screen in characters.
|
||||||
* the width of the screen in characters.
|
* @param totalRows the height of the entire text area, in rows of text.
|
||||||
* @param totalRows
|
* @param screenRows the height of just the screen, not including the transcript that holds lines that have scrolled off
|
||||||
* 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.
|
* the top of the screen.
|
||||||
*/
|
*/
|
||||||
public TerminalBuffer(int columns, int totalRows, int screenRows) {
|
public TerminalBuffer(int columns, int totalRows, int screenRows) {
|
||||||
@@ -78,7 +75,8 @@ public final class TerminalBuffer {
|
|||||||
if (c != ' ') lastPrintingCharIndex = i;
|
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');
|
if (!rowLineWrap && row < selY2 && row < mScreenRows - 1) builder.append('\n');
|
||||||
}
|
}
|
||||||
return builder.toString();
|
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.
|
* Convert a row value from the public external coordinate system to our internal private coordinate system.
|
||||||
*
|
* <p/>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>External coordinate system: -mActiveTranscriptRows to mScreenRows-1, with the screen being 0..mScreenRows-1.
|
* <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
|
* <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).
|
* mActiveTranscriptRows lines ending at mScreenFirstRow-1 form the transcript (as a circular buffer).
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
* <p/>
|
||||||
* External <---> Internal:
|
* External <---> Internal:
|
||||||
*
|
* <p/>
|
||||||
* <pre>
|
* <pre>
|
||||||
* [ ... ] [ ... ]
|
* [ ... ] [ ... ]
|
||||||
* [ -mActiveTranscriptRows ] [ mScreenFirstRow - mActiveTranscriptRows ]
|
* [ -mActiveTranscriptRows ] [ mScreenFirstRow - mActiveTranscriptRows ]
|
||||||
@@ -112,8 +110,7 @@ public final class TerminalBuffer {
|
|||||||
* [ mScreenRows-1 ] [ mScreenFirstRow + mScreenRows-1 ]
|
* [ mScreenRows-1 ] [ mScreenFirstRow + mScreenRows-1 ]
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param externalRow
|
* @param externalRow a row in the external coordinate system.
|
||||||
* a row in the external coordinate system.
|
|
||||||
* @return The row corresponding to the input argument in the private coordinate system.
|
* @return The row corresponding to the input argument in the private coordinate system.
|
||||||
*/
|
*/
|
||||||
public int externalToInternalRow(int externalRow) {
|
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
|
* 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).
|
* change or the rows expand (that is, it only works when shrinking the number of rows).
|
||||||
*
|
*
|
||||||
* @param newColumns
|
* @param newColumns The number of columns the screen should have.
|
||||||
* The number of columns the screen should have.
|
* @param newRows The number of rows the screen should have.
|
||||||
* @param newRows
|
* @param cursor An int[2] containing the (column, row) cursor location.
|
||||||
* 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) {
|
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):
|
// newRows > mTotalRows should not normally happen since mTotalRows is TRANSCRIPT_ROWS (10000):
|
||||||
@@ -238,7 +232,8 @@ public final class TerminalBuffer {
|
|||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < oldLine.getSpaceUsed(); i++)
|
for (int i = 0; i < oldLine.getSpaceUsed(); i++)
|
||||||
// NEWLY INTRODUCED BUG! Should not index oldLine.mStyle with char indices
|
// 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;
|
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
|
* Block copy lines and associated metadata from one location to another in the circular buffer, taking wraparound
|
||||||
* into account.
|
* into account.
|
||||||
*
|
*
|
||||||
* @param srcInternal
|
* @param srcInternal The first line to be copied.
|
||||||
* The first line to be copied.
|
* @param len The number of lines to be copied.
|
||||||
* @param len
|
|
||||||
* The number of lines to be copied.
|
|
||||||
*/
|
*/
|
||||||
private void blockCopyLinesDown(int srcInternal, int len) {
|
private void blockCopyLinesDown(int srcInternal, int len) {
|
||||||
if (len == 0) return;
|
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).
|
* Scroll the screen down one line. To scroll the whole screen of a 24 line screen, the arguments would be (0, 24).
|
||||||
*
|
*
|
||||||
* @param topMargin
|
* @param topMargin First line that is scrolled.
|
||||||
* First line that is scrolled.
|
* @param bottomMargin One line after the last line that is scrolled.
|
||||||
* @param bottomMargin
|
* @param style the style for the newly exposed line.
|
||||||
* 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) {
|
public void scrollDownOneLine(int topMargin, int bottomMargin, int style) {
|
||||||
if (topMargin > bottomMargin - 1 || topMargin < 0 || bottomMargin > mScreenRows)
|
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
|
* of the source and destination must be within the bounds of the screen, or else an InvalidParameterException will
|
||||||
* be thrown.
|
* be thrown.
|
||||||
*
|
*
|
||||||
* @param sx
|
* @param sx source X coordinate
|
||||||
* source X coordinate
|
* @param sy source Y coordinate
|
||||||
* @param sy
|
* @param w width
|
||||||
* source Y coordinate
|
* @param h height
|
||||||
* @param w
|
* @param dx destination X coordinate
|
||||||
* width
|
* @param dy destination Y coordinate
|
||||||
* @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) {
|
public void blockCopy(int sx, int sy, int w, int h, int dx, int dy) {
|
||||||
if (w == 0) return;
|
if (w == 0) return;
|
||||||
|
@@ -93,7 +93,8 @@ public final class TerminalColorScheme {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int colorValue = TerminalColors.parse(value);
|
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;
|
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
|
* 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.
|
* Highest bit is set if successful, so return value is 0xFF${R}${G}${B}. Return 0 if failed.
|
||||||
*/
|
*/
|
||||||
static int parse(String c) {
|
static int parse(String c) {
|
||||||
|
@@ -1,18 +1,18 @@
|
|||||||
package com.termux.terminal;
|
package com.termux.terminal;
|
||||||
|
|
||||||
|
import android.util.Base64;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Stack;
|
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
|
* Renders text into a screen. Contains all the terminal-specific knowledge and state. Emulates a subset of the X Window
|
||||||
* System xterm terminal, which in turn is an emulator for a subset of the Digital Equipment Corporation vt100 terminal.
|
* System xterm terminal, which in turn is an emulator for a subset of the Digital Equipment Corporation vt100 terminal.
|
||||||
*
|
* <p/>
|
||||||
* References:
|
* References:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>http://invisible-island.net/xterm/ctlseqs/ctlseqs.html</li>
|
* <li>http://invisible-island.net/xterm/ctlseqs/ctlseqs.html</li>
|
||||||
@@ -145,7 +145,7 @@ public final class TerminalEmulator {
|
|||||||
/**
|
/**
|
||||||
* The alternate screen buffer, exactly as large as the display and contains no additional saved lines (so that when
|
* The alternate screen buffer, exactly as large as the display and contains no additional saved lines (so that when
|
||||||
* the alternate screen buffer is active, you cannot scroll back to view saved lines).
|
* the alternate screen buffer is active, you cannot scroll back to view saved lines).
|
||||||
*
|
* <p/>
|
||||||
* See http://www.xfree86.org/current/ctlseqs.html#The%20Alternate%20Screen%20Buffer
|
* See http://www.xfree86.org/current/ctlseqs.html#The%20Alternate%20Screen%20Buffer
|
||||||
*/
|
*/
|
||||||
final TerminalBuffer mAltBuffer;
|
final TerminalBuffer mAltBuffer;
|
||||||
@@ -294,8 +294,7 @@ public final class TerminalEmulator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mouseButton
|
* @param mouseButton one of the MOUSE_* constants of this class.
|
||||||
* one of the MOUSE_* constants of this class.
|
|
||||||
*/
|
*/
|
||||||
public void sendMouseEvent(int mouseButton, int column, int row, boolean pressed) {
|
public void sendMouseEvent(int mouseButton, int column, int row, boolean pressed) {
|
||||||
if (mouseButton == MOUSE_LEFT_BUTTON_MOVED && !isDecsetInternalBitSet(DECSET_BIT_MOUSE_TRACKING_BUTTON_EVENT)) {
|
if (mouseButton == MOUSE_LEFT_BUTTON_MOVED && !isDecsetInternalBitSet(DECSET_BIT_MOUSE_TRACKING_BUTTON_EVENT)) {
|
||||||
@@ -390,10 +389,8 @@ public final class TerminalEmulator {
|
|||||||
/**
|
/**
|
||||||
* Accept bytes (typically from the pseudo-teletype) and process them.
|
* Accept bytes (typically from the pseudo-teletype) and process them.
|
||||||
*
|
*
|
||||||
* @param buffer
|
* @param buffer a byte array containing the bytes to be processed
|
||||||
* a byte array containing the bytes to be processed
|
* @param length the number of bytes in the array to process
|
||||||
* @param length
|
|
||||||
* the number of bytes in the array to process
|
|
||||||
*/
|
*/
|
||||||
public void append(byte[] buffer, int length) {
|
public void append(byte[] buffer, int length) {
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
@@ -897,7 +894,8 @@ public final class TerminalEmulator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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();
|
finishSequence();
|
||||||
}
|
}
|
||||||
@@ -1086,7 +1084,8 @@ public final class TerminalEmulator {
|
|||||||
// Check if buffer size needs to be updated:
|
// Check if buffer size needs to be updated:
|
||||||
if (resized) resizeScreen();
|
if (resized) resizeScreen();
|
||||||
// Clear new screen if alt buffer:
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1721,7 +1720,8 @@ public final class TerminalEmulator {
|
|||||||
mBackColor = color;
|
mBackColor = color;
|
||||||
}
|
}
|
||||||
} else {
|
} 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).
|
} else if (code >= 100 && code <= 107) { // Bright background color (aixterm codes).
|
||||||
mBackColor = code - 100 + 8;
|
mBackColor = code - 100 + 8;
|
||||||
} else {
|
} 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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1855,7 +1856,8 @@ public final class TerminalEmulator {
|
|||||||
mSession.onColorsChanged();
|
mSession.onColorsChanged();
|
||||||
}
|
}
|
||||||
specialIndex++;
|
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;
|
lastSemiIndex = charIndex;
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
// Ignore.
|
// Ignore.
|
||||||
@@ -2075,8 +2077,7 @@ public final class TerminalEmulator {
|
|||||||
/**
|
/**
|
||||||
* Send a Unicode code point to the screen.
|
* Send a Unicode code point to the screen.
|
||||||
*
|
*
|
||||||
* @param codePoint
|
* @param codePoint The code point of the character to display
|
||||||
* The code point of the character to display
|
|
||||||
*/
|
*/
|
||||||
private void emitCodePoint(int codePoint) {
|
private void emitCodePoint(int codePoint) {
|
||||||
if (mUseLineDrawingUsesG0 ? mUseLineDrawingG0 : mUseLineDrawingG1) {
|
if (mUseLineDrawingUsesG0 ? mUseLineDrawingG0 : mUseLineDrawingG1) {
|
||||||
@@ -2207,13 +2208,15 @@ public final class TerminalEmulator {
|
|||||||
if (mInsertMode && displayWidth > 0) {
|
if (mInsertMode && displayWidth > 0) {
|
||||||
// Move character to right one space.
|
// Move character to right one space.
|
||||||
int destCol = mCursorCol + displayWidth;
|
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);
|
int offsetDueToCombiningChar = ((displayWidth <= 0 && mCursorCol > 0 && !mAboutToAutoWrap) ? 1 : 0);
|
||||||
mScreen.setChar(mCursorCol - offsetDueToCombiningChar, mCursorRow, codePoint, getStyle());
|
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);
|
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.
|
* 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.
|
* The text in the row is stored in a char[] array, {@link #mText}, for quick access during rendering.
|
||||||
*/
|
*/
|
||||||
public final class TerminalRow {
|
public final class TerminalRow {
|
||||||
|
@@ -19,13 +19,13 @@ import java.util.UUID;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A terminal session, consisting of a process coupled to a terminal interface.
|
* 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
|
* 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.
|
* {@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.
|
* 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.
|
* 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!
|
* NOTE: The terminal session may outlive the EmulatorView, so be careful with callbacks!
|
||||||
*/
|
*/
|
||||||
public final class TerminalSession extends TerminalOutput {
|
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.
|
* Set the terminal emulator's window size and start terminal emulation.
|
||||||
*
|
*
|
||||||
* @param columns
|
* @param columns The number of columns in the terminal window.
|
||||||
* The number of columns in the terminal window.
|
* @param rows The number of rows in the terminal window.
|
||||||
* @param rows
|
|
||||||
* The number of rows in the terminal window.
|
|
||||||
*/
|
*/
|
||||||
public void initializeEmulator(int columns, int rows) {
|
public void initializeEmulator(int columns, int rows) {
|
||||||
mEmulator = new TerminalEmulator(this, columns, rows, /* transcript= */5000);
|
mEmulator = new TerminalEmulator(this, columns, rows, /* transcript= */5000);
|
||||||
@@ -337,6 +335,8 @@ public final class TerminalSession extends TerminalOutput {
|
|||||||
mChangeCallback.onColorsChanged(this);
|
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
|
* 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}.
|
* 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 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).
|
* (the different CHARACTER_ATTRIBUTE_* bits).
|
||||||
*/
|
*/
|
||||||
@@ -18,7 +18,7 @@ public final class TextStyle {
|
|||||||
public final static int CHARACTER_ATTRIBUTE_STRIKETHROUGH = 1 << 6;
|
public final static int CHARACTER_ATTRIBUTE_STRIKETHROUGH = 1 << 6;
|
||||||
/**
|
/**
|
||||||
* The selective erase control functions (DECSED and DECSEL) can only erase characters defined as erasable.
|
* 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
|
* 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.
|
* come after it as erasable from the screen.
|
||||||
*/
|
*/
|
||||||
|
@@ -2,7 +2,7 @@ package com.termux.terminal;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* wcwidth() implementation from http://git.musl-libc.org/cgit/musl/tree/src/ctype
|
* wcwidth() implementation from http://git.musl-libc.org/cgit/musl/tree/src/ctype
|
||||||
*
|
* <p/>
|
||||||
* Modified to return 0 instead of -1.
|
* Modified to return 0 instead of -1.
|
||||||
*/
|
*/
|
||||||
public final class WcWidth {
|
public final class WcWidth {
|
||||||
|
@@ -9,7 +9,7 @@ import com.termux.terminal.TerminalSession;
|
|||||||
/**
|
/**
|
||||||
* Input and scale listener which may be set on a {@link TerminalView} through
|
* Input and scale listener which may be set on a {@link TerminalView} through
|
||||||
* {@link TerminalView#setOnKeyListener(TerminalKeyListener)}.
|
* {@link TerminalView#setOnKeyListener(TerminalKeyListener)}.
|
||||||
*
|
* <p/>
|
||||||
* TODO: Rename to TerminalViewClient.
|
* TODO: Rename to TerminalViewClient.
|
||||||
*/
|
*/
|
||||||
public interface TerminalKeyListener {
|
public interface TerminalKeyListener {
|
||||||
|
@@ -13,7 +13,7 @@ import com.termux.terminal.WcWidth;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Renderer of a {@link TerminalEmulator} into a {@link Canvas}.
|
* 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.
|
* Saves font metrics, so needs to be recreated each time the typeface or font size changes.
|
||||||
*/
|
*/
|
||||||
final class TerminalRenderer {
|
final class TerminalRenderer {
|
||||||
@@ -64,7 +64,8 @@ final class TerminalRenderer {
|
|||||||
final TerminalBuffer screen = mEmulator.getScreen();
|
final TerminalBuffer screen = mEmulator.getScreen();
|
||||||
final int[] palette = mEmulator.mColors.mCurrentColors;
|
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;
|
float heightOffset = mFontLineSpacingAndAscent;
|
||||||
for (int row = topRow; row < endRow; row++) {
|
for (int row = topRow; row < endRow; row++) {
|
||||||
@@ -140,28 +141,17 @@ final class TerminalRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param canvas
|
* @param canvas the canvas to render on
|
||||||
* the canvas to render on
|
* @param palette the color palette to look up colors from textStyle
|
||||||
* @param palette
|
* @param y height offset into the canvas where to render the line: line * {@link #mFontLineSpacing}
|
||||||
* the color palette to look up colors from textStyle
|
* @param startColumn the run offset in columns
|
||||||
* @param y
|
* @param runWidthColumns the run width in columns - this is computed from wcwidth() and may not be what the font measures to
|
||||||
* height offset into the canvas where to render the line: line * {@link #mFontLineSpacing}
|
* @param text the java char array to render text from
|
||||||
* @param startColumn
|
* @param startCharIndex index into the text array where to start
|
||||||
* the run offset in columns
|
* @param runWidthChars number of java characters from the text array to render
|
||||||
* @param runWidthColumns
|
* @param cursor true if rendering a cursor or selection
|
||||||
* the run width in columns - this is computed from wcwidth() and may not be what the font measures to
|
* @param textStyle the background, foreground and effect encoded using {@link TextStyle}
|
||||||
* @param text
|
* @param reverseVideo if the screen is rendered with the global reverse video flag set
|
||||||
* 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,
|
private void drawTextRun(Canvas canvas, char[] text, int[] palette, float y, int startColumn, int runWidthColumns, int startCharIndex, int runWidthChars,
|
||||||
float mes, boolean cursor, int textStyle, boolean reverseVideo) {
|
float mes, boolean cursor, int textStyle, boolean reverseVideo) {
|
||||||
|
@@ -96,7 +96,10 @@ public final class TerminalView extends View {
|
|||||||
@Override
|
@Override
|
||||||
public boolean onSingleTapUp(MotionEvent e) {
|
public boolean onSingleTapUp(MotionEvent e) {
|
||||||
if (mEmulator == null) return true;
|
if (mEmulator == null) return true;
|
||||||
if (mIsSelectingText) { toggleSelectingText(null); return true; }
|
if (mIsSelectingText) {
|
||||||
|
toggleSelectingText(null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
requestFocus();
|
requestFocus();
|
||||||
if (!mEmulator.isMouseTrackingActive()) {
|
if (!mEmulator.isMouseTrackingActive()) {
|
||||||
if (!e.isFromSource(InputDevice.SOURCE_MOUSE)) {
|
if (!e.isFromSource(InputDevice.SOURCE_MOUSE)) {
|
||||||
@@ -192,8 +195,7 @@ public final class TerminalView extends View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param onKeyListener
|
* @param onKeyListener Listener for all kinds of key events, both hardware and IME (which makes it different from that
|
||||||
* Listener for all kinds of key events, both hardware and IME (which makes it different from that
|
|
||||||
* available with {@link View#setOnKeyListener(OnKeyListener)}.
|
* available with {@link View#setOnKeyListener(OnKeyListener)}.
|
||||||
*/
|
*/
|
||||||
public void setOnKeyListener(TerminalKeyListener onKeyListener) {
|
public void setOnKeyListener(TerminalKeyListener onKeyListener) {
|
||||||
@@ -203,8 +205,7 @@ public final class TerminalView extends View {
|
|||||||
/**
|
/**
|
||||||
* Attach a {@link TerminalSession} to this view.
|
* Attach a {@link TerminalSession} to this view.
|
||||||
*
|
*
|
||||||
* @param session
|
* @param session The {@link TerminalSession} this view will be displaying.
|
||||||
* The {@link TerminalSession} this view will be displaying.
|
|
||||||
*/
|
*/
|
||||||
public boolean attachSession(TerminalSession session) {
|
public boolean attachSession(TerminalSession session) {
|
||||||
if (session == mTermSession) return false;
|
if (session == mTermSession) return false;
|
||||||
@@ -258,7 +259,8 @@ public final class TerminalView extends View {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean commitText(CharSequence text, int newCursorPosition) {
|
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;
|
if (mEmulator == null) return true;
|
||||||
final int textLengthInChars = text.length();
|
final int textLengthInChars = text.length();
|
||||||
for (int i = 0; i < textLengthInChars; i++) {
|
for (int i = 0; i < textLengthInChars; i++) {
|
||||||
@@ -280,11 +282,21 @@ public final class TerminalView extends View {
|
|||||||
// E.g. penti keyboard for ctrl input.
|
// E.g. penti keyboard for ctrl input.
|
||||||
ctrlHeld = true;
|
ctrlHeld = true;
|
||||||
switch (codePoint) {
|
switch (codePoint) {
|
||||||
case 31: codePoint = '_'; break;
|
case 31:
|
||||||
case 30: codePoint = '^'; break;
|
codePoint = '_';
|
||||||
case 29: codePoint = ']'; break;
|
break;
|
||||||
case 28: codePoint = '\\'; break;
|
case 30:
|
||||||
default: codePoint += 96; break;
|
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
|
@Override
|
||||||
public boolean deleteSurroundingText(int leftLength, int rightLength) {
|
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:
|
// Swype keyboard sometimes(?) sends this on backspace:
|
||||||
if (leftLength == 0 && rightLength == 0) leftLength = 1;
|
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.
|
* Sets the text size, which in turn sets the number of rows and columns.
|
||||||
*
|
*
|
||||||
* @param textSize
|
* @param textSize the new font size, in density-independent pixels.
|
||||||
* the new font size, in density-independent pixels.
|
|
||||||
*/
|
*/
|
||||||
public void setTextSize(int textSize) {
|
public void setTextSize(int textSize) {
|
||||||
mRenderer = new TerminalRenderer(textSize, mRenderer == null ? Typeface.MONOSPACE : mRenderer.mTypeface);
|
mRenderer = new TerminalRenderer(textSize, mRenderer == null ? Typeface.MONOSPACE : mRenderer.mTypeface);
|
||||||
@@ -490,11 +502,14 @@ public final class TerminalView extends View {
|
|||||||
// Switch handles.
|
// Switch handles.
|
||||||
mIsDraggingLeftSelection = !mIsDraggingLeftSelection;
|
mIsDraggingLeftSelection = !mIsDraggingLeftSelection;
|
||||||
int tmpX1 = mSelX1, tmpY1 = mSelY1;
|
int tmpX1 = mSelX1, tmpY1 = mSelY1;
|
||||||
mSelX1 = mSelX2; mSelY1 = mSelY2;
|
mSelX1 = mSelX2;
|
||||||
mSelX2 = tmpX1; mSelY2 = tmpY1;
|
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();
|
invalidate();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -533,7 +548,8 @@ public final class TerminalView extends View {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
|
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 (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||||
if (mIsSelectingText) {
|
if (mIsSelectingText) {
|
||||||
toggleSelectingText(null);
|
toggleSelectingText(null);
|
||||||
@@ -553,7 +569,8 @@ public final class TerminalView extends View {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
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 (mEmulator == null) return true;
|
||||||
|
|
||||||
if (mOnKeyListener.onKeyDown(keyCode, event, mTermSession)) {
|
if (mOnKeyListener.onKeyDown(keyCode, event, mTermSession)) {
|
||||||
@@ -591,7 +608,8 @@ public final class TerminalView extends View {
|
|||||||
int effectiveMetaState = event.getMetaState() & ~bitsToClear;
|
int effectiveMetaState = event.getMetaState() & ~bitsToClear;
|
||||||
|
|
||||||
int result = event.getUnicodeChar(effectiveMetaState);
|
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) {
|
if (result == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -599,7 +617,8 @@ public final class TerminalView extends View {
|
|||||||
int oldCombiningAccent = mCombiningAccent;
|
int oldCombiningAccent = mCombiningAccent;
|
||||||
if ((result & KeyCharacterMap.COMBINING_ACCENT) != 0) {
|
if ((result & KeyCharacterMap.COMBINING_ACCENT) != 0) {
|
||||||
// If entered combining accent previously, write it out:
|
// 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;
|
mCombiningAccent = result & KeyCharacterMap.COMBINING_ACCENT_MASK;
|
||||||
} else {
|
} else {
|
||||||
if (mCombiningAccent != 0) {
|
if (mCombiningAccent != 0) {
|
||||||
@@ -681,15 +700,14 @@ public final class TerminalView extends View {
|
|||||||
/**
|
/**
|
||||||
* Called when a key is released in the view.
|
* Called when a key is released in the view.
|
||||||
*
|
*
|
||||||
* @param keyCode
|
* @param keyCode The keycode of the key which was released.
|
||||||
* The keycode of the key which was released.
|
* @param event A {@link KeyEvent} describing the event.
|
||||||
* @param event
|
|
||||||
* A {@link KeyEvent} describing the event.
|
|
||||||
* @return Whether the event was handled.
|
* @return Whether the event was handled.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
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 (mEmulator == null) return true;
|
||||||
|
|
||||||
if (mOnKeyListener.onKeyUp(keyCode, event)) {
|
if (mOnKeyListener.onKeyUp(keyCode, event)) {
|
||||||
|
Reference in New Issue
Block a user