diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:16 -0800 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:16 -0800 |
| commit | d4aee0c0caa00aa02d4c50ed28151591ac0456b5 (patch) | |
| tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /apps/Term | |
| parent | d2f2b1d7b77d06bce8cf9340171cf6c25cd720c4 (diff) | |
| download | android_development-d4aee0c0caa00aa02d4c50ed28151591ac0456b5.tar.gz android_development-d4aee0c0caa00aa02d4c50ed28151591ac0456b5.tar.bz2 android_development-d4aee0c0caa00aa02d4c50ed28151591ac0456b5.zip | |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'apps/Term')
| -rw-r--r-- | apps/Term/Android.mk | 10 | ||||
| -rw-r--r-- | apps/Term/AndroidManifest.xml | 16 | ||||
| -rw-r--r-- | apps/Term/MODULE_LICENSE_APACHE2 | 0 | ||||
| -rw-r--r-- | apps/Term/NOTICE | 190 | ||||
| -rw-r--r-- | apps/Term/res/drawable/app_terminal.png | bin | 1409 -> 0 bytes | |||
| -rw-r--r-- | apps/Term/res/drawable/atari_small.png | bin | 1006 -> 0 bytes | |||
| -rw-r--r-- | apps/Term/res/drawable/atari_small_notice.txt | 11 | ||||
| -rw-r--r-- | apps/Term/res/layout/term_activity.xml | 30 | ||||
| -rw-r--r-- | apps/Term/res/menu/main.xml | 27 | ||||
| -rw-r--r-- | apps/Term/res/values/arrays.xml | 73 | ||||
| -rw-r--r-- | apps/Term/res/values/attrs.xml | 22 | ||||
| -rw-r--r-- | apps/Term/res/values/strings.xml | 55 | ||||
| -rw-r--r-- | apps/Term/res/values/styles.xml | 23 | ||||
| -rw-r--r-- | apps/Term/res/xml/preferences.xml | 73 | ||||
| -rw-r--r-- | apps/Term/src/com/android/term/Term.java | 3262 | ||||
| -rw-r--r-- | apps/Term/src/com/android/term/TermPreferences.java | 32 |
16 files changed, 0 insertions, 3824 deletions
diff --git a/apps/Term/Android.mk b/apps/Term/Android.mk deleted file mode 100644 index 843aec59b..000000000 --- a/apps/Term/Android.mk +++ /dev/null @@ -1,10 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := eng - -LOCAL_SRC_FILES := $(call all-subdir-java-files) - -LOCAL_PACKAGE_NAME := Term - -include $(BUILD_PACKAGE) diff --git a/apps/Term/AndroidManifest.xml b/apps/Term/AndroidManifest.xml deleted file mode 100644 index 7084d2c2c..000000000 --- a/apps/Term/AndroidManifest.xml +++ /dev/null @@ -1,16 +0,0 @@ -<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.term"> - <application android:icon="@drawable/app_terminal" - android:label="@string/application_terminal"> - <activity android:name="Term" - android:theme="@style/Theme" - android:launchMode="singleInstance" - android:configChanges="keyboard|keyboardHidden|orientation" - android:windowSoftInputMode="adjustResize|stateVisible"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.TEST" /> - </intent-filter> - </activity> - <activity android:name="TermPreferences"/> - </application> -</manifest> diff --git a/apps/Term/MODULE_LICENSE_APACHE2 b/apps/Term/MODULE_LICENSE_APACHE2 deleted file mode 100644 index e69de29bb..000000000 --- a/apps/Term/MODULE_LICENSE_APACHE2 +++ /dev/null diff --git a/apps/Term/NOTICE b/apps/Term/NOTICE deleted file mode 100644 index c5b1efa7a..000000000 --- a/apps/Term/NOTICE +++ /dev/null @@ -1,190 +0,0 @@ - - Copyright (c) 2005-2008, The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - diff --git a/apps/Term/res/drawable/app_terminal.png b/apps/Term/res/drawable/app_terminal.png Binary files differdeleted file mode 100644 index 1ec3b4b88..000000000 --- a/apps/Term/res/drawable/app_terminal.png +++ /dev/null diff --git a/apps/Term/res/drawable/atari_small.png b/apps/Term/res/drawable/atari_small.png Binary files differdeleted file mode 100644 index 535e295c8..000000000 --- a/apps/Term/res/drawable/atari_small.png +++ /dev/null diff --git a/apps/Term/res/drawable/atari_small_notice.txt b/apps/Term/res/drawable/atari_small_notice.txt deleted file mode 100644 index afa8539b8..000000000 --- a/apps/Term/res/drawable/atari_small_notice.txt +++ /dev/null @@ -1,11 +0,0 @@ -COMMENT Copyright (c) 1999, Thomas A. Fine -COMMENT -COMMENT License to copy, modify, and distribute for both commercial and -COMMENT non-commercial use is herby granted, provided this notice -COMMENT is preserved. -COMMENT -COMMENT Email to my last name at head.cfa.harvard.edu -COMMENT http://hea-www.harvard.edu/~fine/ -COMMENT -COMMENT Produced with bdfedit, a tcl/tk font editing program -COMMENT written by Thomas A. Fine
\ No newline at end of file diff --git a/apps/Term/res/layout/term_activity.xml b/apps/Term/res/layout/term_activity.xml deleted file mode 100644 index 7d93d1659..000000000 --- a/apps/Term/res/layout/term_activity.xml +++ /dev/null @@ -1,30 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:orientation="vertical"> - - <com.android.term.EmulatorView android:id="@+id/emulatorView" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_alignParentLeft="true" - /> - -</LinearLayout> diff --git a/apps/Term/res/menu/main.xml b/apps/Term/res/menu/main.xml deleted file mode 100644 index 5f6e9d808..000000000 --- a/apps/Term/res/menu/main.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. ---> - -<menu xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:id="@+id/menu_preferences" - android:title="@string/preferences" /> - <item android:id="@+id/menu_reset" - android:title="@string/reset" /> - <item android:id="@+id/menu_send_email" - android:title="@string/send_email" /> - <item android:id="@+id/menu_special_keys" - android:title="@string/special_keys" /> -</menu> diff --git a/apps/Term/res/values/arrays.xml b/apps/Term/res/values/arrays.xml deleted file mode 100644 index b4857a2ea..000000000 --- a/apps/Term/res/values/arrays.xml +++ /dev/null @@ -1,73 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - --> - -<resources> - <string-array name="entries_fontsize_preference"> - <item>4 x 8 pixels</item> - <item>6 pt</item> - <item>7 pt</item> - <item>8 pt</item> - <item>9 pt</item> - <item>10 pt</item> - <item>12 pt</item> - <item>14 pt</item> - <item>16 pt</item> - <item>20 pt</item> - </string-array> - - <!-- Do not localize entryvalues --> - <string-array name="entryvalues_fontsize_preference"> - <item>0</item> - <item>6</item> - <item>7</item> - <item>8</item> - <item>9</item> - <item>10</item> - <item>12</item> - <item>14</item> - <item>16</item> - <item>20</item> - </string-array> - - <string-array name="entries_color_preference"> - <item>Black text on white</item> - <item>White text on black</item> - <item>White text on blue</item> - </string-array> - - <!-- Do not localize entryvalues --> - <string-array name="entryvalues_color_preference"> - <item>0</item> - <item>1</item> - <item>2</item> - </string-array> - - <string-array name="entries_controlkey_preference"> - <item>Jog ball</item> - <item>\@ key</item> - <item>Left Alt key</item> - <item>Right Alt key</item> - </string-array> - - <!-- Do not localize entryvalues --> - <string-array name="entryvalues_controlkey_preference"> - <item>0</item> - <item>1</item> - <item>2</item> - <item>3</item> - </string-array> -</resources> diff --git a/apps/Term/res/values/attrs.xml b/apps/Term/res/values/attrs.xml deleted file mode 100644 index 3787d7e84..000000000 --- a/apps/Term/res/values/attrs.xml +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -/* Copyright 2007, The Android Open Source Project -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ ---> - -<resources> - <declare-styleable name="EmulatorView"> - </declare-styleable> -</resources> diff --git a/apps/Term/res/values/strings.xml b/apps/Term/res/values/strings.xml deleted file mode 100644 index e3f8fcf91..000000000 --- a/apps/Term/res/values/strings.xml +++ /dev/null @@ -1,55 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. ---> -<resources> - <string name="application_terminal">Terminal Emulator</string> - <string name="preferences">Preferences</string> - <string name="reset">Reset term</string> - <string name="send_email">Email to</string> - <string name="special_keys">Special keys</string> - - <!-- Preference dialog --> - <string name="text_preferences">Text</string> - - <string name="title_fontsize_preference">Font size</string> - <string name="summary_fontsize_preference">Choose character height in pixels.</string> - <string name="dialog_title_fontsize_preference">Font size</string> - - <string name="title_color_preference">Colors</string> - <string name="summary_color_preference">Choose text color.</string> - <string name="dialog_title_color_preference">Text color</string> - - <string name="keyboard_preferences">Keyboard</string> - <string name="title_controlkey_preference">Control key</string> - <string name="summary_controlkey_preference">Choose control key.</string> - <string name="dialog_title_controlkey_preference">Control key</string> - - <string name="shell_preferences">Shell</string> - <string name="title_shell_preference">Command line</string> - <string name="summary_shell_preference">Specify the shell command line.</string> - <string name="dialog_title_shell_preference">Shell</string> - - <string name="title_initialcommand_preference">Initial command</string> - <string name="summary_initialcommand_preference">Sent to the shell when it starts.</string> - <string name="dialog_title_initialcommand_preference">Initial Command</string> - - <!-- Don't localize these default values --> - <string name="default_value_fontsize_preference">10</string> - <string name="default_value_color_preference">2</string> - <string name="default_value_controlkey_preference">0</string> - <string name="default_value_shell_preference">/system/bin/sh -</string> - <string name="default_value_initialcommand_preference">export PATH=/data/local/bin:$PATH</string> -</resources> diff --git a/apps/Term/res/values/styles.xml b/apps/Term/res/values/styles.xml deleted file mode 100644 index 0e59f4a76..000000000 --- a/apps/Term/res/values/styles.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2007 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<resources> - <style name="Theme" parent="@android:style/Theme.Light"> - <item name="android:windowNoTitle">true</item> - <item name="android:windowFrame">@null</item> - </style> -</resources> - diff --git a/apps/Term/res/xml/preferences.xml b/apps/Term/res/xml/preferences.xml deleted file mode 100644 index 779215325..000000000 --- a/apps/Term/res/xml/preferences.xml +++ /dev/null @@ -1,73 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- Copyright (C) 2008 The Android Open Source Project - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---> - -<PreferenceScreen - xmlns:android="http://schemas.android.com/apk/res/android"> - - <PreferenceCategory - android:title="@string/text_preferences"> - - <ListPreference - android:key="fontsize" - android:defaultValue="@string/default_value_fontsize_preference" - android:title="@string/title_fontsize_preference" - android:summary="@string/summary_fontsize_preference" - android:entries="@array/entries_fontsize_preference" - android:entryValues="@array/entryvalues_fontsize_preference" - android:dialogTitle="@string/dialog_title_fontsize_preference" /> - - <ListPreference - android:key="color" - android:defaultValue="@string/default_value_color_preference" - android:title="@string/title_color_preference" - android:summary="@string/summary_color_preference" - android:entries="@array/entries_color_preference" - android:entryValues="@array/entryvalues_color_preference" - android:dialogTitle="@string/dialog_title_color_preference" /> - - </PreferenceCategory> - - <PreferenceCategory - android:title="@string/keyboard_preferences"> - - <ListPreference - android:key="controlkey" - android:defaultValue="@string/default_value_controlkey_preference" - android:title="@string/title_controlkey_preference" - android:summary="@string/summary_controlkey_preference" - android:entries="@array/entries_controlkey_preference" - android:entryValues="@array/entryvalues_controlkey_preference" - android:dialogTitle="@string/dialog_title_controlkey_preference" /> - - </PreferenceCategory> - - <PreferenceCategory - android:title="@string/shell_preferences"> - - <EditTextPreference - android:key="shell" - android:defaultValue="@string/default_value_shell_preference" - android:title="@string/title_shell_preference" - android:summary="@string/summary_shell_preference" - android:dialogTitle="@string/dialog_title_shell_preference" /> - <EditTextPreference - android:key="initialcommand" - android:defaultValue="@string/default_value_initialcommand_preference" - android:title="@string/title_initialcommand_preference" - android:summary="@string/summary_initialcommand_preference" - android:dialogTitle="@string/dialog_title_initialcommand_preference" /> - </PreferenceCategory> -</PreferenceScreen> diff --git a/apps/Term/src/com/android/term/Term.java b/apps/Term/src/com/android/term/Term.java deleted file mode 100644 index d74159b90..000000000 --- a/apps/Term/src/com/android/term/Term.java +++ /dev/null @@ -1,3262 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.term; - -import android.app.Activity; -import android.app.AlertDialog; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.ColorMatrixColorFilter; -import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; -import android.graphics.Rect; -import android.graphics.Typeface; -import android.net.Uri; -import android.os.Bundle; -import android.os.Exec; -import android.os.Handler; -import android.os.Message; -import android.os.SystemClock; -import android.preference.PreferenceManager; -import android.util.AttributeSet; -import android.util.Log; -import android.view.GestureDetector; -import android.view.KeyEvent; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.View; -import android.view.inputmethod.BaseInputConnection; -import android.view.inputmethod.CompletionInfo; -import android.view.inputmethod.EditorInfo; -import android.view.inputmethod.ExtractedText; -import android.view.inputmethod.ExtractedTextRequest; -import android.view.inputmethod.InputConnection; -import android.view.inputmethod.InputMethodManager; - -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; - -/** - * A terminal emulator activity. - */ - -public class Term extends Activity { - /** - * Set to true to add debugging code and logging. - */ - public static final boolean DEBUG = false; - - /** - * Set to true to log each character received from the remote process to the - * android log, which makes it easier to debug some kinds of problems with - * emulating escape sequences and control codes. - */ - public static final boolean LOG_CHARACTERS_FLAG = DEBUG && false; - - /** - * Set to true to log unknown escape sequences. - */ - public static final boolean LOG_UNKNOWN_ESCAPE_SEQUENCES = DEBUG && false; - - /** - * The tag we use when logging, so that our messages can be distinguished - * from other messages in the log. Public because it's used by several - * classes. - */ - public static final String LOG_TAG = "Term"; - - /** - * Our main view. Displays the emulated terminal screen. - */ - private EmulatorView mEmulatorView; - - /** - * The pseudo-teletype (pty) file descriptor that we use to communicate with - * another process, typically a shell. Currently we just use this to get the - * mTermIn / mTermOut file descriptors, but when we implement resizing of - * the terminal we will need it to issue the ioctl to inform the other - * process that we've changed the terminal size. - */ - private FileDescriptor mTermFd; - - private boolean mShellRunning; - - /** - * Used to send data to the remote process. - */ - private FileOutputStream mTermOut; - - /** - * A key listener that tracks the modifier keys and allows the full ASCII - * character set to be entered. - */ - private TermKeyListener mKeyListener; - - /** - * The name of our emulator view in the view resource. - */ - private static final int EMULATOR_VIEW = R.id.emulatorView; - - private int mFontSize = 9; - private int mColorId = 2; - private int mControlKeyId = 0; - - private static final String FONTSIZE_KEY = "fontsize"; - private static final String COLOR_KEY = "color"; - private static final String CONTROLKEY_KEY = "controlkey"; - private static final String SHELL_KEY = "shell"; - private static final String INITIALCOMMAND_KEY = "initialcommand"; - - public static final int WHITE = 0xffffffff; - public static final int BLACK = 0xff000000; - public static final int BLUE = 0xff344ebd; - - private static final int[][] COLOR_SCHEMES = { - {BLACK, WHITE}, {WHITE, BLACK}, {WHITE, BLUE}}; - - private static final int[] CONTROL_KEY_SCHEMES = { - KeyEvent.KEYCODE_DPAD_CENTER, - KeyEvent.KEYCODE_AT, - KeyEvent.KEYCODE_ALT_LEFT, - KeyEvent.KEYCODE_ALT_RIGHT - }; - private static final String[] CONTROL_KEY_NAME = { - "Ball", "@", "Left-Alt", "Right-Alt" - }; - - private int mControlKeyCode; - - private final static String DEFAULT_SHELL = "/system/bin/sh -"; - private String mShell; - - private final static String DEFAULT_INITIAL_COMMAND = - "export PATH=/data/local/bin:$PATH"; - private String mInitialCommand; - - private SharedPreferences mPrefs; - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - Log.e(Term.LOG_TAG, "onCreate"); - mPrefs = PreferenceManager.getDefaultSharedPreferences(this); - mPrefs.registerOnSharedPreferenceChangeListener( - new SharedPreferences.OnSharedPreferenceChangeListener(){ - - public void onSharedPreferenceChanged( - SharedPreferences sharedPreferences, String key) { - readPrefs(); - updatePrefs(); - }}); - readPrefs(); - - setContentView(R.layout.term_activity); - - mEmulatorView = (EmulatorView) findViewById(EMULATOR_VIEW); - - startListening(); - - mKeyListener = new TermKeyListener(); - - mEmulatorView.setFocusable(true); - mEmulatorView.requestFocus(); - - updatePrefs(); - } - - private void startListening() { - int[] processId = new int[1]; - - createSubprocess(processId); - mShellRunning = true; - - final int procId = processId[0]; - - final Handler handler = new Handler() { - @Override - public void handleMessage(Message msg) { - mShellRunning = false; - } - }; - - Runnable watchForDeath = new Runnable() { - - public void run() { - Log.i(Term.LOG_TAG, "waiting for: " + procId); - int result = Exec.waitFor(procId); - Log.i(Term.LOG_TAG, "Subprocess exited: " + result); - handler.sendEmptyMessage(result); - } - - }; - Thread watcher = new Thread(watchForDeath); - watcher.start(); - - mTermOut = new FileOutputStream(mTermFd); - - mEmulatorView.initialize(mTermFd, mTermOut); - - sendInitialCommand(); - } - - private void sendInitialCommand() { - String initialCommand = mInitialCommand; - if (initialCommand == null) { - initialCommand = DEFAULT_INITIAL_COMMAND; - } - if (initialCommand.length() > 0) { - write(initialCommand + '\r'); - } - } - - private void restart() { - startActivity(getIntent()); - finish(); - } - - private void write(String data) { - try { - mTermOut.write(data.getBytes()); - mTermOut.flush(); - } catch (IOException e) { - // Ignore exception - // We don't really care if the receiver isn't listening. - // We just make a best effort to answer the query. - } - } - - private void createSubprocess(int[] processId) { - String shell = mShell; - if (shell == null) { - shell = DEFAULT_SHELL; - } - ArrayList<String> args = parse(shell); - String arg0 = args.get(0); - String arg1 = null; - String arg2 = null; - if (args.size() >= 2) { - arg1 = args.get(1); - } - if (args.size() >= 3) { - arg2 = args.get(2); - } - mTermFd = Exec.createSubprocess(arg0, arg1, arg2, processId); - } - - private ArrayList<String> parse(String cmd) { - final int PLAIN = 0; - final int WHITESPACE = 1; - final int INQUOTE = 2; - int state = WHITESPACE; - ArrayList<String> result = new ArrayList<String>(); - int cmdLen = cmd.length(); - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < cmdLen; i++) { - char c = cmd.charAt(i); - if (state == PLAIN) { - if (Character.isWhitespace(c)) { - result.add(builder.toString()); - builder.delete(0,builder.length()); - state = WHITESPACE; - } else if (c == '"') { - state = INQUOTE; - } else { - builder.append(c); - } - } else if (state == WHITESPACE) { - if (Character.isWhitespace(c)) { - // do nothing - } else if (c == '"') { - state = INQUOTE; - } else { - state = PLAIN; - builder.append(c); - } - } else if (state == INQUOTE) { - if (c == '\\') { - if (i + 1 < cmdLen) { - i += 1; - builder.append(cmd.charAt(i)); - } - } else if (c == '"') { - state = PLAIN; - } else { - builder.append(c); - } - } - } - if (builder.length() > 0) { - result.add(builder.toString()); - } - return result; - } - - private void readPrefs() { - mFontSize = readIntPref(FONTSIZE_KEY, mFontSize, 20); - mColorId = readIntPref(COLOR_KEY, mColorId, COLOR_SCHEMES.length - 1); - mControlKeyId = readIntPref(CONTROLKEY_KEY, mControlKeyId, - CONTROL_KEY_SCHEMES.length - 1); - { - String newShell = readStringPref(SHELL_KEY, mShell); - if ((newShell == null) || ! newShell.equals(mShell)) { - if (mShell != null) { - Log.i(Term.LOG_TAG, "New shell set. Restarting."); - restart(); - } - mShell = newShell; - } - } - { - String newInitialCommand = readStringPref(INITIALCOMMAND_KEY, - mInitialCommand); - if ((newInitialCommand == null) - || ! newInitialCommand.equals(mInitialCommand)) { - if (mInitialCommand != null) { - Log.i(Term.LOG_TAG, "New initial command set. Restarting."); - restart(); - } - mInitialCommand = newInitialCommand; - } - } - } - - private void updatePrefs() { - mEmulatorView.setTextSize(mFontSize); - setColors(); - mControlKeyCode = CONTROL_KEY_SCHEMES[mControlKeyId]; - } - - private int readIntPref(String key, int defaultValue, int maxValue) { - int val; - try { - val = Integer.parseInt( - mPrefs.getString(key, Integer.toString(defaultValue))); - } catch (NumberFormatException e) { - val = defaultValue; - } - val = Math.max(0, Math.min(val, maxValue)); - return val; - } - - private String readStringPref(String key, String defaultValue) { - return mPrefs.getString(key, defaultValue); - } - - @Override - public void onPause() { - SharedPreferences.Editor e = mPrefs.edit(); - e.clear(); - e.putString(FONTSIZE_KEY, Integer.toString(mFontSize)); - e.putString(COLOR_KEY, Integer.toString(mColorId)); - e.putString(CONTROLKEY_KEY, Integer.toString(mControlKeyId)); - e.putString(SHELL_KEY, mShell); - e.putString(INITIALCOMMAND_KEY, mInitialCommand); - e.commit(); - - super.onPause(); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - - mEmulatorView.updateSize(); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (handleControlKey(keyCode, true)) { - return true; - } else if (isSystemKey(keyCode, event)) { - // Don't intercept the system keys - return super.onKeyDown(keyCode, event); - } else if (handleDPad(keyCode, true)) { - return true; - } - - // Translate the keyCode into an ASCII character. - int letter = mKeyListener.keyDown(keyCode, event); - - if (letter >= 0) { - try { - mTermOut.write(letter); - } catch (IOException e) { - // Ignore I/O exceptions - } - } - return true; - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - if (handleControlKey(keyCode, false)) { - return true; - } else if (isSystemKey(keyCode, event)) { - // Don't intercept the system keys - return super.onKeyUp(keyCode, event); - } else if (handleDPad(keyCode, false)) { - return true; - } - - mKeyListener.keyUp(keyCode); - return true; - } - - private boolean handleControlKey(int keyCode, boolean down) { - if (keyCode == mControlKeyCode) { - mKeyListener.handleControlKey(down); - return true; - } - return false; - } - - /** - * Handle dpad left-right-up-down events. Don't handle - * dpad-center, that's our control key. - * @param keyCode - * @param down - */ - private boolean handleDPad(int keyCode, boolean down) { - if (keyCode < KeyEvent.KEYCODE_DPAD_UP || - keyCode > KeyEvent.KEYCODE_DPAD_CENTER) { - return false; - } - - if (down) { - try { - if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { - mTermOut.write('\r'); - } else { - char code; - switch (keyCode) { - case KeyEvent.KEYCODE_DPAD_UP: - code = 'A'; - break; - case KeyEvent.KEYCODE_DPAD_DOWN: - code = 'B'; - break; - case KeyEvent.KEYCODE_DPAD_LEFT: - code = 'D'; - break; - default: - case KeyEvent.KEYCODE_DPAD_RIGHT: - code = 'C'; - break; - } - mTermOut.write(27); // ESC - if (mEmulatorView.getKeypadApplicationMode()) { - mTermOut.write('O'); - } else { - mTermOut.write('['); - } - mTermOut.write(code); - } - } catch (IOException e) { - // Ignore - } - } - return true; - } - - private boolean isSystemKey(int keyCode, KeyEvent event) { - return event.isSystem(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.main, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int id = item.getItemId(); - if (id == R.id.menu_preferences) { - doPreferences(); - } else if (id == R.id.menu_reset) { - doResetTerminal(); - } else if (id == R.id.menu_send_email) { - doEmailTranscript(); - } else if (id == R.id.menu_special_keys) { - doDocumentKeys(); - } - return super.onOptionsItemSelected(item); - } - - private void doPreferences() { - startActivity(new Intent(this, TermPreferences.class)); - } - - private void setColors() { - int[] scheme = COLOR_SCHEMES[mColorId]; - mEmulatorView.setColors(scheme[0], scheme[1]); - } - - private void doResetTerminal() { - restart(); - } - - private void doEmailTranscript() { - // Don't really want to supply an address, but - // currently it's required, otherwise we get an - // exception. - String addr = "user@example.com"; - Intent intent = - new Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:" - + addr)); - - intent.putExtra("body", mEmulatorView.getTranscriptText()); - startActivity(intent); - } - - private void doDocumentKeys() { - String controlKey = CONTROL_KEY_NAME[mControlKeyId]; - new AlertDialog.Builder(this). - setTitle("Press " + controlKey + " and Key"). - setMessage(controlKey + " Space ==> Control-@ (NUL)\n" - + controlKey + " A..Z ==> Control-A..Z\n" - + controlKey + " 1 ==> Control-[ (ESC)\n" - + controlKey + " 5 ==> Control-_\n" - + controlKey + " . ==> Control-\\\n" - + controlKey + " 0 ==> Control-]\n" - + controlKey + " 6 ==> Control-^"). - show(); - } - - private void print(String msg) { - char[] chars = msg.toCharArray(); - int len = chars.length; - byte[] bytes = new byte[len]; - for (int i = 0; i < len; i++) { - bytes[i] = (byte) chars[i]; - } - mEmulatorView.append(bytes, 0, len); - } -} - - -/** - * An abstract screen interface. A terminal screen stores lines of text. (The - * reason to abstract it is to allow different implementations, and to hide - * implementation details from clients.) - */ -interface Screen { - - /** - * Set line wrap flag for a given row. Affects how lines are logically - * wrapped when changing screen size or converting to a transcript. - */ - void setLineWrap(int row); - - /** - * Store byte b into the screen at location (x, y) - * - * @param x X coordinate (also known as column) - * @param y Y coordinate (also known as row) - * @param b ASCII character to store - * @param foreColor the foreground color - * @param backColor the background color - */ - void set(int x, int y, byte b, int foreColor, int backColor); - - /** - * Scroll the screen down one line. To scroll the whole screen of a 24 line - * screen, the arguments would be (0, 24). - * - * @param topMargin First line that is scrolled. - * @param bottomMargin One line after the last line that is scrolled. - */ - void scroll(int topMargin, int bottomMargin, int foreColor, int backColor); - - /** - * Block copy characters from one position in the screen to another. The two - * positions can overlap. All characters of the source and destination must - * be within the bounds of the screen, or else an InvalidParemeterException - * will be thrown. - * - * @param sx source X coordinate - * @param sy source Y coordinate - * @param w width - * @param h height - * @param dx destination X coordinate - * @param dy destination Y coordinate - */ - void blockCopy(int sx, int sy, int w, int h, int dx, int dy); - - /** - * Block set characters. All characters must be within the bounds of the - * screen, or else and InvalidParemeterException will be thrown. Typically - * this is called with a "val" argument of 32 to clear a block of - * characters. - * - * @param sx source X - * @param sy source Y - * @param w width - * @param h height - * @param val value to set. - * @param foreColor the foreground color - * @param backColor the background color - */ - void blockSet(int sx, int sy, int w, int h, int val, int foreColor, int - backColor); - - /** - * Get the contents of the transcript buffer as a text string. - * - * @return the contents of the transcript buffer. - */ - String getTranscriptText(); - - /** - * Resize the screen - * @param columns - * @param rows - */ - void resize(int columns, int rows, int foreColor, int backColor); -} - - -/** - * A TranscriptScreen is a screen that remembers data that's been scrolled. The - * old data is stored in a ring buffer to minimize the amount of copying that - * needs to be done. The transcript does its own drawing, to avoid having to - * expose its internal data structures. - */ -class TranscriptScreen implements Screen { - - /** - * The width of the transcript, in characters. Fixed at initialization. - */ - private int mColumns; - - /** - * The total number of rows in the transcript and the screen. Fixed at - * initialization. - */ - private int mTotalRows; - - /** - * The number of rows in the active portion of the transcript. Doesn't - * include the screen. - */ - private int mActiveTranscriptRows; - - /** - * Which row is currently the topmost line of the transcript. Used to - * implement a circular buffer. - */ - private int mHead; - - /** - * The number of active rows, includes both the transcript and the screen. - */ - private int mActiveRows; - - /** - * The number of rows in the screen. - */ - private int mScreenRows; - - /** - * The data for both the screen and the transcript. The first mScreenRows * - * mLineWidth characters are the screen, the rest are the transcript. - * The low byte encodes the ASCII character, the high byte encodes the - * foreground and background colors, plus underline and bold. - */ - private char[] mData; - - /** - * The data's stored as color-encoded chars, but the drawing routines require chars, so we - * need a temporary buffer to hold a row's worth of characters. - */ - private char[] mRowBuffer; - - /** - * Flags that keep track of whether the current line logically wraps to the - * next line. This is used when resizing the screen and when copying to the - * clipboard or an email attachment - */ - - private boolean[] mLineWrap; - - /** - * Create a transcript screen. - * - * @param columns the width of the screen in characters. - * @param totalRows the height of the entire text area, in rows of text. - * @param screenRows the height of just the screen, not including the - * transcript that holds lines that have scrolled off the top of the - * screen. - */ - public TranscriptScreen(int columns, int totalRows, int screenRows, - int foreColor, int backColor) { - init(columns, totalRows, screenRows, foreColor, backColor); - } - - private void init(int columns, int totalRows, int screenRows, int foreColor, int backColor) { - mColumns = columns; - mTotalRows = totalRows; - mActiveTranscriptRows = 0; - mHead = 0; - mActiveRows = screenRows; - mScreenRows = screenRows; - int totalSize = columns * totalRows; - mData = new char[totalSize]; - blockSet(0, 0, mColumns, mScreenRows, ' ', foreColor, backColor); - mRowBuffer = new char[columns]; - mLineWrap = new boolean[totalRows]; - consistencyCheck(); - } - - /** - * Convert a row value from the public external coordinate system to our - * internal private coordinate system. External coordinate system: - * -mActiveTranscriptRows to mScreenRows-1, with the screen being - * 0..mScreenRows-1 Internal coordinate system: 0..mScreenRows-1 rows of - * mData are the visible rows. mScreenRows..mActiveRows - 1 are the - * transcript, stored as a circular buffer. - * - * @param row a row in the external coordinate system. - * @return The row corresponding to the input argument in the private - * coordinate system. - */ - private int externalToInternalRow(int row) { - if (row < -mActiveTranscriptRows || row >= mScreenRows) { - throw new IllegalArgumentException(); - } - if (row >= 0) { - return row; // This is a visible row. - } - return mScreenRows - + ((mHead + mActiveTranscriptRows + row) % mActiveTranscriptRows); - } - - private int getOffset(int externalLine) { - return externalToInternalRow(externalLine) * mColumns; - } - - private int getOffset(int x, int y) { - return getOffset(y) + x; - } - - public void setLineWrap(int row) { - mLineWrap[externalToInternalRow(row)] = true; - } - - /** - * Store byte b into the screen at location (x, y) - * - * @param x X coordinate (also known as column) - * @param y Y coordinate (also known as row) - * @param b ASCII character to store - * @param foreColor the foreground color - * @param backColor the background color - */ - public void set(int x, int y, byte b, int foreColor, int backColor) { - mData[getOffset(x, y)] = encode(b, foreColor, backColor); - } - - private char encode(int b, int foreColor, int backColor) { - return (char) ((foreColor << 12) | (backColor << 8) | b); - } - - /** - * Scroll the screen down one line. To scroll the whole screen of a 24 line - * screen, the arguments would be (0, 24). - * - * @param topMargin First line that is scrolled. - * @param bottomMargin One line after the last line that is scrolled. - */ - public void scroll(int topMargin, int bottomMargin, int foreColor, - int backColor) { - if (topMargin > bottomMargin - 2 || topMargin > mScreenRows - 2 - || bottomMargin > mScreenRows) { - throw new IllegalArgumentException(); - } - - // Adjust the transcript so that the last line of the transcript - // is ready to receive the newly scrolled data - consistencyCheck(); - int expansionRows = Math.min(1, mTotalRows - mActiveRows); - int rollRows = 1 - expansionRows; - mActiveRows += expansionRows; - mActiveTranscriptRows += expansionRows; - if (mActiveTranscriptRows > 0) { - mHead = (mHead + rollRows) % mActiveTranscriptRows; - } - consistencyCheck(); - - // Block move the scroll line to the transcript - int topOffset = getOffset(topMargin); - int destOffset = getOffset(-1); - System.arraycopy(mData, topOffset, mData, destOffset, mColumns); - - int topLine = externalToInternalRow(topMargin); - int destLine = externalToInternalRow(-1); - System.arraycopy(mLineWrap, topLine, mLineWrap, destLine, 1); - - // Block move the scrolled data up - int numScrollChars = (bottomMargin - topMargin - 1) * mColumns; - System.arraycopy(mData, topOffset + mColumns, mData, topOffset, - numScrollChars); - int numScrollLines = (bottomMargin - topMargin - 1); - System.arraycopy(mLineWrap, topLine + 1, mLineWrap, topLine, - numScrollLines); - - // Erase the bottom line of the scroll region - blockSet(0, bottomMargin - 1, mColumns, 1, ' ', foreColor, backColor); - mLineWrap[externalToInternalRow(bottomMargin-1)] = false; - } - - private void consistencyCheck() { - checkPositive(mColumns); - checkPositive(mTotalRows); - checkRange(0, mActiveTranscriptRows, mTotalRows); - if (mActiveTranscriptRows == 0) { - checkEqual(mHead, 0); - } else { - checkRange(0, mHead, mActiveTranscriptRows-1); - } - checkEqual(mScreenRows + mActiveTranscriptRows, mActiveRows); - checkRange(0, mScreenRows, mTotalRows); - - checkEqual(mTotalRows, mLineWrap.length); - checkEqual(mTotalRows*mColumns, mData.length); - checkEqual(mColumns, mRowBuffer.length); - } - - private void checkPositive(int n) { - if (n < 0) { - throw new IllegalArgumentException("checkPositive " + n); - } - } - - private void checkRange(int a, int b, int c) { - if (a > b || b > c) { - throw new IllegalArgumentException("checkRange " + a + " <= " + b + " <= " + c); - } - } - - private void checkEqual(int a, int b) { - if (a != b) { - throw new IllegalArgumentException("checkEqual " + a + " == " + b); - } - } - - /** - * Block copy characters from one position in the screen to another. The two - * positions can overlap. All characters of the source and destination must - * be within the bounds of the screen, or else an InvalidParemeterException - * will be thrown. - * - * @param sx source X coordinate - * @param sy source Y coordinate - * @param w width - * @param h height - * @param dx destination X coordinate - * @param dy destination Y coordinate - */ - public void blockCopy(int sx, int sy, int w, int h, int dx, int dy) { - if (sx < 0 || sx + w > mColumns || sy < 0 || sy + h > mScreenRows - || dx < 0 || dx + w > mColumns || dy < 0 - || dy + h > mScreenRows) { - throw new IllegalArgumentException(); - } - if (sy <= dy) { - // Move in increasing order - for (int y = 0; y < h; y++) { - int srcOffset = getOffset(sx, sy + y); - int dstOffset = getOffset(dx, dy + y); - System.arraycopy(mData, srcOffset, mData, dstOffset, w); - } - } else { - // Move in decreasing order - for (int y = 0; y < h; y++) { - int y2 = h - (y + 1); - int srcOffset = getOffset(sx, sy + y2); - int dstOffset = getOffset(dx, dy + y2); - System.arraycopy(mData, srcOffset, mData, dstOffset, w); - } - } - } - - /** - * Block set characters. All characters must be within the bounds of the - * screen, or else and InvalidParemeterException will be thrown. Typically - * this is called with a "val" argument of 32 to clear a block of - * characters. - * - * @param sx source X - * @param sy source Y - * @param w width - * @param h height - * @param val value to set. - */ - public void blockSet(int sx, int sy, int w, int h, int val, - int foreColor, int backColor) { - if (sx < 0 || sx + w > mColumns || sy < 0 || sy + h > mScreenRows) { - throw new IllegalArgumentException(); - } - char[] data = mData; - char encodedVal = encode(val, foreColor, backColor); - for (int y = 0; y < h; y++) { - int offset = getOffset(sx, sy + y); - for (int x = 0; x < w; x++) { - data[offset + x] = encodedVal; - } - } - } - - /** - * Draw a row of text. Out-of-bounds rows are blank, not errors. - * - * @param row The row of text to draw. - * @param canvas The canvas to draw to. - * @param x The x coordinate origin of the drawing - * @param y The y coordinate origin of the drawing - * @param renderer The renderer to use to draw the text - * @param cx the cursor X coordinate, -1 means don't draw it - */ - public final void drawText(int row, Canvas canvas, float x, float y, - TextRenderer renderer, int cx) { - - // Out-of-bounds rows are blank. - if (row < -mActiveTranscriptRows || row >= mScreenRows) { - return; - } - - // Copy the data from the byte array to a char array so they can - // be drawn. - - int offset = getOffset(row); - char[] rowBuffer = mRowBuffer; - char[] data = mData; - int columns = mColumns; - int lastColors = 0; - int lastRunStart = -1; - final int CURSOR_MASK = 0x10000; - for (int i = 0; i < columns; i++) { - char c = data[offset + i]; - int colors = (char) (c & 0xff00); - if (cx == i) { - // Set cursor background color: - colors |= CURSOR_MASK; - } - rowBuffer[i] = (char) (c & 0x00ff); - if (colors != lastColors) { - if (lastRunStart >= 0) { - renderer.drawTextRun(canvas, x, y, lastRunStart, rowBuffer, - lastRunStart, i - lastRunStart, - (lastColors & CURSOR_MASK) != 0, - 0xf & (lastColors >> 12), 0xf & (lastColors >> 8)); - } - lastColors = colors; - lastRunStart = i; - } - } - if (lastRunStart >= 0) { - renderer.drawTextRun(canvas, x, y, lastRunStart, rowBuffer, - lastRunStart, columns - lastRunStart, - (lastColors & CURSOR_MASK) != 0, - 0xf & (lastColors >> 12), 0xf & (lastColors >> 8)); - } - } - - /** - * Get the count of active rows. - * - * @return the count of active rows. - */ - public int getActiveRows() { - return mActiveRows; - } - - /** - * Get the count of active transcript rows. - * - * @return the count of active transcript rows. - */ - public int getActiveTranscriptRows() { - return mActiveTranscriptRows; - } - - public String getTranscriptText() { - return internalGetTranscriptText(true); - } - - private String internalGetTranscriptText(boolean stripColors) { - StringBuilder builder = new StringBuilder(); - char[] rowBuffer = mRowBuffer; - char[] data = mData; - int columns = mColumns; - for (int row = -mActiveTranscriptRows; row < mScreenRows; row++) { - int offset = getOffset(row); - int lastPrintingChar = -1; - for (int column = 0; column < columns; column++) { - char c = data[offset + column]; - if (stripColors) { - c = (char) (c & 0xff); - } - if ((c & 0xff) != ' ') { - lastPrintingChar = column; - } - rowBuffer[column] = c; - } - if (mLineWrap[externalToInternalRow(row)]) { - builder.append(rowBuffer, 0, columns); - } else { - builder.append(rowBuffer, 0, lastPrintingChar + 1); - builder.append('\n'); - } - } - return builder.toString(); - } - - public void resize(int columns, int rows, int foreColor, int backColor) { - init(columns, mTotalRows, rows, foreColor, backColor); - } -} - -/** - * Renders text into a screen. Contains all the terminal-specific knowlege and - * state. Emulates a subset of the X Window System xterm terminal, which in turn - * is an emulator for a subset of the Digital Equipment Corporation vt100 - * terminal. Missing functionality: text attributes (bold, underline, reverse - * video, color) alternate screen cursor key and keypad escape sequences. - */ -class TerminalEmulator { - - /** - * The cursor row. Numbered 0..mRows-1. - */ - private int mCursorRow; - - /** - * The cursor column. Numbered 0..mColumns-1. - */ - private int mCursorCol; - - /** - * The number of character rows in the terminal screen. - */ - private int mRows; - - /** - * The number of character columns in the terminal screen. - */ - private int mColumns; - - /** - * Used to send data to the remote process. Needed to implement the various - * "report" escape sequences. - */ - private FileOutputStream mTermOut; - - /** - * Stores the characters that appear on the screen of the emulated terminal. - */ - private Screen mScreen; - - /** - * Keeps track of the current argument of the current escape sequence. - * Ranges from 0 to MAX_ESCAPE_PARAMETERS-1. (Typically just 0 or 1.) - */ - private int mArgIndex; - - /** - * The number of parameter arguments. This name comes from the ANSI standard - * for terminal escape codes. - */ - private static final int MAX_ESCAPE_PARAMETERS = 16; - - /** - * Holds the arguments of the current escape sequence. - */ - private int[] mArgs = new int[MAX_ESCAPE_PARAMETERS]; - - // Escape processing states: - - /** - * Escape processing state: Not currently in an escape sequence. - */ - private static final int ESC_NONE = 0; - - /** - * Escape processing state: Have seen an ESC character - */ - private static final int ESC = 1; - - /** - * Escape processing state: Have seen ESC POUND - */ - private static final int ESC_POUND = 2; - - /** - * Escape processing state: Have seen ESC and a character-set-select char - */ - private static final int ESC_SELECT_LEFT_PAREN = 3; - - /** - * Escape processing state: Have seen ESC and a character-set-select char - */ - private static final int ESC_SELECT_RIGHT_PAREN = 4; - - /** - * Escape processing state: ESC [ - */ - private static final int ESC_LEFT_SQUARE_BRACKET = 5; - - /** - * Escape processing state: ESC [ ? - */ - private static final int ESC_LEFT_SQUARE_BRACKET_QUESTION_MARK = 6; - - /** - * True if the current escape sequence should continue, false if the current - * escape sequence should be terminated. Used when parsing a single - * character. - */ - private boolean mContinueSequence; - - /** - * The current state of the escape sequence state machine. - */ - private int mEscapeState; - - /** - * Saved state of the cursor row, Used to implement the save/restore cursor - * position escape sequences. - */ - private int mSavedCursorRow; - - /** - * Saved state of the cursor column, Used to implement the save/restore - * cursor position escape sequences. - */ - private int mSavedCursorCol; - - // DecSet booleans - - /** - * This mask indicates 132-column mode is set. (As opposed to 80-column - * mode.) - */ - private static final int K_132_COLUMN_MODE_MASK = 1 << 3; - - /** - * This mask indicates that origin mode is set. (Cursor addressing is - * relative to the absolute screen size, rather than the currently set top - * and bottom margins.) - */ - private static final int K_ORIGIN_MODE_MASK = 1 << 6; - - /** - * This mask indicates that wraparound mode is set. (As opposed to - * stop-at-right-column mode.) - */ - private static final int K_WRAPAROUND_MODE_MASK = 1 << 7; - - /** - * Holds multiple DECSET flags. The data is stored this way, rather than in - * separate booleans, to make it easier to implement the save-and-restore - * semantics. The various k*ModeMask masks can be used to extract and modify - * the individual flags current states. - */ - private int mDecFlags; - - /** - * Saves away a snapshot of the DECSET flags. Used to implement save and - * restore escape sequences. - */ - private int mSavedDecFlags; - - // Modes set with Set Mode / Reset Mode - - /** - * True if insert mode (as opposed to replace mode) is active. In insert - * mode new characters are inserted, pushing existing text to the right. - */ - private boolean mInsertMode; - - /** - * Automatic newline mode. Configures whether pressing return on the - * keyboard automatically generates a return as well. Not currently - * implemented. - */ - private boolean mAutomaticNewlineMode; - - /** - * An array of tab stops. mTabStop[i] is true if there is a tab stop set for - * column i. - */ - private boolean[] mTabStop; - - // The margins allow portions of the screen to be locked. - - /** - * The top margin of the screen, for scrolling purposes. Ranges from 0 to - * mRows-2. - */ - private int mTopMargin; - - /** - * The bottom margin of the screen, for scrolling purposes. Ranges from - * mTopMargin + 2 to mRows. (Defines the first row after the scrolling - * region. - */ - private int mBottomMargin; - - /** - * True if the next character to be emitted will be automatically wrapped to - * the next line. Used to disambiguate the case where the cursor is - * positioned on column mColumns-1. - */ - private boolean mAboutToAutoWrap; - - /** - * Used for debugging, counts how many chars have been processed. - */ - private int mProcessedCharCount; - - /** - * Foreground color, 0..7, mask with 8 for bold - */ - private int mForeColor; - - /** - * Background color, 0..7, mask with 8 for underline - */ - private int mBackColor; - - private boolean mInverseColors; - - private boolean mbKeypadApplicationMode; - - private boolean mAlternateCharSet; - - /** - * Construct a terminal emulator that uses the supplied screen - * - * @param screen the screen to render characters into. - * @param columns the number of columns to emulate - * @param rows the number of rows to emulate - * @param termOut the output file descriptor that talks to the pseudo-tty. - */ - public TerminalEmulator(Screen screen, int columns, int rows, - FileOutputStream termOut) { - mScreen = screen; - mRows = rows; - mColumns = columns; - mTabStop = new boolean[mColumns]; - mTermOut = termOut; - reset(); - } - - public void updateSize(int columns, int rows) { - if (mRows == rows && mColumns == columns) { - return; - } - String transcriptText = mScreen.getTranscriptText(); - - mScreen.resize(columns, rows, mForeColor, mBackColor); - - if (mRows != rows) { - mRows = rows; - mTopMargin = 0; - mBottomMargin = mRows; - } - if (mColumns != columns) { - int oldColumns = mColumns; - mColumns = columns; - boolean[] oldTabStop = mTabStop; - mTabStop = new boolean[mColumns]; - int toTransfer = Math.min(oldColumns, columns); - System.arraycopy(oldTabStop, 0, mTabStop, 0, toTransfer); - while (mCursorCol >= columns) { - mCursorCol -= columns; - mCursorRow = Math.min(mBottomMargin-1, mCursorRow + 1); - } - } - mCursorRow = 0; - mCursorCol = 0; - mAboutToAutoWrap = false; - - int end = transcriptText.length()-1; - while ((end >= 0) && transcriptText.charAt(end) == '\n') { - end--; - } - for(int i = 0; i <= end; i++) { - byte c = (byte) transcriptText.charAt(i); - if (c == '\n') { - setCursorCol(0); - doLinefeed(); - } else { - emit(c); - } - } - } - - /** - * Get the cursor's current row. - * - * @return the cursor's current row. - */ - public final int getCursorRow() { - return mCursorRow; - } - - /** - * Get the cursor's current column. - * - * @return the cursor's current column. - */ - public final int getCursorCol() { - return mCursorCol; - } - - public final boolean getKeypadApplicationMode() { - return mbKeypadApplicationMode; - } - - private void setDefaultTabStops() { - for (int i = 0; i < mColumns; i++) { - mTabStop[i] = (i & 7) == 0 && i != 0; - } - } - - /** - * Accept bytes (typically from the pseudo-teletype) and process them. - * - * @param buffer a byte array containing the bytes to be processed - * @param base the first index of the array to process - * @param length the number of bytes in the array to process - */ - public void append(byte[] buffer, int base, int length) { - for (int i = 0; i < length; i++) { - byte b = buffer[base + i]; - try { - if (Term.LOG_CHARACTERS_FLAG) { - char printableB = (char) b; - if (b < 32 || b > 126) { - printableB = ' '; - } - Log.w(Term.LOG_TAG, "'" + Character.toString(printableB) - + "' (" + Integer.toString((int) b) + ")"); - } - process(b); - mProcessedCharCount++; - } catch (Exception e) { - Log.e(Term.LOG_TAG, "Exception while processing character " - + Integer.toString(mProcessedCharCount) + " code " - + Integer.toString(b), e); - } - } - } - - private void process(byte b) { - switch (b) { - case 0: // NUL - // Do nothing - break; - - case 7: // BEL - // Do nothing - break; - - case 8: // BS - setCursorCol(Math.max(0, mCursorCol - 1)); - break; - - case 9: // HT - // Move to next tab stop, but not past edge of screen - setCursorCol(nextTabStop(mCursorCol)); - break; - - case 13: - setCursorCol(0); - break; - - case 10: // CR - case 11: // VT - case 12: // LF - doLinefeed(); - break; - - case 14: // SO: - setAltCharSet(true); - break; - - case 15: // SI: - setAltCharSet(false); - break; - - - case 24: // CAN - case 26: // SUB - if (mEscapeState != ESC_NONE) { - mEscapeState = ESC_NONE; - emit((byte) 127); - } - break; - - case 27: // ESC - // Always starts an escape sequence - startEscapeSequence(ESC); - break; - - case (byte) 0x9b: // CSI - startEscapeSequence(ESC_LEFT_SQUARE_BRACKET); - break; - - default: - mContinueSequence = false; - switch (mEscapeState) { - case ESC_NONE: - if (b >= 32) { - emit(b); - } - break; - - case ESC: - doEsc(b); - break; - - case ESC_POUND: - doEscPound(b); - break; - - case ESC_SELECT_LEFT_PAREN: - doEscSelectLeftParen(b); - break; - - case ESC_SELECT_RIGHT_PAREN: - doEscSelectRightParen(b); - break; - - case ESC_LEFT_SQUARE_BRACKET: - doEscLeftSquareBracket(b); - break; - - case ESC_LEFT_SQUARE_BRACKET_QUESTION_MARK: - doEscLSBQuest(b); - break; - - default: - unknownSequence(b); - break; - } - if (!mContinueSequence) { - mEscapeState = ESC_NONE; - } - break; - } - } - - private void setAltCharSet(boolean alternateCharSet) { - mAlternateCharSet = alternateCharSet; - } - - private int nextTabStop(int cursorCol) { - for (int i = cursorCol; i < mColumns; i++) { - if (mTabStop[i]) { - return i; - } - } - return mColumns - 1; - } - - private void doEscLSBQuest(byte b) { - int mask = getDecFlagsMask(getArg0(0)); - switch (b) { - case 'h': // Esc [ ? Pn h - DECSET - mDecFlags |= mask; - break; - - case 'l': // Esc [ ? Pn l - DECRST - mDecFlags &= ~mask; - break; - - case 'r': // Esc [ ? Pn r - restore - mDecFlags = (mDecFlags & ~mask) | (mSavedDecFlags & mask); - break; - - case 's': // Esc [ ? Pn s - save - mSavedDecFlags = (mSavedDecFlags & ~mask) | (mDecFlags & mask); - break; - - default: - parseArg(b); - break; - } - - // 132 column mode - if ((mask & K_132_COLUMN_MODE_MASK) != 0) { - // We don't actually set 132 cols, but we do want the - // side effect of clearing the screen and homing the cursor. - blockClear(0, 0, mColumns, mRows); - setCursorRowCol(0, 0); - } - - // origin mode - if ((mask & K_ORIGIN_MODE_MASK) != 0) { - // Home the cursor. - setCursorPosition(0, 0); - } - } - - private int getDecFlagsMask(int argument) { - if (argument >= 1 && argument <= 9) { - return (1 << argument); - } - - return 0; - } - - private void startEscapeSequence(int escapeState) { - mEscapeState = escapeState; - mArgIndex = 0; - for (int j = 0; j < MAX_ESCAPE_PARAMETERS; j++) { - mArgs[j] = -1; - } - } - - private void doLinefeed() { - int newCursorRow = mCursorRow + 1; - if (newCursorRow >= mBottomMargin) { - scroll(); - newCursorRow = mBottomMargin - 1; - } - setCursorRow(newCursorRow); - } - - private void continueSequence() { - mContinueSequence = true; - } - - private void continueSequence(int state) { - mEscapeState = state; - mContinueSequence = true; - } - - private void doEscSelectLeftParen(byte b) { - doSelectCharSet(true, b); - } - - private void doEscSelectRightParen(byte b) { - doSelectCharSet(false, b); - } - - private void doSelectCharSet(boolean isG0CharSet, byte b) { - switch (b) { - case 'A': // United Kingdom character set - break; - case 'B': // ASCII set - break; - case '0': // Special Graphics - break; - case '1': // Alternate character set - break; - case '2': - break; - default: - unknownSequence(b); - } - } - - private void doEscPound(byte b) { - switch (b) { - case '8': // Esc # 8 - DECALN alignment test - mScreen.blockSet(0, 0, mColumns, mRows, 'E', - getForeColor(), getBackColor()); - break; - - default: - unknownSequence(b); - break; - } - } - - private void doEsc(byte b) { - switch (b) { - case '#': - continueSequence(ESC_POUND); - break; - - case '(': - continueSequence(ESC_SELECT_LEFT_PAREN); - break; - - case ')': - continueSequence(ESC_SELECT_RIGHT_PAREN); - break; - - case '7': // DECSC save cursor - mSavedCursorRow = mCursorRow; - mSavedCursorCol = mCursorCol; - break; - - case '8': // DECRC restore cursor - setCursorRowCol(mSavedCursorRow, mSavedCursorCol); - break; - - case 'D': // INDEX - doLinefeed(); - break; - - case 'E': // NEL - setCursorCol(0); - doLinefeed(); - break; - - case 'F': // Cursor to lower-left corner of screen - setCursorRowCol(0, mBottomMargin - 1); - break; - - case 'H': // Tab set - mTabStop[mCursorCol] = true; - break; - - case 'M': // Reverse index - if (mCursorRow == 0) { - mScreen.blockCopy(0, mTopMargin + 1, mColumns, mBottomMargin - - (mTopMargin + 1), 0, mTopMargin); - blockClear(0, mBottomMargin - 1, mColumns); - } else { - mCursorRow--; - } - - break; - - case 'N': // SS2 - unimplementedSequence(b); - break; - - case '0': // SS3 - unimplementedSequence(b); - break; - - case 'P': // Device control string - unimplementedSequence(b); - break; - - case 'Z': // return terminal ID - sendDeviceAttributes(); - break; - - case '[': - continueSequence(ESC_LEFT_SQUARE_BRACKET); - break; - - case '=': // DECKPAM - mbKeypadApplicationMode = true; - break; - - case '>' : // DECKPNM - mbKeypadApplicationMode = false; - break; - - default: - unknownSequence(b); - break; - } - } - - private void doEscLeftSquareBracket(byte b) { - switch (b) { - case '@': // ESC [ Pn @ - ICH Insert Characters - { - int charsAfterCursor = mColumns - mCursorCol; - int charsToInsert = Math.min(getArg0(1), charsAfterCursor); - int charsToMove = charsAfterCursor - charsToInsert; - mScreen.blockCopy(mCursorCol, mCursorRow, charsToMove, 1, - mCursorCol + charsToInsert, mCursorRow); - blockClear(mCursorCol, mCursorRow, charsToInsert); - } - break; - - case 'A': // ESC [ Pn A - Cursor Up - setCursorRow(Math.max(mTopMargin, mCursorRow - getArg0(1))); - break; - - case 'B': // ESC [ Pn B - Cursor Down - setCursorRow(Math.min(mBottomMargin - 1, mCursorRow + getArg0(1))); - break; - - case 'C': // ESC [ Pn C - Cursor Right - setCursorCol(Math.min(mColumns - 1, mCursorCol + getArg0(1))); - break; - - case 'D': // ESC [ Pn D - Cursor Left - setCursorCol(Math.max(0, mCursorCol - getArg0(1))); - break; - - case 'G': // ESC [ Pn G - Cursor Horizontal Absolute - setCursorCol(Math.min(Math.max(1, getArg0(1)), mColumns) - 1); - break; - - case 'H': // ESC [ Pn ; H - Cursor Position - setHorizontalVerticalPosition(); - break; - - case 'J': // ESC [ Pn J - Erase in Display - switch (getArg0(0)) { - case 0: // Clear below - blockClear(mCursorCol, mCursorRow, mColumns - mCursorCol); - blockClear(0, mCursorRow + 1, mColumns, - mBottomMargin - (mCursorRow + 1)); - break; - - case 1: // Erase from the start of the screen to the cursor. - blockClear(0, mTopMargin, mColumns, mCursorRow - mTopMargin); - blockClear(0, mCursorRow, mCursorCol + 1); - break; - - case 2: // Clear all - blockClear(0, mTopMargin, mColumns, mBottomMargin - mTopMargin); - break; - - default: - unknownSequence(b); - break; - } - break; - - case 'K': // ESC [ Pn K - Erase in Line - switch (getArg0(0)) { - case 0: // Clear to right - blockClear(mCursorCol, mCursorRow, mColumns - mCursorCol); - break; - - case 1: // Erase start of line to cursor (including cursor) - blockClear(0, mCursorRow, mCursorCol + 1); - break; - - case 2: // Clear whole line - blockClear(0, mCursorRow, mColumns); - break; - - default: - unknownSequence(b); - break; - } - break; - - case 'L': // Insert Lines - { - int linesAfterCursor = mBottomMargin - mCursorRow; - int linesToInsert = Math.min(getArg0(1), linesAfterCursor); - int linesToMove = linesAfterCursor - linesToInsert; - mScreen.blockCopy(0, mCursorRow, mColumns, linesToMove, 0, - mCursorRow + linesToInsert); - blockClear(0, mCursorRow, mColumns, linesToInsert); - } - break; - - case 'M': // Delete Lines - { - int linesAfterCursor = mBottomMargin - mCursorRow; - int linesToDelete = Math.min(getArg0(1), linesAfterCursor); - int linesToMove = linesAfterCursor - linesToDelete; - mScreen.blockCopy(0, mCursorRow + linesToDelete, mColumns, - linesToMove, 0, mCursorRow); - blockClear(0, mCursorRow + linesToMove, mColumns, linesToDelete); - } - break; - - case 'P': // Delete Characters - { - int charsAfterCursor = mColumns - mCursorCol; - int charsToDelete = Math.min(getArg0(1), charsAfterCursor); - int charsToMove = charsAfterCursor - charsToDelete; - mScreen.blockCopy(mCursorCol + charsToDelete, mCursorRow, - charsToMove, 1, mCursorCol, mCursorRow); - blockClear(mCursorCol + charsToMove, mCursorRow, charsToDelete); - } - break; - - case 'T': // Mouse tracking - unimplementedSequence(b); - break; - - case '?': // Esc [ ? -- start of a private mode set - continueSequence(ESC_LEFT_SQUARE_BRACKET_QUESTION_MARK); - break; - - case 'c': // Send device attributes - sendDeviceAttributes(); - break; - - case 'd': // ESC [ Pn d - Vert Position Absolute - setCursorRow(Math.min(Math.max(1, getArg0(1)), mRows) - 1); - break; - - case 'f': // Horizontal and Vertical Position - setHorizontalVerticalPosition(); - break; - - case 'g': // Clear tab stop - switch (getArg0(0)) { - case 0: - mTabStop[mCursorCol] = false; - break; - - case 3: - for (int i = 0; i < mColumns; i++) { - mTabStop[i] = false; - } - break; - - default: - // Specified to have no effect. - break; - } - break; - - case 'h': // Set Mode - doSetMode(true); - break; - - case 'l': // Reset Mode - doSetMode(false); - break; - - case 'm': // Esc [ Pn m - character attributes. - selectGraphicRendition(); - break; - - case 'r': // Esc [ Pn ; Pn r - set top and bottom margins - { - // The top margin defaults to 1, the bottom margin - // (unusually for arguments) defaults to mRows. - // - // The escape sequence numbers top 1..23, but we - // number top 0..22. - // The escape sequence numbers bottom 2..24, and - // so do we (because we use a zero based numbering - // scheme, but we store the first line below the - // bottom-most scrolling line. - // As a result, we adjust the top line by -1, but - // we leave the bottom line alone. - // - // Also require that top + 2 <= bottom - - int top = Math.max(0, Math.min(getArg0(1) - 1, mRows - 2)); - int bottom = Math.max(top + 2, Math.min(getArg1(mRows), mRows)); - mTopMargin = top; - mBottomMargin = bottom; - - // The cursor is placed in the home position - setCursorRowCol(mTopMargin, 0); - } - break; - - default: - parseArg(b); - break; - } - } - - private void selectGraphicRendition() { - for (int i = 0; i <= mArgIndex; i++) { - int code = mArgs[i]; - if ( code < 0) { - if (mArgIndex > 0) { - continue; - } else { - code = 0; - } - } - if (code == 0) { // reset - mInverseColors = false; - mForeColor = 7; - mBackColor = 0; - } else if (code == 1) { // bold - mForeColor |= 0x8; - } else if (code == 4) { // underscore - mBackColor |= 0x8; - } else if (code == 7) { // inverse - mInverseColors = true; - } else if (code >= 30 && code <= 37) { // foreground color - mForeColor = (mForeColor & 0x8) | (code - 30); - } else if (code >= 40 && code <= 47) { // background color - mBackColor = (mBackColor & 0x8) | (code - 40); - } else { - if (Term.LOG_UNKNOWN_ESCAPE_SEQUENCES) { - Log.w(Term.LOG_TAG, String.format("SGR unknown code %d", code)); - } - } - } - } - - private void blockClear(int sx, int sy, int w) { - blockClear(sx, sy, w, 1); - } - - private void blockClear(int sx, int sy, int w, int h) { - mScreen.blockSet(sx, sy, w, h, ' ', getForeColor(), getBackColor()); - } - - private int getForeColor() { - return mInverseColors ? - ((mBackColor & 0x7) | (mForeColor & 0x8)) : mForeColor; - } - - private int getBackColor() { - return mInverseColors ? - ((mForeColor & 0x7) | (mBackColor & 0x8)) : mBackColor; - } - - private void doSetMode(boolean newValue) { - int modeBit = getArg0(0); - switch (modeBit) { - case 4: - mInsertMode = newValue; - break; - - case 20: - mAutomaticNewlineMode = newValue; - break; - - default: - unknownParameter(modeBit); - break; - } - } - - private void setHorizontalVerticalPosition() { - - // Parameters are Row ; Column - - setCursorPosition(getArg1(1) - 1, getArg0(1) - 1); - } - - private void setCursorPosition(int x, int y) { - int effectiveTopMargin = 0; - int effectiveBottomMargin = mRows; - if ((mDecFlags & K_ORIGIN_MODE_MASK) != 0) { - effectiveTopMargin = mTopMargin; - effectiveBottomMargin = mBottomMargin; - } - int newRow = - Math.max(effectiveTopMargin, Math.min(effectiveTopMargin + y, - effectiveBottomMargin - 1)); - int newCol = Math.max(0, Math.min(x, mColumns - 1)); - setCursorRowCol(newRow, newCol); - } - - private void sendDeviceAttributes() { - // This identifies us as a DEC vt100 with advanced - // video options. This is what the xterm terminal - // emulator sends. - byte[] attributes = - { - /* VT100 */ - (byte) 27, (byte) '[', (byte) '?', (byte) '1', - (byte) ';', (byte) '2', (byte) 'c' - - /* VT220 - (byte) 27, (byte) '[', (byte) '?', (byte) '6', - (byte) '0', (byte) ';', - (byte) '1', (byte) ';', - (byte) '2', (byte) ';', - (byte) '6', (byte) ';', - (byte) '8', (byte) ';', - (byte) '9', (byte) ';', - (byte) '1', (byte) '5', (byte) ';', - (byte) 'c' - */ - }; - - write(attributes); - } - - /** - * Send data to the shell process - * @param data - */ - private void write(byte[] data) { - try { - mTermOut.write(data); - mTermOut.flush(); - } catch (IOException e) { - // Ignore exception - // We don't really care if the receiver isn't listening. - // We just make a best effort to answer the query. - } - } - - private void scroll() { - mScreen.scroll(mTopMargin, mBottomMargin, - getForeColor(), getBackColor()); - } - - /** - * Process the next ASCII character of a parameter. - * - * @param b The next ASCII character of the paramater sequence. - */ - private void parseArg(byte b) { - if (b >= '0' && b <= '9') { - if (mArgIndex < mArgs.length) { - int oldValue = mArgs[mArgIndex]; - int thisDigit = b - '0'; - int value; - if (oldValue >= 0) { - value = oldValue * 10 + thisDigit; - } else { - value = thisDigit; - } - mArgs[mArgIndex] = value; - } - continueSequence(); - } else if (b == ';') { - if (mArgIndex < mArgs.length) { - mArgIndex++; - } - continueSequence(); - } else { - unknownSequence(b); - } - } - - private int getArg0(int defaultValue) { - return getArg(0, defaultValue); - } - - private int getArg1(int defaultValue) { - return getArg(1, defaultValue); - } - - private int getArg(int index, int defaultValue) { - int result = mArgs[index]; - if (result < 0) { - result = defaultValue; - } - return result; - } - - private void unimplementedSequence(byte b) { - if (Term.LOG_UNKNOWN_ESCAPE_SEQUENCES) { - logError("unimplemented", b); - } - finishSequence(); - } - - private void unknownSequence(byte b) { - if (Term.LOG_UNKNOWN_ESCAPE_SEQUENCES) { - logError("unknown", b); - } - finishSequence(); - } - - private void unknownParameter(int parameter) { - if (Term.LOG_UNKNOWN_ESCAPE_SEQUENCES) { - StringBuilder buf = new StringBuilder(); - buf.append("Unknown parameter"); - buf.append(parameter); - logError(buf.toString()); - } - } - - private void logError(String errorType, byte b) { - if (Term.LOG_UNKNOWN_ESCAPE_SEQUENCES) { - StringBuilder buf = new StringBuilder(); - buf.append(errorType); - buf.append(" sequence "); - buf.append(" EscapeState: "); - buf.append(mEscapeState); - buf.append(" char: '"); - buf.append((char) b); - buf.append("' ("); - buf.append((int) b); - buf.append(")"); - boolean firstArg = true; - for (int i = 0; i <= mArgIndex; i++) { - int value = mArgs[i]; - if (value >= 0) { - if (firstArg) { - firstArg = false; - buf.append("args = "); - } - buf.append(String.format("%d; ", value)); - } - } - logError(buf.toString()); - } - } - - private void logError(String error) { - if (Term.LOG_UNKNOWN_ESCAPE_SEQUENCES) { - Log.e(Term.LOG_TAG, error); - } - finishSequence(); - } - - private void finishSequence() { - mEscapeState = ESC_NONE; - } - - private boolean autoWrapEnabled() { - // Always enable auto wrap, because it's useful on a small screen - return true; - // return (mDecFlags & K_WRAPAROUND_MODE_MASK) != 0; - } - - /** - * Send an ASCII character to the screen. - * - * @param b the ASCII character to display. - */ - private void emit(byte b) { - boolean autoWrap = autoWrapEnabled(); - - if (autoWrap) { - if (mCursorCol == mColumns - 1 && mAboutToAutoWrap) { - mScreen.setLineWrap(mCursorRow); - mCursorCol = 0; - if (mCursorRow + 1 < mBottomMargin) { - mCursorRow++; - } else { - scroll(); - } - } - } - - if (mInsertMode) { // Move character to right one space - int destCol = mCursorCol + 1; - if (destCol < mColumns) { - mScreen.blockCopy(mCursorCol, mCursorRow, mColumns - destCol, - 1, destCol, mCursorRow); - } - } - - mScreen.set(mCursorCol, mCursorRow, b, getForeColor(), getBackColor()); - - if (autoWrap) { - mAboutToAutoWrap = (mCursorCol == mColumns - 1); - } - - mCursorCol = Math.min(mCursorCol + 1, mColumns - 1); - } - - private void setCursorRow(int row) { - mCursorRow = row; - mAboutToAutoWrap = false; - } - - private void setCursorCol(int col) { - mCursorCol = col; - mAboutToAutoWrap = false; - } - - private void setCursorRowCol(int row, int col) { - mCursorRow = Math.min(row, mRows-1); - mCursorCol = Math.min(col, mColumns-1); - mAboutToAutoWrap = false; - } - - /** - * Reset the terminal emulator to its initial state. - */ - public void reset() { - mCursorRow = 0; - mCursorCol = 0; - mArgIndex = 0; - mContinueSequence = false; - mEscapeState = ESC_NONE; - mSavedCursorRow = 0; - mSavedCursorCol = 0; - mDecFlags = 0; - mSavedDecFlags = 0; - mInsertMode = false; - mAutomaticNewlineMode = false; - mTopMargin = 0; - mBottomMargin = mRows; - mAboutToAutoWrap = false; - mForeColor = 7; - mBackColor = 0; - mInverseColors = false; - mbKeypadApplicationMode = false; - mAlternateCharSet = false; - // mProcessedCharCount is preserved unchanged. - setDefaultTabStops(); - blockClear(0, 0, mColumns, mRows); - } - - public String getTranscriptText() { - return mScreen.getTranscriptText(); - } -} - -/** - * Text renderer interface - */ - -interface TextRenderer { - int getCharacterWidth(); - int getCharacterHeight(); - void drawTextRun(Canvas canvas, float x, float y, - int lineOffset, char[] text, - int index, int count, boolean cursor, int foreColor, int backColor); -} - -abstract class BaseTextRenderer implements TextRenderer { - protected int[] mForePaint = { - 0xff000000, // Black - 0xffff0000, // Red - 0xff00ff00, // green - 0xffffff00, // yellow - 0xff0000ff, // blue - 0xffff00ff, // magenta - 0xff00ffff, // cyan - 0xffffffff // white -- is overridden by constructor - }; - protected int[] mBackPaint = { - 0xff000000, // Black -- is overridden by constructor - 0xffcc0000, // Red - 0xff00cc00, // green - 0xffcccc00, // yellow - 0xff0000cc, // blue - 0xffff00cc, // magenta - 0xff00cccc, // cyan - 0xffffffff // white - }; - protected final static int mCursorPaint = 0xff808080; - - public BaseTextRenderer(int forePaintColor, int backPaintColor) { - mForePaint[7] = forePaintColor; - mBackPaint[0] = backPaintColor; - - } -} - -class Bitmap4x8FontRenderer extends BaseTextRenderer { - private final static int kCharacterWidth = 4; - private final static int kCharacterHeight = 8; - private Bitmap mFont; - private int mCurrentForeColor; - private int mCurrentBackColor; - private float[] mColorMatrix; - private Paint mPaint; - private static final float BYTE_SCALE = 1.0f / 255.0f; - - public Bitmap4x8FontRenderer(Resources resources, - int forePaintColor, int backPaintColor) { - super(forePaintColor, backPaintColor); - mFont = BitmapFactory.decodeResource(resources, - R.drawable.atari_small); - mPaint = new Paint(); - mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); - } - - public int getCharacterWidth() { - return kCharacterWidth; - } - - public int getCharacterHeight() { - return kCharacterHeight; - } - - public void drawTextRun(Canvas canvas, float x, float y, - int lineOffset, char[] text, int index, int count, - boolean cursor, int foreColor, int backColor) { - setColorMatrix(mForePaint[foreColor & 7], - cursor ? mCursorPaint : mBackPaint[backColor & 7]); - int destX = (int) x + kCharacterWidth * lineOffset; - int destY = (int) y; - Rect srcRect = new Rect(); - Rect destRect = new Rect(); - destRect.top = (destY - kCharacterHeight); - destRect.bottom = destY; - for(int i = 0; i < count; i++) { - char c = text[i + index]; - if ((cursor || (c != 32)) && (c < 128)) { - int cellX = c & 31; - int cellY = (c >> 5) & 3; - int srcX = cellX * kCharacterWidth; - int srcY = cellY * kCharacterHeight; - srcRect.set(srcX, srcY, - srcX + kCharacterWidth, srcY + kCharacterHeight); - destRect.left = destX; - destRect.right = destX + kCharacterWidth; - canvas.drawBitmap(mFont, srcRect, destRect, mPaint); - } - destX += kCharacterWidth; - } - } - - private void setColorMatrix(int foreColor, int backColor) { - if ((foreColor != mCurrentForeColor) - || (backColor != mCurrentBackColor) - || (mColorMatrix == null)) { - mCurrentForeColor = foreColor; - mCurrentBackColor = backColor; - if (mColorMatrix == null) { - mColorMatrix = new float[20]; - mColorMatrix[18] = 1.0f; // Just copy Alpha - } - for (int component = 0; component < 3; component++) { - int rightShift = (2 - component) << 3; - int fore = 0xff & (foreColor >> rightShift); - int back = 0xff & (backColor >> rightShift); - int delta = back - fore; - mColorMatrix[component * 6] = delta * BYTE_SCALE; - mColorMatrix[component * 5 + 4] = fore; - } - mPaint.setColorFilter(new ColorMatrixColorFilter(mColorMatrix)); - } - } -} - -class PaintRenderer extends BaseTextRenderer { - public PaintRenderer(int fontSize, int forePaintColor, int backPaintColor) { - super(forePaintColor, backPaintColor); - mTextPaint = new Paint(); - mTextPaint.setTypeface(Typeface.MONOSPACE); - mTextPaint.setAntiAlias(true); - mTextPaint.setTextSize(fontSize); - - mCharHeight = (int) Math.ceil(mTextPaint.getFontSpacing()); - mCharAscent = (int) Math.ceil(mTextPaint.ascent()); - mCharDescent = mCharHeight + mCharAscent; - mCharWidth = (int) mTextPaint.measureText(EXAMPLE_CHAR, 0, 1); - } - - public void drawTextRun(Canvas canvas, float x, float y, int lineOffset, - char[] text, int index, int count, - boolean cursor, int foreColor, int backColor) { - if (cursor) { - mTextPaint.setColor(mCursorPaint); - } else { - mTextPaint.setColor(mBackPaint[backColor & 0x7]); - } - float left = x + lineOffset * mCharWidth; - canvas.drawRect(left, y + mCharAscent, - left + count * mCharWidth, y + mCharDescent, - mTextPaint); - boolean bold = ( foreColor & 0x8 ) != 0; - boolean underline = (backColor & 0x8) != 0; - if (bold) { - mTextPaint.setFakeBoldText(true); - } - if (underline) { - mTextPaint.setUnderlineText(true); - } - mTextPaint.setColor(mForePaint[foreColor & 0x7]); - canvas.drawText(text, index, count, left, y, mTextPaint); - if (bold) { - mTextPaint.setFakeBoldText(false); - } - if (underline) { - mTextPaint.setUnderlineText(false); - } - } - - public int getCharacterHeight() { - return mCharHeight; - } - - public int getCharacterWidth() { - return mCharWidth; - } - - - private Paint mTextPaint; - private int mCharWidth; - private int mCharHeight; - private int mCharAscent; - private int mCharDescent; - private static final char[] EXAMPLE_CHAR = {'X'}; - } - -/** - * A multi-thread-safe produce-consumer byte array. - * Only allows one producer and one consumer. - */ - -class ByteQueue { - public ByteQueue(int size) { - mBuffer = new byte[size]; - } - - public int getBytesAvailable() { - synchronized(this) { - return mStoredBytes; - } - } - - public int read(byte[] buffer, int offset, int length) - throws InterruptedException { - if (length + offset > buffer.length) { - throw - new IllegalArgumentException("length + offset > buffer.length"); - } - if (length < 0) { - throw - new IllegalArgumentException("length < 0"); - - } - if (length == 0) { - return 0; - } - synchronized(this) { - while (mStoredBytes == 0) { - wait(); - } - int totalRead = 0; - int bufferLength = mBuffer.length; - boolean wasFull = bufferLength == mStoredBytes; - while (length > 0 && mStoredBytes > 0) { - int oneRun = Math.min(bufferLength - mHead, mStoredBytes); - int bytesToCopy = Math.min(length, oneRun); - System.arraycopy(mBuffer, mHead, buffer, offset, bytesToCopy); - mHead += bytesToCopy; - if (mHead >= bufferLength) { - mHead = 0; - } - mStoredBytes -= bytesToCopy; - length -= bytesToCopy; - offset += bytesToCopy; - totalRead += bytesToCopy; - } - if (wasFull) { - notify(); - } - return totalRead; - } - } - - public void write(byte[] buffer, int offset, int length) - throws InterruptedException { - if (length + offset > buffer.length) { - throw - new IllegalArgumentException("length + offset > buffer.length"); - } - if (length < 0) { - throw - new IllegalArgumentException("length < 0"); - - } - if (length == 0) { - return; - } - synchronized(this) { - int bufferLength = mBuffer.length; - boolean wasEmpty = mStoredBytes == 0; - while (length > 0) { - while(bufferLength == mStoredBytes) { - wait(); - } - int tail = mHead + mStoredBytes; - int oneRun; - if (tail >= bufferLength) { - tail = tail - bufferLength; - oneRun = mHead - tail; - } else { - oneRun = bufferLength - tail; - } - int bytesToCopy = Math.min(oneRun, length); - System.arraycopy(buffer, offset, mBuffer, tail, bytesToCopy); - offset += bytesToCopy; - mStoredBytes += bytesToCopy; - length -= bytesToCopy; - } - if (wasEmpty) { - notify(); - } - } - } - - private byte[] mBuffer; - private int mHead; - private int mStoredBytes; -} -/** - * A view on a transcript and a terminal emulator. Displays the text of the - * transcript and the current cursor position of the terminal emulator. - */ -class EmulatorView extends View implements GestureDetector.OnGestureListener { - - /** - * We defer some initialization until we have been layed out in the view - * hierarchy. The boolean tracks when we know what our size is. - */ - private boolean mKnownSize; - - /** - * Our transcript. Contains the screen and the transcript. - */ - private TranscriptScreen mTranscriptScreen; - - /** - * Number of rows in the transcript. - */ - private static final int TRANSCRIPT_ROWS = 10000; - - /** - * Total width of each character, in pixels - */ - private int mCharacterWidth; - - /** - * Total height of each character, in pixels - */ - private int mCharacterHeight; - - /** - * Used to render text - */ - private TextRenderer mTextRenderer; - - /** - * Text size. Zero means 4 x 8 font. - */ - private int mTextSize; - - /** - * Foreground color. - */ - private int mForeground; - - /** - * Background color. - */ - private int mBackground; - - /** - * Used to paint the cursor - */ - private Paint mCursorPaint; - - private Paint mBackgroundPaint; - - /** - * Our terminal emulator. We use this to get the current cursor position. - */ - private TerminalEmulator mEmulator; - - /** - * The number of rows of text to display. - */ - private int mRows; - - /** - * The number of columns of text to display. - */ - private int mColumns; - - /** - * The number of columns that are visible on the display. - */ - - private int mVisibleColumns; - - /** - * The top row of text to display. Ranges from -activeTranscriptRows to 0 - */ - private int mTopRow; - - private int mLeftColumn; - - private FileDescriptor mTermFd; - /** - * Used to receive data from the remote process. - */ - private FileInputStream mTermIn; - - private FileOutputStream mTermOut; - - private ByteQueue mByteQueue; - - /** - * Used to temporarily hold data received from the remote process. Allocated - * once and used permanently to minimize heap thrashing. - */ - private byte[] mReceiveBuffer; - - /** - * Our private message id, which we use to receive new input from the - * remote process. - */ - private static final int UPDATE = 1; - - /** - * Thread that polls for input from the remote process - */ - - private Thread mPollingThread; - - private GestureDetector mGestureDetector; - private float mScrollRemainder; - - /** - * Our message handler class. Implements a periodic callback. - */ - private final Handler mHandler = new Handler() { - /** - * Handle the callback message. Call our enclosing class's update - * method. - * - * @param msg The callback message. - */ - public void handleMessage(Message msg) { - if (msg.what == UPDATE) { - update(); - } - } - }; - - public EmulatorView(Context context) { - super(context); - commonConstructor(); - } - - public void setColors(int foreground, int background) { - mForeground = foreground; - mBackground = background; - updateText(); - } - - public String getTranscriptText() { - return mEmulator.getTranscriptText(); - } - - public void resetTerminal() { - mEmulator.reset(); - invalidate(); - } - - @Override - public boolean onCheckIsTextEditor() { - return true; - } - - @Override - public InputConnection onCreateInputConnection(EditorInfo outAttrs) { - return new BaseInputConnection(this, false) { - - public boolean beginBatchEdit() { - return true; - } - - public boolean clearMetaKeyStates(int states) { - return true; - } - - public boolean commitCompletion(CompletionInfo text) { - return true; - } - - public boolean commitText(CharSequence text, int newCursorPosition) { - sendText(text); - return true; - } - - public boolean deleteSurroundingText(int leftLength, int rightLength) { - return true; - } - - public boolean endBatchEdit() { - return true; - } - - public boolean finishComposingText() { - return true; - } - - public int getCursorCapsMode(int reqModes) { - return 0; - } - - public ExtractedText getExtractedText(ExtractedTextRequest request, - int flags) { - return null; - } - - public CharSequence getTextAfterCursor(int n, int flags) { - return null; - } - - public CharSequence getTextBeforeCursor(int n, int flags) { - return null; - } - - public boolean hideStatusIcon() { - return true; - } - - public boolean performContextMenuAction(int id) { - return true; - } - - public boolean performPrivateCommand(String action, Bundle data) { - return true; - } - - public boolean sendKeyEvent(KeyEvent event) { - switch(event.getKeyCode()) { - case KeyEvent.KEYCODE_ENTER: - sendChar('\r'); - break; - case KeyEvent.KEYCODE_DEL: - sendChar(127); - break; - } - return true; - } - - public boolean setComposingText(CharSequence text, int newCursorPosition) { - return true; - } - - public boolean setSelection(int start, int end) { - return true; - } - - public boolean showStatusIcon(String packageName, int resId) { - return true; - } - - private void sendChar(int c) { - try { - mTermOut.write(c); - } catch (IOException ex) { - - } - } - private void sendText(CharSequence text) { - int n = text.length(); - try { - for(int i = 0; i < n; i++) { - char c = text.charAt(i); - mTermOut.write(c); - } - } catch (IOException e) { - } - } - }; - } - - public boolean getKeypadApplicationMode() { - return mEmulator.getKeypadApplicationMode(); - } - - public EmulatorView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public EmulatorView(Context context, AttributeSet attrs, - int defStyle) { - super(context, attrs, defStyle); - TypedArray a = - context.obtainStyledAttributes(android.R.styleable.View); - initializeScrollbars(a); - a.recycle(); - commonConstructor(); - } - - private void commonConstructor() { - mTextRenderer = null; - mCursorPaint = new Paint(); - mCursorPaint.setARGB(255,128,128,128); - mBackgroundPaint = new Paint(); - mTopRow = 0; - mLeftColumn = 0; - mGestureDetector = new GestureDetector(this); - mGestureDetector.setIsLongpressEnabled(false); - setVerticalScrollBarEnabled(true); - } - - @Override - protected int computeVerticalScrollRange() { - return mTranscriptScreen.getActiveRows(); - } - - @Override - protected int computeVerticalScrollExtent() { - return mRows; - } - - @Override - protected int computeVerticalScrollOffset() { - return mTranscriptScreen.getActiveRows() + mTopRow - mRows; - } - - /** - * Call this to initialize the view. - * - * @param termFd the file descriptor - * @param termOut the output stream for the pseudo-teletype - */ - public void initialize(FileDescriptor termFd, FileOutputStream termOut) { - mTermOut = termOut; - mTermFd = termFd; - mTextSize = 10; - mForeground = Term.WHITE; - mBackground = Term.BLACK; - updateText(); - mTermIn = new FileInputStream(mTermFd); - mReceiveBuffer = new byte[4 * 1024]; - mByteQueue = new ByteQueue(4 * 1024); - } - - /** - * Accept a sequence of bytes (typically from the pseudo-tty) and process - * them. - * - * @param buffer a byte array containing bytes to be processed - * @param base the index of the first byte in the buffer to process - * @param length the number of bytes to process - */ - public void append(byte[] buffer, int base, int length) { - mEmulator.append(buffer, base, length); - ensureCursorVisible(); - invalidate(); - } - - /** - * Page the terminal view (scroll it up or down by delta screenfulls.) - * - * @param delta the number of screens to scroll. Positive means scroll down, - * negative means scroll up. - */ - public void page(int delta) { - mTopRow = - Math.min(0, Math.max(-(mTranscriptScreen - .getActiveTranscriptRows()), mTopRow + mRows * delta)); - invalidate(); - } - - /** - * Page the terminal view horizontally. - * - * @param deltaColumns the number of columns to scroll. Positive scrolls to - * the right. - */ - public void pageHorizontal(int deltaColumns) { - mLeftColumn = - Math.max(0, Math.min(mLeftColumn + deltaColumns, mColumns - - mVisibleColumns)); - invalidate(); - } - - /** - * Sets the text size, which in turn sets the number of rows and columns - * - * @param fontSize the new font size, in pixels. - */ - public void setTextSize(int fontSize) { - mTextSize = fontSize; - updateText(); - } - - // Begin GestureDetector.OnGestureListener methods - - public boolean onSingleTapUp(MotionEvent e) { - return true; - } - - public void onLongPress(MotionEvent e) { - } - - public boolean onScroll(MotionEvent e1, MotionEvent e2, - float distanceX, float distanceY) { - distanceY += mScrollRemainder; - int deltaRows = (int) (distanceY / mCharacterHeight); - mScrollRemainder = distanceY - deltaRows * mCharacterHeight; - mTopRow = - Math.min(0, Math.max(-(mTranscriptScreen - .getActiveTranscriptRows()), mTopRow + deltaRows)); - invalidate(); - - return true; - } - - public void onSingleTapConfirmed(MotionEvent e) { - } - - public boolean onJumpTapDown(MotionEvent e1, MotionEvent e2) { - // Scroll to bottom - mTopRow = 0; - invalidate(); - return true; - } - - public boolean onJumpTapUp(MotionEvent e1, MotionEvent e2) { - // Scroll to top - mTopRow = -mTranscriptScreen.getActiveTranscriptRows(); - invalidate(); - return true; - } - - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, - float velocityY) { - // TODO: add animation man's (non animated) fling - mScrollRemainder = 0.0f; - onScroll(e1, e2, 2 * velocityX, -2 * velocityY); - return true; - } - - public void onShowPress(MotionEvent e) { - } - - public boolean onDown(MotionEvent e) { - mScrollRemainder = 0.0f; - return true; - } - - // End GestureDetector.OnGestureListener methods - - @Override public boolean onTouchEvent(MotionEvent ev) { - return mGestureDetector.onTouchEvent(ev); - } - - private void updateText() { - if (mTextSize > 0) { - mTextRenderer = new PaintRenderer(mTextSize, mForeground, - mBackground); - } - else { - mTextRenderer = new Bitmap4x8FontRenderer(getResources(), - mForeground, mBackground); - } - mBackgroundPaint.setColor(mBackground); - mCharacterWidth = mTextRenderer.getCharacterWidth(); - mCharacterHeight = mTextRenderer.getCharacterHeight(); - - if (mKnownSize) { - updateSize(getWidth(), getHeight()); - } - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - updateSize(w, h); - if (!mKnownSize) { - mKnownSize = true; - - // Set up a thread to read input from the - // pseudo-teletype: - - mPollingThread = new Thread(new Runnable() { - - public void run() { - try { - while(true) { - int read = mTermIn.read(mBuffer); - mByteQueue.write(mBuffer, 0, read); - mHandler.sendMessage( - mHandler.obtainMessage(UPDATE)); - } - } catch (IOException e) { - } catch (InterruptedException e) { - } - } - private byte[] mBuffer = new byte[4096]; - }); - mPollingThread.setName("Input reader"); - mPollingThread.start(); - } - } - - private void updateSize(int w, int h) { - mColumns = w / mCharacterWidth; - mRows = h / mCharacterHeight; - - // Inform the attached pty of our new size: - Exec.setPtyWindowSize(mTermFd, mRows, mColumns, w, h); - - - if (mTranscriptScreen != null) { - mEmulator.updateSize(mColumns, mRows); - } else { - mTranscriptScreen = - new TranscriptScreen(mColumns, TRANSCRIPT_ROWS, mRows, 0, 7); - mEmulator = - new TerminalEmulator(mTranscriptScreen, mColumns, mRows, - mTermOut); - } - - // Reset our paging: - mTopRow = 0; - mLeftColumn = 0; - - invalidate(); - } - - void updateSize() { - if (mKnownSize) { - updateSize(getWidth(), getHeight()); - } - } - - /** - * Look for new input from the ptty, send it to the terminal emulator. - */ - private void update() { - int bytesAvailable = mByteQueue.getBytesAvailable(); - int bytesToRead = Math.min(bytesAvailable, mReceiveBuffer.length); - try { - int bytesRead = mByteQueue.read(mReceiveBuffer, 0, bytesToRead); - append(mReceiveBuffer, 0, bytesRead); - } catch (InterruptedException e) { - } - } - - @Override - protected void onDraw(Canvas canvas) { - int w = getWidth(); - int h = getHeight(); - canvas.drawRect(0, 0, w, h, mBackgroundPaint); - mVisibleColumns = w / mCharacterWidth; - float x = -mLeftColumn * mCharacterWidth; - float y = mCharacterHeight; - int endLine = mTopRow + mRows; - int cx = mEmulator.getCursorCol(); - int cy = mEmulator.getCursorRow(); - for (int i = mTopRow; i < endLine; i++) { - int cursorX = -1; - if (i == cy) { - cursorX = cx; - } - mTranscriptScreen.drawText(i, canvas, x, y, mTextRenderer, cursorX); - y += mCharacterHeight; - } - } - - private void ensureCursorVisible() { - mTopRow = 0; - if (mVisibleColumns > 0) { - int cx = mEmulator.getCursorCol(); - int visibleCursorX = mEmulator.getCursorCol() - mLeftColumn; - if (visibleCursorX < 0) { - mLeftColumn = cx; - } else if (visibleCursorX >= mVisibleColumns) { - mLeftColumn = (cx - mVisibleColumns) + 1; - } - } - } -} - - -/** - * An ASCII key listener. Supports control characters and escape. Keeps track of - * the current state of the alt, shift, and control keys. - */ -class TermKeyListener { - /** - * The state engine for a modifier key. Can be pressed, released, locked, - * and so on. - * - */ - private class ModifierKey { - - private int mState; - - private static final int UNPRESSED = 0; - - private static final int PRESSED = 1; - - private static final int RELEASED = 2; - - private static final int USED = 3; - - private static final int LOCKED = 4; - - /** - * Construct a modifier key. UNPRESSED by default. - * - */ - public ModifierKey() { - mState = UNPRESSED; - } - - public void onPress() { - switch (mState) { - case PRESSED: - // This is a repeat before use - break; - case RELEASED: - mState = LOCKED; - break; - case USED: - // This is a repeat after use - break; - case LOCKED: - mState = UNPRESSED; - break; - default: - mState = PRESSED; - break; - } - } - - public void onRelease() { - switch (mState) { - case USED: - mState = UNPRESSED; - break; - case PRESSED: - mState = RELEASED; - break; - default: - // Leave state alone - break; - } - } - - public void adjustAfterKeypress() { - switch (mState) { - case PRESSED: - mState = USED; - break; - case RELEASED: - mState = UNPRESSED; - break; - default: - // Leave state alone - break; - } - } - - public boolean isActive() { - return mState != UNPRESSED; - } - } - - private ModifierKey mAltKey = new ModifierKey(); - - private ModifierKey mCapKey = new ModifierKey(); - - private ModifierKey mControlKey = new ModifierKey(); - - /** - * Construct a term key listener. - * - */ - public TermKeyListener() { - } - - public void handleControlKey(boolean down) { - if (down) { - mControlKey.onPress(); - } else { - mControlKey.onRelease(); - } - } - - /** - * Handle a keyDown event. - * - * @param keyCode the keycode of the keyDown event - * @return the ASCII byte to transmit to the pseudo-teletype, or -1 if this - * event does not produce an ASCII byte. - */ - public int keyDown(int keyCode, KeyEvent event) { - int result = -1; - switch (keyCode) { - case KeyEvent.KEYCODE_ALT_RIGHT: - case KeyEvent.KEYCODE_ALT_LEFT: - mAltKey.onPress(); - break; - - case KeyEvent.KEYCODE_SHIFT_LEFT: - case KeyEvent.KEYCODE_SHIFT_RIGHT: - mCapKey.onPress(); - break; - - case KeyEvent.KEYCODE_ENTER: - // Convert newlines into returns. The vt100 sends a - // '\r' when the 'Return' key is pressed, but our - // KeyEvent translates this as a '\n'. - result = '\r'; - break; - - case KeyEvent.KEYCODE_DEL: - // Convert DEL into 127 (instead of 8) - result = 127; - break; - - default: { - result = event.getUnicodeChar( - (mCapKey.isActive() ? KeyEvent.META_SHIFT_ON : 0) | - (mAltKey.isActive() ? KeyEvent.META_ALT_ON : 0)); - break; - } - } - - if (mControlKey.isActive()) { - // Search is the control key. - if (result >= 'a' && result <= 'z') { - result = (char) (result - 'a' + '\001'); - } else if (result == ' ') { - result = 0; - } else if ((result == '[') || (result == '1')) { - result = 27; - } else if ((result == '\\') || (result == '.')) { - result = 28; - } else if ((result == ']') || (result == '0')) { - result = 29; - } else if ((result == '^') || (result == '6')) { - result = 30; // control-^ - } else if ((result == '_') || (result == '5')) { - result = 31; - } - } - - if (result > -1) { - mAltKey.adjustAfterKeypress(); - mCapKey.adjustAfterKeypress(); - mControlKey.adjustAfterKeypress(); - } - - return result; - } - - /** - * Handle a keyUp event. - * - * @param keyCode the keyCode of the keyUp event - */ - public void keyUp(int keyCode) { - switch (keyCode) { - case KeyEvent.KEYCODE_ALT_LEFT: - case KeyEvent.KEYCODE_ALT_RIGHT: - mAltKey.onRelease(); - break; - case KeyEvent.KEYCODE_SHIFT_LEFT: - case KeyEvent.KEYCODE_SHIFT_RIGHT: - mCapKey.onRelease(); - break; - default: - // Ignore other keyUps - break; - } - } -} diff --git a/apps/Term/src/com/android/term/TermPreferences.java b/apps/Term/src/com/android/term/TermPreferences.java deleted file mode 100644 index 3102963a4..000000000 --- a/apps/Term/src/com/android/term/TermPreferences.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.term; - -import android.os.Bundle; -import android.preference.PreferenceActivity; - -public class TermPreferences extends PreferenceActivity { - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // Load the preferences from an XML resource - addPreferencesFromResource(R.xml.preferences); - } - -} |
