├── .gitattributes
├── .gitignore
├── LICENSE
├── MODULE_LICENSE_APACHE2
├── NOTICE
├── README.adoc
├── build.gradle
├── buildTools.gradle
├── docs
├── UTF-8-SMP-chars-demo.txt
├── UTF-8-demo.txt
├── atari_small_notice.txt
├── google-play-description
├── termoneplus-launcher-icon.xcf
├── termoneplus-launcher-round_icon.xcf
├── termoneplus-logo.xcf
└── termoneplus-notification-icon.svg
├── emulatorview
├── .gitignore
├── build.gradle
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ ├── com
│ │ └── termoneplus
│ │ │ ├── compat
│ │ │ └── CharacterCompat.java
│ │ │ └── utils
│ │ │ └── SimpleClipboardManager.java
│ └── jackpal
│ │ └── androidterm
│ │ └── emulatorview
│ │ ├── BaseTextRenderer.java
│ │ ├── Bitmap4x8FontRenderer.java
│ │ ├── ByteQueue.java
│ │ ├── ColorScheme.java
│ │ ├── EmulatorDebug.java
│ │ ├── EmulatorView.java
│ │ ├── GrowableIntArray.java
│ │ ├── PaintRenderer.java
│ │ ├── Screen.java
│ │ ├── StyleRow.java
│ │ ├── TermKeyListener.java
│ │ ├── TermSession.java
│ │ ├── TerminalEmulator.java
│ │ ├── TextRenderer.java
│ │ ├── TextStyle.java
│ │ ├── TranscriptScreen.java
│ │ ├── UnicodeTranscript.java
│ │ ├── UpdateCallback.java
│ │ ├── compat
│ │ ├── KeyCharacterMapCompat.java
│ │ ├── KeycodeConstants.java
│ │ └── Patterns.java
│ │ └── package.html
│ └── res
│ └── drawable-nodpi
│ └── atari_small_nodpi.png
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── libtermexec
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── CMakeLists.txt
│ └── main
│ ├── AndroidManifest.xml
│ ├── aidl
│ └── jackpal
│ │ └── androidterm
│ │ └── libtermexec
│ │ └── v1
│ │ └── ITerminal.aidl
│ ├── cpp
│ ├── compat.c
│ ├── compat.h
│ ├── process.c
│ ├── registration.c
│ ├── registration.h
│ └── termio.c
│ └── java
│ ├── com
│ └── termoneplus
│ │ ├── Process.java
│ │ └── TermIO.java
│ └── jackpal
│ └── androidterm
│ └── TermExec.java
├── samples
├── NOTE.pathbroadcasts
├── intents
│ ├── .gitignore
│ ├── build.gradle
│ ├── lint.xml
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── java
│ │ └── com
│ │ │ └── termoneplus
│ │ │ └── sample
│ │ │ └── intents
│ │ │ └── IntentSampleActivity.java
│ │ └── res
│ │ ├── dimens.xml
│ │ ├── drawable
│ │ └── background_rectangle.xml
│ │ ├── layout
│ │ └── main.xml
│ │ └── values
│ │ ├── dimens.xml
│ │ └── strings.xml
├── pathbroadcasts
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── assets
│ │ ├── .gitattributes
│ │ ├── hello
│ │ └── ls
│ │ ├── java
│ │ └── jackpal
│ │ │ └── androidterm
│ │ │ └── sample
│ │ │ └── pathbroadcasts
│ │ │ └── PathReceiver.java
│ │ └── res
│ │ └── values
│ │ └── strings.xml
└── telnet
│ ├── .gitignore
│ ├── build.gradle
│ └── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── jackpal
│ │ └── androidterm
│ │ └── sample
│ │ └── telnet
│ │ ├── LaunchActivity.java
│ │ ├── TelnetSession.java
│ │ └── TermActivity.java
│ └── res
│ ├── layout
│ ├── launch_activity.xml
│ └── term_activity.xml
│ └── values
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── scripts
├── termoneplus-launcher-foreground.sh
├── termoneplus-launcher-resources.sh
└── termoneplus-notification-resources.sh
├── settings.gradle
├── term
├── .gitignore
├── build.gradle
├── lint.xml
└── src
│ ├── CMakeLists.txt
│ └── main
│ ├── AndroidManifest.xml
│ ├── assets
│ └── skel
│ │ └── shrc
│ ├── java
│ ├── com
│ │ └── termoneplus
│ │ │ ├── Application.java
│ │ │ ├── BaseActivity.java
│ │ │ ├── Installer.java
│ │ │ ├── Permissions.java
│ │ │ ├── RemoteActionActivity.java
│ │ │ ├── Settings.java
│ │ │ ├── TermActionBar.java
│ │ │ ├── TermActivity.java
│ │ │ ├── TermPreferencesActivity.java
│ │ │ ├── WindowListActivity.java
│ │ │ ├── WindowListAdapter.java
│ │ │ ├── WindowListFragment.java
│ │ │ ├── services
│ │ │ ├── CommandService.java
│ │ │ └── UnixSocketServer.java
│ │ │ ├── shortcuts
│ │ │ ├── AddShortcut.java
│ │ │ ├── ColorValue.java
│ │ │ └── FileSelection.java
│ │ │ └── utils
│ │ │ ├── ConsoleStartupScript.java
│ │ │ ├── TextIcon.java
│ │ │ ├── ThemeManager.java
│ │ │ ├── WakeLock.java
│ │ │ └── WrapOpenURL.java
│ └── jackpal
│ │ └── androidterm
│ │ ├── BoundSession.java
│ │ ├── GenericTermSession.java
│ │ ├── RemoteInterface.java
│ │ ├── RunScript.java
│ │ ├── RunShortcut.java
│ │ ├── ShellTermSession.java
│ │ ├── Term.java
│ │ ├── TermService.java
│ │ ├── TermView.java
│ │ ├── TermViewFlipper.java
│ │ ├── compat
│ │ ├── Base64.java
│ │ ├── PRNGFixes.java
│ │ ├── PathCollector.java
│ │ └── PathSettings.java
│ │ └── util
│ │ ├── SessionList.java
│ │ ├── ShortcutEncryption.java
│ │ └── TermSettings.java
│ ├── jni
│ ├── appcmd.c
│ ├── appinfo.h
│ ├── atomicio.c
│ └── socket.c
│ └── res
│ ├── drawable-hdpi
│ └── ic_stat_service_notification_icon.png
│ ├── drawable-ldpi
│ └── ic_stat_service_notification_icon.png
│ ├── drawable-mdpi
│ └── ic_stat_service_notification_icon.png
│ ├── drawable-v21
│ └── header_background.xml
│ ├── drawable-xhdpi
│ └── ic_stat_service_notification_icon.png
│ ├── drawable-xxhdpi
│ └── ic_stat_service_notification_icon.png
│ ├── drawable
│ ├── background_rectangle.xml
│ ├── fs_directory_24dp.xml
│ ├── fs_file_24dp.xml
│ ├── fs_parent_24dp.xml
│ ├── fs_unknown_24dp.xml
│ ├── header_background.xml
│ ├── ic_add_circle_outline_24dp.xml
│ ├── ic_close_24dp.xml
│ ├── ic_email_white_24dp.xml
│ ├── ic_help_outline_white_24dp.xml
│ ├── ic_launcher_background.xml
│ ├── ic_settings_white_24dp.xml
│ ├── ic_stat_service_notification_icon.png
│ ├── ic_vpn_key_white_24dp.xml
│ └── ic_windows_white_24dp.xml
│ ├── layout
│ ├── actionbar_windowlist.xml
│ ├── activity_addshortcut.xml
│ ├── activity_color_value.xml
│ ├── activity_file_selection.xml
│ ├── activity_preferences.xml
│ ├── activity_term.xml
│ ├── activity_term_floatbar.xml
│ ├── activity_windowlist.xml
│ ├── content_file_selection.xml
│ ├── fragment_windowlist.xml
│ ├── item_window.xml
│ └── pref_shell_script.xml
│ ├── menu
│ └── main.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ ├── ic_launcher_foreground.png
│ └── ic_launcher_round.png
│ ├── mipmap-ldpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ ├── ic_launcher_foreground.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ ├── ic_launcher_foreground.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ ├── ic_launcher_foreground.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ ├── ic_launcher_foreground.png
│ └── ic_launcher_round.png
│ ├── values-bg
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-cs
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-de
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-en-rGB
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-es
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-eu
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-fr
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-hu
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-it
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-iw
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-ja
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-ka
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-ko
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-nb
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-night
│ ├── colors.xml
│ └── styles.xml
│ ├── values-nl
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-pl
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-pt-rPT
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-pt
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-ro
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-ru
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-sk
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-sr
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-sv
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-tr
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-uk
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-zh-rCN
│ ├── arrays.xml
│ └── strings.xml
│ ├── values-zh-rTW
│ ├── arrays.xml
│ └── strings.xml
│ ├── values
│ ├── arrays.xml
│ ├── arraysNoLocalize.xml
│ ├── attrs.xml
│ ├── colors.xml
│ ├── defaults.xml
│ ├── dimens.xml
│ ├── id.xml
│ ├── strings.xml
│ └── styles.xml
│ └── xml
│ └── preferences.xml
├── tests
├── .gitattributes
├── background-lastline
├── background-outofindex
├── controlSequences
│ ├── 256color.txt
│ ├── combiningCharReplacement.txt
│ ├── combiningChars.txt
│ ├── hideCursor.txt
│ ├── setTitle.txt
│ ├── showCursor.txt
│ └── textStyle.txt
├── cursor-down
├── cursor-down2
├── cursor-down3
├── cursor-up
├── cursor-up2
├── cursor-up3
├── echo-smiley
├── emulatorview-test
│ ├── AndroidManifest.xml
│ ├── proguard-project.txt
│ ├── res
│ │ ├── drawable-hdpi
│ │ │ └── ic_launcher.png
│ │ ├── drawable-ldpi
│ │ │ └── ic_launcher.png
│ │ ├── drawable-mdpi
│ │ │ └── ic_launcher.png
│ │ ├── drawable-xhdpi
│ │ │ └── ic_launcher.png
│ │ └── values
│ │ │ └── strings.xml
│ └── src
│ │ └── jackpal
│ │ └── androidterm
│ │ └── emulatorview
│ │ ├── InputConnectionTest.java
│ │ ├── ModifierKeyTest.java
│ │ └── TermKeyListenerTest.java
├── fullWidthText
├── issue145
│ ├── README.md
│ ├── fuzzer.go
│ ├── issue145repro-2.txt
│ └── issue145repro.txt
├── issue149
│ └── colors.go
├── reset
├── scroll-at-bottom-margin
└── wideChars
│ ├── combining-chars.txt
│ ├── last-column-wrapping.txt
│ ├── linkification.txt
│ ├── overwriting1.txt
│ ├── overwriting2.txt
│ ├── overwriting3.txt
│ ├── overwriting4.txt
│ ├── overwriting5.txt
│ └── sip-chars.txt
└── version.gradle
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Normalize line endings for text files.
2 | # This only affects how files are stored within the repo. Git will
3 | # automatically convert line endings to the platform choice when checking out,
4 | # and automatically convert them back to the normal form when checking in.
5 |
6 | * text=auto
7 |
8 | # Ensure XML files are treated a text files.
9 |
10 | *.xml text
11 |
12 | # Use java diff syntax for java files.
13 |
14 | *.java diff=java
15 |
16 | # Declare files that will always have CRLF line endings on checkout.
17 | *.bat text eol=crlf
18 |
19 | # shell files have unix(LF) end-of-line conversion
20 |
21 | *.sh text eol=lf
22 |
23 | # gradle wrapper shell script must have unix(LF) end-of-line conversion
24 |
25 | gradlew eol=lf
26 |
27 | # skeleton files must have end-of-line conversion as shell script, i.e. unix(LF)
28 |
29 | /**/assets/skel/* eol=lf
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | .DS_Store
4 | /build
5 | /.idea
6 | *.iml
7 |
--------------------------------------------------------------------------------
/MODULE_LICENSE_APACHE2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/MODULE_LICENSE_APACHE2
--------------------------------------------------------------------------------
/NOTICE:
--------------------------------------------------------------------------------
1 |
2 | Copyright (c) 2005-2008, The Android Open Source Project
3 |
4 | Licensed under the Apache License, Version 2.0 (the "License");
5 | you may not use this file except in compliance with the License.
6 | You may obtain a copy of the License at
7 |
8 | http://www.apache.org/licenses/LICENSE-2.0
9 |
10 | Unless required by applicable law or agreed to in writing, software
11 | distributed under the License is distributed on an "AS IS" BASIS,
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | See the License for the specific language governing permissions and
14 | limitations under the License.
15 |
--------------------------------------------------------------------------------
/README.adoc:
--------------------------------------------------------------------------------
1 | Terminal Emulator for Android
2 | =============================
3 |
4 | https://termoneplus.com/
5 |
6 | *"TermOne Plus"* is an Android application that turns your Android device into an computer terminal. It is successor of abandoned Jack Palevich's terminal emulator.
7 |
8 | Terminal is useful for accessing the command line shell (built into every Android phone) or use custom one (installed separately).
9 | This allows you to run various command line utilities.
10 | It emulates a reasonably large subset of Digital Equipment Corporation VT-100 terminal codes.
11 | Supported terminal types include *vt100*, *screen* (default), *linux* and *xterm*.
12 | As result console programs like *ssh* (PKIX-SSH), *vi* (unix visual editor), *emacs*, *mc* (Midnight Commander file manager), *nano* (Nano's ANOther editor), and other work smoothly.
13 |
14 | Code of "TermOne Plus" is hosted in https://gitlab.com/termapps/termoneplus[public repository].
15 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | //maven { url 'https://maven.google.com' }
7 | google()
8 | mavenCentral()
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:4.0.2'
12 | }
13 | }
14 |
15 | apply from: 'buildTools.gradle'
16 | allprojects {
17 | repositories {
18 | jcenter()
19 | //maven { url 'https://maven.google.com' }
20 | google()
21 | mavenCentral()
22 | }
23 | project.ext {
24 | compileSdkVersion = 30
25 | targetSdkVersion = 30
26 | minSdkVersion = 21
27 | }
28 | }
29 |
30 | task clean(type: Delete) {
31 | delete rootProject.buildDir
32 | }
33 |
--------------------------------------------------------------------------------
/buildTools.gradle:
--------------------------------------------------------------------------------
1 | allprojects {
2 | project.ext {
3 | buildToolsVersion = '30.0.2'
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/docs/UTF-8-SMP-chars-demo.txt:
--------------------------------------------------------------------------------
1 | These are some characters in the Supplementary Multilingual Plane:
2 | 𝄞 𝄴𝅘𝅥𝅯𝅗𝅥 𝑥𝄽
3 |
--------------------------------------------------------------------------------
/docs/atari_small_notice.txt:
--------------------------------------------------------------------------------
1 | COMMENT Copyright (c) 1999, Thomas A. Fine
2 | COMMENT
3 | COMMENT License to copy, modify, and distribute for both commercial and
4 | COMMENT non-commercial use is herby granted, provided this notice
5 | COMMENT is preserved.
6 | COMMENT
7 | COMMENT Email to my last name at head.cfa.harvard.edu
8 | COMMENT http://hea-www.harvard.edu/~fine/
9 | COMMENT
10 | COMMENT Produced with bdfedit, a tcl/tk font editing program
11 | COMMENT written by Thomas A. Fine
--------------------------------------------------------------------------------
/docs/google-play-description:
--------------------------------------------------------------------------------
1 | "TermOne Plus" is a terminal emulator application for Android devices.
2 | Each android device has a build-in born shell and a number of shell command that allows user to:
3 | - manage files and directories: list, create, move(rename), delete, compare, view, and etc;
4 | - get information for running processes, network status and connections, mounted file system, free space, device;
5 | - use package and application manager;
6 | - do screen-shots.
7 |
8 | Application supports multiple terminal windows(screens). Each terminal starts own console session with build-in shell (by default).
9 | Terminal emulates large subset of Digital Equipment Corporation VT-100 terminal capabilities - supported are following terminal types: vt100, screen (default), linux, screen-256color, xterm and xterm-256color. Also it supports UTF-8 console text mode by default.
10 | For instance supported terminal capabilities allows users fully to use textual interface in remote login programs (ssh connections).
11 | Terminal screen support color schemes like "Dark Pastels", "Solarized Light", "Solarized Dark", "Linux Console" and etc. Also user could chose size of text.
12 |
13 | Terminal session use "shell start-up script" where you could tune environment setting, add shell functions or command aliases.
14 |
15 | "TermOne Plus" user interface is based on material design - icons, colors. It uses navigation drawer as main menu. Also user could switch between "Light" and "Dark" theme mode.
16 |
17 | Launcher short-cut functionality allows user to create "button"(android short-cut widget) to a command or shell script.
18 | Build-in file selector (aka file explorer) is exported and so allows other applications easy to pick a file.
19 |
20 | Application is localized in many languages and/or territories (locales).
21 |
22 | "TermOne Plus" is successor of excellent but un-maintained since 2015 "Terminal Emulator for Android". This new application includes rewritten user interface, many compatibility and portability improvements, stability and defect fixes, and localization enhancements. As result it works fine with recent android releases (Android 11). Even on ancient like Gingerbread(2.3) it looks and works the same as for recent one.
23 |
24 | Please visit application site to find out how to participate into development and/or localization, how to request new or enhanced functionality.
25 |
26 | WARNING: Upgrade from pre 3.1.0 versions:
27 | Due to hardened SE Linux rules on Android 9.0(Pie) and to allow use of executables provided by other applications "TermOne Plus" start to use "shared user id" functionality. Unfortunately Android package manager (PM) consider this as incompatible change and does not allow automatic upgrade. The only way to bay-pass limitation of Android PM is to reinstall application.
28 | Advantage is that now on Android 9.0(Pie) executables provided by SecureBox are again available for use in terminal application.
29 |
--------------------------------------------------------------------------------
/docs/termoneplus-launcher-icon.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/docs/termoneplus-launcher-icon.xcf
--------------------------------------------------------------------------------
/docs/termoneplus-launcher-round_icon.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/docs/termoneplus-launcher-round_icon.xcf
--------------------------------------------------------------------------------
/docs/termoneplus-logo.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/docs/termoneplus-logo.xcf
--------------------------------------------------------------------------------
/docs/termoneplus-notification-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
--------------------------------------------------------------------------------
/emulatorview/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/emulatorview/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion project.ext.compileSdkVersion
5 | buildToolsVersion project.ext.buildToolsVersion
6 | defaultConfig {
7 | minSdkVersion project.ext.minSdkVersion
8 | targetSdkVersion project.ext.targetSdkVersion
9 |
10 | //Major.Minor.Patch
11 | versionCode 10601
12 | versionName '1.6.1'
13 | }
14 | compileOptions {
15 | sourceCompatibility JavaVersion.VERSION_1_8
16 | targetCompatibility JavaVersion.VERSION_1_8
17 | }
18 | productFlavors {
19 | }
20 | buildTypes {
21 | release {
22 | minifyEnabled false
23 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
24 | }
25 | }
26 | }
27 |
28 | dependencies {
29 | implementation "androidx.annotation:annotation:1.1.0"
30 | }
31 |
--------------------------------------------------------------------------------
/emulatorview/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/emulatorview/src/main/java/com/termoneplus/compat/CharacterCompat.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.termoneplus.compat;
18 |
19 | import android.icu.lang.UCharacter;
20 | import android.icu.lang.UProperty;
21 | import android.os.Build;
22 |
23 | import androidx.annotation.RequiresApi;
24 |
25 | public class CharacterCompat {
26 | public static int charCount(int cp /*code point*/) {
27 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N /*API Level 24*/) {
28 | return Compat1.charCount(cp);
29 | } else {
30 | return Compat24.charCount(cp);
31 | }
32 | }
33 |
34 | public static int toChars(int cp, char[] dst, int dstIndex) {
35 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N /*API Level 24*/) {
36 | return Compat1.toChars(cp, dst, dstIndex);
37 | } else {
38 | return Compat24.toChars(cp, dst, dstIndex);
39 | }
40 | }
41 |
42 | public static boolean isEastAsianDoubleWidth(int ch /*code point*/) {
43 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N /*API Level 24*/) {
44 | return Compat1.isEastAsianDoubleWidth(ch);
45 | } else {
46 | return Compat24.isEastAsianDoubleWidth(ch);
47 | }
48 | }
49 |
50 | private static class Compat1 {
51 | private static int charCount(int cp) {
52 | return Character.charCount(cp);
53 | }
54 |
55 | private static int toChars(int cp, char[] dst, int dstIndex) {
56 | return Character.toChars(cp, dst, dstIndex);
57 | }
58 |
59 | @SuppressWarnings("deprecation")
60 | private static boolean isEastAsianDoubleWidth(int ch) {
61 | // Android's getEastAsianWidth() only works for BMP characters
62 | // use fully-qualified class name to avoid deprecation warning on import
63 | switch (android.text.AndroidCharacter.getEastAsianWidth((char) ch)) {
64 | case android.text.AndroidCharacter.EAST_ASIAN_WIDTH_FULL_WIDTH:
65 | case android.text.AndroidCharacter.EAST_ASIAN_WIDTH_WIDE:
66 | return true;
67 | }
68 | return false;
69 | }
70 | }
71 |
72 | @RequiresApi(24)
73 | private static class Compat24 {
74 | private static int charCount(int cp) {
75 | return UCharacter.charCount(cp);
76 | }
77 |
78 | private static int toChars(int cp, char[] dst, int dstIndex) {
79 | return UCharacter.toChars(cp, dst, dstIndex);
80 | }
81 |
82 | private static boolean isEastAsianDoubleWidth(int ch) {
83 | int ea = UCharacter.getIntPropertyValue(ch, UProperty.EAST_ASIAN_WIDTH);
84 | switch (ea) {
85 | case UCharacter.EastAsianWidth.FULLWIDTH:
86 | case UCharacter.EastAsianWidth.WIDE:
87 | return true;
88 | }
89 | return false;
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/emulatorview/src/main/java/com/termoneplus/utils/SimpleClipboardManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.termoneplus.utils;
18 |
19 | import android.content.ClipData;
20 | import android.content.ClipDescription;
21 | import android.content.ClipboardManager;
22 | import android.content.Context;
23 |
24 | public class SimpleClipboardManager {
25 | private final ClipboardManager clip;
26 |
27 | public SimpleClipboardManager(Context context) {
28 | clip = (ClipboardManager) context.getApplicationContext().getSystemService(Context.CLIPBOARD_SERVICE);
29 | }
30 |
31 | public CharSequence getText() {
32 | ClipData.Item item = clip.getPrimaryClip().getItemAt(0);
33 | return item.getText();
34 | }
35 |
36 | public void setText(CharSequence text) {
37 | ClipData clipData = ClipData.newPlainText("simple text", text);
38 | clip.setPrimaryClip(clipData);
39 | }
40 |
41 | public boolean hasText() {
42 | return (clip.hasPrimaryClip() &&
43 | clip.getPrimaryClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN));
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/emulatorview/src/main/java/jackpal/androidterm/emulatorview/EmulatorDebug.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2007 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package jackpal.androidterm.emulatorview;
18 |
19 | /**
20 | * Debug settings.
21 | */
22 | class EmulatorDebug {
23 | /**
24 | * Set to true to add debugging code and logging.
25 | */
26 | public static final boolean DEBUG = false;
27 |
28 | /**
29 | * Set to true to log IME calls.
30 | */
31 | public static final boolean LOG_IME = DEBUG & false;
32 |
33 | /**
34 | * Set to true to log each character received from the remote process to the
35 | * android log, which makes it easier to debug some kinds of problems with
36 | * emulating escape sequences and control codes.
37 | */
38 | public static final boolean LOG_CHARACTERS_FLAG = DEBUG & false;
39 |
40 | /**
41 | * Set to true to log unknown escape sequences.
42 | */
43 | public static final boolean LOG_UNKNOWN_ESCAPE_SEQUENCES = DEBUG & false;
44 |
45 | /**
46 | * The tag we use when logging, so that our messages can be distinguished
47 | * from other messages in the log. Public because it's used by several
48 | * classes.
49 | */
50 | public static final String LOG_TAG = "EmulatorView";
51 |
52 | public static String bytesToString(byte[] data, int base, int length) {
53 | StringBuilder buf = new StringBuilder();
54 | for (int i = 0; i < length; i++) {
55 | byte b = data[base + i];
56 | if (b < 32 || b > 126) {
57 | buf.append(String.format("\\x%02x", b));
58 | } else {
59 | buf.append((char) b);
60 | }
61 | }
62 | return buf.toString();
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/emulatorview/src/main/java/jackpal/androidterm/emulatorview/GrowableIntArray.java:
--------------------------------------------------------------------------------
1 | package jackpal.androidterm.emulatorview;
2 |
3 | class GrowableIntArray {
4 | GrowableIntArray(int initalCapacity) {
5 | mData = new int[initalCapacity];
6 | mLength = 0;
7 | }
8 |
9 | void append(int i) {
10 | if (mLength + 1 > mData.length) {
11 | int newLength = Math.max((mData.length * 3) >> 1, 16);
12 | int[] temp = new int[newLength];
13 | System.arraycopy(mData, 0, temp, 0, mLength);
14 | mData = temp;
15 | }
16 | mData[mLength++] = i;
17 | }
18 |
19 | int length() {
20 | return mLength;
21 | }
22 |
23 | int at(int index) {
24 | return mData[index];
25 | }
26 |
27 | int[] mData;
28 | int mLength;
29 | }
30 |
--------------------------------------------------------------------------------
/emulatorview/src/main/java/jackpal/androidterm/emulatorview/StyleRow.java:
--------------------------------------------------------------------------------
1 | package jackpal.androidterm.emulatorview;
2 |
3 | /**
4 | * Utility class for dealing with text style lines.
5 | *
6 | * We pack color and formatting information for a particular character into an
7 | * int -- see the TextStyle class for details. The simplest way of storing
8 | * that information for a screen row would be to use an array of int -- but
9 | * given that we only use the lower three bytes of the int to store information,
10 | * that effectively wastes one byte per character -- nearly 8 KB per 100 lines
11 | * with an 80-column transcript.
12 | *
13 | * Instead, we use an array of bytes and store the bytes of each int
14 | * consecutively in big-endian order.
15 | */
16 | final class StyleRow {
17 | private int mStyle;
18 | private final int mColumns;
19 | /**
20 | * Initially null, will be allocated when needed.
21 | */
22 | private byte[] mData;
23 |
24 | StyleRow(int style, int columns) {
25 | mStyle = style;
26 | mColumns = columns;
27 | }
28 |
29 | void set(int column, int style) {
30 | if (style == mStyle && mData == null) {
31 | return;
32 | }
33 | ensureData();
34 | setStyle(column, style);
35 | }
36 |
37 | int get(int column) {
38 | if (mData == null) {
39 | return mStyle;
40 | }
41 | return getStyle(column);
42 | }
43 |
44 | boolean isSolidStyle() {
45 | return mData == null;
46 | }
47 |
48 | int getSolidStyle() {
49 | if (mData != null) {
50 | throw new IllegalArgumentException("Not a solid style");
51 | }
52 | return mStyle;
53 | }
54 |
55 | void copy(int start, StyleRow dst, int offset, int len) {
56 | // fast case
57 | if (mData == null && dst.mData == null && start == 0 && offset == 0
58 | && len == mColumns) {
59 | dst.mStyle = mStyle;
60 | return;
61 | }
62 | // There are other potentially fast cases, but let's just treat them
63 | // all the same for simplicity.
64 | ensureData();
65 | dst.ensureData();
66 | System.arraycopy(mData, 3 * start, dst.mData, 3 * offset, 3 * len);
67 |
68 | }
69 |
70 | void ensureData() {
71 | if (mData == null) {
72 | allocate();
73 | }
74 | }
75 |
76 | private void allocate() {
77 | mData = new byte[3 * mColumns];
78 | for (int i = 0; i < mColumns; i++) {
79 | setStyle(i, mStyle);
80 | }
81 | }
82 |
83 | private int getStyle(int column) {
84 | int index = 3 * column;
85 | byte[] line = mData;
86 | return line[index] & 0xff | (line[index + 1] & 0xff) << 8
87 | | (line[index + 2] & 0xff) << 16;
88 | }
89 |
90 | private void setStyle(int column, int value) {
91 | int index = 3 * column;
92 | byte[] line = mData;
93 | line[index] = (byte) (value & 0xff);
94 | line[index + 1] = (byte) ((value >> 8) & 0xff);
95 | line[index + 2] = (byte) ((value >> 16) & 0xff);
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/emulatorview/src/main/java/jackpal/androidterm/emulatorview/TextRenderer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2007 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package jackpal.androidterm.emulatorview;
18 |
19 | import android.graphics.Canvas;
20 |
21 | /**
22 | * Text renderer interface
23 | */
24 | interface TextRenderer {
25 | int MODE_OFF = 0;
26 | int MODE_ON = 1;
27 | int MODE_LOCKED = 2;
28 | int MODE_MASK = 3;
29 |
30 | int MODE_SHIFT_SHIFT = 0;
31 | int MODE_ALT_SHIFT = 2;
32 | int MODE_CTRL_SHIFT = 4;
33 | int MODE_FN_SHIFT = 6;
34 |
35 | void setReverseVideo(boolean reverseVideo);
36 |
37 | float getCharacterWidth();
38 |
39 | int getCharacterHeight();
40 |
41 | /**
42 | * @return pixels above top row of text to avoid looking cramped.
43 | */
44 | int getTopMargin();
45 |
46 | /**
47 | * Draw a run of text
48 | *
49 | * @param canvas The canvas to draw into.
50 | * @param x Canvas coordinate of the left edge of the whole line.
51 | * @param y Canvas coordinate of the bottom edge of the whole line.
52 | * @param lineOffset The screen character offset of this text run (0..length of line)
53 | * @param runWidth
54 | * @param text
55 | * @param index
56 | * @param count
57 | * @param selectionStyle True to draw the text using the "selected" style (for clipboard copy)
58 | * @param textStyle
59 | * @param cursorOffset The screen character offset of the cursor (or -1 if not on this line.)
60 | * @param cursorIndex The index of the cursor in text chars.
61 | * @param cursorIncr The width of the cursor in text chars. (1 or 2)
62 | * @param cursorWidth The width of the cursor in screen columns (1 or 2)
63 | * @param cursorMode The cursor mode (used to show state of shift/control/alt/fn locks.
64 | */
65 | void drawTextRun(Canvas canvas, float x, float y,
66 | int lineOffset, int runWidth, char[] text,
67 | int index, int count, boolean selectionStyle, int textStyle,
68 | int cursorOffset, int cursorIndex, int cursorIncr, int cursorWidth, int cursorMode);
69 | }
70 |
--------------------------------------------------------------------------------
/emulatorview/src/main/java/jackpal/androidterm/emulatorview/TextStyle.java:
--------------------------------------------------------------------------------
1 | package jackpal.androidterm.emulatorview;
2 |
3 | final class TextStyle {
4 | // Effect bitmasks:
5 | final static int fxNormal = 0;
6 | final static int fxBold = 1; // Originally Bright
7 | //final static int fxFaint = 2;
8 | final static int fxItalic = 1 << 1;
9 | final static int fxUnderline = 1 << 2;
10 | final static int fxBlink = 1 << 3;
11 | final static int fxInverse = 1 << 4;
12 | final static int fxInvisible = 1 << 5;
13 |
14 | // Special color indices
15 | final static int ciForeground = 256; // VT100 text foreground color
16 | final static int ciBackground = 257; // VT100 text background color
17 | final static int ciCursorForeground = 258; // VT100 text cursor foreground color
18 | final static int ciCursorBackground = 259; // VT100 text cursor background color
19 |
20 | final static int ciColorLength = ciCursorBackground + 1;
21 |
22 | final static int kNormalTextStyle = encode(ciForeground, ciBackground, fxNormal);
23 |
24 | static int encode(int foreColor, int backColor, int effect) {
25 | return ((effect & 0x3f) << 18) | ((foreColor & 0x1ff) << 9) | (backColor & 0x1ff);
26 | }
27 |
28 | static int decodeForeColor(int encodedColor) {
29 | return (encodedColor >> 9) & 0x1ff;
30 | }
31 |
32 | static int decodeBackColor(int encodedColor) {
33 | return encodedColor & 0x1ff;
34 | }
35 |
36 | static int decodeEffect(int encodedColor) {
37 | return (encodedColor >> 18) & 0x3f;
38 | }
39 |
40 | private TextStyle() {
41 | // Prevent instantiation
42 | throw new UnsupportedOperationException();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/emulatorview/src/main/java/jackpal/androidterm/emulatorview/UpdateCallback.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2007 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package jackpal.androidterm.emulatorview;
18 |
19 | /**
20 | * Generic callback to be invoked to notify of updates.
21 | */
22 | public interface UpdateCallback {
23 | /**
24 | * Callback function to be invoked when an update happens.
25 | */
26 | void onUpdate();
27 | }
28 |
--------------------------------------------------------------------------------
/emulatorview/src/main/java/jackpal/androidterm/emulatorview/compat/KeyCharacterMapCompat.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2011 Jack Palevich
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package jackpal.androidterm.emulatorview.compat;
18 |
19 | import android.view.KeyCharacterMap;
20 |
21 | public abstract class KeyCharacterMapCompat {
22 | public static final int MODIFIER_BEHAVIOR_CHORDED = 0;
23 | public static final int MODIFIER_BEHAVIOR_CHORDED_OR_TOGGLED = 1;
24 |
25 | public static KeyCharacterMapCompat wrap(Object map) {
26 | if (map == null) return null;
27 |
28 | return new KeyCharacterMapApi11OrLater(map);
29 | }
30 |
31 | private static class KeyCharacterMapApi11OrLater extends KeyCharacterMapCompat {
32 | private final KeyCharacterMap mMap;
33 |
34 | public KeyCharacterMapApi11OrLater(Object map) {
35 | mMap = (KeyCharacterMap) map;
36 | }
37 |
38 | public int getModifierBehaviour() {
39 | return mMap.getModifierBehavior();
40 | }
41 | }
42 |
43 | public abstract int getModifierBehaviour();
44 | }
45 |
--------------------------------------------------------------------------------
/emulatorview/src/main/java/jackpal/androidterm/emulatorview/package.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
This package provides a fairly complete VT100 terminal emulator {@link
4 | jackpal.androidterm.emulatorview.TermSession TermSession} and a corresponding
5 | Android view {@link jackpal.androidterm.emulatorview.EmulatorView EmulatorView}.
6 |
7 |
Most users will create a TermSession, connect it to an {@link
8 | java.io.InputStream InputStream} and {@link java.io.OutputStream OutputStream}
9 | from the emulation client, then instantiate the EmulatorView and
10 | add it to an activity's layout.
11 |
12 |
13 |
--------------------------------------------------------------------------------
/emulatorview/src/main/res/drawable-nodpi/atari_small_nodpi.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/emulatorview/src/main/res/drawable-nodpi/atari_small_nodpi.png
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 |
11 | # When configured, Gradle will run in incubating parallel mode.
12 | # This option should only be used with decoupled projects. More details, visit
13 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
14 | # org.gradle.parallel=true
15 |
16 | # AndroidX package structure to make it clearer which packages are bundled with the
17 | # Android operating system, and which are packaged with your app's APK
18 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
19 | android.useAndroidX=true
20 | # Automatically convert third-party libraries to use AndroidX
21 | android.enableJetifier=true
22 |
23 | # NOTE: R8 enabled by default in gradle plugin 3.4.0!
24 | # Disables R8 for Android Library modules only.
25 | #android.enableR8.libraries = false
26 | # Disables R8 for all modules.
27 | #android.enableR8 = false
28 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/libtermexec/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | /.externalNativeBuild
3 | /.cxx
4 |
--------------------------------------------------------------------------------
/libtermexec/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion project.ext.compileSdkVersion
5 | buildToolsVersion project.ext.buildToolsVersion
6 | defaultConfig {
7 | minSdkVersion project.ext.minSdkVersion
8 | targetSdkVersion project.ext.targetSdkVersion
9 |
10 | //Major.Minor.Patch
11 | versionCode 10100
12 | versionName '1.1.0'
13 | }
14 | externalNativeBuild {
15 | cmake {
16 | path "src/CMakeLists.txt"
17 | }
18 | }
19 | compileOptions {
20 | sourceCompatibility JavaVersion.VERSION_1_8
21 | targetCompatibility JavaVersion.VERSION_1_8
22 | }
23 | productFlavors {
24 | }
25 | buildTypes {
26 | release {
27 | minifyEnabled false
28 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
29 | }
30 | }
31 | }
32 |
33 | // by default recent plugin version does not copy any AIDL files "to avoid publishing too much"
34 | android.libraryVariants.all { variant ->
35 | Sync packageAidl = project.tasks.create("addPublic${variant.name.capitalize()}Aidl", Sync) { sync ->
36 | from "$project.projectDir/src/main/aidl/"
37 | into "$buildDir/intermediates/bundles/${variant.dirName}/aidl/"
38 | }
39 |
40 | Task javaCompileTask
41 | if (variant.hasProperty('javaCompileProvider')) {
42 | // gradle plugin 3.3.+
43 | javaCompileTask = variant.javaCompileProvider.get()
44 | } else {
45 | javaCompileTask = variant.javaCompile
46 | }
47 | javaCompileTask.dependsOn packageAidl
48 | }
49 |
50 | dependencies {
51 | implementation fileTree(include: ['*.jar'], dir: 'libs')
52 | implementation "androidx.annotation:annotation:1.1.0"
53 | }
54 |
--------------------------------------------------------------------------------
/libtermexec/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /home/uniqa/android-sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/libtermexec/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ##
2 | # Copyright (C) 2018-2019 Roumen Petrov. All rights reserved.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | ##
16 |
17 | cmake_minimum_required(VERSION 2.4)
18 |
19 | add_library(
20 | term-system
21 | SHARED
22 | main/cpp/registration.c
23 | main/cpp/process.c
24 | main/cpp/termio.c
25 | main/cpp/compat.c
26 | )
27 | target_link_libraries(
28 | term-system
29 | log
30 | )
31 |
--------------------------------------------------------------------------------
/libtermexec/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/libtermexec/src/main/aidl/jackpal/androidterm/libtermexec/v1/ITerminal.aidl:
--------------------------------------------------------------------------------
1 | package jackpal.androidterm.libtermexec.v1;
2 |
3 | import android.content.IntentSender;
4 | import android.os.ParcelFileDescriptor;
5 | import android.os.ResultReceiver;
6 |
7 | // see also:
8 | // the (clumsy) way to handle object inheritance with Binder:
9 | // https://kevinhartman.github.io/blog/2012/07/23/inheritance-through-ipc-using-aidl-in-android/
10 | // some (possibly outdated) notes on preserving backward compatibility:
11 | // https://stackoverflow.com/questions/18197783/android-aidl-interface-parcelables-and-backwards-compatibility
12 | /**
13 | * An interface for interacting with Terminal implementation.
14 | *
15 | * The version of the interface is encoded in Intent action and the AIDL package name. New versions
16 | * of this interface may be implemented in future. Those versions will be made available
17 | * in separate packages and older versions will continue to work.
18 | */
19 | interface ITerminal {
20 | /**
21 | * Start a new Terminal session. A session will remain hosted by service, that provides binding,
22 | * but no gurantees of process pesistence as well as stability of connection are made. You
23 | * should keep your ParcelFileDescriptor around and allow ServiceConnection to call this method
24 | * again, when reconnection happens, in case service hosting the session is killed by system.
25 | *
26 | * Allows caller to be notified of terminal session events. Multiple calls can happen on each,
27 | * and new call types can be introduced, so prepare to ignore unknown event codes.
28 | *
29 | * So far only notifications about session end (code 0) are supported. This notification is
30 | * issued after abovementioned file descriptor is closed and the session is ended from
31 | * Terminal's standpoint.
32 | *
33 | * @param pseudoTerminalMultiplexerFd file descriptor, obtained by opening /dev/ptmx.
34 | * @param a callback
35 | *
36 | * @return IntentSender, that can be used to start corresponding Terminal Activity.
37 | */
38 | IntentSender startSession(in ParcelFileDescriptor pseudoTerminalMultiplexerFd, in ResultReceiver callback);
39 | }
40 |
--------------------------------------------------------------------------------
/libtermexec/src/main/cpp/compat.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "compat.h"
18 |
19 | #if defined(__cplusplus)
20 | # error "__cplusplus"
21 | #endif
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 |
29 | void
30 | closefrom(int lowfd) {
31 | int pws_fd = -1;
32 | DIR *dirp;
33 |
34 | { /* keep android property workspace open */
35 | char *pws_env = getenv("ANDROID_PROPERTY_WORKSPACE");
36 | if (pws_env) {
37 | /* format "int,int" */
38 | pws_fd = atoi(pws_env);
39 | }
40 | }
41 |
42 | dirp = opendir("/proc/self/fd");
43 | if (dirp != NULL) {
44 | int dir_fd = dirfd(dirp);
45 | struct dirent *dent;
46 | long fd;
47 | char *endp;
48 |
49 | for (dent = readdir(dirp); dent != NULL; dent = readdir(dirp)) {
50 | fd = strtol(dent->d_name, &endp, 10);
51 | if (
52 | (dent->d_name != endp) && (*endp == '\0') &&
53 | (fd >= 0) && (fd < INT_MAX) &&
54 | (fd >= lowfd) &&
55 | (fd != pws_fd) && (fd != dir_fd)
56 | )
57 | (void) close((int) fd);
58 | }
59 |
60 | (void) closedir(dirp);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/libtermexec/src/main/cpp/compat.h:
--------------------------------------------------------------------------------
1 | #ifndef TERMONEPLUS_COMPAT_H
2 | #define TERMONEPLUS_COMPAT_H
3 | /*
4 | * Copyright (C) 2018 Roumen Petrov. All rights reserved.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | /**
20 | * NAME
21 | * closefrom -- delete open file descriptors
22 | *
23 | * SYNOPSIS
24 | * void closefrom(int lowfd);
25 | *
26 | * DESCRIPTION
27 | * The closefrom() system call deletes all open file descriptors greater
28 | * than or equal to lowfd from the per-process object reference table. Any
29 | * errors encountered while closing file descriptors are ignored.
30 | */
31 | void closefrom(int lowfd);
32 |
33 | #endif /* ndef TERMONEPLUS_COMPAT_H */
34 |
--------------------------------------------------------------------------------
/libtermexec/src/main/cpp/registration.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018-2020 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "registration.h"
18 |
19 | #if defined(__cplusplus)
20 | # error "__cplusplus"
21 | #endif
22 |
23 | #include
24 |
25 |
26 | /*
27 | * Register several "native"-methods for specified class.
28 | */
29 | int register_native(
30 | JNIEnv *env, const char *class_name,
31 | JNINativeMethod *methods, size_t num_methods
32 | ) {
33 | jint r;
34 | jclass clazz;
35 | jint nMethods;
36 |
37 | clazz = (*env)->FindClass(env, class_name);
38 | if (clazz == NULL) {
39 | LOGE("Unable to find class '%s'", class_name);
40 | return JNI_ERR;
41 | }
42 |
43 | nMethods = (jint) num_methods;
44 | if (num_methods != (size_t) nMethods) { /*paranoid check*/
45 | LOGE("Number of methods overflow for '%s'", class_name);
46 | return JNI_ERR;
47 | }
48 |
49 | r = (*env)->RegisterNatives(env, clazz, methods, nMethods);
50 | if (r < 0) {
51 | return r;
52 | }
53 |
54 | return JNI_OK;
55 | }
56 |
57 |
58 | static void
59 | throwNewException(JNIEnv *env, const char *clazz, const char *msg) {
60 | jclass exception = (*env)->FindClass(env, clazz);
61 | (*env)->ThrowNew(env, exception, msg);
62 | }
63 |
64 | void
65 | throwOutOfMemoryError(JNIEnv *env, const char *msg) {
66 | throwNewException(env, "java/lang/OutOfMemoryError", msg);
67 | }
68 |
69 | void
70 | throwIOException(JNIEnv *env, const char *fmt, ...) {
71 | char msg[1024];
72 | va_list args;
73 |
74 | va_start(args, fmt);
75 | (void)vsnprintf(msg, sizeof(msg), fmt, args);
76 | va_end(args);
77 |
78 | throwNewException(env, "java/io/IOException", msg);
79 | }
80 |
81 |
82 | int
83 | termoneplus_log_print(int prio, const char *fmt, ...) {
84 | int r;
85 | va_list args;
86 |
87 | va_start(args, fmt);
88 | r = __android_log_vprint(prio, "TermOnePlus(native)", fmt, args);
89 | va_end(args);
90 |
91 | return r;
92 | }
93 |
94 |
95 | jint JNICALL
96 | JNI_OnLoad(JavaVM *vm, void *reserved) {
97 | jint r;
98 | union {
99 | JNIEnv *p;
100 | void *v;
101 | } env;
102 |
103 | (void) reserved;
104 |
105 | r = (*vm)->GetEnv(vm, &env.v, JNI_VERSION_1_2);
106 | if (r != JNI_OK) {
107 | LOGE("ERROR: GetEnv failed with error code %d", r);
108 | return -1;
109 | }
110 |
111 | r = register_process(env.p);
112 | if (r != JNI_OK) {
113 | LOGE("ERROR: 'process' registration fail");
114 | return -1;
115 | }
116 |
117 | r = register_termio(env.p);
118 | if (r != JNI_OK) {
119 | LOGE("ERROR: 'termio' registration fail");
120 | return -1;
121 | }
122 |
123 | return JNI_VERSION_1_2;
124 | }
125 |
--------------------------------------------------------------------------------
/libtermexec/src/main/cpp/registration.h:
--------------------------------------------------------------------------------
1 | #ifndef TERMONEPLUS_REGISTRATION_H
2 | #define TERMONEPLUS_REGISTRATION_H
3 | /*
4 | * Copyright (C) 2018-2020 Roumen Petrov. All rights reserved.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | #include
20 | #include
21 |
22 |
23 | int register_native(
24 | JNIEnv *env, const char *class_name,
25 | JNINativeMethod *methods, size_t num_methods
26 | );
27 |
28 | int register_process(JNIEnv *env);
29 | int register_termio(JNIEnv *env);
30 |
31 |
32 | void throwOutOfMemoryError(JNIEnv *env, const char *msg) ;
33 | void throwIOException(JNIEnv *env, const char *fmt, ...);
34 |
35 |
36 | int termoneplus_log_print(int prio, const char *fmt, ...);
37 | #define LOGE(...) do { termoneplus_log_print(ANDROID_LOG_ERROR, __VA_ARGS__); } while(0)
38 |
39 | #endif /* ndef TERMONEPLUS_REGISTRATION_H */
40 |
--------------------------------------------------------------------------------
/libtermexec/src/main/cpp/termio.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018-2020 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include "registration.h"
18 |
19 | #if defined(__cplusplus)
20 | # error "__cplusplus"
21 | #endif
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 |
28 |
29 | static void
30 | termios_setUTF8Input(
31 | JNIEnv *env, jobject clazz,
32 | jint fd, jboolean flag
33 | ) {
34 | struct termios tio;
35 |
36 | (void) clazz;
37 |
38 | if (tcgetattr(fd, &tio) != 0) {
39 | throwIOException(env, "Failed to get the parameters associated with the terminal");
40 | return;
41 | }
42 |
43 | /* quoted from termios(3) manual page:
44 | * c_iflag flag constants:
45 | * ...
46 | * IUTF8 (since Linux 2.6.4)
47 | * (not in POSIX) Input is UTF8; this allows character-erase to be correctly performed in cooked mode.
48 | */
49 | if (flag) {
50 | tio.c_iflag |= IUTF8;
51 | } else {
52 | tio.c_iflag &= ~IUTF8;
53 | }
54 |
55 | if (tcsetattr(fd, TCSANOW, &tio) != 0) {
56 | throwIOException(env, "Failed to set the parameters associated with the terminal");
57 | }
58 | }
59 |
60 |
61 | static void
62 | ioctl_setWindowSize(
63 | JNIEnv *env, jobject clazz,
64 | jint fd, jint row, jint col, jint xpixel, jint ypixel
65 | ) {
66 | struct winsize arg;
67 |
68 | (void) clazz;
69 |
70 | arg.ws_row = (unsigned short) row;
71 | arg.ws_col = (unsigned short) col;
72 | arg.ws_xpixel = (unsigned short) xpixel;
73 | arg.ws_ypixel = (unsigned short) ypixel;
74 |
75 | /* quoted from tty_ioctl(4) manual page:
76 | * TIOCSWINSZ const struct winsize *argp
77 | * Set window size.
78 | * ...
79 | * When the window size changes, a SIGWINCH signal is sent to the foreground process group.
80 | */
81 | if (ioctl(fd, TIOCSWINSZ, &arg) != 0) {
82 | throwIOException(env, "ioctl: set tty window size fail / error %d/%s",
83 | errno, strerror(errno));
84 | }
85 | }
86 |
87 |
88 | int
89 | register_termio(JNIEnv *env) {
90 | static JNINativeMethod methods[] = {
91 | {"setUTF8Input", "(IZ)V", (void *) termios_setUTF8Input},
92 | {"setWindowSize", "(IIIII)V", (void *) ioctl_setWindowSize}
93 | };
94 | return register_native(
95 | env,
96 | "com/termoneplus/TermIO$Native",
97 | methods, sizeof(methods) / sizeof(*methods)
98 | );
99 | }
100 |
--------------------------------------------------------------------------------
/libtermexec/src/main/java/com/termoneplus/Process.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.termoneplus;
18 |
19 | import android.os.ParcelFileDescriptor;
20 |
21 | import java.io.IOException;
22 | import java.nio.charset.StandardCharsets;
23 |
24 |
25 | public class Process {
26 |
27 | static {
28 | System.loadLibrary("term-system");
29 | }
30 |
31 | public static int createSubprocess(ParcelFileDescriptor masterPty,
32 | String cmd,
33 | String[] arguments,
34 | String[] environment)
35 | throws IOException {
36 | // Let convert to UTF-8 in java code instead in native methods
37 | // prepare command path
38 | byte[] path = cmd.getBytes(StandardCharsets.UTF_8);
39 |
40 | // prepare command arguments
41 | byte[][] argv;
42 | argv = new byte[arguments.length][0];
43 | for (int k = 0; k < arguments.length; k++) {
44 | String val = arguments[k];
45 | argv[k] = val.getBytes(StandardCharsets.UTF_8);
46 | }
47 |
48 | // prepare command environment
49 | byte[][] envp;
50 | envp = new byte[environment.length][0];
51 | for (int k = 0; k < environment.length; k++) {
52 | String val = environment[k];
53 | envp[k] = val.getBytes(StandardCharsets.UTF_8);
54 | }
55 |
56 | // create terminal process ...
57 | int ptm = masterPty.getFd();
58 | return Native.createSubprocess(ptm, path, argv, envp);
59 | }
60 |
61 | public static int waitExit(int pid) {
62 | return Native.waitExit(pid);
63 | }
64 |
65 | public static void finishChilds(int pid) {
66 | Native.finishChilds(pid);
67 | }
68 |
69 |
70 | private static class Native {
71 | private static native int createSubprocess(int ptm, byte[] path, byte[][] argv, byte[][] envp)
72 | throws IOException;
73 |
74 | private static native int waitExit(int pid);
75 |
76 | private static native void finishChilds(int pid);
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/libtermexec/src/main/java/com/termoneplus/TermIO.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.termoneplus;
18 |
19 | import android.os.ParcelFileDescriptor;
20 |
21 | import java.io.IOException;
22 |
23 |
24 | public class TermIO {
25 |
26 | static {
27 | System.loadLibrary("term-system");
28 | }
29 |
30 | public static void setUTF8Input(ParcelFileDescriptor masterPty, boolean flag) throws IOException {
31 | int fd = masterPty.getFd();
32 | Native.setUTF8Input(fd, flag);
33 | }
34 |
35 | public static void setWindowSize(ParcelFileDescriptor masterPty, int row, int col) throws IOException {
36 | int fd = masterPty.getFd();
37 | Native.setWindowSize(fd, row, col, 0, 0);
38 | }
39 |
40 | private static class Native {
41 | private static native void setUTF8Input(int fd, boolean flag) throws IOException;
42 |
43 | private static native void setWindowSize(int fd, int row, int col, int xpixel, int ypixel) throws IOException;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/libtermexec/src/main/java/jackpal/androidterm/TermExec.java:
--------------------------------------------------------------------------------
1 | package jackpal.androidterm;
2 |
3 | import android.os.Looper;
4 | import android.os.ParcelFileDescriptor;
5 |
6 | import com.termoneplus.Process;
7 |
8 | import java.io.IOException;
9 | import java.util.ArrayList;
10 | import java.util.Arrays;
11 | import java.util.Hashtable;
12 | import java.util.List;
13 | import java.util.Map;
14 |
15 | import androidx.annotation.NonNull;
16 |
17 |
18 | /**
19 | * Utility methods for creating and managing a subprocess. This class differs from
20 | * {@link java.lang.ProcessBuilder} in that a pty is used to communicate with the subprocess.
21 | *
22 | * Pseudo-terminals are a powerful Unix feature, that allows programs to interact with other programs
23 | * they start in slightly more human-like way. For example, a pty owner can send ^C (aka SIGINT)
24 | * to attached shell, even if said shell runs under a different user ID.
25 | */
26 | public class TermExec {
27 | public static final String SERVICE_ACTION_V1 = "jackpal.androidterm.action.START_TERM.v1";
28 |
29 | private final List command;
30 | private final Map environment;
31 |
32 | public TermExec(@NonNull String... command) {
33 | this(new ArrayList<>(Arrays.asList(command)));
34 | }
35 |
36 | public TermExec(@NonNull List command) {
37 | this.command = command;
38 | this.environment = new Hashtable<>(System.getenv());
39 | }
40 |
41 |
42 | public @NonNull
43 | List command() {
44 | return command;
45 | }
46 |
47 | public @NonNull
48 | Map environment() {
49 | return environment;
50 | }
51 |
52 | public @NonNull
53 | TermExec command(@NonNull String... command) {
54 | return command(new ArrayList<>(Arrays.asList(command)));
55 | }
56 |
57 | public @NonNull
58 | TermExec command(List command) {
59 | this.command.clear();
60 | this.command.addAll(command);
61 | return this;
62 | }
63 |
64 | /**
65 | * Start the process and attach it to the pty, corresponding to given file descriptor.
66 | * You have to obtain this file descriptor yourself by calling
67 | * {@link android.os.ParcelFileDescriptor#open} on special terminal multiplexer
68 | * device (located at /dev/ptmx).
69 | *
70 | * Callers are responsible for closing the descriptor.
71 | *
72 | * @return the PID of the started process.
73 | */
74 | public int start(@NonNull ParcelFileDescriptor ptmxFd) throws IOException {
75 | if (Looper.getMainLooper() == Looper.myLooper())
76 | throw new IllegalStateException("This method must not be called from the main thread!");
77 |
78 | if (command.size() == 0)
79 | throw new IllegalStateException("Empty command!");
80 |
81 | final String cmd = command.remove(0);
82 | final String[] cmdArray = command.toArray(new String[0]);
83 | final String[] envArray = new String[environment.size()];
84 | int i = 0;
85 | for (Map.Entry entry : environment.entrySet()) {
86 | envArray[i++] = entry.getKey() + "=" + entry.getValue();
87 | }
88 |
89 | return Process.createSubprocess(ptmxFd, cmd, cmdArray, envArray);
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/samples/NOTE.pathbroadcasts:
--------------------------------------------------------------------------------
1 | DEPRECATION:
2 |
3 | Functionality that uses "broadcasts" to collect extra paths with shell commands is deprecated.
4 |
5 | 1) It collects only one path for "prepend" and only one for "append" to the system PATH. Winner is last received.
6 | 2) It is used only in normal start of terminal session but not if terminal is opened from external applications.
7 | 3) Collection of "extra" path components slow down opening of normal sessions.
8 | 4) Applications that run on Android 8.0 (Oreo, API Level 26) or higher no longer receive implicit broadcasts registered in their manifest.
9 |
10 | In transition period "broadcast" functionality will be restricted only to applications signed with the same certificate, i.e. "SecureBox".
11 |
12 |
13 | FUTURE:
14 | Broadcasts based path collection will be replaced with one action based.
15 | External application, according to permissions, could send one or more path components.
16 | "TermOne Plus" activity will allow user to position paths sent in PATH variable.
17 | Also activity will allows user to ignore or delete a path component.
18 |
--------------------------------------------------------------------------------
/samples/intents/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/samples/intents/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion project.ext.compileSdkVersion
5 | buildToolsVersion project.ext.buildToolsVersion
6 | defaultConfig {
7 | applicationId "com.termoneplus.sample.intents"
8 | minSdkVersion project.ext.minSdkVersion
9 | targetSdkVersion project.ext.targetSdkVersion
10 |
11 | versionCode 210
12 | versionName '2.1.0'
13 |
14 | // TermOnePlus applicationId
15 | manifestPlaceholders = [ termApplicationId:"com.termoneplus"]
16 | buildConfigField("String", "TERM_APPLICATION_ID", "\"com.termoneplus\"")
17 | }
18 | compileOptions {
19 | sourceCompatibility JavaVersion.VERSION_1_8
20 | targetCompatibility JavaVersion.VERSION_1_8
21 | }
22 | productFlavors {
23 | }
24 | buildTypes {
25 | release {
26 | minifyEnabled false
27 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
28 | }
29 | }
30 | }
31 |
32 | dependencies {
33 | implementation 'androidx.appcompat:appcompat:1.3.0-beta01'
34 | implementation 'com.google.android.material:material:1.3.0-rc01'
35 | }
36 |
--------------------------------------------------------------------------------
/samples/intents/lint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/samples/intents/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
15 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/samples/intents/src/main/res/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/samples/intents/src/main/res/drawable/background_rectangle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/samples/intents/src/main/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
19 |
20 |
26 |
27 |
33 |
34 |
40 |
41 |
49 |
50 |
59 |
60 |
61 |
62 |
68 |
69 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/samples/intents/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/samples/intents/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Intents (sample)
5 | This sample shows how to send intents to terminal emulator \"TermOne Plus\".
6 |
7 | Open New Window
8 | Script:
9 | Run Script
10 | Run Script and Save Window
11 | Run Script in Saved Window
12 |
13 |
14 | echo \'Hello world!\'
15 | \necho \'Здравейте!\'
16 | \necho \'Καλημέρα κόσμε!\'
17 | \necho \'コンニチハ!\'
18 |
19 | No Activity found
20 |
21 | Permission denial. You have to reinstall application to grant permissions.
22 | Permission denial. You have to grant permissions.
23 | Permission is required to run script in a terminal window.
24 |
25 |
--------------------------------------------------------------------------------
/samples/pathbroadcasts/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/samples/pathbroadcasts/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion project.ext.compileSdkVersion
5 | buildToolsVersion project.ext.buildToolsVersion
6 | defaultConfig {
7 | applicationId "com.termoneplus.sample.pathbroadcasts"
8 | minSdkVersion project.ext.minSdkVersion
9 | targetSdkVersion project.ext.targetSdkVersion
10 |
11 | versionCode 210
12 | versionName '2.1.0'
13 |
14 | // TermOnePlus applicationId
15 | manifestPlaceholders = [ termApplicationId:"com.termoneplus"]
16 | buildConfigField("String", "TERM_APPLICATION_ID", "\"com.termoneplus\"")
17 | }
18 | compileOptions {
19 | sourceCompatibility JavaVersion.VERSION_1_8
20 | targetCompatibility JavaVersion.VERSION_1_8
21 | }
22 | productFlavors {
23 | }
24 | buildTypes {
25 | release {
26 | minifyEnabled false
27 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
28 | }
29 | }
30 | }
31 |
32 | dependencies {
33 | implementation project(':emulatorview')
34 | }
35 |
--------------------------------------------------------------------------------
/samples/pathbroadcasts/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/samples/pathbroadcasts/src/main/assets/.gitattributes:
--------------------------------------------------------------------------------
1 | hello eol=lf
2 | ls eol=lf
3 |
--------------------------------------------------------------------------------
/samples/pathbroadcasts/src/main/assets/hello:
--------------------------------------------------------------------------------
1 | #!/system/bin/sh
2 |
3 | echo "Hello, world!"
4 | exit 0
5 |
--------------------------------------------------------------------------------
/samples/pathbroadcasts/src/main/assets/ls:
--------------------------------------------------------------------------------
1 | #!/system/bin/sh
2 |
3 | echo "Hello, I'm pretending to be ls!"
4 | exec /system/bin/ls "$@"
5 |
--------------------------------------------------------------------------------
/samples/pathbroadcasts/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Deprecated: Path Broadcast
4 |
5 |
--------------------------------------------------------------------------------
/samples/telnet/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/samples/telnet/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion project.ext.compileSdkVersion
5 | buildToolsVersion project.ext.buildToolsVersion
6 | defaultConfig {
7 | applicationId "com.termoneplus.sample.telnet"
8 | minSdkVersion project.ext.minSdkVersion
9 | targetSdkVersion project.ext.targetSdkVersion
10 |
11 | versionCode 210
12 | versionName '2.1.0'
13 | }
14 | compileOptions {
15 | sourceCompatibility JavaVersion.VERSION_1_8
16 | targetCompatibility JavaVersion.VERSION_1_8
17 | }
18 | productFlavors {
19 | }
20 | buildTypes {
21 | release {
22 | minifyEnabled false
23 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
24 | }
25 | }
26 | }
27 |
28 | dependencies {
29 | implementation project(':emulatorview')
30 | implementation 'androidx.appcompat:appcompat:1.3.0-beta01'
31 | }
32 |
--------------------------------------------------------------------------------
/samples/telnet/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
14 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/samples/telnet/src/main/java/jackpal/androidterm/sample/telnet/LaunchActivity.java:
--------------------------------------------------------------------------------
1 | package jackpal.androidterm.sample.telnet;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.view.View.OnClickListener;
7 | import android.widget.EditText;
8 |
9 | import androidx.appcompat.app.AppCompatActivity;
10 |
11 |
12 | /**
13 | * Provides a UI to launch the terminal emulator activity, connected to
14 | * either a local shell or a Telnet server.
15 | */
16 | public class LaunchActivity extends AppCompatActivity {
17 | private static final String TAG = "TelnetLaunchActivity";
18 |
19 | /**
20 | * Called when the activity is first created.
21 | */
22 | @Override
23 | public void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.launch_activity);
26 | final Context context = this;
27 | addClickListener(R.id.launchLocal, v -> {
28 | Intent intent = new Intent(context, TermActivity.class);
29 | intent.putExtra("type", "local");
30 | startActivity(intent);
31 | });
32 |
33 | final EditText hostEdit = findViewById(R.id.hostname);
34 | addClickListener(R.id.launchTelnet, v -> {
35 | Intent intent = new Intent(context, TermActivity.class);
36 | intent.putExtra("type", "telnet");
37 | String hostname = hostEdit.getText().toString();
38 | intent.putExtra("host", hostname);
39 | startActivity(intent);
40 | });
41 | }
42 |
43 | private void addClickListener(int buttonId, OnClickListener onClickListener) {
44 | findViewById(buttonId).setOnClickListener(onClickListener);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/samples/telnet/src/main/res/layout/launch_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
14 |
15 |
20 |
21 |
26 |
27 |
32 |
33 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/samples/telnet/src/main/res/layout/term_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
21 |
22 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/samples/telnet/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 16dp
6 |
7 |
--------------------------------------------------------------------------------
/samples/telnet/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | TermOnePlus(sample): Telnet
4 | Open shell
5 | Connect
6 | Telnet to:
7 | Send
8 | This example Telnet client demonstrates the use of the EmulatorView widget and the TermSession class.
9 |
10 |
11 | telehack.com
12 |
13 |
--------------------------------------------------------------------------------
/samples/telnet/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
30 |
31 |
32 |
33 |
34 |
40 |
41 |
42 |
47 |
48 |
49 |
50 |
51 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/scripts/termoneplus-launcher-foreground.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 |
3 | set -e
4 |
5 | cd `dirname $0`
6 |
7 | XCFFILE=../docs/termoneplus-launcher-icon.xcf
8 |
9 | for MODE in l m h xh xxh xxxh ; do
10 | case "$MODE" in
11 | l) dpi=120; continue;; # unused
12 | m) dpi=160;;
13 | h) dpi=240;;
14 | xh) dpi=320;;
15 | xxh) dpi=480;;
16 | xxxh) dpi=640;;
17 | *) dpi=160;;
18 | esac
19 |
20 | # launcher icon size = 32 dp * ( dpi / 160 ) * 1.5
21 | size=`expr $dpi \* 3 / 10`
22 | xsize=`expr $dpi / 2`
23 | off=`expr \( $xsize - $size \) / 2`
24 |
25 | qualifier=
26 | test -z "$MODE" || qualifier=-"$MODE"dpi
27 |
28 | PNGFILE=mipmap"$qualifier"/ic_launcher_foreground.png
29 | echo creating .../$PNGFILE ... >&2
30 |
31 | # Start gimp with python-fu batch-interpreter
32 | gimp -i --batch-interpreter=python-fu-eval -b - << EOF
33 | import gimpfu
34 |
35 | def convert(xcf_file, png_file):
36 | img = pdb.gimp_file_load(xcf_file, xcf_file)
37 | layer = pdb.gimp_image_merge_visible_layers(img, 1)
38 |
39 | #pdb.gimp_image_convert_indexed(img, NO_DITHER, MAKE_PALETTE, 255, False, True, '');
40 | pdb.gimp_image_scale(img, $size, $size);
41 | pdb.gimp_image_resize(img, $xsize, $xsize, $off, $off)
42 | pdb.gimp_layer_resize (layer, $xsize, $xsize, $off, $off)
43 |
44 | pdb.gimp_file_save(img, layer, png_file, png_file)
45 | pdb.gimp_image_delete(img)
46 |
47 | convert('$XCFFILE', '../term/src/main/res/$PNGFILE')
48 |
49 | pdb.gimp_quit(1)
50 | EOF
51 | done
52 |
--------------------------------------------------------------------------------
/scripts/termoneplus-launcher-resources.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 |
3 | set -e
4 |
5 | cd `dirname $0`
6 |
7 | for T in n r ; do
8 |
9 | case $T in
10 | n) XCFFILE=../docs/termoneplus-launcher-icon.xcf;;
11 | r) XCFFILE=../docs/termoneplus-launcher-round_icon.xcf;;
12 | *) exit 99;;
13 | esac
14 |
15 | for MODE in l m h xh xxh xxxh ; do
16 | case "$MODE" in
17 | l) dpi=120;;
18 | m) dpi=160;;
19 | h) dpi=240;;
20 | xh) dpi=320;;
21 | xxh) dpi=480;;
22 | xxxh) dpi=640;;
23 | *) dpi=160;;
24 | esac
25 |
26 | # launcher icon size = 32 dp * ( dpi / 160 ) * 1.5
27 | size=`expr $dpi \* 3 / 10`
28 |
29 | qualifier=
30 | test -z "$MODE" || qualifier=-"$MODE"dpi
31 |
32 | case $T in
33 | n) PNGFILE=mipmap"$qualifier"/ic_launcher.png;;
34 | r) PNGFILE=mipmap"$qualifier"/ic_launcher_round.png;;
35 | esac
36 | echo creating .../$PNGFILE ... >&2
37 |
38 | # Start gimp with python-fu batch-interpreter
39 | gimp -i --batch-interpreter=python-fu-eval -b - << EOF
40 | import gimpfu
41 |
42 | def convert(xcf_file, png_file):
43 | img = pdb.gimp_file_load(xcf_file, xcf_file)
44 | layer = pdb.gimp_image_merge_visible_layers(img, 1)
45 |
46 | #pdb.gimp_image_convert_indexed(img, NO_DITHER, MAKE_PALETTE, 255, False, True, '');
47 | pdb.gimp_image_scale(img, $size, $size);
48 |
49 | pdb.gimp_file_save(img, layer, png_file, png_file)
50 | pdb.gimp_image_delete(img)
51 |
52 | convert('$XCFFILE', '../term/src/main/res/$PNGFILE')
53 |
54 | pdb.gimp_quit(1)
55 | EOF
56 | done
57 | done
58 |
--------------------------------------------------------------------------------
/scripts/termoneplus-notification-resources.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 |
3 | set -e
4 |
5 | cd `dirname $0`
6 |
7 | SOURCE=../docs/termoneplus-notification-icon.svg
8 |
9 | for DENSITY in l m h xh xxh xxxh ; do
10 | #for VERSION in 11 9 '' ; do
11 | for VERSION in 11 ; do
12 | QUALIFIERS=
13 | test -n "$DENSITY" && QUALIFIERS="-$DENSITY"dpi
14 | case $DENSITY/$VERSION in
15 | l/11) W=18; H=18;;
16 | #l/9) W=12; H=19;;
17 | #l/) W=19; H=19;;
18 | m/11) W=24; H=24;;
19 | #m/9) W=16; H=25;;
20 | #m/) W=25; H=25;;
21 | h/11) W=36; H=36;;
22 | #h/9) W=24; H=38;;
23 | #h/) W=38; H=38;;
24 | xh/11) W=48; H=48;;
25 | #xh/9) W=32; H=50;;
26 | #xh/) W=50; H=50;;
27 | xxh/11) W=72; H=72;;
28 | #xxh/9) W=48; H=75;;
29 | #xxh/) W=75; H=75;;
30 | xxxh*) # TODO
31 | continue;;
32 | *)
33 | echo "unsupported density-version: $DENSITY-$VERSION" >&2
34 | exit 1
35 | ;;
36 | esac
37 | test -n "$VERSION" && QUALIFIERS=$QUALIFIERS-v$VERSION
38 |
39 | rsvg-convert -w $W -h $H $SOURCE -o notification-icon$QUALIFIERS.png
40 |
41 | #DIR=../term/src/main/res/drawable$QUALIFIERS
42 | DIR=../term/src/main/res/drawable"-$DENSITY"dpi
43 | test -d $DIR || mkdir -p $DIR
44 | mv -v notification-icon$QUALIFIERS.png $DIR/ic_stat_service_notification_icon.png
45 | done
46 | done
47 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':term'
2 | include ':libtermexec'
3 | include ':emulatorview'
4 | include ':samples:intents'
5 | include ':samples:pathbroadcasts'
6 | include ':samples:telnet'
7 |
--------------------------------------------------------------------------------
/term/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | # Android Studio < 3.5
3 | /.externalNativeBuild
4 | # Android Studio >= 3.5
5 | /.cxx
6 |
--------------------------------------------------------------------------------
/term/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion project.ext.compileSdkVersion
5 | buildToolsVersion project.ext.buildToolsVersion
6 | defaultConfig {
7 | applicationId "com.termoneplus"
8 | minSdkVersion project.ext.minSdkVersion
9 | targetSdkVersion project.ext.targetSdkVersion
10 |
11 | vectorDrawables.useSupportLibrary = true
12 |
13 | versionCode 353
14 | versionName '3.5.3'
15 |
16 | externalNativeBuild {
17 | cmake {
18 | arguments "-DAPPLICATION_ID:STRING=${applicationId}"
19 | }
20 | }
21 | }
22 | externalNativeBuild {
23 | cmake {
24 | path "src/CMakeLists.txt"
25 | }
26 | }
27 | compileOptions {
28 | sourceCompatibility JavaVersion.VERSION_1_8
29 | targetCompatibility JavaVersion.VERSION_1_8
30 | }
31 | productFlavors {
32 | }
33 | if (project.hasProperty("signing.properties")) {
34 |
35 | Properties properties = new Properties()
36 | properties.load(new FileInputStream(file(project.property("signing.properties"))))
37 |
38 | signingConfigs {
39 | release {
40 | storeFile file(properties["store.file"])
41 | storePassword properties["store.password"]
42 | keyAlias properties["key.alias"]
43 | keyPassword properties["key.password"]
44 | }
45 | }
46 |
47 | android.buildTypes.release.signingConfig = signingConfigs.release
48 | }
49 | buildTypes {
50 | release {
51 | minifyEnabled false
52 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
53 | }
54 | }
55 | }
56 |
57 | dependencies {
58 | implementation project(':emulatorview')
59 | implementation project(':libtermexec')
60 |
61 | implementation 'androidx.appcompat:appcompat:1.3.0-beta01'
62 | implementation 'androidx.preference:preference:1.1.1'
63 | implementation 'com.google.android.material:material:1.3.0-rc01'
64 | }
65 |
66 | task elfcleaner(type: Exec) {
67 | // only unix
68 | commandLine 'sh', '-c', 'find build/*/stripped* -name lib*.so -exec elf-cleaner {} \\;'
69 | }
70 |
71 | tasks.whenTaskAdded { task ->
72 | if (task.name.matches('strip.*DebugSymbols')) {
73 | task.finalizedBy elfcleaner
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/term/lint.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/term/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ##
2 | # Copyright (C) 2019 Roumen Petrov. All rights reserved.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | ##
16 |
17 | cmake_minimum_required(VERSION 2.4)
18 |
19 | add_executable(
20 | libexec-t1plus.so
21 | main/jni/appcmd.c
22 | main/jni/socket.c
23 | main/jni/atomicio.c
24 | )
25 | target_compile_definitions(
26 | libexec-t1plus.so
27 | PRIVATE
28 | PACKAGE_NAME="${APPLICATION_ID}"
29 | )
30 | target_compile_options(
31 | libexec-t1plus.so
32 | PRIVATE
33 | -fPIC
34 | )
35 | target_link_libraries(
36 | libexec-t1plus.so
37 | -pie
38 | )
39 |
--------------------------------------------------------------------------------
/term/src/main/assets/skel/shrc:
--------------------------------------------------------------------------------
1 | # Note build-in shell startup script sets unconditionally variable PS1
2 |
3 | #PS1='$ '
4 | #export PS1
5 |
--------------------------------------------------------------------------------
/term/src/main/java/com/termoneplus/BaseActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.termoneplus;
18 |
19 | import android.annotation.SuppressLint;
20 | import android.os.Bundle;
21 | import android.view.Menu;
22 | import androidx.annotation.CallSuper;
23 | import androidx.annotation.Nullable;
24 | import androidx.appcompat.app.AppCompatActivity;
25 | import androidx.appcompat.view.menu.MenuBuilder;
26 | import androidx.core.view.MenuCompat;
27 | import com.termoneplus.utils.ThemeManager;
28 |
29 | public class BaseActivity extends AppCompatActivity {
30 | @Override
31 | protected void onCreate(@Nullable Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | ThemeManager.setTheme(getApplicationContext(), null);
34 | }
35 |
36 | @SuppressLint("RestrictedApi")
37 | @CallSuper
38 | @Override
39 | public boolean onCreateOptionsMenu(Menu menu) {
40 | MenuCompat.setGroupDividerEnabled(menu, true);
41 | if (menu instanceof MenuBuilder) {
42 | ((MenuBuilder) menu).setOptionalIconsVisible(true);
43 | }
44 | return super.onCreateOptionsMenu(menu);
45 | }
46 |
47 | protected void restart(int rid) {
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/term/src/main/java/com/termoneplus/Permissions.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018-2019 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.termoneplus;
18 |
19 | import android.Manifest;
20 | import android.content.pm.PackageManager;
21 | import android.os.Build;
22 |
23 | import java.util.ArrayList;
24 |
25 | import androidx.appcompat.app.AppCompatActivity;
26 | import androidx.core.app.ActivityCompat;
27 |
28 |
29 | public class Permissions {
30 |
31 | public static final int REQUEST_EXTERNAL_STORAGE = 101;
32 |
33 | static String[] external_stogare_permissions = null;
34 |
35 |
36 | public static void constructExternalStoragePermissions() {
37 | if (external_stogare_permissions != null) return;
38 |
39 | ArrayList list = new ArrayList<>();
40 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN /*API Level 16*/) {
41 | // added in API level 16
42 | list.add(Manifest.permission.READ_EXTERNAL_STORAGE);
43 | }
44 | list.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
45 |
46 | external_stogare_permissions = list.toArray(new String[0]);
47 | }
48 |
49 | public static boolean permissionExternalStorage(AppCompatActivity activity) {
50 | boolean granted = true;
51 | constructExternalStoragePermissions();
52 | for (String permission : external_stogare_permissions) {
53 | int status = ActivityCompat.checkSelfPermission(activity, permission);
54 | if (status == PackageManager.PERMISSION_GRANTED) continue;
55 | granted = false;
56 | break;
57 | }
58 | return granted;
59 | }
60 |
61 | public static boolean shouldShowExternalStorageRationale(AppCompatActivity activity) {
62 | boolean flag = false;
63 | constructExternalStoragePermissions();
64 | for (String permission : external_stogare_permissions) {
65 | if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission)) {
66 | flag = true;
67 | break;
68 | }
69 | }
70 | return flag;
71 | }
72 |
73 | public static void requestPermissionExternalStorage(AppCompatActivity activity, int requestCode) {
74 | ActivityCompat.requestPermissions(activity, external_stogare_permissions, requestCode);
75 | }
76 |
77 | public static boolean isPermissionGranted(int[] grantResults) {
78 | // Note if request is cancelled, the result arrays are empty.
79 | for (int result : grantResults) {
80 | if (result != PackageManager.PERMISSION_GRANTED)
81 | return false;
82 | }
83 | return grantResults.length > 0; // i.e. false by default
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/term/src/main/java/com/termoneplus/TermActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018-2019 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.termoneplus;
18 |
19 | import android.content.SharedPreferences;
20 |
21 | import com.termoneplus.utils.ThemeManager;
22 | import jackpal.androidterm.Term;
23 |
24 | public class TermActivity extends Term {
25 | @Override
26 | public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
27 | // do not process preference "Theme Mode"
28 | if (ThemeManager.PREF_THEME_MODE.equals(key)) return;
29 |
30 | super.onSharedPreferenceChanged(sharedPreferences, key);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/term/src/main/java/com/termoneplus/TermPreferencesActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018-2020 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.termoneplus;
18 |
19 | import android.content.SharedPreferences;
20 | import android.os.Bundle;
21 | import android.view.MenuItem;
22 | import androidx.appcompat.app.ActionBar;
23 | import androidx.preference.EditTextPreference;
24 | import androidx.preference.ListPreference;
25 | import androidx.preference.PreferenceFragmentCompat;
26 | import androidx.preference.PreferenceManager;
27 | import com.termoneplus.utils.ConsoleStartupScript;
28 | import com.termoneplus.utils.ThemeManager;
29 |
30 | import java.util.Objects;
31 |
32 |
33 | public class TermPreferencesActivity extends BaseActivity {
34 |
35 | protected void onCreate(Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 | setContentView(R.layout.activity_preferences);
38 | setSupportActionBar(findViewById(R.id.toolbar));
39 | ActionBar actionBar = getSupportActionBar();
40 | if (actionBar != null) {
41 | actionBar.setDisplayHomeAsUpEnabled(true);
42 | actionBar.setTitle(R.string.preferences);
43 | }
44 | getSupportFragmentManager()
45 | .beginTransaction()
46 | .replace(R.id.fragment, new TermPreferencesFragment())
47 | .commit();
48 | }
49 |
50 | @Override
51 | public boolean onOptionsItemSelected(MenuItem item) {
52 | if (item.getItemId() == android.R.id.home) { // Action bar home button selected
53 | finish();
54 | return true;
55 | }
56 | return super.onOptionsItemSelected(item);
57 | }
58 |
59 | public static class TermPreferencesFragment extends PreferenceFragmentCompat {
60 | @Override
61 | public void onCreatePreferences(Bundle bundle, String rootKey) {
62 | // Load the preferences from an XML resource
63 | setPreferencesFromResource(R.xml.preferences, rootKey);
64 |
65 | SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(requireActivity().getApplicationContext());
66 | String pref_home_path = getString(R.string.key_home_path_preference);
67 | String homedir = prefs.getString(pref_home_path, "");
68 |
69 | String pref_shellrc = getString(R.string.key_shellrc_preference);
70 | ((EditTextPreference) findPreference(pref_shellrc)).setText(ConsoleStartupScript.read(homedir));
71 |
72 | ListPreference themePref = findPreference(ThemeManager.PREF_THEME_MODE);
73 | Objects.requireNonNull(themePref).setOnPreferenceChangeListener((preference, newValue) -> {
74 | ThemeManager.setTheme(requireActivity().getApplicationContext(), Integer.parseInt((String) newValue));
75 | return true;
76 | });
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/term/src/main/java/com/termoneplus/WindowListFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2018-2019 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.termoneplus;
18 |
19 | import android.content.Context;
20 | import android.os.Bundle;
21 |
22 | import android.util.AttributeSet;
23 | import android.view.LayoutInflater;
24 | import android.view.View;
25 | import android.view.ViewGroup;
26 | import android.widget.AdapterView;
27 |
28 | import androidx.annotation.Nullable;
29 | import androidx.appcompat.widget.AppCompatImageView;
30 | import androidx.fragment.app.ListFragment;
31 |
32 |
33 | public class WindowListFragment extends ListFragment implements AdapterView.OnItemClickListener {
34 | private OnItemSelectedListener listener;
35 |
36 | @Override
37 | public void onAttach(Context context) {
38 | super.onAttach(context);
39 | try {
40 | listener = (OnItemSelectedListener) context;
41 | } catch (ClassCastException e) {
42 | throw new ClassCastException(context.toString()
43 | + " must implement OnItemSelectedListener");
44 | }
45 | }
46 |
47 | @Override
48 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
49 | return inflater.inflate(R.layout.fragment_windowlist, container, false);
50 | }
51 |
52 | @Override
53 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
54 | super.onActivityCreated(savedInstanceState);
55 | WindowListAdapter adapter = new WindowListAdapter(getActivity());
56 |
57 | setListAdapter(adapter);
58 | getListView().setOnItemClickListener(this);
59 | }
60 |
61 | @Override
62 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
63 | if (listener != null) listener.onPositionSelected(position);
64 | }
65 |
66 | public interface OnItemSelectedListener {
67 | void onPositionSelected(int position);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/term/src/main/java/com/termoneplus/utils/ConsoleStartupScript.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.termoneplus.utils;
18 |
19 | import android.text.TextUtils;
20 |
21 | import java.io.BufferedReader;
22 | import java.io.File;
23 | import java.io.FileReader;
24 | import java.io.FileWriter;
25 | import java.io.IOException;
26 | import java.io.PrintWriter;
27 | import java.util.Date;
28 |
29 |
30 | public class ConsoleStartupScript {
31 | public static String read(String homedir) {
32 | StringBuilder builder = new StringBuilder();
33 | final String nl = System.getProperty("line.separator");
34 |
35 | try {
36 | BufferedReader in = new BufferedReader(new FileReader(getScriptFile(homedir)));
37 | while (true) {
38 | String line = in.readLine();
39 | if (line == null) break;
40 | builder.append(line).append(nl);
41 | }
42 | return builder.toString();
43 | } catch (IOException ignored) {
44 | }
45 | return "# ~/.shrc";
46 | }
47 |
48 | public static void write(String homedir, String script) {
49 | if (script == null) return;
50 | try {
51 | PrintWriter out = new PrintWriter(getScriptFile(homedir));
52 | for (String line : script.split("\n"))
53 | out.println(line);
54 | out.flush();
55 | out.close();
56 | } catch (IOException ignored) {
57 | }
58 | }
59 |
60 | public static void rename(String olddir, String newdir) {
61 | File oldshrc = getScriptFile(olddir);
62 | if (!oldshrc.exists()) return;
63 |
64 | File shrc = getScriptFile(newdir);
65 | oldshrc.renameTo(shrc);
66 | }
67 |
68 | public static File getScriptFile(String homedir) {
69 | return new File(homedir, ".shrc");
70 | }
71 |
72 | public static void migrateInitialCommand(String homedir, String cmd) {
73 | if (TextUtils.isEmpty(cmd)) return;
74 |
75 | try {
76 | PrintWriter out = new PrintWriter(
77 | new FileWriter(getScriptFile(homedir), true));
78 | out.println("");
79 | String timestamp = java.text.DateFormat.getDateTimeInstance().format(new Date());
80 | out.println("# migrated initial command (" + timestamp + "):");
81 | out.println(cmd);
82 | out.flush();
83 | out.close();
84 | } catch (IOException ignored) {
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/term/src/main/java/com/termoneplus/utils/ThemeManager.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2020 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.termoneplus.utils;
18 |
19 |
20 | import android.content.Context;
21 | import android.content.SharedPreferences;
22 | import android.content.res.Configuration;
23 | import androidx.annotation.NonNull;
24 | import androidx.annotation.Nullable;
25 | import androidx.appcompat.app.AppCompatDelegate;
26 | import androidx.preference.PreferenceManager;
27 | import jackpal.androidterm.emulatorview.ColorScheme;
28 |
29 | public class ThemeManager {
30 | public static final String PREF_THEME_MODE = "theme_mode";
31 |
32 | public static void setTheme(@NonNull Context context, @Nullable Integer mode) {
33 | if (mode == null) {
34 | mode = getTheme(context);
35 | }
36 | AppCompatDelegate.setDefaultNightMode(mode);
37 | }
38 |
39 | public static int getTheme(@NonNull Context context) {
40 | final SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
41 | return Integer.parseInt(sharedPreferences.getString(PREF_THEME_MODE, "" + AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM));
42 | }
43 |
44 | public static ColorScheme getColorSchemeMatchingTheme(Context context, ColorScheme colorScheme) {
45 | if (isNightMode(context) && colorScheme.isNightScheme()) {
46 | return colorScheme;
47 | } else {
48 | // Swap colours
49 | return new ColorScheme(colorScheme.getBackColor(), colorScheme.getForeColor(),
50 | colorScheme.getCursorBackColor(), colorScheme.getCursorForeColor(), false);
51 | }
52 | }
53 |
54 | public static boolean isNightMode(@NonNull Context context) {
55 | int currentNightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
56 | switch (currentNightMode) {
57 | case Configuration.UI_MODE_NIGHT_YES:
58 | return true;
59 | case Configuration.UI_MODE_NIGHT_NO:
60 | case Configuration.UI_MODE_NIGHT_UNDEFINED:
61 | default:
62 | return false;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/term/src/main/java/com/termoneplus/utils/WrapOpenURL.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017-2019 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.termoneplus.utils;
18 |
19 | import android.content.Context;
20 | import android.content.Intent;
21 | import android.content.pm.PackageManager;
22 | import android.content.pm.ResolveInfo;
23 | import android.net.Uri;
24 |
25 | import java.util.List;
26 |
27 | import androidx.appcompat.app.AlertDialog;
28 | import androidx.fragment.app.FragmentActivity;
29 |
30 |
31 | public class WrapOpenURL {
32 |
33 | public static void launch(Context context, Uri uri) {
34 |
35 | Intent intent = new Intent(Intent.ACTION_VIEW, uri);
36 |
37 | PackageManager pm = context.getPackageManager();
38 | List activities = pm.queryIntentActivities(intent, 0);
39 |
40 | if (activities.size() > 0) {
41 | try {
42 | context.startActivity(intent);
43 | } catch (android.content.ActivityNotFoundException e) {
44 | alert(context,
45 | android.R.drawable.ic_dialog_alert,
46 | "Failed to launch view action!"
47 | );
48 | }
49 | } else {
50 | alert(context,
51 | android.R.drawable.ic_dialog_info,
52 | "Missing view actions!"
53 | );
54 | }
55 | }
56 |
57 | public static void launch(Context context, String path) {
58 | Uri uri = Uri.parse(path);
59 | launch(context, uri);
60 | }
61 |
62 | public static void launch(Context context, int resId) {
63 | String path = context.getString(resId);
64 | launch(context, path);
65 | }
66 |
67 |
68 | private static void alert(Context context, int iconId, CharSequence message) {
69 | Class clazz = FragmentActivity.class;
70 | if (clazz.isInstance(context)) {
71 | new androidx.appcompat.app.AlertDialog.Builder(context)
72 | .setTitle(android.R.string.dialog_alert_title)
73 | .setIcon(iconId)
74 | .setMessage(message)
75 | .setNeutralButton(android.R.string.ok, null)
76 | .create().show();
77 | } else {
78 | new AlertDialog.Builder(context)
79 | .setTitle(android.R.string.dialog_alert_title)
80 | .setIcon(iconId)
81 | .setMessage(message)
82 | .setNeutralButton(android.R.string.ok, null)
83 | .create().show();
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/term/src/main/java/jackpal/androidterm/BoundSession.java:
--------------------------------------------------------------------------------
1 | package jackpal.androidterm;
2 |
3 | import android.os.ParcelFileDescriptor;
4 | import android.text.TextUtils;
5 | import jackpal.androidterm.util.TermSettings;
6 |
7 |
8 | class BoundSession extends GenericTermSession {
9 | private final String issuerTitle;
10 |
11 | private boolean fullyInitialized;
12 |
13 | BoundSession(ParcelFileDescriptor ptmxFd, TermSettings settings, String issuerTitle) {
14 | super(ptmxFd, settings, true);
15 |
16 | this.issuerTitle = issuerTitle;
17 | }
18 |
19 | @Override
20 | public String getTitle() {
21 | final String extraTitle = super.getTitle();
22 |
23 | return TextUtils.isEmpty(extraTitle)
24 | ? issuerTitle
25 | : issuerTitle + " — " + extraTitle;
26 | }
27 |
28 | @Override
29 | public void initializeEmulator(int columns, int rows) {
30 | super.initializeEmulator(columns, rows);
31 |
32 | fullyInitialized = true;
33 | }
34 |
35 | @Override
36 | boolean isFailFast() {
37 | return !fullyInitialized;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/term/src/main/java/jackpal/androidterm/RunShortcut.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015 Steven Luo
3 | * Copyright (C) 2019 Roumen Petrov. All rights reserved.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 |
18 | package jackpal.androidterm;
19 |
20 | import android.content.Intent;
21 | import android.util.Log;
22 |
23 | import com.termoneplus.Application;
24 |
25 | import java.security.GeneralSecurityException;
26 |
27 | import androidx.annotation.NonNull;
28 | import jackpal.androidterm.util.ShortcutEncryption;
29 |
30 |
31 | public final class RunShortcut extends RemoteInterface {
32 |
33 | @Override
34 | protected void processAction(@NonNull Intent intent, @NonNull String action) {
35 | switch (action) {
36 | case Application.ACTION_RUN_SHORTCUT:
37 | runShortcut(intent);
38 | break;
39 | }
40 | }
41 |
42 | private void runShortcut(@NonNull Intent intent) {
43 | // Decrypt and verify the command
44 | String command;
45 | try {
46 | String request = intent.getStringExtra(Application.ARGUMENT_SHELL_COMMAND);
47 | if (request == null) {
48 | Log.e(Application.APP_TAG, "No command provided in shortcut!");
49 | return;
50 | }
51 | ShortcutEncryption.Keys keys = ShortcutEncryption.getKeys(this);
52 | if (keys == null) {
53 | // No keys -- no valid shortcuts can exist
54 | Log.e(Application.APP_TAG, "No shortcut encryption keys found!");
55 | return;
56 | }
57 | command = ShortcutEncryption.decrypt(request, keys);
58 | } catch (GeneralSecurityException e) {
59 | Log.e(Application.APP_TAG, "Invalid shortcut: " + e.toString());
60 | return;
61 | }
62 |
63 | String handle = intent.getStringExtra(Application.ARGUMENT_WINDOW_HANDLE);
64 | if (handle != null) {
65 | // Target the request at an existing window if open
66 | handle = appendToWindow(handle, command);
67 | } else {
68 | // Open a new window
69 | handle = openNewWindow(command);
70 | }
71 |
72 | Intent result = new Intent();
73 | result.putExtra(Application.ARGUMENT_WINDOW_HANDLE, handle);
74 | setResult(RESULT_OK, result);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/term/src/main/java/jackpal/androidterm/TermView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2012 Steven Luo
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package jackpal.androidterm;
18 |
19 | import android.content.Context;
20 | import android.util.DisplayMetrics;
21 |
22 | import androidx.annotation.NonNull;
23 | import com.termoneplus.utils.ThemeManager;
24 | import jackpal.androidterm.emulatorview.ColorScheme;
25 | import jackpal.androidterm.emulatorview.EmulatorView;
26 | import jackpal.androidterm.emulatorview.TermSession;
27 | import jackpal.androidterm.util.TermSettings;
28 |
29 |
30 | public class TermView extends EmulatorView {
31 | public TermView(Context context, TermSession session, DisplayMetrics metrics) {
32 | super(context, session, metrics);
33 | }
34 |
35 | public void updatePrefs(TermSettings settings, ColorScheme scheme) {
36 | if (scheme == null) {
37 | scheme = settings.getColorScheme();
38 | }
39 |
40 | setTextSize(settings.getFontSize());
41 | setUseCookedIME(settings.useCookedIME());
42 | setColorScheme(ThemeManager.getColorSchemeMatchingTheme(getContext(), scheme));
43 | setBackKeyCharacter(settings.getBackKeyCharacter());
44 | setAltSendsEsc(settings.getAltSendsEscFlag());
45 | setControlKeyCode(settings.getControlKeyCode());
46 | setFnKeyCode(settings.getFnKeyCode());
47 | setTermType(settings.getTermType());
48 | setMouseTracking(settings.getMouseTrackingFlag());
49 | }
50 |
51 | public void updatePrefs(TermSettings settings) {
52 | updatePrefs(settings, null);
53 | }
54 |
55 | @Override
56 | @NonNull
57 | public String toString() {
58 | return getClass().toString() + '(' + getTermSession() + ')';
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/term/src/main/jni/appcmd.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2020 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 | #include "appinfo.h"
24 |
25 |
26 | static int/*bool*/
27 | get_info(int argc, char *argv[]) {
28 | int ret = 0, k = 0;
29 | char msg[1024];
30 | int msgres;
31 | char buf[4096];
32 | int sock;
33 |
34 | msgres = snprintf(msg, sizeof(msg), "get %s\n", argv[k]);
35 | if (msgres < 0 || msgres >= sizeof(msg))
36 | return 0;
37 |
38 | sock = open_appsocket();
39 | if (sock == -1) return 0;
40 |
41 | if (!write_msg(sock, msg)) goto done;
42 |
43 | for (k++; k < argc; k++) {
44 | msgres = snprintf(msg, sizeof(msg), "%s\n", argv[k]);
45 | if (msgres < 0 || msgres >= sizeof(msg))
46 | goto done;
47 | if (!write_msg(sock, msg)) goto done;
48 | }
49 | if (k > 1) {
50 | msgres = snprintf(msg, sizeof(msg), "%s\n", "");
51 | if (msgres < 0 || msgres >= sizeof(msg))
52 | goto done;
53 | if (!write_msg(sock, msg)) goto done;
54 | }
55 |
56 | while (1) {
57 | size_t len;
58 | int read_errno;
59 | errno = 0;
60 | len = atomicio(read, sock, buf, sizeof(buf));
61 | read_errno = errno;
62 | if (len > 0) {
63 | size_t res;
64 | ret = 1;
65 | errno = 0;
66 | res = atomicio(vwrite, STDOUT_FILENO, buf, len);
67 | if (res != len) {
68 | ret = 0;
69 | goto done;
70 | }
71 | }
72 | if (read_errno == EPIPE) break;
73 | }
74 | (void) fsync(STDOUT_FILENO);
75 |
76 | done:
77 | close(sock);
78 | return ret;
79 | }
80 |
81 |
82 | #include
83 |
84 | int
85 | main(int argc, char *argv[]) {
86 | int ret;
87 |
88 | if (argc < 2) exit(EX_USAGE);
89 |
90 | ret = get_info(argc - 1, argv + 1);
91 |
92 | return ret ? 0 : EX_SOFTWARE;
93 | }
94 |
--------------------------------------------------------------------------------
/term/src/main/jni/appinfo.h:
--------------------------------------------------------------------------------
1 | #ifndef TERMONEPLUS_APPINFO_H
2 | #define TERMONEPLUS_APPINFO_H
3 |
4 | /*
5 | * Copyright (C) 2019-2020 Roumen Petrov. All rights reserved.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License");
8 | * you may not use this file except in compliance with the License.
9 | * You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | #ifndef PACKAGE_NAME
21 | # error "package name is not defined"
22 | #endif
23 |
24 | int/*bool*/ get_socketname(char *buf, size_t len) ;
25 | int open_socket(const char *name);
26 | int open_appsocket(void);
27 |
28 |
29 | typedef ssize_t (*atomicio_f)(int fd, void *buf, size_t count);
30 | #define vwrite (atomicio_f)write
31 |
32 | size_t atomicio(atomicio_f f, int fd, void *buf, size_t count);
33 |
34 |
35 | int/*bool*/ write_msg(int sock, const char *msg);
36 |
37 | #endif /*TERMONEPLUS_APPINFO_H*/
38 |
--------------------------------------------------------------------------------
/term/src/main/jni/atomicio.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2020 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include "appinfo.h"
23 |
24 |
25 | /* Ensure all of data on socket comes through. f==read || f==vwrite */
26 | size_t
27 | atomicio(atomicio_f f, int fd, void *_buf, size_t n) {
28 | char *buf = _buf;
29 | size_t pos = 0;
30 | ssize_t res;
31 | struct pollfd pfd;
32 |
33 | pfd.fd = fd;
34 | pfd.events = (short) ((f == read) ? POLLIN : POLLOUT);
35 | while (n > pos) {
36 | res = (f)(fd, buf + pos, n - pos);
37 | switch (res) {
38 | case -1:
39 | if (errno == EINTR) {
40 | /* possible SIGALARM? */
41 | continue;
42 | }
43 | if (errno == EAGAIN || errno == EWOULDBLOCK) {
44 | (void) poll(&pfd, 1, -1);
45 | continue;
46 | }
47 | return 0;
48 | case 0:
49 | errno = EPIPE;
50 | return pos;
51 | default:
52 | pos += (size_t) res;
53 | }
54 | }
55 | return pos;
56 | }
57 |
58 |
59 | int/*bool*/
60 | write_msg(int sock, const char *msg) {
61 | size_t len, res;
62 | len = strlen(msg);
63 | res = atomicio(vwrite, sock, (void *) msg, len);
64 | return res == len;
65 | }
66 |
--------------------------------------------------------------------------------
/term/src/main/jni/socket.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019-2020 Roumen Petrov. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include "appinfo.h"
26 |
27 |
28 | int/*bool*/
29 | get_socketname(char *buf, size_t len) {
30 | int ret = snprintf(buf, len, "%s-app_info-%ld", PACKAGE_NAME, (long) getuid());
31 | return 0 < ret && ret < len;
32 | }
33 |
34 | int
35 | open_socket(const char *name) {
36 | int sock;
37 | struct sockaddr_un addr;
38 | size_t namelen;
39 | socklen_t addrlen;
40 |
41 | sock = socket(AF_UNIX, SOCK_STREAM, 0);
42 | if (sock == -1) {
43 | return -1;
44 | }
45 |
46 | memset(&addr, 0, sizeof(addr));
47 | addr.sun_family = AF_UNIX;
48 |
49 | namelen = strlen(name);
50 | if (namelen >= sizeof(addr.sun_path))
51 | namelen = sizeof(addr.sun_path) - 1;
52 | strncpy(addr.sun_path + 1, name, namelen);
53 | addrlen = (socklen_t) offsetof(struct sockaddr_un, sun_path) + 1 + (socklen_t) namelen;
54 |
55 | if (connect(sock, (const struct sockaddr *) &addr, addrlen) == -1) {
56 | close(sock);
57 | return -1;
58 | }
59 |
60 | return sock;
61 | }
62 |
63 |
64 | int
65 | open_appsocket() {
66 | char sockname[PATH_MAX + 1];
67 |
68 | if (!get_socketname(sockname, sizeof(sockname)))
69 | return -1;
70 |
71 | return open_socket(sockname);
72 | }
73 |
--------------------------------------------------------------------------------
/term/src/main/res/drawable-hdpi/ic_stat_service_notification_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/drawable-hdpi/ic_stat_service_notification_icon.png
--------------------------------------------------------------------------------
/term/src/main/res/drawable-ldpi/ic_stat_service_notification_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/drawable-ldpi/ic_stat_service_notification_icon.png
--------------------------------------------------------------------------------
/term/src/main/res/drawable-mdpi/ic_stat_service_notification_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/drawable-mdpi/ic_stat_service_notification_icon.png
--------------------------------------------------------------------------------
/term/src/main/res/drawable-v21/header_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
24 |
27 |
33 |
34 |
--------------------------------------------------------------------------------
/term/src/main/res/drawable-xhdpi/ic_stat_service_notification_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/drawable-xhdpi/ic_stat_service_notification_icon.png
--------------------------------------------------------------------------------
/term/src/main/res/drawable-xxhdpi/ic_stat_service_notification_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/drawable-xxhdpi/ic_stat_service_notification_icon.png
--------------------------------------------------------------------------------
/term/src/main/res/drawable/background_rectangle.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
21 |
22 |
25 |
26 |
--------------------------------------------------------------------------------
/term/src/main/res/drawable/fs_directory_24dp.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
24 |
25 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/term/src/main/res/drawable/fs_file_24dp.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
24 |
25 |
35 |
36 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/term/src/main/res/drawable/fs_parent_24dp.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
24 |
25 |
38 |
39 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/term/src/main/res/drawable/fs_unknown_24dp.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
24 |
27 |
28 |
--------------------------------------------------------------------------------
/term/src/main/res/drawable/header_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
24 |
27 |
32 |
38 |
39 |
--------------------------------------------------------------------------------
/term/src/main/res/drawable/ic_add_circle_outline_24dp.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/term/src/main/res/drawable/ic_close_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/term/src/main/res/drawable/ic_email_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/term/src/main/res/drawable/ic_help_outline_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/term/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/term/src/main/res/drawable/ic_settings_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/term/src/main/res/drawable/ic_stat_service_notification_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/drawable/ic_stat_service_notification_icon.png
--------------------------------------------------------------------------------
/term/src/main/res/drawable/ic_vpn_key_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/term/src/main/res/drawable/ic_windows_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
24 |
25 |
35 |
36 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/term/src/main/res/layout/actionbar_windowlist.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/term/src/main/res/layout/activity_file_selection.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
26 |
27 |
31 |
32 |
38 |
39 |
40 |
41 |
49 |
50 |
59 |
60 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/term/src/main/res/layout/activity_preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
17 |
18 |
19 |
20 |
25 |
26 |
--------------------------------------------------------------------------------
/term/src/main/res/layout/activity_term.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
23 |
24 |
29 |
30 |
37 |
38 |
43 |
44 |
45 |
46 |
47 |
48 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/term/src/main/res/layout/activity_term_floatbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
23 |
24 |
34 |
35 |
41 |
42 |
50 |
51 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/term/src/main/res/layout/content_file_selection.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
23 |
24 |
30 |
31 |
33 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/term/src/main/res/layout/fragment_windowlist.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
24 |
25 |
34 |
35 |
36 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/term/src/main/res/layout/item_window.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
24 |
25 |
35 |
36 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/term/src/main/res/layout/pref_shell_script.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
23 |
24 |
30 |
31 |
40 |
41 |
47 |
48 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/term/src/main/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
58 |
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-hdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-ldpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-ldpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-mdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
--------------------------------------------------------------------------------
/term/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/term/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/term/src/main/res/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | #FF121212
20 | #FF121212
21 | #FFC89666
22 | @android:color/white
23 | #FFBEBEBE
24 |
25 |
--------------------------------------------------------------------------------
/term/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
22 |
23 |
--------------------------------------------------------------------------------
/term/src/main/res/values-sv/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Terminalemulator
5 | Inställningar
6 | Återställ terminal
7 | E-posta till
8 | Special tangenter
9 | Växla till virtuellt tangentbord
10 | Aktivera VäckningsLås
11 | Inaktivera VäckningsLås
12 | Aktivera WifiLås
13 | Inaktivera WifiLås
14 | Redigera text
15 | Markera text
16 | Kopiera allt
17 | Klistra in
18 | Terminalsessionen är igång
19 | Skärm
20 | Statusfält
21 | Visa/Dölj statusfält
22 | Statusfält
23 | Markörstil
24 | Välj markörstil.
25 | Markörstil
26 | Blinkande markör
27 | Välj blinkande markör
28 | Blinkande markör
29 | Text
30 | Teckenstorlek
31 | Välj teckenhöjd i punkter.
32 | Teckenstorlek
33 | Färger
34 | Välj textfärg.
35 | Textfärg
36 | Tangentbord
37 | Ctrl-tangent
38 | Välj Ctrl-tangent
39 | Ctrl-tangent
40 | Fn-tangent
41 | Välj Fn-tangent.
42 | Fn-tangent
43 | Inmatningsmetod
44 | Välj inmatningsmetod för virtuellt tangentbord.
45 | Inmatningsmetod
46 | Skal
47 | Kommandorad
48 | Ange skalkommandorad.
49 | Skal
50 | Inledande kommando
51 | Skickas till skalet när det börjar.
52 | Inledande kommando
53 |
54 |
--------------------------------------------------------------------------------
/term/src/main/res/values-tr/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 | Uyarı çubuğunu göster
21 | Uyarı çubuğunu sakla
22 |
23 |
24 |
25 | Non-blinking cursor
26 | Blinking cursor
27 |
28 |
29 |
30 | Rectangle
31 | Underline
32 | Vertical bar
33 |
34 |
35 |
36 | 4 x 8 piksel
37 | 6 pt
38 | 7 pt
39 | 8 pt
40 | 9 pt
41 | 10 pt
42 | 12 pt
43 | 14 pt
44 | 16 pt
45 | 20 pt
46 | 24 pt
47 | 28 pt
48 | 32 pt
49 | 36 pt
50 | 42 pt
51 | 48 pt
52 | 64 pt
53 | 72 pt
54 | 96 pt
55 | 144 pt
56 | 288 pt
57 |
58 |
59 |
60 | Beyaz arkaplan üzerinde siyah metin
61 | Siyah arkaplan üzerinde beyaz metin
62 | Mavi arkaplan üzerinde beyaz metin
63 | Siyah arkaplan üzerinde yeşil metin
64 | Siyah arkaplan üzerinde turuncu metin
65 | Siyah arkaplan üzerinde kırmızı metin
66 | Holo blue text on black
67 | Solarized Light
68 | Solarized Dark
69 | Linux Console
70 | Dark Pastels
71 |
72 |
73 |
74 | Jog ball
75 | \@ Tuşu
76 | Sol Alt Tuşu
77 | Sağ Alt Tuşu
78 | Ses Arttırma Tuşu
79 | Ses Kısma Tuşu
80 | Kamera Tuşu
81 | None
82 |
83 |
84 |
85 | Harf tabanlı
86 | Kelime tabanlı
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/term/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/term/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 | @android:color/white
20 | @android:color/white
21 | #6200EE
22 | #DE000000
23 | #99000000
24 |
25 | #FFFFFFFF
26 | #FFFF0000
27 | #FF00FF00
28 | #FF0000FF
29 |
30 |
--------------------------------------------------------------------------------
/term/src/main/res/values/defaults.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1
5 | 1
6 | -1
7 | 0
8 | 0
9 | 0
10 | 0
11 | 10
12 | 1
13 | true
14 | 2
15 | 5
16 | 4
17 | 0
18 | false
19 | /system/bin/sh -
20 | true
21 |
22 | screen
23 | true
24 | true
25 |
26 | false
27 | true
28 |
29 |
--------------------------------------------------------------------------------
/term/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 | 16dp
3 | 8dp
4 | 4dp
5 | 16dp
6 |
7 | 16dp
8 | 16dp
9 | 16dp
10 |
11 |
--------------------------------------------------------------------------------
/term/src/main/res/values/id.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/term/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
29 |
33 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/tests/.gitattributes:
--------------------------------------------------------------------------------
1 | # test shell script must have unix(LF) end-of-line conversion
2 | background-lastline text eol=lf
3 | background-outofindex text eol=lf
4 | cursor-down text eol=lf
5 | cursor-down2 text eol=lf
6 | cursor-down3 text eol=lf
7 | cursor-up text eol=lf
8 | cursor-up2 text eol=lf
9 | cursor-up3 text eol=lf
10 | echo-smiley text eol=lf
11 | reset text eol=lf
12 | scroll-at-bottom-margin text eol=lf
13 |
--------------------------------------------------------------------------------
/tests/background-lastline:
--------------------------------------------------------------------------------
1 | # https://gitlab.com/termapps/termoneplus/issues/14
2 | # Remark : repeat test until last line is scrolled
3 | # Expected : default background from ':' until end of line
4 | # Result : background with color #160
5 |
6 | ESC=$'\033'
7 | CSI="${ESC}["
8 | RST="${CSI}m"
9 |
10 | # 6 × 6 × 6 cube (0 ≤ r, g, b ≤ 5)
11 | color=196 # 16 + 36 * {r} + 6 * {g} + {b}
12 |
13 | echo "${CSI}48;5;${color}mL1"
14 | echo "L2${RST}:"
15 |
--------------------------------------------------------------------------------
/tests/background-outofindex:
--------------------------------------------------------------------------------
1 | # https://gitlab.com/termapps/termoneplus/issues/19
2 | # Expected : ignore sequence and continue output with current background
3 | # Result : crash
4 |
5 | ESC=$'\033'
6 | CSI="${ESC}["
7 | RST="${CSI}m"
8 |
9 | # output four lines with background color #160(hex):
10 | echo "${CSI}48;5;196m"L1
11 | echo "${CSI}48;5;256m"L2 # incorrect
12 | echo "${CSI}48;5;260m"L3 # crash
13 | echo L4"${RST}"
14 |
--------------------------------------------------------------------------------
/tests/controlSequences/combiningCharReplacement.txt:
--------------------------------------------------------------------------------
1 | Overwriting a letter with combining diacritic with a letter without in an
2 | 80-column line:
3 |
4 | xxxxxMu[combining diaeresis]nchenxxx[...] ESC [ 7 G u:
5 | xxxxxMünchenxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[7Gu
6 |
7 | Overwriting a letter without combining diacritic with a letter with combining diacritic in an 80-column line:
8 |
9 | xxxxMunchenxxx[...] ESC [ 6 G u [combining diaeresis]:
10 | xxxxMunchenxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx[6Gü
11 |
--------------------------------------------------------------------------------
/tests/controlSequences/combiningChars.txt:
--------------------------------------------------------------------------------
1 | a combining grave accent: à
2 | a combining grave accent combining low line: à̲
3 | a combining enclosing circle backslash: à̲⃠
4 | musical symbol g clef: 𝄞
5 |
6 | a combining grave accent combining low line at the end of an 80-column line: à̲
7 |
--------------------------------------------------------------------------------
/tests/controlSequences/hideCursor.txt:
--------------------------------------------------------------------------------
1 | [?25lThe cursor is now hidden.
2 |
--------------------------------------------------------------------------------
/tests/controlSequences/setTitle.txt:
--------------------------------------------------------------------------------
1 | ]0;I am a title\Window title should now be 'I am a title'.
2 |
--------------------------------------------------------------------------------
/tests/controlSequences/showCursor.txt:
--------------------------------------------------------------------------------
1 | [?25hThe cursor is now visible.
2 |
--------------------------------------------------------------------------------
/tests/controlSequences/textStyle.txt:
--------------------------------------------------------------------------------
1 | Text style test
2 | normal: [0mtext[0m
3 | bold: [1mtext[0m
4 | faint: [2mtext[0m
5 | italic: [3mtext[0m (may show as inverse)
6 | underline: [4mtext[0m
7 | blink: [5mtext[0m (may show as bold)
8 | 6: [6mtext[0m
9 | inverse: [7mtext[0m
10 | invisible: [8mtext[0m
11 | bold-underline: [1;4mtext[0m
12 | bold-ul-inverse: [1;4;7mtext[0m
13 | invis-bold-ul: [1;4;8mtext[0m
14 | invis-bold-ul-invrs: [1;4;7;8mtext[0m
15 | everything: [1;2;3;4;5;6;7;8mtext[0m
16 | Reset bold/faint: [1;2;3;4;5;6;7mtext[22mtext[23;24;25;27mtext[0m
17 | Reset bold/faint: [1mtext[22mtext[0m
18 | Reset bold/faint: [2mtext[22mtext[0m
19 | dim colors: [31;42mred on green[0m
20 | bright colors: [91;102mred on green[0m
21 |
--------------------------------------------------------------------------------
/tests/cursor-down:
--------------------------------------------------------------------------------
1 | ESC=$'\033'
2 | CSI="${ESC}["
3 |
4 | # // ESC [ Pn J - ED - Erase in Display
5 | echo -n "${CSI}2J" # // Clear all
6 |
7 | # // Esc [ Pn ; Pn r - set top and bottom margins
8 | echo -n "${CSI}4;7r"
9 |
10 | # // ESC [ Pn ; H - Cursor Position
11 | echo -n "${CSI}7;1H" # at bottom margins
12 |
13 |
14 | # // ESC [ Pn B - Cursor Down
15 | echo -n "L1${CSI}BL2"
16 |
17 | sleep 1; echo text1
18 | sleep 1; echo text2
19 | sleep 1; echo text3
20 |
21 | #expected screen:
22 | #
23 | #
24 | #
25 | #L1L2text1
26 | #text2
27 | #text3
28 | #
29 | #<... empty lines ...>
30 |
--------------------------------------------------------------------------------
/tests/cursor-down2:
--------------------------------------------------------------------------------
1 | ESC=$'\033'
2 | CSI="${ESC}["
3 |
4 | # // ESC [ Pn J - ED - Erase in Display
5 | echo -n "${CSI}2J" # // Clear all
6 |
7 | # // Esc [ Pn ; Pn r - set top and bottom margins
8 | echo -n "${CSI}4;7r"
9 |
10 | # // ESC [ Pn ; H - Cursor Position
11 | echo -n "${CSI}2;1H" # above top margin
12 |
13 |
14 | # // ESC [ Pn B - Cursor Down
15 | echo -n "L1${CSI}6BL2" # stop at bottom margin!
16 |
17 | sleep 1; echo text1
18 | sleep 1; echo text2
19 | sleep 1; echo text3
20 |
21 | #expected screen:
22 | #
23 | #L1
24 | #
25 | # L2text1
26 | #text2
27 | #text3
28 | #
29 | #<... empty lines ...>
30 |
--------------------------------------------------------------------------------
/tests/cursor-down3:
--------------------------------------------------------------------------------
1 | ESC=$'\033'
2 | CSI="${ESC}["
3 |
4 | # // ESC [ Pn J - ED - Erase in Display
5 | echo -n "${CSI}2J" # // Clear all
6 |
7 | # // Esc [ Pn ; Pn r - set top and bottom margins
8 | echo -n "${CSI}4;7r"
9 |
10 | # // ESC [ Pn ; H - Cursor Position
11 | echo -n "${CSI}8;1H" # below bottom margin
12 |
13 |
14 | # // ESC [ Pn B - Cursor Down
15 | echo -n "L1${CSI}BL2"
16 |
17 | sleep 1; echo text1
18 | sleep 1; echo text2
19 | sleep 1; echo text3
20 |
21 | #expected screen:
22 | #
23 | #
24 | #
25 | #
26 | #
27 | #
28 | #L1
29 | # L2text1
30 | #text2
31 | #text3
32 | #
33 | #<... empty lines ...>
34 |
--------------------------------------------------------------------------------
/tests/cursor-up:
--------------------------------------------------------------------------------
1 | ESC=$'\033'
2 | CSI="${ESC}["
3 |
4 | # // ESC [ Pn J - ED - Erase in Display
5 | echo -n "${CSI}2J" # // Clear all
6 |
7 | # // Esc [ Pn ; Pn r - set top and bottom margins
8 | echo -n "${CSI}4;7r"
9 |
10 | # // ESC [ Pn ; H - Cursor Position
11 | echo -n "${CSI}4;1H" # at top margins
12 |
13 |
14 | # // ESC [ Pn A - Cursor Up
15 | echo -n "L1${CSI}AL2"
16 |
17 | sleep 1; echo text1
18 | sleep 1; echo text2
19 | sleep 1; echo text3
20 |
21 | #expected screen:
22 | #
23 | #
24 | #
25 | #L1L2text1
26 | #text2
27 | #text3
28 | #
29 | #<... empty lines ...>
30 |
--------------------------------------------------------------------------------
/tests/cursor-up2:
--------------------------------------------------------------------------------
1 | ESC=$'\033'
2 | CSI="${ESC}["
3 |
4 | # // ESC [ Pn J - ED - Erase in Display
5 | echo -n "${CSI}2J" # // Clear all
6 |
7 | # // Esc [ Pn ; Pn r - set top and bottom margins
8 | echo -n "${CSI}4;7r"
9 |
10 | # // ESC [ Pn ; H - Cursor Position
11 | echo -n "${CSI}2;1H" # above top margin
12 |
13 |
14 | # // ESC [ Pn A - Cursor Up
15 | echo -n "L1${CSI}AL2"
16 |
17 | sleep 1; echo text1
18 | sleep 1; echo text2
19 | sleep 1; echo text3
20 | sleep 1; echo text4
21 | sleep 1; echo text5
22 | sleep 1; echo text6
23 | sleep 1; echo text7
24 |
25 | #expected screen:
26 | # L2text1
27 | #text2
28 | #text3
29 | #text5
30 | #text6
31 | #text7
32 | #
33 | #<... empty lines ...>
34 |
--------------------------------------------------------------------------------
/tests/cursor-up3:
--------------------------------------------------------------------------------
1 | ESC=$'\033'
2 | CSI="${ESC}["
3 |
4 | # // ESC [ Pn J - ED - Erase in Display
5 | echo -n "${CSI}2J" # // Clear all
6 |
7 | # // Esc [ Pn ; Pn r - set top and bottom margins
8 | echo -n "${CSI}4;7r"
9 |
10 | # // ESC [ Pn ; H - Cursor Position
11 | echo -n "${CSI}8;1H" # below bottom margin
12 |
13 |
14 | # // ESC [ Pn A - Cursor Up
15 | echo -n "L1${CSI}6AL2" # stop at top margin
16 |
17 | sleep 1; echo text1
18 | sleep 1; echo text2
19 | sleep 1; echo text3
20 | sleep 2; echo text4
21 |
22 | #expected screen:
23 | #
24 | #
25 | #
26 | #text2
27 | #text3
28 | #text4
29 | #
30 | #L1
31 | #<... empty lines ...>
32 |
--------------------------------------------------------------------------------
/tests/echo-smiley:
--------------------------------------------------------------------------------
1 | # print "rolling on the floor laughing" emoji
2 | # UTF-8: \xf0\x9f\xa4\xa3
3 | # UTF-32: u+0001f923
4 |
5 | k=${1-263}
6 | while test $k -gt 0 ; do
7 | #printf '\U01F923' # format not supported
8 | #printf '\xf0\x9f\xa4\xa3' # command not found (toolbox)
9 | echo -n '🤣'
10 |
11 | # To reproduce issue #25 output from regression test
12 | # must ensure terminal to draw characters one by one!
13 | sleep 1
14 |
15 | #k=`expr $k - 1` # command not found (toolbox)
16 | ((k=$k-1))
17 | done
18 |
--------------------------------------------------------------------------------
/tests/emulatorview-test/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/tests/emulatorview-test/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/tests/emulatorview-test/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/tests/emulatorview-test/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/tests/emulatorview-test/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/tests/emulatorview-test/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/tests/emulatorview-test/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/tests/emulatorview-test/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/tests/emulatorview-test/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MuntashirAkon/termoneplus/02c1bfa9cfa4d24f39deb0047513e9ea42f6a183/tests/emulatorview-test/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/tests/emulatorview-test/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Emulatorview-testTest
5 |
6 |
--------------------------------------------------------------------------------
/tests/emulatorview-test/src/jackpal/androidterm/emulatorview/InputConnectionTest.java:
--------------------------------------------------------------------------------
1 | package jackpal.androidterm.emulatorview;
2 |
3 | import android.test.AndroidTestCase;
4 | // import android.test.mock.MockApplication;
5 | // import android.test.mock.MockContext;
6 | // import android.util.DisplayMetrics;
7 | // import android.view.inputmethod.InputConnection;
8 |
9 | public class InputConnectionTest extends AndroidTestCase {
10 |
11 | public InputConnectionTest() {
12 | super();
13 | }
14 |
15 | public void testBackSpace() {
16 | // MockContext cn = new MockContext();
17 | // MockApplication a = new MockApplication();
18 | // TermSession ts = new TermSession();
19 | // DisplayMetrics m = new DisplayMetrics();
20 | // EmulatorView e = new EmulatorView(cn, ts, m);
21 | // InputConnection c = e.onCreateInputConnection(null);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/tests/emulatorview-test/src/jackpal/androidterm/emulatorview/ModifierKeyTest.java:
--------------------------------------------------------------------------------
1 | package jackpal.androidterm.emulatorview;
2 |
3 | import android.test.AndroidTestCase;
4 | // import android.view.KeyEvent;
5 |
6 | public class ModifierKeyTest extends AndroidTestCase {
7 |
8 | public void testCtrlKey() {
9 | // ModifierKey mk = new ModifierKey(KeyEvent.KEYCODE_CTRL_LEFT);
10 | // assertFalse(mk.isActive());
11 | // mk.handleModifierKey(KeyEvent.KEYCODE_CTRL_LEFT, true);
12 | // assertTrue(mk.isActive());
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/tests/fullWidthText:
--------------------------------------------------------------------------------
1 | Make sure UTF-8 is enabled.
2 | Full-width text: [ABC]
3 | Normal-width text: [ABC ]
4 |
--------------------------------------------------------------------------------
/tests/issue145/README.md:
--------------------------------------------------------------------------------
1 | This directory contains files to help reproduce issue 145
2 |
3 | fuzzer.go generates random strings of UTF-encoded characters.
4 |
5 | issue145repro.txt - some text from a run of fuzzer.go.
6 |
7 | Created by ./fuzzer | head -c 983 | tail -c 6 >issue145repro.txt
8 |
9 | This is a minimal repro case for
10 |
11 | https://github.com/jackpal/Android-Terminal-Emulator/issues/145
12 |
13 | Repro steps
14 | -----------
15 |
16 | On a PC:
17 |
18 | adb shell mkdir /data/local
19 | adb push issue145repro.txt /data/local/issue145repro.txt
20 |
21 | Run ATE
22 |
23 | Configure ATE's preferences for UTF8
24 |
25 | On ATE:
26 |
27 | cat /data/local/issue145repro.txt
28 |
--------------------------------------------------------------------------------
/tests/issue145/fuzzer.go:
--------------------------------------------------------------------------------
1 | // Generate a repatable string of characters for fuzz testing.
2 |
3 | package main
4 |
5 | import (
6 | "fmt"
7 | "math/rand"
8 | "unicode"
9 | )
10 |
11 | func main() {
12 | source := rand.NewSource(17)
13 | r := rand.New(source)
14 |
15 | for {
16 | switch r.Intn(4) {
17 | case 0:
18 | if r.Intn(20) == 0 {
19 | fmt.Printf("\n")
20 | } else {
21 | out(r, 32, 128)
22 | }
23 | case 1:
24 | out(r, 128, 256)
25 | case 2:
26 | out(r, 256, 0x10000)
27 | default:
28 | out(r, 0x10000, unicode.MaxRune)
29 | }
30 | }
31 | }
32 |
33 | func out(r *rand.Rand, begin, end int) {
34 | var c rune
35 | c = (rune)(r.Intn(end-begin) + begin)
36 | fmt.Printf("%c", c)
37 | }
38 |
--------------------------------------------------------------------------------
/tests/issue145/issue145repro-2.txt:
--------------------------------------------------------------------------------
1 | a8珮蠟茤퓉�B應Z
--------------------------------------------------------------------------------
/tests/issue145/issue145repro.txt:
--------------------------------------------------------------------------------
1 | 𬘴
2 | (
--------------------------------------------------------------------------------
/tests/issue149/colors.go:
--------------------------------------------------------------------------------
1 | // Generate a repatable string of characters for fuzz testing.
2 |
3 | package main
4 |
5 | import (
6 | "fmt"
7 | )
8 |
9 | func setFore(c int) {
10 | fmt.Printf("\x1b[38;5;%dm", c)
11 | }
12 |
13 | func setBack(c int) {
14 | fmt.Printf("\x1b[48;5;%dm", c)
15 | }
16 |
17 | func main() {
18 | /*
19 | for i := 0; i < 255; i++ {
20 | setFore(i)
21 | fmt.Printf("Fore Color %d \n", i)
22 | }
23 | setFore(0)
24 | */
25 |
26 | for i := 0; i < 255; i++ {
27 | setBack(i)
28 | fmt.Printf("Back Color %d \n", i)
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/tests/reset:
--------------------------------------------------------------------------------
1 | ESC=$'\033'
2 | echo -n "${ESC}c" # // ESC c - RIS - Reset to Initial State
3 |
--------------------------------------------------------------------------------
/tests/scroll-at-bottom-margin:
--------------------------------------------------------------------------------
1 | BS=$'\010'
2 | ESC=$'\033'
3 | CSI="${ESC}["
4 |
5 | # // Esc [ Pn ; Pn r - set top and bottom margins
6 | echo -n "${CSI}1;10r"
7 |
8 | # Select default (ISO 8859-1 mapping)
9 | echo -n "${ESC}(B"
10 |
11 | # Select Graphic Rendition / Default foreground and background color
12 | echo -n "${CSI}39;49m"
13 |
14 | # Set foreground color / White
15 | echo -n "${CSI}37m"
16 |
17 | # Set background color / Black
18 | echo -n "${CSI}40m"
19 |
20 | # Cursor Position
21 | echo -n "${CSI}H"
22 |
23 | # Erase in Display / clear entire screen(2)
24 | echo -n "${CSI}2J"
25 |
26 | # Cursor Position / 3x3
27 | echo -n "${CSI}3;3H"
28 |
29 | echo -n "X"
30 |
31 | # Cursor Horizontal Absolute / 9
32 | echo -n "${CSI}9G"
33 |
34 | echo -n "Z"
35 |
36 | # // Esc [ Pn ; Pn r - set top and bottom margins
37 | echo -n "${CSI}1;5r"
38 |
39 | # Cursor Position / 5x1
40 | echo -n "${CSI}5;1H"
41 |
42 | echo -n o
43 |
44 | sleep 2 # wait before to scroll (better visibility)
45 |
46 | # expected is White on Black line on scroll
47 | echo
48 |
49 | # move down to avoid shell prompt to override line
50 | # // ESC [ Pn B - Cursor Down
51 | echo -n "${CSI}B"
52 |
53 | sleep 2 # wait before to exit (better visibility)
54 |
--------------------------------------------------------------------------------
/tests/wideChars/combining-chars.txt:
--------------------------------------------------------------------------------
1 | East Asian wide characters with combining diacritics:
2 |
3 | 中文 [combining low line]:
4 | 中文̲
5 |
6 | xxx中[combining low line]文:
7 | xxx中̲文
8 |
9 | Overwriting an East Asian wide character with combining diacritic with an East
10 | Asian wide character without combining diacritic, in the middle of an 80-column
11 | line with mixed narrow and wide chars:
12 |
13 | xxx[...]xxx中文[combining low line]xxx[...]xxx你好ESC [ 23 G 国:
14 | xxxxxxxxxxxxxxxxxxxx中文̲xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好[23G国
15 |
16 | xxx[...]xxx中文[combining low line]。xxx[...]xxx你好xESC [ 23 G 国:
17 | xxxxxxxxxxxxxxxxxxxx中文̲。xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好x[23G国
18 |
19 | Overwriting an East Asian wide character with another one with a combining
20 | diacritic, in the middle of an 80-column line with mixed narrow and wide chars:
21 |
22 | xxx[...]xxx中文xxx[...]xxx你好ESC [ 23 G 国[combining low line]:
23 | xxxxxxxxxxxxxxxxxxxx中文xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好[23G国̲
24 |
25 | xxx[...]xxx中文。xxx[...]xxx你好xESC [ 23 G 国[combining low line]:
26 | xxxxxxxxxxxxxxxxxxxx中文。xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好x[23G国̲
27 |
28 | Overwriting a narrow character with an East Asian wide character with a
29 | combining diacritic, in the middle of an 80-column line with mixed narrow and
30 | wide chars:
31 |
32 | xxx[...]xxx中文xxx[...]xxx你好xESC [ 25 G 。[combining low line]:
33 | xxxxxxxxxxxxxxxxxxxx中文xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好x[25G。̲
34 |
35 | xxx[...]xxx中y文xxx[...]xxx你好ESC [ 23 G ,[combining low line]:
36 | xxxxxxxxxxxxxxxxxxxx中y文xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好[23G,̲
37 |
38 | Overwriting a narrow character with a combining diacritic with an East Asian
39 | wide character, in the middle of an 80-column line with mixed narrow and
40 | widechars:
41 |
42 | xxxxxxxxàxxx[...]xxx中文xxx[...]xxx你好xESC [ 9 G 中:
43 | xxxxxxxxàxxxxxxxxxxx中文xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好x[9G中
44 |
45 | xxxxxxxxàxxx[...]xxx中文xxx[...]xxx你好xESC [ 8 G 中:
46 | xxxxxxxxàxxxxxxxxxxx中文xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好x[8G中
47 |
48 | Overwriting an East Asian wide character with combining diacritic with a narrow
49 | character without combining diacritic, in the middle of an 80-column line with
50 | mixed narrow and wide chars:
51 |
52 | xxx[...]xxx中文[combining low line]xxx[...]xxx你好ESC [ 23 G y:
53 | xxxxxxxxxxxxxxxxxxxx中文̲xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好[23Gy
54 |
55 | xxx[...]xxx中文[combining low line]。xxx[...]xxx你好xESC [ 23 G y:
56 | xxxxxxxxxxxxxxxxxxxx中文̲。xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好x[23Gy
57 |
58 |
--------------------------------------------------------------------------------
/tests/wideChars/last-column-wrapping.txt:
--------------------------------------------------------------------------------
1 | A line taking 81 screen columns, with an East Asian wide character at column 79
2 | (should be truncated or wrapped on an 80-column terminal):
3 |
4 | xxxxxxxxxxxxxxxxxxxx中文xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好
5 |
--------------------------------------------------------------------------------
/tests/wideChars/linkification.txt:
--------------------------------------------------------------------------------
1 | A link on a line with East Asian wide characters:
2 | 中国国际航空公司 http://www.airchina.com/
3 |
4 | A link on a long line with East Asian wide characters (the link should be
5 | wrapped across two lines on an 80-column terminal):
6 | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 中国国际航空公司 http://www.airchina.com/
7 |
--------------------------------------------------------------------------------
/tests/wideChars/overwriting1.txt:
--------------------------------------------------------------------------------
1 | Overwriting an East Asian wide character with another one:
2 |
3 | 中国 ESC [ 2 D 文:
4 | 中国[2D文
5 |
6 | xxx中文 ESC [ 2 D 国:
7 | xxx中文[2D国
8 |
9 | Overwriting an East Asian wide character with another one, in the middle of
10 | an 80-column line with mixed narrow and wide chars:
11 |
12 | xxx[...]xxx中文xxx[...]xxx你好ESC [ 23 G 国:
13 | xxxxxxxxxxxxxxxxxxxx中文xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好[23G国
14 |
15 | xxx[...]xxx中文。xxx[...]xxx你好xESC [ 23 G 国:
16 | xxxxxxxxxxxxxxxxxxxx中文。xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好x[23G国
17 |
--------------------------------------------------------------------------------
/tests/wideChars/overwriting2.txt:
--------------------------------------------------------------------------------
1 | Inserting an East Asian wide character into the middle of another one:
2 |
3 | 中国 ESC [ D 文:
4 | 中国[D文
5 |
6 | xxx中文 ESC [ D 国:
7 | xxx中文[D国
8 |
9 | Inserting an East Asian wide character into the middle of another one, in the
10 | middle of an 80-column line with mixed narrow and wide chars:
11 |
12 | xxx[...]xxx中文xxx[...]xxx你好xESC [ 24 G 国:
13 | xxxxxxxxxxxxxxxxxxxx中文xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好x[24G国
14 |
15 | xxx[...]xxx中文。xxx[...]xxx你好ESC [ 24 G 国:
16 | xxxxxxxxxxxxxxxxxxxx中文。xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好[24G国
17 |
--------------------------------------------------------------------------------
/tests/wideChars/overwriting3.txt:
--------------------------------------------------------------------------------
1 | Overwriting an East Asian wide character with a narrow character:
2 |
3 | 中国 ESC [ 2 D x:
4 | 中国[2Dx
5 |
6 | xxx中文 ESC [ 2 D x:
7 | xxx中文[2Dx
8 |
9 | Overwriting an East Asian wide character with a narrow character, in the middle
10 | of an 80-column line with mixed narrow and wide chars:
11 |
12 | xxx[...]xxx中文xxx[...]xxx你好xESC [ 23 G y:
13 | xxxxxxxxxxxxxxxxxxxx中文xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好x[23Gy
14 |
15 | xxx[...]xxx中文。xxx[...]xxx你好ESC [ 23 G y:
16 | xxxxxxxxxxxxxxxxxxxx中文。xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好[23Gy
17 |
--------------------------------------------------------------------------------
/tests/wideChars/overwriting4.txt:
--------------------------------------------------------------------------------
1 | Overwriting a narrow character with an East Asian wide character:
2 |
3 | xxx ESC [ D 中:
4 | xxx[D中
5 |
6 | xxx ESC [ 3 D 中:
7 | xxx[3D中
8 |
9 | Overwriting a narrow character with an East Asian wide character, in the middle
10 | of an 80-column line with mixed narrow and wide chars:
11 |
12 | xxx[...]xxx中文xxx[...]xxx你好xESC [ 25 G 版:
13 | xxxxxxxxxxxxxxxxxxxx中文xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好x[25G版
14 |
15 | xxx[...]xxx中文y。xxx[...]xxx你好ESC [ 25 G 版:
16 | xxxxxxxxxxxxxxxxxxxx中文y。xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好[25G版
17 |
--------------------------------------------------------------------------------
/tests/wideChars/overwriting5.txt:
--------------------------------------------------------------------------------
1 | Inserting a narrow character into the middle of an East Asian wide character:
2 |
3 | 中国 ESC [ D x:
4 | 中国[Dx
5 |
6 | xxx中文 ESC [ D x:
7 | xxx中文[Dx
8 |
9 | Inserting a narrow character into the middle of an East Asian wide character,
10 | in the middle of an 80-column line with mixed narrow and wide chars:
11 |
12 | xxx[...]xxx中文xxx[...]xxx你好xESC [ 24 G y:
13 | xxxxxxxxxxxxxxxxxxxx中文xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好x[24Gy
14 |
15 | xxx[...]xxx中文。xxx[...]xxx你好ESC [ 24 G y:
16 | xxxxxxxxxxxxxxxxxxxx中文。xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx你好[24Gy
17 |
--------------------------------------------------------------------------------
/version.gradle:
--------------------------------------------------------------------------------
1 | tasks.named('wrapper') {
2 | gradleVersion = '6.8.1'
3 | distributionSha256Sum = 'fd591a34af7385730970399f473afabdb8b28d57fd97d6625c388d090039d6fd'
4 | }
5 | /* Notes for distributionSha256Sum
6 | Android Studio 3.5 explicitly require checksum to be removed, see
7 | https://github.com/gradle/gradle/issues/9361 !
8 | Restored for Android Studio 3.5.2, see
9 | https://issuetracker.google.com/issues/129261435 !
10 | */
11 |
--------------------------------------------------------------------------------