Compare commits

..

47 Commits

Author SHA1 Message Date
Leonid Pliushch
ad64dd7c3d update bootstrap archives 2020-10-12 20:39:28 +03:00
Fredrik Fornwall
dfc4595ec5 version 0.102 2020-10-02 10:30:18 +02:00
Fabian Henneke
8c80efb904 Add an "Autofill password" context menu action 2020-10-02 10:21:34 +02:00
Leonid Pliushch
564079c7e9 update .gitattributes 2020-10-01 01:08:39 +03:00
Leonid Pliushch
5b6fd9b88c version 0.101 2020-09-28 03:30:21 +03:00
Leonid Pliushch
63bfe95848 update bootstrap archives again
Fixes faulty dpkg https://github.com/termux/termux-packages/issues/5858.
2020-09-28 03:28:49 +03:00
Leonid Pliushch
af95a99854 version 0.100 2020-09-28 00:59:52 +03:00
Leonid Pliushch
25523ae224 fix bootstrap archive checksum for arm
Due to leading zero issues, SHA-256 checksum for ARM variant will
have 63 characters instead of correct 64...
2020-09-28 00:52:44 +03:00
Leonid Pliushch
665adb6895 update bootstrap archives 2020-09-28 00:46:38 +03:00
Henrik Grimler
eb7fda28df Merge pull request #1764 from agnostic-apollo/termux-run-command-crash-and-foreground-patch
Fix RunCommandService crash and foreground issue
2020-09-27 21:02:56 +02:00
agnostic-apollo
7063a3a9da Add @override annotation to onStartCommand() function of RunCommandService. 2020-09-18 22:25:05 +05:00
agnostic-apollo
6e02b99ff6 Update RunCommandService docs. 2020-09-18 22:22:35 +05:00
agnostic-apollo
9aae665bfc Fix issue where termux session does not come to foreground automatically in android >= 10 unless user manually clicks termux notification for "RUN_COMMAND" intents and "Termux:Tasker" plugin actions that have background mode "false" because of new restrictions of starting activities from background. This is done by adding "android.permission.SYSTEM_ALERT_WINDOW" permission in AndroidManifest.xml so that the user may optionally grant "Draw Over Apps" permission to termux to fix the issue. 2020-09-18 22:21:58 +05:00
agnostic-apollo
52ce6cc94b Add support for "$PREFIX/" and "~/" prefix in "RUN_COMMAND" intent extras for paths. 2020-09-18 22:21:31 +05:00
agnostic-apollo
f91168eff4 Fix issue where termux crashes occasionally in android >= 8 because "startForeground()" function is not being called before running "startForegroundService()" in RunCommandService. 2020-09-18 22:20:23 +05:00
Henrik Grimler
8faa5b2151 TerminalEmulator: fix bug in DECRQM handling
Reported in https://github.com/termux/termux-app/issues/1752
2020-09-12 21:27:24 +02:00
Leonid Pliushch
216cc10f3c Revert "add gradle distribution sha256"
Was initially added to try fix F-Droid builds but appears missing
distribution sha256 is not a cause of the issue.

F-Droid maintains own set of Gradle SHA-256 checksums.

This reverts commit cba80b6c0b.
2020-09-12 19:06:54 +00:00
Leonid Pliushch
cba80b6c0b add gradle distribution sha256 2020-09-01 03:38:53 +03:00
Leonid Pliushch
850faa25dd version 0.99 2020-08-26 20:51:05 +03:00
Leonid Pliushch
a108b2bd6b gradle 6.6.1 2020-08-26 20:40:29 +03:00
Leonid Pliushch
b95823d7a8 update bootstrap archives 2020-08-26 20:27:47 +03:00
Leonid Pliushch
382da7e8f7 terminal view: provide a workaroud for issue with some keyboards
Issue https://github.com/termux/termux-app/issues/686.

Note that there can be a better workaround which I don't know...
2020-08-26 20:04:22 +03:00
blackcat-917
ba9c118b50 readme: fix a copy-paste typo (#1720) 2020-08-22 00:17:45 +03:00
Leonid Pliushch
531c32f3c9 CI: do builds for android-10 branch 2020-08-16 22:56:55 +03:00
Leonid Pliushch
db2f50c76e extra keys: use TextUtils.join instead of String.join
String.join() is available only on Android API 26+ but our current
minimal is 24.

See https://github.com/termux/termux-app/issues/1670.
2020-08-14 15:08:32 +03:00
Leonid Pliushch
784affe39c linter: fix wakelock log tag
See https://github.com/termux/termux-app/issues/1670.
2020-08-14 15:03:51 +03:00
Leonid Pliushch
b486d29d23 fix RUN_COMMAND permission description
See https://github.com/termux/termux-app/issues/1713.
2020-08-14 14:50:34 +03:00
Fredrik Fornwall
332f1104a3 Update drawerlayout library 2020-08-09 00:07:35 +02:00
Leonid Pliushch
5a70be1523 terminal emulator: flush remaining process output data when terminating session 2020-08-08 02:22:47 +03:00
Leonid Pliushch
619552ec5c version 0.98 (v0.97 is non-release, so updating from 0.96 to 0.98) 2020-08-07 15:39:44 +03:00
Leonid Pliushch
70580abd50 update bootstrap archives 2020-08-07 15:39:11 +03:00
Henrik Grimler
f191c35851 Merge pull request #1693 from landfillbaby/patch-1
update WcWidth.java, add note about c version
2020-08-07 13:39:33 +02:00
lucy phipps
bd7ed28981 update WcWidth.java, add note about c version 2020-08-07 07:38:06 +01:00
hannesa2
b68bd107c1 Gradle 6.5.1 (#1686) 2020-08-04 15:37:18 +03:00
hannesa2
5075273362 Android Studio 4.0.1 (#1687) 2020-08-04 15:36:41 +03:00
cn
04268f4c20 move sdk version configs to gradle.properties (#1685) 2020-08-04 15:36:14 +03:00
Leonid Pliushch
6f24628fd2 version 0.96 2020-07-30 23:56:27 +03:00
Leonid Pliushch
debbe44809 update bootstrap archives 2020-07-30 23:47:26 +03:00
Agnostic Apollo
b2ff0e4051 Changed static string "EXTRA_EXECUTE_IN_BACKGROUND" access to public 2020-07-30 21:39:41 +03:00
Agnostic Apollo
9e7029b76a Receive "RUN_COMMAND_ARGUMENTS" extra for "RUN_COMMAND_ACTION" intent
as a string array extra instead of a string extra since TermuxService expects it that way.

Added "RUN_COMMAND_BACKGROUND" boolean extra so that Termux session can be started in background
when running a command.

Updated usage docs.

Check #1029 for details.
2020-07-30 21:39:41 +03:00
Egor Zhdanov
51370799c7 update notification icon 2020-07-14 12:36:56 +03:00
Danny Lin
0910844896 Invert selected text instead of highlighting
Highlighting text in the terminal often makes it hard to read, which
can be problematic for users who want to adjust or review selections
before copying them. For example, the default theme makes white and
green text hard to read on its light gray selection background, and
there are plenty of other themes where the choice of text and cursor
colors would hinder selection readability.

To fix this issue and make selected text more legible in nearly all
combinations of colors, invert selected text instead of highlighting it.
This is more common among terminal emulators anyway:
    Invert:    xterm, fbcon, kitty, Konsole, Alacritty, Tilix,
               gnome-terminal (7)
    Highlight: Termux, Terminal.app, iTerm2, Windows Terminal (4)
2020-07-12 17:54:47 +03:00
Danny Lin
f33ebf810f Fix selection rendering with alternate cursor styles
There is currently a bug where selection rendering is broken if the
active cursor shape is anything other than the default solid box.
Selected text is normally highlighted by effectively rendering a cursor
over all of the characters in the selection region, but if the cursor is
a bar, the resulting selection highlight is too narrow to cover the full
width of the selection. Similarly, if the cursor is an underline, all of
the selected text will be underlined instead of highlighted.

To fix this issue, treat selections different from cursors in the
rendering logic and force the renderer to always use the block cursor
style for rendering selections. That way, we get correct behavior
regardless of what the current cursor shape is.
2020-07-04 15:31:45 +03:00
Felix C. Stegerman
930029b5d2 export COLORTERM=truecolor 2020-06-22 02:07:20 +03:00
Leonid Pliushch
33def928cf add DEX2OATBOOTCLASSPATH environment variable 2020-06-19 22:25:51 +03:00
Leonid Pliushch
fc04a93990 get rid of Android 5 legacy stuff
We don't need LD_LIBRARY_PATH as of Android 7.0.
2020-06-19 22:18:28 +03:00
Leonid Pliushch
8d302aa9fe fix am on Android R 2020-06-19 22:18:21 +03:00
28 changed files with 641 additions and 431 deletions

8
.gitattributes vendored
View File

@@ -1,3 +1,5 @@
* text=auto * text=auto
*.bat eol=crlf *.bat eol=crlf
*.sh eol=lf *.gradle eol=lf
*.mk eol=lf
*.sh eol=lf

View File

@@ -4,9 +4,11 @@ on:
push: push:
branches: branches:
- master - master
- android-10
pull_request: pull_request:
branches: branches:
- master - master
- android-10
jobs: jobs:
build: build:

View File

@@ -4,9 +4,11 @@ on:
push: push:
branches: branches:
- master - master
- android-10
pull_request: pull_request:
branches: branches:
- master - master
- android-10
jobs: jobs:
validation: validation:

View File

@@ -4,9 +4,11 @@ on:
push: push:
branches: branches:
- master - master
- android-10
pull_request: pull_request:
branches: branches:
- master - master
- android-10
jobs: jobs:
testing: testing:

View File

@@ -16,7 +16,7 @@ terminal emulation). For the packages installable inside the app, see
## Installation ## Installation
Termux:Widget application can be obtained from: Termux application can be obtained from:
- [Google Play](https://play.google.com/store/apps/details?id=com.termux) - [Google Play](https://play.google.com/store/apps/details?id=com.termux)
- [F-Droid](https://f-droid.org/en/packages/com.termux/) - [F-Droid](https://f-droid.org/en/packages/com.termux/)

View File

@@ -3,22 +3,22 @@ plugins {
} }
android { android {
compileSdkVersion 28 compileSdkVersion project.properties.compileSdkVersion.toInteger()
ndkVersion '21.3.6528147' ndkVersion project.properties.ndkVersion
dependencies { dependencies {
implementation "androidx.annotation:annotation:1.1.0" implementation "androidx.annotation:annotation:1.1.0"
implementation "androidx.viewpager:viewpager:1.0.0" implementation "androidx.viewpager:viewpager:1.0.0"
implementation "androidx.drawerlayout:drawerlayout:1.0.0" implementation "androidx.drawerlayout:drawerlayout:1.1.0"
implementation project(":terminal-view") implementation project(":terminal-view")
} }
defaultConfig { defaultConfig {
applicationId "com.termux" applicationId "com.termux"
minSdkVersion 24 minSdkVersion project.properties.minSdkVersion.toInteger()
targetSdkVersion 28 targetSdkVersion project.properties.targetSdkVersion.toInteger()
versionCode 95 versionCode 102
versionName "0.95" versionName "0.102"
externalNativeBuild { externalNativeBuild {
ndkBuild { ndkBuild {
@@ -133,11 +133,11 @@ clean {
task downloadBootstraps(){ task downloadBootstraps(){
doLast { doLast {
def version = 25 def version = 31
downloadBootstrap("aarch64", "633baa1f7edfd81f6064338a68d1149aa203d4b24cbc4f7c64283aaca109609e", version) downloadBootstrap("aarch64", "e9149cb01735f04b180434093dfb8e703015f8a66044acaead7cbff1e536a990", version)
downloadBootstrap("arm", "a581a22e0d79a0e8cef9395b1bd951ba066ac2d688522e17cca0b3e1c0649daa", version) downloadBootstrap("arm", "8e5776074c58b3e94b1336f2ec0e840057fce9c089faee6683ae5c136441da7b", version)
downloadBootstrap("i686", "8288e13f0a6ddeb2ff9406d8f968a8930a58e9318d09fadb2b7c8970a034cfdc", version) downloadBootstrap("i686", "f89be9d0197fb9c6b498922ff0f95562fd17b63c934617858f959b8e452ade27", version)
downloadBootstrap("x86_64", "c99b80a18d6bbb64c24c5a64d6ee6b8d4306729ebd172662b807bcb4a46dd39a", version) downloadBootstrap("x86_64", "9aa97647afc085fae4e8485458a7d15f23db6e1e3601727f014af8b8eb4519a9", version)
} }
} }

View File

@@ -21,6 +21,7 @@
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application <application
android:extractNativeLibs="true" android:extractNativeLibs="true"

View File

@@ -139,6 +139,7 @@ public final class BackgroundJob {
List<String> environment = new ArrayList<>(); List<String> environment = new ArrayList<>();
environment.add("TERM=xterm-256color"); environment.add("TERM=xterm-256color");
environment.add("COLORTERM=truecolor");
environment.add("HOME=" + TermuxService.HOME_PATH); environment.add("HOME=" + TermuxService.HOME_PATH);
environment.add("PREFIX=" + TermuxService.PREFIX_PATH); environment.add("PREFIX=" + TermuxService.PREFIX_PATH);
environment.add("BOOTCLASSPATH=" + System.getenv("BOOTCLASSPATH")); environment.add("BOOTCLASSPATH=" + System.getenv("BOOTCLASSPATH"));
@@ -147,16 +148,18 @@ public final class BackgroundJob {
// EXTERNAL_STORAGE is needed for /system/bin/am to work on at least // EXTERNAL_STORAGE is needed for /system/bin/am to work on at least
// Samsung S7 - see https://plus.google.com/110070148244138185604/posts/gp8Lk3aCGp3. // Samsung S7 - see https://plus.google.com/110070148244138185604/posts/gp8Lk3aCGp3.
environment.add("EXTERNAL_STORAGE=" + System.getenv("EXTERNAL_STORAGE")); environment.add("EXTERNAL_STORAGE=" + System.getenv("EXTERNAL_STORAGE"));
// ANDROID_RUNTIME_ROOT and ANDROID_TZDATA_ROOT are required for `am` to run on Android Q
// These variables are needed if running on Android 10 and higher.
addToEnvIfPresent(environment, "ANDROID_ART_ROOT");
addToEnvIfPresent(environment, "DEX2OATBOOTCLASSPATH");
addToEnvIfPresent(environment, "ANDROID_I18N_ROOT");
addToEnvIfPresent(environment, "ANDROID_RUNTIME_ROOT"); addToEnvIfPresent(environment, "ANDROID_RUNTIME_ROOT");
addToEnvIfPresent(environment, "ANDROID_TZDATA_ROOT"); addToEnvIfPresent(environment, "ANDROID_TZDATA_ROOT");
if (failSafe) { if (failSafe) {
// Keep the default path so that system binaries can be used in the failsafe session. // Keep the default path so that system binaries can be used in the failsafe session.
environment.add("PATH= " + System.getenv("PATH")); environment.add("PATH= " + System.getenv("PATH"));
} else { } else {
if (shouldAddLdLibraryPath()) {
environment.add("LD_LIBRARY_PATH=" + TermuxService.PREFIX_PATH + "/lib");
}
environment.add("LANG=en_US.UTF-8"); environment.add("LANG=en_US.UTF-8");
environment.add("PATH=" + TermuxService.PREFIX_PATH + "/bin:" + TermuxService.PREFIX_PATH + "/bin/applets"); environment.add("PATH=" + TermuxService.PREFIX_PATH + "/bin:" + TermuxService.PREFIX_PATH + "/bin/applets");
environment.add("PWD=" + cwd); environment.add("PWD=" + cwd);
@@ -166,20 +169,6 @@ public final class BackgroundJob {
return environment.toArray(new String[0]); return environment.toArray(new String[0]);
} }
private static boolean shouldAddLdLibraryPath() {
try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(TermuxService.PREFIX_PATH + "/etc/apt/sources.list")))) {
String line;
while ((line = in.readLine()) != null) {
if (!line.startsWith("#") && line.contains("//termux.net stable")) {
return true;
}
}
} catch (IOException e) {
Log.e(LOG_TAG, "Error trying to read sources.list", e);
}
return false;
}
public static int getPid(Process p) { public static int getPid(Process p) {
try { try {
Field f = p.getClass().getDeclaredField("pid"); Field f = p.getClass().getDeclaredField("pid");

View File

@@ -1,5 +1,7 @@
package com.termux.app; package com.termux.app;
import android.text.TextUtils;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import org.json.JSONArray; import org.json.JSONArray;
@@ -305,7 +307,7 @@ class ExtraKeyButton {
keys[i] = ExtraKeysInfos.replaceAlias(keys[i]); keys[i] = ExtraKeysInfos.replaceAlias(keys[i]);
} }
this.key = String.join(" ", keys); this.key = TextUtils.join(" ", keys);
String displayFromConfig = config.optString("display", null); String displayFromConfig = config.optString("display", null);
if (displayFromConfig != null) { if (displayFromConfig != null) {

View File

@@ -1,6 +1,10 @@
package com.termux.app; package com.termux.app;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service; import android.app.Service;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Binder; import android.os.Binder;
@@ -8,6 +12,8 @@ import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.util.Log; import android.util.Log;
import com.termux.R;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
@@ -15,18 +21,44 @@ import java.nio.charset.StandardCharsets;
import java.util.Properties; import java.util.Properties;
/** /**
* When allow-external-apps property is set to "true", Termux is able to process execute intents * When allow-external-apps property is set to "true" in ~/.termux/termux.properties, Termux
* sent by third-party applications. * is able to process execute intents sent by third-party applications.
* *
* Third-party program must declare com.termux.permission.RUN_COMMAND permission and it should be * Third-party program must declare com.termux.permission.RUN_COMMAND permission and it should be
* granted by user. * granted by user.
* *
* Sample code to run command "top": * Absolute path of command or script must be given in "RUN_COMMAND_PATH" extra.
* The "RUN_COMMAND_ARGUMENTS", "RUN_COMMAND_WORKDIR" and "RUN_COMMAND_BACKGROUND" extras are
* optional. The workdir defaults to termux home. The background mode defaults to "false".
* The command path and workdir can optionally be prefixed with "$PREFIX/" or "~/" if an absolute
* path is not to be given.
*
* To automatically bring to foreground and start termux commands that were started with
* background mode "false" in android >= 10 without user having to click the notification manually,
* requires termux to be granted draw over apps permission due to new restrictions
* of starting activities from the background, this also applies to Termux:Tasker plugin.
*
* To reduce the chance of termux being killed by android even further due to violation of not
* being able to call startForeground() within ~5s of service start in android >= 8, the user
* may disable battery optimizations for termux.
*
* Sample code to run command "top" with java:
* Intent intent = new Intent(); * Intent intent = new Intent();
* intent.setClassName("com.termux", "com.termux.app.RunCommandService"); * intent.setClassName("com.termux", "com.termux.app.RunCommandService");
* intent.setAction("com.termux.RUN_COMMAND"); * intent.setAction("com.termux.RUN_COMMAND");
* intent.putExtra("com.termux.RUN_COMMAND_PATH", "/data/data/com.termux/files/usr/bin/top"); * intent.putExtra("com.termux.RUN_COMMAND_PATH", "/data/data/com.termux/files/usr/bin/top");
* intent.putExtra("com.termux.RUN_COMMAND_ARGUMENTS", new String[]{"-n", "5"});
* intent.putExtra("com.termux.RUN_COMMAND_WORKDIR", "/data/data/com.termux/files/home");
* intent.putExtra("com.termux.RUN_COMMAND_BACKGROUND", false);
* startService(intent); * startService(intent);
*
* Sample code to run command "top" with "am startservice" command:
* am startservice --user 0 -n com.termux/com.termux.app.RunCommandService
* -a com.termux.RUN_COMMAND
* --es com.termux.RUN_COMMAND_PATH '/data/data/com.termux/files/usr/bin/top'
* --esa com.termux.RUN_COMMAND_ARGUMENTS '-n,5'
* --es com.termux.RUN_COMMAND_WORKDIR '/data/data/com.termux/files/home'
* --ez com.termux.RUN_COMMAND_BACKGROUND 'false'
*/ */
public class RunCommandService extends Service { public class RunCommandService extends Service {
@@ -34,6 +66,10 @@ public class RunCommandService extends Service {
public static final String RUN_COMMAND_PATH = "com.termux.RUN_COMMAND_PATH"; public static final String RUN_COMMAND_PATH = "com.termux.RUN_COMMAND_PATH";
public static final String RUN_COMMAND_ARGUMENTS = "com.termux.RUN_COMMAND_ARGUMENTS"; public static final String RUN_COMMAND_ARGUMENTS = "com.termux.RUN_COMMAND_ARGUMENTS";
public static final String RUN_COMMAND_WORKDIR = "com.termux.RUN_COMMAND_WORKDIR"; public static final String RUN_COMMAND_WORKDIR = "com.termux.RUN_COMMAND_WORKDIR";
public static final String RUN_COMMAND_BACKGROUND = "com.termux.RUN_COMMAND_BACKGROUND";
private static final String NOTIFICATION_CHANNEL_ID = "termux_run_command_notification_channel";
private static final int NOTIFICATION_ID = 1338;
class LocalBinder extends Binder { class LocalBinder extends Binder {
public final RunCommandService service = RunCommandService.this; public final RunCommandService service = RunCommandService.this;
@@ -46,14 +82,24 @@ public class RunCommandService extends Service {
return mBinder; return mBinder;
} }
@Override
public void onCreate() {
runStartForeground();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) { public int onStartCommand(Intent intent, int flags, int startId) {
// Run again in case service is already started and onCreate() is not called
runStartForeground();
if (allowExternalApps() && RUN_COMMAND_ACTION.equals(intent.getAction())) { if (allowExternalApps() && RUN_COMMAND_ACTION.equals(intent.getAction())) {
Uri programUri = new Uri.Builder().scheme("com.termux.file").path(intent.getStringExtra(RUN_COMMAND_PATH)).build(); Uri programUri = new Uri.Builder().scheme("com.termux.file").path(parsePath(intent.getStringExtra(RUN_COMMAND_PATH))).build();
Intent execIntent = new Intent(TermuxService.ACTION_EXECUTE, programUri); Intent execIntent = new Intent(TermuxService.ACTION_EXECUTE, programUri);
execIntent.setClass(this, TermuxService.class); execIntent.setClass(this, TermuxService.class);
execIntent.putExtra(TermuxService.EXTRA_ARGUMENTS, intent.getStringExtra(RUN_COMMAND_ARGUMENTS)); execIntent.putExtra(TermuxService.EXTRA_ARGUMENTS, intent.getStringArrayExtra(RUN_COMMAND_ARGUMENTS));
execIntent.putExtra(TermuxService.EXTRA_CURRENT_WORKING_DIRECTORY, intent.getStringExtra(RUN_COMMAND_WORKDIR)); execIntent.putExtra(TermuxService.EXTRA_CURRENT_WORKING_DIRECTORY, parsePath(intent.getStringExtra(RUN_COMMAND_WORKDIR)));
execIntent.putExtra(TermuxService.EXTRA_EXECUTE_IN_BACKGROUND, intent.getBooleanExtra(RUN_COMMAND_BACKGROUND, false));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
this.startForegroundService(execIntent); this.startForegroundService(execIntent);
@@ -62,9 +108,56 @@ public class RunCommandService extends Service {
} }
} }
runStopForeground();
return Service.START_NOT_STICKY; return Service.START_NOT_STICKY;
} }
private void runStartForeground() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
setupNotificationChannel();
startForeground(NOTIFICATION_ID, buildNotification());
}
}
private void runStopForeground() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
stopForeground(true);
}
}
private Notification buildNotification() {
Notification.Builder builder = new Notification.Builder(this);
builder.setContentTitle(getText(R.string.application_name) + " Run Command");
builder.setSmallIcon(R.drawable.ic_service_notification);
// Use a low priority:
builder.setPriority(Notification.PRIORITY_LOW);
// No need to show a timestamp:
builder.setShowWhen(false);
// Background color for small notification icon:
builder.setColor(0xFF607D8B);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setChannelId(NOTIFICATION_CHANNEL_ID);
}
return builder.build();
}
private void setupNotificationChannel() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return;
String channelName = "Termux Run Command";
int importance = NotificationManager.IMPORTANCE_LOW;
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName, importance);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.createNotificationChannel(channel);
}
private boolean allowExternalApps() { private boolean allowExternalApps() {
File propsFile = new File(TermuxService.HOME_PATH + "/.termux/termux.properties"); File propsFile = new File(TermuxService.HOME_PATH + "/.termux/termux.properties");
if (!propsFile.exists()) if (!propsFile.exists())
@@ -83,4 +176,14 @@ public class RunCommandService extends Service {
return props.getProperty("allow-external-apps", "false").equals("true"); return props.getProperty("allow-external-apps", "false").equals("true");
} }
/** Replace "$PREFIX/" or "~/" prefix with termux absolute paths */
private String parsePath(String path) {
if(path != null && !path.isEmpty()) {
path = path.replaceAll("^\\$PREFIX\\/", TermuxService.PREFIX_PATH + "/");
path = path.replaceAll("^~\\/", TermuxService.HOME_PATH + "/");
}
return path;
}
} }

View File

@@ -38,6 +38,7 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.autofill.AutofillManager;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
import android.widget.EditText; import android.widget.EditText;
@@ -92,6 +93,7 @@ public final class TermuxActivity extends Activity implements ServiceConnection
private static final int CONTEXTMENU_STYLING_ID = 6; private static final int CONTEXTMENU_STYLING_ID = 6;
private static final int CONTEXTMENU_HELP_ID = 8; private static final int CONTEXTMENU_HELP_ID = 8;
private static final int CONTEXTMENU_TOGGLE_KEEP_SCREEN_ON = 9; private static final int CONTEXTMENU_TOGGLE_KEEP_SCREEN_ON = 9;
private static final int CONTEXTMENU_AUTOFILL_ID = 10;
private static final int MAX_SESSIONS = 8; private static final int MAX_SESSIONS = 8;
@@ -655,6 +657,12 @@ public final class TermuxActivity extends Activity implements ServiceConnection
menu.add(Menu.NONE, CONTEXTMENU_SELECT_URL_ID, Menu.NONE, R.string.select_url); menu.add(Menu.NONE, CONTEXTMENU_SELECT_URL_ID, Menu.NONE, R.string.select_url);
menu.add(Menu.NONE, CONTEXTMENU_SHARE_TRANSCRIPT_ID, Menu.NONE, R.string.select_all_and_share); menu.add(Menu.NONE, CONTEXTMENU_SHARE_TRANSCRIPT_ID, Menu.NONE, R.string.select_all_and_share);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AutofillManager autofillManager = getSystemService(AutofillManager.class);
if (autofillManager != null && autofillManager.isEnabled()) {
menu.add(Menu.NONE, CONTEXTMENU_AUTOFILL_ID, Menu.NONE, R.string.autofill_password);
}
}
menu.add(Menu.NONE, CONTEXTMENU_RESET_TERMINAL_ID, Menu.NONE, R.string.reset_terminal); menu.add(Menu.NONE, CONTEXTMENU_RESET_TERMINAL_ID, Menu.NONE, R.string.reset_terminal);
menu.add(Menu.NONE, CONTEXTMENU_KILL_PROCESS_ID, Menu.NONE, getResources().getString(R.string.kill_process, getCurrentTermSession().getPid())).setEnabled(currentSession.isRunning()); menu.add(Menu.NONE, CONTEXTMENU_KILL_PROCESS_ID, Menu.NONE, getResources().getString(R.string.kill_process, getCurrentTermSession().getPid())).setEnabled(currentSession.isRunning());
menu.add(Menu.NONE, CONTEXTMENU_STYLING_ID, Menu.NONE, R.string.style_terminal); menu.add(Menu.NONE, CONTEXTMENU_STYLING_ID, Menu.NONE, R.string.style_terminal);
@@ -870,6 +878,14 @@ public final class TermuxActivity extends Activity implements ServiceConnection
} }
return true; return true;
} }
case CONTEXTMENU_AUTOFILL_ID: {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AutofillManager autofillManager = getSystemService(AutofillManager.class);
if (autofillManager != null && autofillManager.isEnabled()) {
autofillManager.requestAutofill(mTerminalView);
}
}
}
default: default:
return super.onContextItemSelected(item); return super.onContextItemSelected(item);
} }

View File

@@ -63,7 +63,7 @@ public final class TermuxService extends Service implements SessionChangedCallba
public static final String EXTRA_ARGUMENTS = "com.termux.execute.arguments"; public static final String EXTRA_ARGUMENTS = "com.termux.execute.arguments";
public static final String EXTRA_CURRENT_WORKING_DIRECTORY = "com.termux.execute.cwd"; public static final String EXTRA_CURRENT_WORKING_DIRECTORY = "com.termux.execute.cwd";
private static final String EXTRA_EXECUTE_IN_BACKGROUND = "com.termux.execute.background"; public static final String EXTRA_EXECUTE_IN_BACKGROUND = "com.termux.execute.background";
/** This service is only bound from inside the same process and never uses IPC. */ /** This service is only bound from inside the same process and never uses IPC. */
class LocalBinder extends Binder { class LocalBinder extends Binder {
@@ -106,7 +106,7 @@ public final class TermuxService extends Service implements SessionChangedCallba
} else if (ACTION_LOCK_WAKE.equals(action)) { } else if (ACTION_LOCK_WAKE.equals(action)) {
if (mWakeLock == null) { if (mWakeLock == null) {
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, EmulatorDebug.LOG_TAG); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, EmulatorDebug.LOG_TAG + ":service-wakelock");
mWakeLock.acquire(); mWakeLock.acquire();
// http://tools.android.com/tech-docs/lint-in-studio-2-3#TOC-WifiManager-Leak // http://tools.android.com/tech-docs/lint-in-studio-2-3#TOC-WifiManager-Leak

View File

@@ -1,40 +1,24 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="108dp" android:width="24dp"
android:width="108dp" android:height="24dp"
android:viewportWidth="108" android:viewportWidth="24"
android:viewportHeight="108"> android:viewportHeight="24">
<!-- <!--
https://material.google.com/style/icons.html Updated notification icon compliant with system icons guidelines
https://material.io/design/iconography/system-icons.html
--> -->
<!-- A circle as the icon border. --> <group>
<path <clip-path
android:fillColor="#00000000" android:pathData="M0,0h24v24h-24z"/>
android:strokeColor="#FFF"
android:strokeWidth="3"
android:pathData="M18,54
A36,36 0 1,1 90,54
A36,36 0 1,1 18,54 Z" />
<!-- Keep in sync with ic_foreground.xml: --> <path
<path android:pathData="M5,4H2L8,12L2,20H5L11,12L5,4Z"
android:fillColor="#FFFFFF" android:fillColor="#ffffff"/>
android:pathData="M34,38
h6
l12,16
l-12,16
h-6
l12,-16
"
/>
<path <path
android:fillColor="#FFFFFF" android:pathData="M13,18H22V20H13V18Z"
android:pathData="M56,66 android:fillColor="#ffffff"/>
h18
v4
h-18
"
/>
</group>
</vector> </vector>

View File

@@ -19,7 +19,9 @@
android:layout_marginLeft="3dp" android:layout_marginLeft="3dp"
android:focusableInTouchMode="true" android:focusableInTouchMode="true"
android:scrollbarThumbVertical="@drawable/terminal_scroll_shape" android:scrollbarThumbVertical="@drawable/terminal_scroll_shape"
android:scrollbars="vertical" /> android:scrollbars="vertical"
android:importantForAutofill="no"
android:autofillHints="password" />
<LinearLayout <LinearLayout
android:id="@+id/left_drawer" android:id="@+id/left_drawer"

View File

@@ -3,7 +3,7 @@
<string name="application_name">Termux</string> <string name="application_name">Termux</string>
<string name="shared_user_label">Termux user</string> <string name="shared_user_label">Termux user</string>
<string name="run_command_permission_label">Run commands in Termux environment</string> <string name="run_command_permission_label">Run commands in Termux environment</string>
<string name="run_command_permission_description">Allow third-party applications to execute arbitrary commands within Termux environment.</string> <string name="run_command_permission_description">execute arbitrary commands within Termux environment</string>
<string name="new_session">New session</string> <string name="new_session">New session</string>
<string name="new_session_failsafe">Failsafe</string> <string name="new_session_failsafe">Failsafe</string>
<string name="toggle_soft_keyboard">Keyboard</string> <string name="toggle_soft_keyboard">Keyboard</string>
@@ -12,6 +12,7 @@
<string name="share_transcript_title">Terminal transcript</string> <string name="share_transcript_title">Terminal transcript</string>
<string name="help">Help</string> <string name="help">Help</string>
<string name="toggle_keep_screen_on">Keep screen on</string> <string name="toggle_keep_screen_on">Keep screen on</string>
<string name="autofill_password">Autofill password</string>
<string name="bootstrap_installer_body">Installing…</string> <string name="bootstrap_installer_body">Installing…</string>
<string name="bootstrap_error_title">Unable to install</string> <string name="bootstrap_error_title">Unable to install</string>

View File

@@ -4,7 +4,7 @@ buildscript {
google() google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.6.3' classpath 'com.android.tools.build:gradle:4.0.1'
} }
} }

View File

@@ -14,3 +14,8 @@
# org.gradle.parallel=true # org.gradle.parallel=true
org.gradle.jvmargs=-Xmx2048M org.gradle.jvmargs=-Xmx2048M
android.useAndroidX=true android.useAndroidX=true
minSdkVersion=24
targetSdkVersion=28
ndkVersion=21.3.6528147
compileSdkVersion=28

Binary file not shown.

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

2
gradlew vendored
View File

@@ -82,6 +82,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@@ -129,6 +130,7 @@ fi
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"` APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"` JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath # We build the pattern for arguments to be converted via cygpath

22
gradlew.bat vendored
View File

@@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init if "%ERRORLEVEL%" == "0" goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -54,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=% set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init if exist "%JAVA_EXE%" goto execute
echo. echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -64,28 +64,14 @@ echo location of your Java installation.
goto fail goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell

View File

@@ -17,12 +17,12 @@ ext {
} }
android { android {
compileSdkVersion 28 compileSdkVersion project.properties.compileSdkVersion.toInteger()
ndkVersion '21.3.6528147' ndkVersion project.properties.ndkVersion
defaultConfig { defaultConfig {
minSdkVersion 21 minSdkVersion project.properties.minSdkVersion.toInteger()
targetSdkVersion 28 targetSdkVersion project.properties.targetSdkVersion.toInteger()
externalNativeBuild { externalNativeBuild {
ndkBuild { ndkBuild {

View File

@@ -748,7 +748,7 @@ public final class TerminalEmulator {
value = (mScreen == mAltBuffer) ? 1 : 2; value = (mScreen == mAltBuffer) ? 1 : 2;
} else { } else {
int internalBit = mapDecSetBitToInternalBit(mode); int internalBit = mapDecSetBitToInternalBit(mode);
if (internalBit == -1) { if (internalBit != -1) {
value = isDecsetInternalBitSet(internalBit) ? 1 : 2; // 1=set, 2=reset. value = isDecsetInternalBitSet(internalBit) ? 1 : 2; // 1=set, 2=reset.
} else { } else {
Log.e(EmulatorDebug.LOG_TAG, "Got DECRQM for unrecognized private DEC mode=" + mode); Log.e(EmulatorDebug.LOG_TAG, "Got DECRQM for unrecognized private DEC mode=" + mode);

View File

@@ -110,13 +110,13 @@ public final class TerminalSession extends TerminalOutput {
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
if (msg.what == MSG_NEW_INPUT && isRunning()) { int bytesRead = mProcessToTerminalIOQueue.read(mReceiveBuffer, false);
int bytesRead = mProcessToTerminalIOQueue.read(mReceiveBuffer, false); if (bytesRead > 0) {
if (bytesRead > 0) { mEmulator.append(mReceiveBuffer, bytesRead);
mEmulator.append(mReceiveBuffer, bytesRead); notifyScreenUpdate();
notifyScreenUpdate(); }
}
} else if (msg.what == MSG_PROCESS_EXITED) { if (msg.what == MSG_PROCESS_EXITED) {
int exitCode = (Integer) msg.obj; int exitCode = (Integer) msg.obj;
cleanupResources(exitCode); cleanupResources(exitCode);
mChangeCallback.onSessionFinished(TerminalSession.this); mChangeCallback.onSessionFinished(TerminalSession.this);

View File

@@ -4,212 +4,225 @@ package com.termux.terminal;
* Implementation of wcwidth(3) for Unicode 9. * Implementation of wcwidth(3) for Unicode 9.
* *
* Implementation from https://github.com/jquast/wcwidth but we return 0 for unprintable characters. * Implementation from https://github.com/jquast/wcwidth but we return 0 for unprintable characters.
*
* IMPORTANT:
* Must be kept in sync with the following:
* https://github.com/termux/wcwidth
* https://github.com/termux/libandroid-support
* https://github.com/termux/termux-packages/tree/master/libandroid-support
*/ */
public final class WcWidth { public final class WcWidth {
// From https://github.com/jquast/wcwidth/blob/master/wcwidth/table_zero.py // From https://github.com/jquast/wcwidth/blob/master/wcwidth/table_zero.py
// t commit 0d7de112202cc8b2ebe9232ff4a5c954f19d561a (2016-07-02): // at commit b29897e5a1b403a0e36f7fc991614981cbc42475 (2020-07-14):
private static final int[][] ZERO_WIDTH = { private static final int[][] ZERO_WIDTH = {
{0x0300, 0x036f}, // Combining Grave Accent ..Combining Latin Small Le {0x00300, 0x0036f}, // Combining Grave Accent ..Combining Latin Small Le
{0x0483, 0x0489}, // Combining Cyrillic Titlo..Combining Cyrillic Milli {0x00483, 0x00489}, // Combining Cyrillic Titlo..Combining Cyrillic Milli
{0x0591, 0x05bd}, // Hebrew Accent Etnahta ..Hebrew Point Meteg {0x00591, 0x005bd}, // Hebrew Accent Etnahta ..Hebrew Point Meteg
{0x05bf, 0x05bf}, // Hebrew Point Rafe ..Hebrew Point Rafe {0x005bf, 0x005bf}, // Hebrew Point Rafe ..Hebrew Point Rafe
{0x05c1, 0x05c2}, // Hebrew Point Shin Dot ..Hebrew Point Sin Dot {0x005c1, 0x005c2}, // Hebrew Point Shin Dot ..Hebrew Point Sin Dot
{0x05c4, 0x05c5}, // Hebrew Mark Upper Dot ..Hebrew Mark Lower Dot {0x005c4, 0x005c5}, // Hebrew Mark Upper Dot ..Hebrew Mark Lower Dot
{0x05c7, 0x05c7}, // Hebrew Point Qamats Qata..Hebrew Point Qamats Qata {0x005c7, 0x005c7}, // Hebrew Point Qamats Qata..Hebrew Point Qamats Qata
{0x0610, 0x061a}, // Arabic Sign Sallallahou ..Arabic Small Kasra {0x00610, 0x0061a}, // Arabic Sign Sallallahou ..Arabic Small Kasra
{0x064b, 0x065f}, // Arabic Fathatan ..Arabic Wavy Hamza Below {0x0064b, 0x0065f}, // Arabic Fathatan ..Arabic Wavy Hamza Below
{0x0670, 0x0670}, // Arabic Letter Superscrip..Arabic Letter Superscrip {0x00670, 0x00670}, // Arabic Letter Superscrip..Arabic Letter Superscrip
{0x06d6, 0x06dc}, // Arabic Small High Ligatu..Arabic Small High Seen {0x006d6, 0x006dc}, // Arabic Small High Ligatu..Arabic Small High Seen
{0x06df, 0x06e4}, // Arabic Small High Rounde..Arabic Small High Madda {0x006df, 0x006e4}, // Arabic Small High Rounde..Arabic Small High Madda
{0x06e7, 0x06e8}, // Arabic Small High Yeh ..Arabic Small High Noon {0x006e7, 0x006e8}, // Arabic Small High Yeh ..Arabic Small High Noon
{0x06ea, 0x06ed}, // Arabic Empty Centre Low ..Arabic Small Low Meem {0x006ea, 0x006ed}, // Arabic Empty Centre Low ..Arabic Small Low Meem
{0x0711, 0x0711}, // Syriac Letter Superscrip..Syriac Letter Superscrip {0x00711, 0x00711}, // Syriac Letter Superscrip..Syriac Letter Superscrip
{0x0730, 0x074a}, // Syriac Pthaha Above ..Syriac Barrekh {0x00730, 0x0074a}, // Syriac Pthaha Above ..Syriac Barrekh
{0x07a6, 0x07b0}, // Thaana Abafili ..Thaana Sukun {0x007a6, 0x007b0}, // Thaana Abafili ..Thaana Sukun
{0x07eb, 0x07f3}, // Nko Combining Sh||t High..Nko Combining Double Dot {0x007eb, 0x007f3}, // Nko Combining Short High..Nko Combining Double Dot
{0x0816, 0x0819}, // Samaritan Mark In ..Samaritan Mark Dagesh {0x007fd, 0x007fd}, // Nko Dantayalan ..Nko Dantayalan
{0x081b, 0x0823}, // Samaritan Mark Epentheti..Samaritan Vowel Sign A {0x00816, 0x00819}, // Samaritan Mark In ..Samaritan Mark Dagesh
{0x0825, 0x0827}, // Samaritan Vowel Sign Sho..Samaritan Vowel Sign U {0x0081b, 0x00823}, // Samaritan Mark Epentheti..Samaritan Vowel Sign A
{0x0829, 0x082d}, // Samaritan Vowel Sign Lon..Samaritan Mark Nequdaa {0x00825, 0x00827}, // Samaritan Vowel Sign Sho..Samaritan Vowel Sign U
{0x0859, 0x085b}, // Mandaic Affrication Mark..Mandaic Gemination Mark {0x00829, 0x0082d}, // Samaritan Vowel Sign Lon..Samaritan Mark Nequdaa
{0x08d4, 0x08e1}, // (nil) .. {0x00859, 0x0085b}, // Mandaic Affrication Mark..Mandaic Gemination Mark
{0x08e3, 0x0902}, // Arabic Turned Damma Belo..Devanagari Sign Anusvara {0x008d3, 0x008e1}, // Arabic Small Low Waw ..Arabic Small High Sign S
{0x093a, 0x093a}, // Devanagari Vowel Sign Oe..Devanagari Vowel Sign Oe {0x008e3, 0x00902}, // Arabic Turned Damma Belo..Devanagari Sign Anusvara
{0x093c, 0x093c}, // Devanagari Sign Nukta ..Devanagari Sign Nukta {0x0093a, 0x0093a}, // Devanagari Vowel Sign Oe..Devanagari Vowel Sign Oe
{0x0941, 0x0948}, // Devanagari Vowel Sign U ..Devanagari Vowel Sign Ai {0x0093c, 0x0093c}, // Devanagari Sign Nukta ..Devanagari Sign Nukta
{0x094d, 0x094d}, // Devanagari Sign Virama ..Devanagari Sign Virama {0x00941, 0x00948}, // Devanagari Vowel Sign U ..Devanagari Vowel Sign Ai
{0x0951, 0x0957}, // Devanagari Stress Sign U..Devanagari Vowel Sign Uu {0x0094d, 0x0094d}, // Devanagari Sign Virama ..Devanagari Sign Virama
{0x0962, 0x0963}, // Devanagari Vowel Sign Vo..Devanagari Vowel Sign Vo {0x00951, 0x00957}, // Devanagari Stress Sign U..Devanagari Vowel Sign Uu
{0x0981, 0x0981}, // Bengali Sign Candrabindu..Bengali Sign Candrabindu {0x00962, 0x00963}, // Devanagari Vowel Sign Vo..Devanagari Vowel Sign Vo
{0x09bc, 0x09bc}, // Bengali Sign Nukta ..Bengali Sign Nukta {0x00981, 0x00981}, // Bengali Sign Candrabindu..Bengali Sign Candrabindu
{0x09c1, 0x09c4}, // Bengali Vowel Sign U ..Bengali Vowel Sign Vocal {0x009bc, 0x009bc}, // Bengali Sign Nukta ..Bengali Sign Nukta
{0x09cd, 0x09cd}, // Bengali Sign Virama ..Bengali Sign Virama {0x009c1, 0x009c4}, // Bengali Vowel Sign U ..Bengali Vowel Sign Vocal
{0x09e2, 0x09e3}, // Bengali Vowel Sign Vocal..Bengali Vowel Sign Vocal {0x009cd, 0x009cd}, // Bengali Sign Virama ..Bengali Sign Virama
{0x0a01, 0x0a02}, // Gurmukhi Sign Adak Bindi..Gurmukhi Sign Bindi {0x009e2, 0x009e3}, // Bengali Vowel Sign Vocal..Bengali Vowel Sign Vocal
{0x0a3c, 0x0a3c}, // Gurmukhi Sign Nukta ..Gurmukhi Sign Nukta {0x009fe, 0x009fe}, // Bengali Sandhi Mark ..Bengali Sandhi Mark
{0x0a41, 0x0a42}, // Gurmukhi Vowel Sign U ..Gurmukhi Vowel Sign Uu {0x00a01, 0x00a02}, // Gurmukhi Sign Adak Bindi..Gurmukhi Sign Bindi
{0x0a47, 0x0a48}, // Gurmukhi Vowel Sign Ee ..Gurmukhi Vowel Sign Ai {0x00a3c, 0x00a3c}, // Gurmukhi Sign Nukta ..Gurmukhi Sign Nukta
{0x0a4b, 0x0a4d}, // Gurmukhi Vowel Sign Oo ..Gurmukhi Sign Virama {0x00a41, 0x00a42}, // Gurmukhi Vowel Sign U ..Gurmukhi Vowel Sign Uu
{0x0a51, 0x0a51}, // Gurmukhi Sign Udaat ..Gurmukhi Sign Udaat {0x00a47, 0x00a48}, // Gurmukhi Vowel Sign Ee ..Gurmukhi Vowel Sign Ai
{0x0a70, 0x0a71}, // Gurmukhi Tippi ..Gurmukhi Addak {0x00a4b, 0x00a4d}, // Gurmukhi Vowel Sign Oo ..Gurmukhi Sign Virama
{0x0a75, 0x0a75}, // Gurmukhi Sign Yakash ..Gurmukhi Sign Yakash {0x00a51, 0x00a51}, // Gurmukhi Sign Udaat ..Gurmukhi Sign Udaat
{0x0a81, 0x0a82}, // Gujarati Sign Candrabind..Gujarati Sign Anusvara {0x00a70, 0x00a71}, // Gurmukhi Tippi ..Gurmukhi Addak
{0x0abc, 0x0abc}, // Gujarati Sign Nukta ..Gujarati Sign Nukta {0x00a75, 0x00a75}, // Gurmukhi Sign Yakash ..Gurmukhi Sign Yakash
{0x0ac1, 0x0ac5}, // Gujarati Vowel Sign U ..Gujarati Vowel Sign Cand {0x00a81, 0x00a82}, // Gujarati Sign Candrabind..Gujarati Sign Anusvara
{0x0ac7, 0x0ac8}, // Gujarati Vowel Sign E ..Gujarati Vowel Sign Ai {0x00abc, 0x00abc}, // Gujarati Sign Nukta ..Gujarati Sign Nukta
{0x0acd, 0x0acd}, // Gujarati Sign Virama ..Gujarati Sign Virama {0x00ac1, 0x00ac5}, // Gujarati Vowel Sign U ..Gujarati Vowel Sign Cand
{0x0ae2, 0x0ae3}, // Gujarati Vowel Sign Voca..Gujarati Vowel Sign Voca {0x00ac7, 0x00ac8}, // Gujarati Vowel Sign E ..Gujarati Vowel Sign Ai
{0x0b01, 0x0b01}, // ||iya Sign Candrabindu ..||iya Sign Candrabindu {0x00acd, 0x00acd}, // Gujarati Sign Virama ..Gujarati Sign Virama
{0x0b3c, 0x0b3c}, // ||iya Sign Nukta ..||iya Sign Nukta {0x00ae2, 0x00ae3}, // Gujarati Vowel Sign Voca..Gujarati Vowel Sign Voca
{0x0b3f, 0x0b3f}, // ||iya Vowel Sign I ..||iya Vowel Sign I {0x00afa, 0x00aff}, // Gujarati Sign Sukun ..Gujarati Sign Two-circle
{0x0b41, 0x0b44}, // ||iya Vowel Sign U ..||iya Vowel Sign Vocalic {0x00b01, 0x00b01}, // Oriya Sign Candrabindu ..Oriya Sign Candrabindu
{0x0b4d, 0x0b4d}, // ||iya Sign Virama ..||iya Sign Virama {0x00b3c, 0x00b3c}, // Oriya Sign Nukta ..Oriya Sign Nukta
{0x0b56, 0x0b56}, // ||iya Ai Length Mark ..||iya Ai Length Mark {0x00b3f, 0x00b3f}, // Oriya Vowel Sign I ..Oriya Vowel Sign I
{0x0b62, 0x0b63}, // ||iya Vowel Sign Vocalic..||iya Vowel Sign Vocalic {0x00b41, 0x00b44}, // Oriya Vowel Sign U ..Oriya Vowel Sign Vocalic
{0x0b82, 0x0b82}, // Tamil Sign Anusvara ..Tamil Sign Anusvara {0x00b4d, 0x00b4d}, // Oriya Sign Virama ..Oriya Sign Virama
{0x0bc0, 0x0bc0}, // Tamil Vowel Sign Ii ..Tamil Vowel Sign Ii {0x00b55, 0x00b56}, // (nil) ..Oriya Ai Length Mark
{0x0bcd, 0x0bcd}, // Tamil Sign Virama ..Tamil Sign Virama {0x00b62, 0x00b63}, // Oriya Vowel Sign Vocalic..Oriya Vowel Sign Vocalic
{0x0c00, 0x0c00}, // Telugu Sign Combining Ca..Telugu Sign Combining Ca {0x00b82, 0x00b82}, // Tamil Sign Anusvara ..Tamil Sign Anusvara
{0x0c3e, 0x0c40}, // Telugu Vowel Sign Aa ..Telugu Vowel Sign Ii {0x00bc0, 0x00bc0}, // Tamil Vowel Sign Ii ..Tamil Vowel Sign Ii
{0x0c46, 0x0c48}, // Telugu Vowel Sign E ..Telugu Vowel Sign Ai {0x00bcd, 0x00bcd}, // Tamil Sign Virama ..Tamil Sign Virama
{0x0c4a, 0x0c4d}, // Telugu Vowel Sign O ..Telugu Sign Virama {0x00c00, 0x00c00}, // Telugu Sign Combining Ca..Telugu Sign Combining Ca
{0x0c55, 0x0c56}, // Telugu Length Mark ..Telugu Ai Length Mark {0x00c04, 0x00c04}, // Telugu Sign Combining An..Telugu Sign Combining An
{0x0c62, 0x0c63}, // Telugu Vowel Sign Vocali..Telugu Vowel Sign Vocali {0x00c3e, 0x00c40}, // Telugu Vowel Sign Aa ..Telugu Vowel Sign Ii
{0x0c81, 0x0c81}, // Kannada Sign Candrabindu..Kannada Sign Candrabindu {0x00c46, 0x00c48}, // Telugu Vowel Sign E ..Telugu Vowel Sign Ai
{0x0cbc, 0x0cbc}, // Kannada Sign Nukta ..Kannada Sign Nukta {0x00c4a, 0x00c4d}, // Telugu Vowel Sign O ..Telugu Sign Virama
{0x0cbf, 0x0cbf}, // Kannada Vowel Sign I ..Kannada Vowel Sign I {0x00c55, 0x00c56}, // Telugu Length Mark ..Telugu Ai Length Mark
{0x0cc6, 0x0cc6}, // Kannada Vowel Sign E ..Kannada Vowel Sign E {0x00c62, 0x00c63}, // Telugu Vowel Sign Vocali..Telugu Vowel Sign Vocali
{0x0ccc, 0x0ccd}, // Kannada Vowel Sign Au ..Kannada Sign Virama {0x00c81, 0x00c81}, // Kannada Sign Candrabindu..Kannada Sign Candrabindu
{0x0ce2, 0x0ce3}, // Kannada Vowel Sign Vocal..Kannada Vowel Sign Vocal {0x00cbc, 0x00cbc}, // Kannada Sign Nukta ..Kannada Sign Nukta
{0x0d01, 0x0d01}, // Malayalam Sign Candrabin..Malayalam Sign Candrabin {0x00cbf, 0x00cbf}, // Kannada Vowel Sign I ..Kannada Vowel Sign I
{0x0d41, 0x0d44}, // Malayalam Vowel Sign U ..Malayalam Vowel Sign Voc {0x00cc6, 0x00cc6}, // Kannada Vowel Sign E ..Kannada Vowel Sign E
{0x0d4d, 0x0d4d}, // Malayalam Sign Virama ..Malayalam Sign Virama {0x00ccc, 0x00ccd}, // Kannada Vowel Sign Au ..Kannada Sign Virama
{0x0d62, 0x0d63}, // Malayalam Vowel Sign Voc..Malayalam Vowel Sign Voc {0x00ce2, 0x00ce3}, // Kannada Vowel Sign Vocal..Kannada Vowel Sign Vocal
{0x0dca, 0x0dca}, // Sinhala Sign Al-lakuna ..Sinhala Sign Al-lakuna {0x00d00, 0x00d01}, // Malayalam Sign Combining..Malayalam Sign Candrabin
{0x0dd2, 0x0dd4}, // Sinhala Vowel Sign Ketti..Sinhala Vowel Sign Ketti {0x00d3b, 0x00d3c}, // Malayalam Sign Vertical ..Malayalam Sign Circular
{0x0dd6, 0x0dd6}, // Sinhala Vowel Sign Diga ..Sinhala Vowel Sign Diga {0x00d41, 0x00d44}, // Malayalam Vowel Sign U ..Malayalam Vowel Sign Voc
{0x0e31, 0x0e31}, // Thai Character Mai Han-a..Thai Character Mai Han-a {0x00d4d, 0x00d4d}, // Malayalam Sign Virama ..Malayalam Sign Virama
{0x0e34, 0x0e3a}, // Thai Character Sara I ..Thai Character Phinthu {0x00d62, 0x00d63}, // Malayalam Vowel Sign Voc..Malayalam Vowel Sign Voc
{0x0e47, 0x0e4e}, // Thai Character Maitaikhu..Thai Character Yamakkan {0x00d81, 0x00d81}, // (nil) ..(nil)
{0x0eb1, 0x0eb1}, // Lao Vowel Sign Mai Kan ..Lao Vowel Sign Mai Kan {0x00dca, 0x00dca}, // Sinhala Sign Al-lakuna ..Sinhala Sign Al-lakuna
{0x0eb4, 0x0eb9}, // Lao Vowel Sign I ..Lao Vowel Sign Uu {0x00dd2, 0x00dd4}, // Sinhala Vowel Sign Ketti..Sinhala Vowel Sign Ketti
{0x0ebb, 0x0ebc}, // Lao Vowel Sign Mai Kon ..Lao Semivowel Sign Lo {0x00dd6, 0x00dd6}, // Sinhala Vowel Sign Diga ..Sinhala Vowel Sign Diga
{0x0ec8, 0x0ecd}, // Lao Tone Mai Ek ..Lao Niggahita {0x00e31, 0x00e31}, // Thai Character Mai Han-a..Thai Character Mai Han-a
{0x0f18, 0x0f19}, // Tibetan Astrological Sig..Tibetan Astrological Sig {0x00e34, 0x00e3a}, // Thai Character Sara I ..Thai Character Phinthu
{0x0f35, 0x0f35}, // Tibetan Mark Ngas Bzung ..Tibetan Mark Ngas Bzung {0x00e47, 0x00e4e}, // Thai Character Maitaikhu..Thai Character Yamakkan
{0x0f37, 0x0f37}, // Tibetan Mark Ngas Bzung ..Tibetan Mark Ngas Bzung {0x00eb1, 0x00eb1}, // Lao Vowel Sign Mai Kan ..Lao Vowel Sign Mai Kan
{0x0f39, 0x0f39}, // Tibetan Mark Tsa -phru ..Tibetan Mark Tsa -phru {0x00eb4, 0x00ebc}, // Lao Vowel Sign I ..Lao Semivowel Sign Lo
{0x0f71, 0x0f7e}, // Tibetan Vowel Sign Aa ..Tibetan Sign Rjes Su Nga {0x00ec8, 0x00ecd}, // Lao Tone Mai Ek ..Lao Niggahita
{0x0f80, 0x0f84}, // Tibetan Vowel Sign Rever..Tibetan Mark Halanta {0x00f18, 0x00f19}, // Tibetan Astrological Sig..Tibetan Astrological Sig
{0x0f86, 0x0f87}, // Tibetan Sign Lci Rtags ..Tibetan Sign Yang Rtags {0x00f35, 0x00f35}, // Tibetan Mark Ngas Bzung ..Tibetan Mark Ngas Bzung
{0x0f8d, 0x0f97}, // Tibetan Subjoined Sign L..Tibetan Subjoined Letter {0x00f37, 0x00f37}, // Tibetan Mark Ngas Bzung ..Tibetan Mark Ngas Bzung
{0x0f99, 0x0fbc}, // Tibetan Subjoined Letter..Tibetan Subjoined Letter {0x00f39, 0x00f39}, // Tibetan Mark Tsa -phru ..Tibetan Mark Tsa -phru
{0x0fc6, 0x0fc6}, // Tibetan Symbol Padma Gda..Tibetan Symbol Padma Gda {0x00f71, 0x00f7e}, // Tibetan Vowel Sign Aa ..Tibetan Sign Rjes Su Nga
{0x102d, 0x1030}, // Myanmar Vowel Sign I ..Myanmar Vowel Sign Uu {0x00f80, 0x00f84}, // Tibetan Vowel Sign Rever..Tibetan Mark Halanta
{0x1032, 0x1037}, // Myanmar Vowel Sign Ai ..Myanmar Sign Dot Below {0x00f86, 0x00f87}, // Tibetan Sign Lci Rtags ..Tibetan Sign Yang Rtags
{0x1039, 0x103a}, // Myanmar Sign Virama ..Myanmar Sign Asat {0x00f8d, 0x00f97}, // Tibetan Subjoined Sign L..Tibetan Subjoined Letter
{0x103d, 0x103e}, // Myanmar Consonant Sign M..Myanmar Consonant Sign M {0x00f99, 0x00fbc}, // Tibetan Subjoined Letter..Tibetan Subjoined Letter
{0x1058, 0x1059}, // Myanmar Vowel Sign Vocal..Myanmar Vowel Sign Vocal {0x00fc6, 0x00fc6}, // Tibetan Symbol Padma Gda..Tibetan Symbol Padma Gda
{0x105e, 0x1060}, // Myanmar Consonant Sign M..Myanmar Consonant Sign M {0x0102d, 0x01030}, // Myanmar Vowel Sign I ..Myanmar Vowel Sign Uu
{0x1071, 0x1074}, // Myanmar Vowel Sign Geba ..Myanmar Vowel Sign Kayah {0x01032, 0x01037}, // Myanmar Vowel Sign Ai ..Myanmar Sign Dot Below
{0x1082, 0x1082}, // Myanmar Consonant Sign S..Myanmar Consonant Sign S {0x01039, 0x0103a}, // Myanmar Sign Virama ..Myanmar Sign Asat
{0x1085, 0x1086}, // Myanmar Vowel Sign Shan ..Myanmar Vowel Sign Shan {0x0103d, 0x0103e}, // Myanmar Consonant Sign M..Myanmar Consonant Sign M
{0x108d, 0x108d}, // Myanmar Sign Shan Counci..Myanmar Sign Shan Counci {0x01058, 0x01059}, // Myanmar Vowel Sign Vocal..Myanmar Vowel Sign Vocal
{0x109d, 0x109d}, // Myanmar Vowel Sign Aiton..Myanmar Vowel Sign Aiton {0x0105e, 0x01060}, // Myanmar Consonant Sign M..Myanmar Consonant Sign M
{0x135d, 0x135f}, // Ethiopic Combining Gemin..Ethiopic Combining Gemin {0x01071, 0x01074}, // Myanmar Vowel Sign Geba ..Myanmar Vowel Sign Kayah
{0x1712, 0x1714}, // Tagalog Vowel Sign I ..Tagalog Sign Virama {0x01082, 0x01082}, // Myanmar Consonant Sign S..Myanmar Consonant Sign S
{0x1732, 0x1734}, // Hanunoo Vowel Sign I ..Hanunoo Sign Pamudpod {0x01085, 0x01086}, // Myanmar Vowel Sign Shan ..Myanmar Vowel Sign Shan
{0x1752, 0x1753}, // Buhid Vowel Sign I ..Buhid Vowel Sign U {0x0108d, 0x0108d}, // Myanmar Sign Shan Counci..Myanmar Sign Shan Counci
{0x1772, 0x1773}, // Tagbanwa Vowel Sign I ..Tagbanwa Vowel Sign U {0x0109d, 0x0109d}, // Myanmar Vowel Sign Aiton..Myanmar Vowel Sign Aiton
{0x17b4, 0x17b5}, // Khmer Vowel Inherent Aq ..Khmer Vowel Inherent Aa {0x0135d, 0x0135f}, // Ethiopic Combining Gemin..Ethiopic Combining Gemin
{0x17b7, 0x17bd}, // Khmer Vowel Sign I ..Khmer Vowel Sign Ua {0x01712, 0x01714}, // Tagalog Vowel Sign I ..Tagalog Sign Virama
{0x17c6, 0x17c6}, // Khmer Sign Nikahit ..Khmer Sign Nikahit {0x01732, 0x01734}, // Hanunoo Vowel Sign I ..Hanunoo Sign Pamudpod
{0x17c9, 0x17d3}, // Khmer Sign Muusikatoan ..Khmer Sign Bathamasat {0x01752, 0x01753}, // Buhid Vowel Sign I ..Buhid Vowel Sign U
{0x17dd, 0x17dd}, // Khmer Sign Atthacan ..Khmer Sign Atthacan {0x01772, 0x01773}, // Tagbanwa Vowel Sign I ..Tagbanwa Vowel Sign U
{0x180b, 0x180d}, // Mongolian Free Variation..Mongolian Free Variation {0x017b4, 0x017b5}, // Khmer Vowel Inherent Aq ..Khmer Vowel Inherent Aa
{0x1885, 0x1886}, // Mongolian Letter Ali Gal..Mongolian Letter Ali Gal {0x017b7, 0x017bd}, // Khmer Vowel Sign I ..Khmer Vowel Sign Ua
{0x18a9, 0x18a9}, // Mongolian Letter Ali Gal..Mongolian Letter Ali Gal {0x017c6, 0x017c6}, // Khmer Sign Nikahit ..Khmer Sign Nikahit
{0x1920, 0x1922}, // Limbu Vowel Sign A ..Limbu Vowel Sign U {0x017c9, 0x017d3}, // Khmer Sign Muusikatoan ..Khmer Sign Bathamasat
{0x1927, 0x1928}, // Limbu Vowel Sign E ..Limbu Vowel Sign O {0x017dd, 0x017dd}, // Khmer Sign Atthacan ..Khmer Sign Atthacan
{0x1932, 0x1932}, // Limbu Small Letter Anusv..Limbu Small Letter Anusv {0x0180b, 0x0180d}, // Mongolian Free Variation..Mongolian Free Variation
{0x1939, 0x193b}, // Limbu Sign Mukphreng ..Limbu Sign Sa-i {0x01885, 0x01886}, // Mongolian Letter Ali Gal..Mongolian Letter Ali Gal
{0x1a17, 0x1a18}, // Buginese Vowel Sign I ..Buginese Vowel Sign U {0x018a9, 0x018a9}, // Mongolian Letter Ali Gal..Mongolian Letter Ali Gal
{0x1a1b, 0x1a1b}, // Buginese Vowel Sign Ae ..Buginese Vowel Sign Ae {0x01920, 0x01922}, // Limbu Vowel Sign A ..Limbu Vowel Sign U
{0x1a56, 0x1a56}, // Tai Tham Consonant Sign ..Tai Tham Consonant Sign {0x01927, 0x01928}, // Limbu Vowel Sign E ..Limbu Vowel Sign O
{0x1a58, 0x1a5e}, // Tai Tham Sign Mai Kang L..Tai Tham Consonant Sign {0x01932, 0x01932}, // Limbu Small Letter Anusv..Limbu Small Letter Anusv
{0x1a60, 0x1a60}, // Tai Tham Sign Sakot ..Tai Tham Sign Sakot {0x01939, 0x0193b}, // Limbu Sign Mukphreng ..Limbu Sign Sa-i
{0x1a62, 0x1a62}, // Tai Tham Vowel Sign Mai ..Tai Tham Vowel Sign Mai {0x01a17, 0x01a18}, // Buginese Vowel Sign I ..Buginese Vowel Sign U
{0x1a65, 0x1a6c}, // Tai Tham Vowel Sign I ..Tai Tham Vowel Sign Oa B {0x01a1b, 0x01a1b}, // Buginese Vowel Sign Ae ..Buginese Vowel Sign Ae
{0x1a73, 0x1a7c}, // Tai Tham Vowel Sign Oa A..Tai Tham Sign Khuen-lue {0x01a56, 0x01a56}, // Tai Tham Consonant Sign ..Tai Tham Consonant Sign
{0x1a7f, 0x1a7f}, // Tai Tham Combining Crypt..Tai Tham Combining Crypt {0x01a58, 0x01a5e}, // Tai Tham Sign Mai Kang L..Tai Tham Consonant Sign
{0x1ab0, 0x1abe}, // Combining Doubled Circum..Combining Parentheses Ov {0x01a60, 0x01a60}, // Tai Tham Sign Sakot ..Tai Tham Sign Sakot
{0x1b00, 0x1b03}, // Balinese Sign Ulu Ricem ..Balinese Sign Surang {0x01a62, 0x01a62}, // Tai Tham Vowel Sign Mai ..Tai Tham Vowel Sign Mai
{0x1b34, 0x1b34}, // Balinese Sign Rerekan ..Balinese Sign Rerekan {0x01a65, 0x01a6c}, // Tai Tham Vowel Sign I ..Tai Tham Vowel Sign Oa B
{0x1b36, 0x1b3a}, // Balinese Vowel Sign Ulu ..Balinese Vowel Sign Ra R {0x01a73, 0x01a7c}, // Tai Tham Vowel Sign Oa A..Tai Tham Sign Khuen-lue
{0x1b3c, 0x1b3c}, // Balinese Vowel Sign La L..Balinese Vowel Sign La L {0x01a7f, 0x01a7f}, // Tai Tham Combining Crypt..Tai Tham Combining Crypt
{0x1b42, 0x1b42}, // Balinese Vowel Sign Pepe..Balinese Vowel Sign Pepe {0x01ab0, 0x01ac0}, // Combining Doubled Circum..(nil)
{0x1b6b, 0x1b73}, // Balinese Musical Symbol ..Balinese Musical Symbol {0x01b00, 0x01b03}, // Balinese Sign Ulu Ricem ..Balinese Sign Surang
{0x1b80, 0x1b81}, // Sundanese Sign Panyecek ..Sundanese Sign Panglayar {0x01b34, 0x01b34}, // Balinese Sign Rerekan ..Balinese Sign Rerekan
{0x1ba2, 0x1ba5}, // Sundanese Consonant Sign..Sundanese Vowel Sign Pan {0x01b36, 0x01b3a}, // Balinese Vowel Sign Ulu ..Balinese Vowel Sign Ra R
{0x1ba8, 0x1ba9}, // Sundanese Vowel Sign Pam..Sundanese Vowel Sign Pan {0x01b3c, 0x01b3c}, // Balinese Vowel Sign La L..Balinese Vowel Sign La L
{0x1bab, 0x1bad}, // Sundanese Sign Virama ..Sundanese Consonant Sign {0x01b42, 0x01b42}, // Balinese Vowel Sign Pepe..Balinese Vowel Sign Pepe
{0x1be6, 0x1be6}, // Batak Sign Tompi ..Batak Sign Tompi {0x01b6b, 0x01b73}, // Balinese Musical Symbol ..Balinese Musical Symbol
{0x1be8, 0x1be9}, // Batak Vowel Sign Pakpak ..Batak Vowel Sign Ee {0x01b80, 0x01b81}, // Sundanese Sign Panyecek ..Sundanese Sign Panglayar
{0x1bed, 0x1bed}, // Batak Vowel Sign Karo O ..Batak Vowel Sign Karo O {0x01ba2, 0x01ba5}, // Sundanese Consonant Sign..Sundanese Vowel Sign Pan
{0x1bef, 0x1bf1}, // Batak Vowel Sign U F|| S..Batak Consonant Sign H {0x01ba8, 0x01ba9}, // Sundanese Vowel Sign Pam..Sundanese Vowel Sign Pan
{0x1c2c, 0x1c33}, // Lepcha Vowel Sign E ..Lepcha Consonant Sign T {0x01bab, 0x01bad}, // Sundanese Sign Virama ..Sundanese Consonant Sign
{0x1c36, 0x1c37}, // Lepcha Sign Ran ..Lepcha Sign Nukta {0x01be6, 0x01be6}, // Batak Sign Tompi ..Batak Sign Tompi
{0x1cd0, 0x1cd2}, // Vedic Tone Karshana ..Vedic Tone Prenkha {0x01be8, 0x01be9}, // Batak Vowel Sign Pakpak ..Batak Vowel Sign Ee
{0x1cd4, 0x1ce0}, // Vedic Sign Yajurvedic Mi..Vedic Tone Rigvedic Kash {0x01bed, 0x01bed}, // Batak Vowel Sign Karo O ..Batak Vowel Sign Karo O
{0x1ce2, 0x1ce8}, // Vedic Sign Visarga Svari..Vedic Sign Visarga Anuda {0x01bef, 0x01bf1}, // Batak Vowel Sign U For S..Batak Consonant Sign H
{0x1ced, 0x1ced}, // Vedic Sign Tiryak ..Vedic Sign Tiryak {0x01c2c, 0x01c33}, // Lepcha Vowel Sign E ..Lepcha Consonant Sign T
{0x1cf4, 0x1cf4}, // Vedic Tone Candra Above ..Vedic Tone Candra Above {0x01c36, 0x01c37}, // Lepcha Sign Ran ..Lepcha Sign Nukta
{0x1cf8, 0x1cf9}, // Vedic Tone Ring Above ..Vedic Tone Double Ring A {0x01cd0, 0x01cd2}, // Vedic Tone Karshana ..Vedic Tone Prenkha
{0x1dc0, 0x1df5}, // Combining Dotted Grave A..Combining Up Tack Above {0x01cd4, 0x01ce0}, // Vedic Sign Yajurvedic Mi..Vedic Tone Rigvedic Kash
{0x1dfb, 0x1dff}, // (nil) ..Combining Right Arrowhea {0x01ce2, 0x01ce8}, // Vedic Sign Visarga Svari..Vedic Sign Visarga Anuda
{0x20d0, 0x20f0}, // Combining Left Harpoon A..Combining Asterisk Above {0x01ced, 0x01ced}, // Vedic Sign Tiryak ..Vedic Sign Tiryak
{0x2cef, 0x2cf1}, // Coptic Combining Ni Abov..Coptic Combining Spiritu {0x01cf4, 0x01cf4}, // Vedic Tone Candra Above ..Vedic Tone Candra Above
{0x2d7f, 0x2d7f}, // Tifinagh Consonant Joine..Tifinagh Consonant Joine {0x01cf8, 0x01cf9}, // Vedic Tone Ring Above ..Vedic Tone Double Ring A
{0x2de0, 0x2dff}, // Combining Cyrillic Lette..Combining Cyrillic Lette {0x01dc0, 0x01df9}, // Combining Dotted Grave A..Combining Wide Inverted
{0x302a, 0x302d}, // Ideographic Level Tone M..Ideographic Entering Ton {0x01dfb, 0x01dff}, // Combining Deletion Mark ..Combining Right Arrowhea
{0x3099, 0x309a}, // Combining Katakana-hirag..Combining Katakana-hirag {0x020d0, 0x020f0}, // Combining Left Harpoon A..Combining Asterisk Above
{0xa66f, 0xa672}, // Combining Cyrillic Vzmet..Combining Cyrillic Thous {0x02cef, 0x02cf1}, // Coptic Combining Ni Abov..Coptic Combining Spiritu
{0xa674, 0xa67d}, // Combining Cyrillic Lette..Combining Cyrillic Payer {0x02d7f, 0x02d7f}, // Tifinagh Consonant Joine..Tifinagh Consonant Joine
{0xa69e, 0xa69f}, // Combining Cyrillic Lette..Combining Cyrillic Lette {0x02de0, 0x02dff}, // Combining Cyrillic Lette..Combining Cyrillic Lette
{0xa6f0, 0xa6f1}, // Bamum Combining Mark Koq..Bamum Combining Mark Tuk {0x0302a, 0x0302d}, // Ideographic Level Tone M..Ideographic Entering Ton
{0xa802, 0xa802}, // Syloti Nagri Sign Dvisva..Syloti Nagri Sign Dvisva {0x03099, 0x0309a}, // Combining Katakana-hirag..Combining Katakana-hirag
{0xa806, 0xa806}, // Syloti Nagri Sign Hasant..Syloti Nagri Sign Hasant {0x0a66f, 0x0a672}, // Combining Cyrillic Vzmet..Combining Cyrillic Thous
{0xa80b, 0xa80b}, // Syloti Nagri Sign Anusva..Syloti Nagri Sign Anusva {0x0a674, 0x0a67d}, // Combining Cyrillic Lette..Combining Cyrillic Payer
{0xa825, 0xa826}, // Syloti Nagri Vowel Sign ..Syloti Nagri Vowel Sign {0x0a69e, 0x0a69f}, // Combining Cyrillic Lette..Combining Cyrillic Lette
{0xa8c4, 0xa8c5}, // Saurashtra Sign Virama .. {0x0a6f0, 0x0a6f1}, // Bamum Combining Mark Koq..Bamum Combining Mark Tuk
{0xa8e0, 0xa8f1}, // Combining Devanagari Dig..Combining Devanagari Sig {0x0a802, 0x0a802}, // Syloti Nagri Sign Dvisva..Syloti Nagri Sign Dvisva
{0xa926, 0xa92d}, // Kayah Li Vowel Ue ..Kayah Li Tone Calya Plop {0x0a806, 0x0a806}, // Syloti Nagri Sign Hasant..Syloti Nagri Sign Hasant
{0xa947, 0xa951}, // Rejang Vowel Sign I ..Rejang Consonant Sign R {0x0a80b, 0x0a80b}, // Syloti Nagri Sign Anusva..Syloti Nagri Sign Anusva
{0xa980, 0xa982}, // Javanese Sign Panyangga ..Javanese Sign Layar {0x0a825, 0x0a826}, // Syloti Nagri Vowel Sign ..Syloti Nagri Vowel Sign
{0xa9b3, 0xa9b3}, // Javanese Sign Cecak Telu..Javanese Sign Cecak Telu {0x0a82c, 0x0a82c}, // (nil) ..(nil)
{0xa9b6, 0xa9b9}, // Javanese Vowel Sign Wulu..Javanese Vowel Sign Suku {0x0a8c4, 0x0a8c5}, // Saurashtra Sign Virama ..Saurashtra Sign Candrabi
{0xa9bc, 0xa9bc}, // Javanese Vowel Sign Pepe..Javanese Vowel Sign Pepe {0x0a8e0, 0x0a8f1}, // Combining Devanagari Dig..Combining Devanagari Sig
{0xa9e5, 0xa9e5}, // Myanmar Sign Shan Saw ..Myanmar Sign Shan Saw {0x0a8ff, 0x0a8ff}, // Devanagari Vowel Sign Ay..Devanagari Vowel Sign Ay
{0xaa29, 0xaa2e}, // Cham Vowel Sign Aa ..Cham Vowel Sign Oe {0x0a926, 0x0a92d}, // Kayah Li Vowel Ue ..Kayah Li Tone Calya Plop
{0xaa31, 0xaa32}, // Cham Vowel Sign Au ..Cham Vowel Sign Ue {0x0a947, 0x0a951}, // Rejang Vowel Sign I ..Rejang Consonant Sign R
{0xaa35, 0xaa36}, // Cham Consonant Sign La ..Cham Consonant Sign Wa {0x0a980, 0x0a982}, // Javanese Sign Panyangga ..Javanese Sign Layar
{0xaa43, 0xaa43}, // Cham Consonant Sign Fina..Cham Consonant Sign Fina {0x0a9b3, 0x0a9b3}, // Javanese Sign Cecak Telu..Javanese Sign Cecak Telu
{0xaa4c, 0xaa4c}, // Cham Consonant Sign Fina..Cham Consonant Sign Fina {0x0a9b6, 0x0a9b9}, // Javanese Vowel Sign Wulu..Javanese Vowel Sign Suku
{0xaa7c, 0xaa7c}, // Myanmar Sign Tai Laing T..Myanmar Sign Tai Laing T {0x0a9bc, 0x0a9bd}, // Javanese Vowel Sign Pepe..Javanese Consonant Sign
{0xaab0, 0xaab0}, // Tai Viet Mai Kang ..Tai Viet Mai Kang {0x0a9e5, 0x0a9e5}, // Myanmar Sign Shan Saw ..Myanmar Sign Shan Saw
{0xaab2, 0xaab4}, // Tai Viet Vowel I ..Tai Viet Vowel U {0x0aa29, 0x0aa2e}, // Cham Vowel Sign Aa ..Cham Vowel Sign Oe
{0xaab7, 0xaab8}, // Tai Viet Mai Khit ..Tai Viet Vowel Ia {0x0aa31, 0x0aa32}, // Cham Vowel Sign Au ..Cham Vowel Sign Ue
{0xaabe, 0xaabf}, // Tai Viet Vowel Am ..Tai Viet Tone Mai Ek {0x0aa35, 0x0aa36}, // Cham Consonant Sign La ..Cham Consonant Sign Wa
{0xaac1, 0xaac1}, // Tai Viet Tone Mai Tho ..Tai Viet Tone Mai Tho {0x0aa43, 0x0aa43}, // Cham Consonant Sign Fina..Cham Consonant Sign Fina
{0xaaec, 0xaaed}, // Meetei Mayek Vowel Sign ..Meetei Mayek Vowel Sign {0x0aa4c, 0x0aa4c}, // Cham Consonant Sign Fina..Cham Consonant Sign Fina
{0xaaf6, 0xaaf6}, // Meetei Mayek Virama ..Meetei Mayek Virama {0x0aa7c, 0x0aa7c}, // Myanmar Sign Tai Laing T..Myanmar Sign Tai Laing T
{0xabe5, 0xabe5}, // Meetei Mayek Vowel Sign ..Meetei Mayek Vowel Sign {0x0aab0, 0x0aab0}, // Tai Viet Mai Kang ..Tai Viet Mai Kang
{0xabe8, 0xabe8}, // Meetei Mayek Vowel Sign ..Meetei Mayek Vowel Sign {0x0aab2, 0x0aab4}, // Tai Viet Vowel I ..Tai Viet Vowel U
{0xabed, 0xabed}, // Meetei Mayek Apun Iyek ..Meetei Mayek Apun Iyek {0x0aab7, 0x0aab8}, // Tai Viet Mai Khit ..Tai Viet Vowel Ia
{0xfb1e, 0xfb1e}, // Hebrew Point Judeo-spani..Hebrew Point Judeo-spani {0x0aabe, 0x0aabf}, // Tai Viet Vowel Am ..Tai Viet Tone Mai Ek
{0xfe00, 0xfe0f}, // Variation Select||-1 ..Variation Select||-16 {0x0aac1, 0x0aac1}, // Tai Viet Tone Mai Tho ..Tai Viet Tone Mai Tho
{0xfe20, 0xfe2f}, // Combining Ligature Left ..Combining Cyrillic Titlo {0x0aaec, 0x0aaed}, // Meetei Mayek Vowel Sign ..Meetei Mayek Vowel Sign
{0x0aaf6, 0x0aaf6}, // Meetei Mayek Virama ..Meetei Mayek Virama
{0x0abe5, 0x0abe5}, // Meetei Mayek Vowel Sign ..Meetei Mayek Vowel Sign
{0x0abe8, 0x0abe8}, // Meetei Mayek Vowel Sign ..Meetei Mayek Vowel Sign
{0x0abed, 0x0abed}, // Meetei Mayek Apun Iyek ..Meetei Mayek Apun Iyek
{0x0fb1e, 0x0fb1e}, // Hebrew Point Judeo-spani..Hebrew Point Judeo-spani
{0x0fe00, 0x0fe0f}, // Variation Selector-1 ..Variation Selector-16
{0x0fe20, 0x0fe2f}, // Combining Ligature Left ..Combining Cyrillic Titlo
{0x101fd, 0x101fd}, // Phaistos Disc Sign Combi..Phaistos Disc Sign Combi {0x101fd, 0x101fd}, // Phaistos Disc Sign Combi..Phaistos Disc Sign Combi
{0x102e0, 0x102e0}, // Coptic Epact Thousands M..Coptic Epact Thousands M {0x102e0, 0x102e0}, // Coptic Epact Thousands M..Coptic Epact Thousands M
{0x10376, 0x1037a}, // Combining Old Permic Let..Combining Old Permic Let {0x10376, 0x1037a}, // Combining Old Permic Let..Combining Old Permic Let
@@ -219,6 +232,9 @@ public final class WcWidth {
{0x10a38, 0x10a3a}, // Kharoshthi Sign Bar Abov..Kharoshthi Sign Dot Belo {0x10a38, 0x10a3a}, // Kharoshthi Sign Bar Abov..Kharoshthi Sign Dot Belo
{0x10a3f, 0x10a3f}, // Kharoshthi Virama ..Kharoshthi Virama {0x10a3f, 0x10a3f}, // Kharoshthi Virama ..Kharoshthi Virama
{0x10ae5, 0x10ae6}, // Manichaean Abbreviation ..Manichaean Abbreviation {0x10ae5, 0x10ae6}, // Manichaean Abbreviation ..Manichaean Abbreviation
{0x10d24, 0x10d27}, // Hanifi Rohingya Sign Har..Hanifi Rohingya Sign Tas
{0x10eab, 0x10eac}, // (nil) ..(nil)
{0x10f46, 0x10f50}, // Sogdian Combining Dot Be..Sogdian Combining Stroke
{0x11001, 0x11001}, // Brahmi Sign Anusvara ..Brahmi Sign Anusvara {0x11001, 0x11001}, // Brahmi Sign Anusvara ..Brahmi Sign Anusvara
{0x11038, 0x11046}, // Brahmi Vowel Sign Aa ..Brahmi Virama {0x11038, 0x11046}, // Brahmi Vowel Sign Aa ..Brahmi Virama
{0x1107f, 0x11081}, // Brahmi Number Joiner ..Kaithi Sign Anusvara {0x1107f, 0x11081}, // Brahmi Number Joiner ..Kaithi Sign Anusvara
@@ -230,23 +246,25 @@ public final class WcWidth {
{0x11173, 0x11173}, // Mahajani Sign Nukta ..Mahajani Sign Nukta {0x11173, 0x11173}, // Mahajani Sign Nukta ..Mahajani Sign Nukta
{0x11180, 0x11181}, // Sharada Sign Candrabindu..Sharada Sign Anusvara {0x11180, 0x11181}, // Sharada Sign Candrabindu..Sharada Sign Anusvara
{0x111b6, 0x111be}, // Sharada Vowel Sign U ..Sharada Vowel Sign O {0x111b6, 0x111be}, // Sharada Vowel Sign U ..Sharada Vowel Sign O
{0x111ca, 0x111cc}, // Sharada Sign Nukta ..Sharada Extra Sh||t Vowe {0x111c9, 0x111cc}, // Sharada Sandhi Mark ..Sharada Extra Short Vowe
{0x111cf, 0x111cf}, // (nil) ..(nil)
{0x1122f, 0x11231}, // Khojki Vowel Sign U ..Khojki Vowel Sign Ai {0x1122f, 0x11231}, // Khojki Vowel Sign U ..Khojki Vowel Sign Ai
{0x11234, 0x11234}, // Khojki Sign Anusvara ..Khojki Sign Anusvara {0x11234, 0x11234}, // Khojki Sign Anusvara ..Khojki Sign Anusvara
{0x11236, 0x11237}, // Khojki Sign Nukta ..Khojki Sign Shadda {0x11236, 0x11237}, // Khojki Sign Nukta ..Khojki Sign Shadda
{0x1123e, 0x1123e}, // (nil) .. {0x1123e, 0x1123e}, // Khojki Sign Sukun ..Khojki Sign Sukun
{0x112df, 0x112df}, // Khudawadi Sign Anusvara ..Khudawadi Sign Anusvara {0x112df, 0x112df}, // Khudawadi Sign Anusvara ..Khudawadi Sign Anusvara
{0x112e3, 0x112ea}, // Khudawadi Vowel Sign U ..Khudawadi Sign Virama {0x112e3, 0x112ea}, // Khudawadi Vowel Sign U ..Khudawadi Sign Virama
{0x11300, 0x11301}, // Grantha Sign Combining A..Grantha Sign Candrabindu {0x11300, 0x11301}, // Grantha Sign Combining A..Grantha Sign Candrabindu
{0x1133c, 0x1133c}, // Grantha Sign Nukta ..Grantha Sign Nukta {0x1133b, 0x1133c}, // Combining Bindu Below ..Grantha Sign Nukta
{0x11340, 0x11340}, // Grantha Vowel Sign Ii ..Grantha Vowel Sign Ii {0x11340, 0x11340}, // Grantha Vowel Sign Ii ..Grantha Vowel Sign Ii
{0x11366, 0x1136c}, // Combining Grantha Digit ..Combining Grantha Digit {0x11366, 0x1136c}, // Combining Grantha Digit ..Combining Grantha Digit
{0x11370, 0x11374}, // Combining Grantha Letter..Combining Grantha Letter {0x11370, 0x11374}, // Combining Grantha Letter..Combining Grantha Letter
{0x11438, 0x1143f}, // (nil) .. {0x11438, 0x1143f}, // Newa Vowel Sign U ..Newa Vowel Sign Ai
{0x11442, 0x11444}, // (nil) .. {0x11442, 0x11444}, // Newa Sign Virama ..Newa Sign Anusvara
{0x11446, 0x11446}, // (nil) .. {0x11446, 0x11446}, // Newa Sign Nukta ..Newa Sign Nukta
{0x1145e, 0x1145e}, // Newa Sandhi Mark ..Newa Sandhi Mark
{0x114b3, 0x114b8}, // Tirhuta Vowel Sign U ..Tirhuta Vowel Sign Vocal {0x114b3, 0x114b8}, // Tirhuta Vowel Sign U ..Tirhuta Vowel Sign Vocal
{0x114ba, 0x114ba}, // Tirhuta Vowel Sign Sh||t..Tirhuta Vowel Sign Sh||t {0x114ba, 0x114ba}, // Tirhuta Vowel Sign Short..Tirhuta Vowel Sign Short
{0x114bf, 0x114c0}, // Tirhuta Sign Candrabindu..Tirhuta Sign Anusvara {0x114bf, 0x114c0}, // Tirhuta Sign Candrabindu..Tirhuta Sign Anusvara
{0x114c2, 0x114c3}, // Tirhuta Sign Virama ..Tirhuta Sign Nukta {0x114c2, 0x114c3}, // Tirhuta Sign Virama ..Tirhuta Sign Nukta
{0x115b2, 0x115b5}, // Siddham Vowel Sign U ..Siddham Vowel Sign Vocal {0x115b2, 0x115b5}, // Siddham Vowel Sign U ..Siddham Vowel Sign Vocal
@@ -263,16 +281,43 @@ public final class WcWidth {
{0x1171d, 0x1171f}, // Ahom Consonant Sign Medi..Ahom Consonant Sign Medi {0x1171d, 0x1171f}, // Ahom Consonant Sign Medi..Ahom Consonant Sign Medi
{0x11722, 0x11725}, // Ahom Vowel Sign I ..Ahom Vowel Sign Uu {0x11722, 0x11725}, // Ahom Vowel Sign I ..Ahom Vowel Sign Uu
{0x11727, 0x1172b}, // Ahom Vowel Sign Aw ..Ahom Sign Killer {0x11727, 0x1172b}, // Ahom Vowel Sign Aw ..Ahom Sign Killer
{0x11c30, 0x11c36}, // (nil) .. {0x1182f, 0x11837}, // Dogra Vowel Sign U ..Dogra Sign Anusvara
{0x11c38, 0x11c3d}, // (nil) .. {0x11839, 0x1183a}, // Dogra Sign Virama ..Dogra Sign Nukta
{0x11c3f, 0x11c3f}, // (nil) .. {0x1193b, 0x1193c}, // (nil) ..(nil)
{0x11c92, 0x11ca7}, // (nil) .. {0x1193e, 0x1193e}, // (nil) ..(nil)
{0x11caa, 0x11cb0}, // (nil) .. {0x11943, 0x11943}, // (nil) ..(nil)
{0x11cb2, 0x11cb3}, // (nil) .. {0x119d4, 0x119d7}, // Nandinagari Vowel Sign U..Nandinagari Vowel Sign V
{0x11cb5, 0x11cb6}, // (nil) .. {0x119da, 0x119db}, // Nandinagari Vowel Sign E..Nandinagari Vowel Sign A
{0x119e0, 0x119e0}, // Nandinagari Sign Virama ..Nandinagari Sign Virama
{0x11a01, 0x11a0a}, // Zanabazar Square Vowel S..Zanabazar Square Vowel L
{0x11a33, 0x11a38}, // Zanabazar Square Final C..Zanabazar Square Sign An
{0x11a3b, 0x11a3e}, // Zanabazar Square Cluster..Zanabazar Square Cluster
{0x11a47, 0x11a47}, // Zanabazar Square Subjoin..Zanabazar Square Subjoin
{0x11a51, 0x11a56}, // Soyombo Vowel Sign I ..Soyombo Vowel Sign Oe
{0x11a59, 0x11a5b}, // Soyombo Vowel Sign Vocal..Soyombo Vowel Length Mar
{0x11a8a, 0x11a96}, // Soyombo Final Consonant ..Soyombo Sign Anusvara
{0x11a98, 0x11a99}, // Soyombo Gemination Mark ..Soyombo Subjoiner
{0x11c30, 0x11c36}, // Bhaiksuki Vowel Sign I ..Bhaiksuki Vowel Sign Voc
{0x11c38, 0x11c3d}, // Bhaiksuki Vowel Sign E ..Bhaiksuki Sign Anusvara
{0x11c3f, 0x11c3f}, // Bhaiksuki Sign Virama ..Bhaiksuki Sign Virama
{0x11c92, 0x11ca7}, // Marchen Subjoined Letter..Marchen Subjoined Letter
{0x11caa, 0x11cb0}, // Marchen Subjoined Letter..Marchen Vowel Sign Aa
{0x11cb2, 0x11cb3}, // Marchen Vowel Sign U ..Marchen Vowel Sign E
{0x11cb5, 0x11cb6}, // Marchen Sign Anusvara ..Marchen Sign Candrabindu
{0x11d31, 0x11d36}, // Masaram Gondi Vowel Sign..Masaram Gondi Vowel Sign
{0x11d3a, 0x11d3a}, // Masaram Gondi Vowel Sign..Masaram Gondi Vowel Sign
{0x11d3c, 0x11d3d}, // Masaram Gondi Vowel Sign..Masaram Gondi Vowel Sign
{0x11d3f, 0x11d45}, // Masaram Gondi Vowel Sign..Masaram Gondi Virama
{0x11d47, 0x11d47}, // Masaram Gondi Ra-kara ..Masaram Gondi Ra-kara
{0x11d90, 0x11d91}, // Gunjala Gondi Vowel Sign..Gunjala Gondi Vowel Sign
{0x11d95, 0x11d95}, // Gunjala Gondi Sign Anusv..Gunjala Gondi Sign Anusv
{0x11d97, 0x11d97}, // Gunjala Gondi Virama ..Gunjala Gondi Virama
{0x11ef3, 0x11ef4}, // Makasar Vowel Sign I ..Makasar Vowel Sign U
{0x16af0, 0x16af4}, // Bassa Vah Combining High..Bassa Vah Combining High {0x16af0, 0x16af4}, // Bassa Vah Combining High..Bassa Vah Combining High
{0x16b30, 0x16b36}, // Pahawh Hmong Mark Cim Tu..Pahawh Hmong Mark Cim Ta {0x16b30, 0x16b36}, // Pahawh Hmong Mark Cim Tu..Pahawh Hmong Mark Cim Ta
{0x16f4f, 0x16f4f}, // Miao Sign Consonant Modi..Miao Sign Consonant Modi
{0x16f8f, 0x16f92}, // Miao Tone Right ..Miao Tone Below {0x16f8f, 0x16f92}, // Miao Tone Right ..Miao Tone Below
{0x16fe4, 0x16fe4}, // (nil) ..(nil)
{0x1bc9d, 0x1bc9e}, // Duployan Thick Letter Se..Duployan Double Mark {0x1bc9d, 0x1bc9e}, // Duployan Thick Letter Se..Duployan Double Mark
{0x1d167, 0x1d169}, // Musical Symbol Combining..Musical Symbol Combining {0x1d167, 0x1d169}, // Musical Symbol Combining..Musical Symbol Combining
{0x1d17b, 0x1d182}, // Musical Symbol Combining..Musical Symbol Combining {0x1d17b, 0x1d182}, // Musical Symbol Combining..Musical Symbol Combining
@@ -285,97 +330,103 @@ public final class WcWidth {
{0x1da84, 0x1da84}, // Signwriting Location Hea..Signwriting Location Hea {0x1da84, 0x1da84}, // Signwriting Location Hea..Signwriting Location Hea
{0x1da9b, 0x1da9f}, // Signwriting Fill Modifie..Signwriting Fill Modifie {0x1da9b, 0x1da9f}, // Signwriting Fill Modifie..Signwriting Fill Modifie
{0x1daa1, 0x1daaf}, // Signwriting Rotation Mod..Signwriting Rotation Mod {0x1daa1, 0x1daaf}, // Signwriting Rotation Mod..Signwriting Rotation Mod
{0x1e000, 0x1e006}, // (nil) .. {0x1e000, 0x1e006}, // Combining Glagolitic Let..Combining Glagolitic Let
{0x1e008, 0x1e018}, // (nil) .. {0x1e008, 0x1e018}, // Combining Glagolitic Let..Combining Glagolitic Let
{0x1e01b, 0x1e021}, // (nil) .. {0x1e01b, 0x1e021}, // Combining Glagolitic Let..Combining Glagolitic Let
{0x1e023, 0x1e024}, // (nil) .. {0x1e023, 0x1e024}, // Combining Glagolitic Let..Combining Glagolitic Let
{0x1e026, 0x1e02a}, // (nil) .. {0x1e026, 0x1e02a}, // Combining Glagolitic Let..Combining Glagolitic Let
{0x1e130, 0x1e136}, // Nyiakeng Puachue Hmong T..Nyiakeng Puachue Hmong T
{0x1e2ec, 0x1e2ef}, // Wancho Tone Tup ..Wancho Tone Koini
{0x1e8d0, 0x1e8d6}, // Mende Kikakui Combining ..Mende Kikakui Combining {0x1e8d0, 0x1e8d6}, // Mende Kikakui Combining ..Mende Kikakui Combining
{0x1e944, 0x1e94a}, // (nil) .. {0x1e944, 0x1e94a}, // Adlam Alif Lengthener ..Adlam Nukta
{0xe0100, 0xe01ef}, // Variation Select||-17 ..Variation Select||-256 {0xe0100, 0xe01ef}, // Variation Selector-17 ..Variation Selector-256
}; };
// https://github.com/jquast/wcwidth/blob/master/wcwidth/table_wide.py // https://github.com/jquast/wcwidth/blob/master/wcwidth/table_wide.py
// at commit 0d7de112202cc8b2ebe9232ff4a5c954f19d561a (2016-07-02): // at commit b29897e5a1b403a0e36f7fc991614981cbc42475 (2020-07-14):
private static final int[][] WIDE_EASTASIAN = { private static final int[][] WIDE_EASTASIAN = {
{0x1100, 0x115f}, // Hangul Choseong Kiyeok ..Hangul Choseong Filler {0x01100, 0x0115f}, // Hangul Choseong Kiyeok ..Hangul Choseong Filler
{0x231a, 0x231b}, // Watch ..Hourglass {0x0231a, 0x0231b}, // Watch ..Hourglass
{0x2329, 0x232a}, // Left-pointing Angle Brac..Right-pointing Angle Bra {0x02329, 0x0232a}, // Left-pointing Angle Brac..Right-pointing Angle Bra
{0x23e9, 0x23ec}, // Black Right-pointing Dou..Black Down-pointing Doub {0x023e9, 0x023ec}, // Black Right-pointing Dou..Black Down-pointing Doub
{0x23f0, 0x23f0}, // Alarm Clock ..Alarm Clock {0x023f0, 0x023f0}, // Alarm Clock ..Alarm Clock
{0x23f3, 0x23f3}, // Hourglass With Flowing S..Hourglass With Flowing S {0x023f3, 0x023f3}, // Hourglass With Flowing S..Hourglass With Flowing S
{0x25fd, 0x25fe}, // White Medium Small Squar..Black Medium Small Squar {0x025fd, 0x025fe}, // White Medium Small Squar..Black Medium Small Squar
{0x2614, 0x2615}, // Umbrella With Rain Drops..Hot Beverage {0x02614, 0x02615}, // Umbrella With Rain Drops..Hot Beverage
{0x2648, 0x2653}, // Aries ..Pisces {0x02648, 0x02653}, // Aries ..Pisces
{0x267f, 0x267f}, // Wheelchair Symbol ..Wheelchair Symbol {0x0267f, 0x0267f}, // Wheelchair Symbol ..Wheelchair Symbol
{0x2693, 0x2693}, // Anch|| ..Anch|| {0x02693, 0x02693}, // Anchor ..Anchor
{0x26a1, 0x26a1}, // High Voltage Sign ..High Voltage Sign {0x026a1, 0x026a1}, // High Voltage Sign ..High Voltage Sign
{0x26aa, 0x26ab}, // Medium White Circle ..Medium Black Circle {0x026aa, 0x026ab}, // Medium White Circle ..Medium Black Circle
{0x26bd, 0x26be}, // Soccer Ball ..Baseball {0x026bd, 0x026be}, // Soccer Ball ..Baseball
{0x26c4, 0x26c5}, // Snowman Without Snow ..Sun Behind Cloud {0x026c4, 0x026c5}, // Snowman Without Snow ..Sun Behind Cloud
{0x26ce, 0x26ce}, // Ophiuchus ..Ophiuchus {0x026ce, 0x026ce}, // Ophiuchus ..Ophiuchus
{0x26d4, 0x26d4}, // No Entry ..No Entry {0x026d4, 0x026d4}, // No Entry ..No Entry
{0x26ea, 0x26ea}, // Church ..Church {0x026ea, 0x026ea}, // Church ..Church
{0x26f2, 0x26f3}, // Fountain ..Flag In Hole {0x026f2, 0x026f3}, // Fountain ..Flag In Hole
{0x26f5, 0x26f5}, // Sailboat ..Sailboat {0x026f5, 0x026f5}, // Sailboat ..Sailboat
{0x26fa, 0x26fa}, // Tent ..Tent {0x026fa, 0x026fa}, // Tent ..Tent
{0x26fd, 0x26fd}, // Fuel Pump ..Fuel Pump {0x026fd, 0x026fd}, // Fuel Pump ..Fuel Pump
{0x2705, 0x2705}, // White Heavy Check Mark ..White Heavy Check Mark {0x02705, 0x02705}, // White Heavy Check Mark ..White Heavy Check Mark
{0x270a, 0x270b}, // Raised Fist ..Raised Hand {0x0270a, 0x0270b}, // Raised Fist ..Raised Hand
{0x2728, 0x2728}, // Sparkles ..Sparkles {0x02728, 0x02728}, // Sparkles ..Sparkles
{0x274c, 0x274c}, // Cross Mark ..Cross Mark {0x0274c, 0x0274c}, // Cross Mark ..Cross Mark
{0x274e, 0x274e}, // Negative Squared Cross M..Negative Squared Cross M {0x0274e, 0x0274e}, // Negative Squared Cross M..Negative Squared Cross M
{0x2753, 0x2755}, // Black Question Mark ||na..White Exclamation Mark O {0x02753, 0x02755}, // Black Question Mark Orna..White Exclamation Mark O
{0x2757, 0x2757}, // Heavy Exclamation Mark S..Heavy Exclamation Mark S {0x02757, 0x02757}, // Heavy Exclamation Mark S..Heavy Exclamation Mark S
{0x2795, 0x2797}, // Heavy Plus Sign ..Heavy Division Sign {0x02795, 0x02797}, // Heavy Plus Sign ..Heavy Division Sign
{0x27b0, 0x27b0}, // Curly Loop ..Curly Loop {0x027b0, 0x027b0}, // Curly Loop ..Curly Loop
{0x27bf, 0x27bf}, // Double Curly Loop ..Double Curly Loop {0x027bf, 0x027bf}, // Double Curly Loop ..Double Curly Loop
{0x2b1b, 0x2b1c}, // Black Large Square ..White Large Square {0x02b1b, 0x02b1c}, // Black Large Square ..White Large Square
{0x2b50, 0x2b50}, // White Medium Star ..White Medium Star {0x02b50, 0x02b50}, // White Medium Star ..White Medium Star
{0x2b55, 0x2b55}, // Heavy Large Circle ..Heavy Large Circle {0x02b55, 0x02b55}, // Heavy Large Circle ..Heavy Large Circle
{0x2e80, 0x2e99}, // Cjk Radical Repeat ..Cjk Radical Rap {0x02e80, 0x02e99}, // Cjk Radical Repeat ..Cjk Radical Rap
{0x2e9b, 0x2ef3}, // Cjk Radical Choke ..Cjk Radical C-simplified {0x02e9b, 0x02ef3}, // Cjk Radical Choke ..Cjk Radical C-simplified
{0x2f00, 0x2fd5}, // Kangxi Radical One ..Kangxi Radical Flute {0x02f00, 0x02fd5}, // Kangxi Radical One ..Kangxi Radical Flute
{0x2ff0, 0x2ffb}, // Ideographic Description ..Ideographic Description {0x02ff0, 0x02ffb}, // Ideographic Description ..Ideographic Description
{0x3000, 0x303e}, // Ideographic Space ..Ideographic Variation In {0x03000, 0x0303e}, // Ideographic Space ..Ideographic Variation In
{0x3041, 0x3096}, // Hiragana Letter Small A ..Hiragana Letter Small Ke {0x03041, 0x03096}, // Hiragana Letter Small A ..Hiragana Letter Small Ke
{0x3099, 0x30ff}, // Combining Katakana-hirag..Katakana Digraph Koto {0x03099, 0x030ff}, // Combining Katakana-hirag..Katakana Digraph Koto
{0x3105, 0x312d}, // Bopomofo Letter B ..Bopomofo Letter Ih {0x03105, 0x0312f}, // Bopomofo Letter B ..Bopomofo Letter Nn
{0x3131, 0x318e}, // Hangul Letter Kiyeok ..Hangul Letter Araeae {0x03131, 0x0318e}, // Hangul Letter Kiyeok ..Hangul Letter Araeae
{0x3190, 0x31ba}, // Ideographic Annotation L..Bopomofo Letter Zy {0x03190, 0x031e3}, // Ideographic Annotation L..Cjk Stroke Q
{0x31c0, 0x31e3}, // Cjk Stroke T ..Cjk Stroke Q {0x031f0, 0x0321e}, // Katakana Letter Small Ku..Parenthesized Korean Cha
{0x31f0, 0x321e}, // Katakana Letter Small Ku..Parenthesized K||ean Cha {0x03220, 0x03247}, // Parenthesized Ideograph ..Circled Ideograph Koto
{0x3220, 0x3247}, // Parenthesized Ideograph ..Circled Ideograph Koto {0x03250, 0x04dbf}, // Partnership Sign ..(nil)
{0x3250, 0x32fe}, // Partnership Sign ..Circled Katakana Wo {0x04e00, 0x0a48c}, // Cjk Unified Ideograph-4e..Yi Syllable Yyr
{0x3300, 0x4dbf}, // Square Apaato .. {0x0a490, 0x0a4c6}, // Yi Radical Qot ..Yi Radical Ke
{0x4e00, 0xa48c}, // Cjk Unified Ideograph-4e..Yi Syllable Yyr {0x0a960, 0x0a97c}, // Hangul Choseong Tikeut-m..Hangul Choseong Ssangyeo
{0xa490, 0xa4c6}, // Yi Radical Qot ..Yi Radical Ke {0x0ac00, 0x0d7a3}, // Hangul Syllable Ga ..Hangul Syllable Hih
{0xa960, 0xa97c}, // Hangul Choseong Tikeut-m..Hangul Choseong Ssangyeo {0x0f900, 0x0faff}, // Cjk Compatibility Ideogr..(nil)
{0xac00, 0xd7a3}, // Hangul Syllable Ga ..Hangul Syllable Hih {0x0fe10, 0x0fe19}, // Presentation Form For Ve..Presentation Form For Ve
{0xf900, 0xfaff}, // Cjk Compatibility Ideogr.. {0x0fe30, 0x0fe52}, // Presentation Form For Ve..Small Full Stop
{0xfe10, 0xfe19}, // Presentation F||m F|| Ve..Presentation F||m F|| Ve {0x0fe54, 0x0fe66}, // Small Semicolon ..Small Equals Sign
{0xfe30, 0xfe52}, // Presentation F||m F|| Ve..Small Full Stop {0x0fe68, 0x0fe6b}, // Small Reverse Solidus ..Small Commercial At
{0xfe54, 0xfe66}, // Small Semicolon ..Small Equals Sign {0x0ff01, 0x0ff60}, // Fullwidth Exclamation Ma..Fullwidth Right White Pa
{0xfe68, 0xfe6b}, // Small Reverse Solidus ..Small Commercial At {0x0ffe0, 0x0ffe6}, // Fullwidth Cent Sign ..Fullwidth Won Sign
{0xff01, 0xff60}, // Fullwidth Exclamation Ma..Fullwidth Right White Pa {0x16fe0, 0x16fe4}, // Tangut Iteration Mark ..(nil)
{0xffe0, 0xffe6}, // Fullwidth Cent Sign ..Fullwidth Won Sign {0x16ff0, 0x16ff1}, // (nil) ..(nil)
{0x16fe0, 0x16fe0}, // (nil) .. {0x17000, 0x187f7}, // (nil) ..(nil)
{0x17000, 0x187ec}, // (nil) .. {0x18800, 0x18cd5}, // Tangut Component-001 ..(nil)
{0x18800, 0x18af2}, // (nil) .. {0x18d00, 0x18d08}, // (nil) ..(nil)
{0x1b000, 0x1b001}, // Katakana Letter Archaic ..Hiragana Letter Archaic {0x1b000, 0x1b11e}, // Katakana Letter Archaic ..Hentaigana Letter N-mu-m
{0x1b150, 0x1b152}, // Hiragana Letter Small Wi..Hiragana Letter Small Wo
{0x1b164, 0x1b167}, // Katakana Letter Small Wi..Katakana Letter Small N
{0x1b170, 0x1b2fb}, // Nushu Character-1b170 ..Nushu Character-1b2fb
{0x1f004, 0x1f004}, // Mahjong Tile Red Dragon ..Mahjong Tile Red Dragon {0x1f004, 0x1f004}, // Mahjong Tile Red Dragon ..Mahjong Tile Red Dragon
{0x1f0cf, 0x1f0cf}, // Playing Card Black Joker..Playing Card Black Joker {0x1f0cf, 0x1f0cf}, // Playing Card Black Joker..Playing Card Black Joker
{0x1f18e, 0x1f18e}, // Negative Squared Ab ..Negative Squared Ab {0x1f18e, 0x1f18e}, // Negative Squared Ab ..Negative Squared Ab
{0x1f191, 0x1f19a}, // Squared Cl ..Squared Vs {0x1f191, 0x1f19a}, // Squared Cl ..Squared Vs
{0x1f200, 0x1f202}, // Square Hiragana Hoka ..Squared Katakana Sa {0x1f200, 0x1f202}, // Square Hiragana Hoka ..Squared Katakana Sa
{0x1f210, 0x1f23b}, // Squared Cjk Unified Ideo.. {0x1f210, 0x1f23b}, // Squared Cjk Unified Ideo..Squared Cjk Unified Ideo
{0x1f240, 0x1f248}, // T||toise Shell Bracketed..T||toise Shell Bracketed {0x1f240, 0x1f248}, // Tortoise Shell Bracketed..Tortoise Shell Bracketed
{0x1f250, 0x1f251}, // Circled Ideograph Advant..Circled Ideograph Accept {0x1f250, 0x1f251}, // Circled Ideograph Advant..Circled Ideograph Accept
{0x1f260, 0x1f265}, // Rounded Symbol For Fu ..Rounded Symbol For Cai
{0x1f300, 0x1f320}, // Cyclone ..Shooting Star {0x1f300, 0x1f320}, // Cyclone ..Shooting Star
{0x1f32d, 0x1f335}, // Hot Dog ..Cactus {0x1f32d, 0x1f335}, // Hot Dog ..Cactus
{0x1f337, 0x1f37c}, // Tulip ..Baby Bottle {0x1f337, 0x1f37c}, // Tulip ..Baby Bottle
{0x1f37e, 0x1f393}, // Bottle With Popping C||k..Graduation Cap {0x1f37e, 0x1f393}, // Bottle With Popping Cork..Graduation Cap
{0x1f3a0, 0x1f3ca}, // Carousel H||se ..Swimmer {0x1f3a0, 0x1f3ca}, // Carousel Horse ..Swimmer
{0x1f3cf, 0x1f3d3}, // Cricket Bat And Ball ..Table Tennis Paddle And {0x1f3cf, 0x1f3d3}, // Cricket Bat And Ball ..Table Tennis Paddle And
{0x1f3e0, 0x1f3f0}, // House Building ..European Castle {0x1f3e0, 0x1f3f0}, // House Building ..European Castle
{0x1f3f4, 0x1f3f4}, // Waving Black Flag ..Waving Black Flag {0x1f3f4, 0x1f3f4}, // Waving Black Flag ..Waving Black Flag
@@ -383,27 +434,33 @@ public final class WcWidth {
{0x1f440, 0x1f440}, // Eyes ..Eyes {0x1f440, 0x1f440}, // Eyes ..Eyes
{0x1f442, 0x1f4fc}, // Ear ..Videocassette {0x1f442, 0x1f4fc}, // Ear ..Videocassette
{0x1f4ff, 0x1f53d}, // Prayer Beads ..Down-pointing Small Red {0x1f4ff, 0x1f53d}, // Prayer Beads ..Down-pointing Small Red
{0x1f54b, 0x1f54e}, // Kaaba ..Men||ah With Nine Branch {0x1f54b, 0x1f54e}, // Kaaba ..Menorah With Nine Branch
{0x1f550, 0x1f567}, // Clock Face One Oclock ..Clock Face Twelve-thirty {0x1f550, 0x1f567}, // Clock Face One Oclock ..Clock Face Twelve-thirty
{0x1f57a, 0x1f57a}, // (nil) .. {0x1f57a, 0x1f57a}, // Man Dancing ..Man Dancing
{0x1f595, 0x1f596}, // Reversed Hand With Middl..Raised Hand With Part Be {0x1f595, 0x1f596}, // Reversed Hand With Middl..Raised Hand With Part Be
{0x1f5a4, 0x1f5a4}, // (nil) .. {0x1f5a4, 0x1f5a4}, // Black Heart ..Black Heart
{0x1f5fb, 0x1f64f}, // Mount Fuji ..Person With Folded Hands {0x1f5fb, 0x1f64f}, // Mount Fuji ..Person With Folded Hands
{0x1f680, 0x1f6c5}, // Rocket ..Left Luggage {0x1f680, 0x1f6c5}, // Rocket ..Left Luggage
{0x1f6cc, 0x1f6cc}, // Sleeping Accommodation ..Sleeping Accommodation {0x1f6cc, 0x1f6cc}, // Sleeping Accommodation ..Sleeping Accommodation
{0x1f6d0, 0x1f6d2}, // Place Of W||ship .. {0x1f6d0, 0x1f6d2}, // Place Of Worship ..Shopping Trolley
{0x1f6d5, 0x1f6d7}, // Hindu Temple ..(nil)
{0x1f6eb, 0x1f6ec}, // Airplane Departure ..Airplane Arriving {0x1f6eb, 0x1f6ec}, // Airplane Departure ..Airplane Arriving
{0x1f6f4, 0x1f6f6}, // (nil) .. {0x1f6f4, 0x1f6fc}, // Scooter ..(nil)
{0x1f910, 0x1f91e}, // Zipper-mouth Face .. {0x1f7e0, 0x1f7eb}, // Large Orange Circle ..Large Brown Square
{0x1f920, 0x1f927}, // (nil) .. {0x1f90c, 0x1f93a}, // (nil) ..Fencer
{0x1f930, 0x1f930}, // (nil) .. {0x1f93c, 0x1f945}, // Wrestlers ..Goal Net
{0x1f933, 0x1f93e}, // (nil) .. {0x1f947, 0x1f978}, // First Place Medal ..(nil)
{0x1f940, 0x1f94b}, // (nil) .. {0x1f97a, 0x1f9cb}, // Face With Pleading Eyes ..(nil)
{0x1f950, 0x1f95e}, // (nil) .. {0x1f9cd, 0x1f9ff}, // Standing Person ..Nazar Amulet
{0x1f980, 0x1f991}, // Crab .. {0x1fa70, 0x1fa74}, // Ballet Shoes ..(nil)
{0x1f9c0, 0x1f9c0}, // Cheese Wedge ..Cheese Wedge {0x1fa78, 0x1fa7a}, // Drop Of Blood ..Stethoscope
{0x20000, 0x2fffd}, // Cjk Unified Ideograph-20.. {0x1fa80, 0x1fa86}, // Yo-yo ..(nil)
{0x30000, 0x3fffd}, // (nil) .. {0x1fa90, 0x1faa8}, // Ringed Planet ..(nil)
{0x1fab0, 0x1fab6}, // (nil) ..(nil)
{0x1fac0, 0x1fac2}, // (nil) ..(nil)
{0x1fad0, 0x1fad6}, // (nil) ..(nil)
{0x20000, 0x2fffd}, // Cjk Unified Ideograph-20..(nil)
{0x30000, 0x3fffd}, // (nil) ..(nil)
}; };

View File

@@ -17,7 +17,7 @@ ext {
} }
android { android {
compileSdkVersion 28 compileSdkVersion project.properties.compileSdkVersion.toInteger()
dependencies { dependencies {
implementation "androidx.annotation:annotation:1.1.0" implementation "androidx.annotation:annotation:1.1.0"
@@ -25,8 +25,8 @@ android {
} }
defaultConfig { defaultConfig {
minSdkVersion 21 minSdkVersion project.properties.minSdkVersion.toInteger()
targetSdkVersion 28 targetSdkVersion project.properties.targetSdkVersion.toInteger()
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
} }

View File

@@ -86,6 +86,7 @@ public final class TerminalRenderer {
long lastRunStyle = 0; long lastRunStyle = 0;
boolean lastRunInsideCursor = false; boolean lastRunInsideCursor = false;
boolean lastRunInsideSelection = false;
int lastRunStartColumn = -1; int lastRunStartColumn = -1;
int lastRunStartIndex = 0; int lastRunStartIndex = 0;
boolean lastRunFontWidthMismatch = false; boolean lastRunFontWidthMismatch = false;
@@ -98,7 +99,8 @@ public final class TerminalRenderer {
final int charsForCodePoint = charIsHighsurrogate ? 2 : 1; final int charsForCodePoint = charIsHighsurrogate ? 2 : 1;
final int codePoint = charIsHighsurrogate ? Character.toCodePoint(charAtIndex, line[currentCharIndex + 1]) : charAtIndex; final int codePoint = charIsHighsurrogate ? Character.toCodePoint(charAtIndex, line[currentCharIndex + 1]) : charAtIndex;
final int codePointWcWidth = WcWidth.width(codePoint); final int codePointWcWidth = WcWidth.width(codePoint);
final boolean insideCursor = (column >= selx1 && column <= selx2) || (cursorX == column || (codePointWcWidth == 2 && cursorX == column + 1)); final boolean insideCursor = (cursorX == column || (codePointWcWidth == 2 && cursorX == column + 1));
final boolean insideSelection = column >= selx1 && column <= selx2;
final long style = lineObject.getStyle(column); final long style = lineObject.getStyle(column);
// Check if the measured text width for this code point is not the same as that expected by wcwidth(). // Check if the measured text width for this code point is not the same as that expected by wcwidth().
@@ -109,7 +111,7 @@ public final class TerminalRenderer {
currentCharIndex, charsForCodePoint); currentCharIndex, charsForCodePoint);
final boolean fontWidthMismatch = Math.abs(measuredCodePointWidth / mFontWidth - codePointWcWidth) > 0.01; final boolean fontWidthMismatch = Math.abs(measuredCodePointWidth / mFontWidth - codePointWcWidth) > 0.01;
if (style != lastRunStyle || insideCursor != lastRunInsideCursor || fontWidthMismatch || lastRunFontWidthMismatch) { if (style != lastRunStyle || insideCursor != lastRunInsideCursor || insideSelection != lastRunInsideSelection || fontWidthMismatch || lastRunFontWidthMismatch) {
if (column == 0) { if (column == 0) {
// Skip first column as there is nothing to draw, just record the current style. // Skip first column as there is nothing to draw, just record the current style.
} else { } else {
@@ -118,11 +120,12 @@ public final class TerminalRenderer {
int cursorColor = lastRunInsideCursor ? mEmulator.mColors.mCurrentColors[TextStyle.COLOR_INDEX_CURSOR] : 0; int cursorColor = lastRunInsideCursor ? mEmulator.mColors.mCurrentColors[TextStyle.COLOR_INDEX_CURSOR] : 0;
drawTextRun(canvas, line, palette, heightOffset, lastRunStartColumn, columnWidthSinceLastRun, drawTextRun(canvas, line, palette, heightOffset, lastRunStartColumn, columnWidthSinceLastRun,
lastRunStartIndex, charsSinceLastRun, measuredWidthForRun, lastRunStartIndex, charsSinceLastRun, measuredWidthForRun,
cursorColor, cursorShape, lastRunStyle, reverseVideo); cursorColor, cursorShape, lastRunStyle, reverseVideo || lastRunInsideSelection);
} }
measuredWidthForRun = 0.f; measuredWidthForRun = 0.f;
lastRunStyle = style; lastRunStyle = style;
lastRunInsideCursor = insideCursor; lastRunInsideCursor = insideCursor;
lastRunInsideSelection = insideSelection;
lastRunStartColumn = column; lastRunStartColumn = column;
lastRunStartIndex = currentCharIndex; lastRunStartIndex = currentCharIndex;
lastRunFontWidthMismatch = fontWidthMismatch; lastRunFontWidthMismatch = fontWidthMismatch;
@@ -141,7 +144,7 @@ public final class TerminalRenderer {
final int charsSinceLastRun = currentCharIndex - lastRunStartIndex; final int charsSinceLastRun = currentCharIndex - lastRunStartIndex;
int cursorColor = lastRunInsideCursor ? mEmulator.mColors.mCurrentColors[TextStyle.COLOR_INDEX_CURSOR] : 0; int cursorColor = lastRunInsideCursor ? mEmulator.mColors.mCurrentColors[TextStyle.COLOR_INDEX_CURSOR] : 0;
drawTextRun(canvas, line, palette, heightOffset, lastRunStartColumn, columnWidthSinceLastRun, lastRunStartIndex, charsSinceLastRun, drawTextRun(canvas, line, palette, heightOffset, lastRunStartColumn, columnWidthSinceLastRun, lastRunStartIndex, charsSinceLastRun,
measuredWidthForRun, cursorColor, cursorShape, lastRunStyle, reverseVideo); measuredWidthForRun, cursorColor, cursorShape, lastRunStyle, reverseVideo || lastRunInsideSelection);
} }
} }

View File

@@ -31,12 +31,15 @@ import android.view.ViewParent;
import android.view.ViewTreeObserver; import android.view.ViewTreeObserver;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager;
import android.view.autofill.AutofillValue;
import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection;
import android.widget.PopupWindow; import android.widget.PopupWindow;
import android.widget.Scroller; import android.widget.Scroller;
import androidx.annotation.RequiresApi;
import com.termux.terminal.EmulatorDebug; import com.termux.terminal.EmulatorDebug;
import com.termux.terminal.KeyHandler; import com.termux.terminal.KeyHandler;
import com.termux.terminal.TerminalBuffer; import com.termux.terminal.TerminalBuffer;
@@ -44,6 +47,12 @@ import com.termux.terminal.TerminalEmulator;
import com.termux.terminal.TerminalSession; import com.termux.terminal.TerminalSession;
import com.termux.terminal.WcWidth; import com.termux.terminal.WcWidth;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Properties;
/** View displaying and interacting with a {@link TerminalSession}. */ /** View displaying and interacting with a {@link TerminalSession}. */
public final class TerminalView extends View { public final class TerminalView extends View {
@@ -246,14 +255,36 @@ public final class TerminalView extends View {
@Override @Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) { public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
// Using InputType.NULL is the most correct input type and avoids issues with other hacks. File propsFile = new File(getContext().getFilesDir() + "/home/.termux/termux.properties");
// if (!propsFile.exists())
// Previous keyboard issues: propsFile = new File(getContext().getFilesDir() + "/home/.config/termux/termux.properties");
// https://github.com/termux/termux-packages/issues/25
// https://github.com/termux/termux-app/issues/87. Properties props = new Properties();
// https://github.com/termux/termux-app/issues/126. try {
// https://github.com/termux/termux-app/issues/137 (japanese chars and TYPE_NULL). if (propsFile.isFile() && propsFile.canRead()) {
outAttrs.inputType = InputType.TYPE_NULL; try (FileInputStream in = new FileInputStream(propsFile)) {
props.load(new InputStreamReader(in, StandardCharsets.UTF_8));
}
}
} catch (Exception e) {
Log.e("termux", "Error loading props", e);
}
if (props.getProperty("enforce-char-based-input", "false").equals("true")) {
// Some keyboards seems do not reset the internal state on TYPE_NULL.
// Affects mostly Samsung stock keyboards.
// https://github.com/termux/termux-app/issues/686
outAttrs.inputType = InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
} else {
// Using InputType.NULL is the most correct input type and avoids issues with other hacks.
//
// Previous keyboard issues:
// https://github.com/termux/termux-packages/issues/25
// https://github.com/termux/termux-app/issues/87.
// https://github.com/termux/termux-app/issues/126.
// https://github.com/termux/termux-app/issues/137 (japanese chars and TYPE_NULL).
outAttrs.inputType = InputType.TYPE_NULL;
}
// Note that IME_ACTION_NONE cannot be used as that makes it impossible to input newlines using the on-screen // Note that IME_ACTION_NONE cannot be used as that makes it impossible to input newlines using the on-screen
// keyboard on Android TV (see https://github.com/termux/termux-app/issues/221). // keyboard on Android TV (see https://github.com/termux/termux-app/issues/221).
@@ -1512,4 +1543,24 @@ public final class TerminalView extends View {
} }
} }
} }
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void autofill(AutofillValue value) {
if (value.isText()) {
mTermSession.write(value.getTextValue().toString());
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public int getAutofillType() {
return AUTOFILL_TYPE_TEXT;
}
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public AutofillValue getAutofillValue() {
return AutofillValue.forText("");
}
} }