summaryrefslogtreecommitdiffstats
path: root/src/com/android
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android')
-rw-r--r--src/com/android/terminal/Terminal.java68
-rw-r--r--src/com/android/terminal/TerminalActivity.java8
-rw-r--r--src/com/android/terminal/TerminalView.java167
3 files changed, 236 insertions, 7 deletions
diff --git a/src/com/android/terminal/Terminal.java b/src/com/android/terminal/Terminal.java
index 9f3016b..8067b9a 100644
--- a/src/com/android/terminal/Terminal.java
+++ b/src/com/android/terminal/Terminal.java
@@ -16,30 +16,88 @@
package com.android.terminal;
-public class Terminal {
- private TerminalCallbacks mCallbacks;
+import android.graphics.Color;
+/**
+ * Single terminal session backed by a pseudo terminal on the local device.
+ */
+public class Terminal {
static {
System.loadLibrary("jni_terminal");
}
+ public static class Cell {
+ char[] chars = new char[2];
+ int width = 1;
+
+ boolean bold;
+ int underline;
+ boolean blink;
+ boolean reverse;
+ boolean strike;
+ int font;
+
+ int fgColor = Color.RED;
+ int bgColor = Color.BLUE;
+ }
+
+ public interface TerminalClient {
+ public void damage(int startRow, int endRow, int startCol, int endCol);
+ public void bell();
+ }
+
private final int mNativePtr;
+ private TerminalClient mClient;
+
+ private final TerminalCallbacks mCallbacks = new TerminalCallbacks() {
+ @Override
+ public int damage(int startRow, int endRow, int startCol, int endCol) {
+ if (mClient != null) {
+ mClient.damage(startRow, endRow, startCol, endCol);
+ }
+ return 1;
+ }
+
+ @Override
+ public int bell() {
+ if (mClient != null) {
+ mClient.bell();
+ }
+ return 1;
+ }
+ };
public Terminal() {
- mCallbacks = new TerminalCallbacks() {
- };
mNativePtr = nativeInit(mCallbacks, 25, 80);
}
+ public void setClient(TerminalClient client) {
+ mClient = client;
+ }
+
public void resize(int rows, int cols) {
- nativeResize(mNativePtr, rows, cols);
+ if (nativeResize(mNativePtr, rows, cols) != 0) {
+ throw new IllegalStateException("resize failed");
+ }
}
public int getRows() {
return nativeGetRows(mNativePtr);
}
+ public int getCols() {
+ return nativeGetCols(mNativePtr);
+ }
+
+ public void getCell(int row, int col, Cell cell) {
+ if (nativeGetCell(mNativePtr, row, col, cell) != 0) {
+ throw new IllegalStateException("getCell failed");
+ }
+ }
+
private static native int nativeInit(TerminalCallbacks callbacks, int rows, int cols);
private static native int nativeResize(int ptr, int rows, int cols);
+ private static native int nativeGetCell(int ptr, int row, int col, Cell cell);
private static native int nativeGetRows(int ptr);
+ private static native int nativeGetCols(int ptr);
}
diff --git a/src/com/android/terminal/TerminalActivity.java b/src/com/android/terminal/TerminalActivity.java
index 0bb73ff..601fd98 100644
--- a/src/com/android/terminal/TerminalActivity.java
+++ b/src/com/android/terminal/TerminalActivity.java
@@ -27,7 +27,11 @@ public class TerminalActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Terminal t = new Terminal();
- Log.d(TAG, "Rows: " + t.getRows());
+ final Terminal term = new Terminal();
+ final TerminalView view = new TerminalView(this, term);
+
+ setContentView(view);
+
+ Log.d(TAG, "Rows: " + term.getRows());
}
}
diff --git a/src/com/android/terminal/TerminalView.java b/src/com/android/terminal/TerminalView.java
new file mode 100644
index 0000000..adbb0a7
--- /dev/null
+++ b/src/com/android/terminal/TerminalView.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2013 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.terminal;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Paint.FontMetrics;
+import android.graphics.Rect;
+import android.view.View;
+
+import android.os.SystemClock;
+import android.util.Log;
+
+import com.android.terminal.Terminal.TerminalClient;
+
+/**
+ * Rendered contents of a {@link Terminal} session.
+ */
+public class TerminalView extends View {
+ private static final String TAG = "Terminal";
+
+ private final Context mContext;
+ private final Terminal mTerm;
+
+ private final Paint mBgPaint = new Paint();
+ private final Paint mTextPaint = new Paint();
+
+ private int mCharTop;
+ private int mCharWidth;
+ private int mCharHeight;
+
+ private TerminalClient mClient = new TerminalClient() {
+ @Override
+ public void damage(int startRow, int endRow, int startCol, int endCol) {
+ final int top = startRow * mCharHeight;
+ final int bottom = (endRow + 1) * mCharHeight;
+ final int left = startCol * mCharWidth;
+ final int right = (endCol + 1) * mCharWidth;
+
+ // Invalidate region on screen
+ postInvalidate(left, top, right, bottom);
+ }
+
+ @Override
+ public void bell() {
+ Log.i(TAG, "DING!");
+ }
+ };
+
+ public TerminalView(Context context, Terminal term) {
+ super(context);
+ mContext = context;
+ mTerm = term;
+
+ setBackgroundColor(Color.BLACK);
+ setTextSize(20);
+
+ // TODO: remove this test code that triggers invalidates
+ setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ v.invalidate();
+ }
+ });
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ mTerm.setClient(mClient);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ mTerm.setClient(null);
+ }
+
+ public void setTextSize(float textSize) {
+ mTextPaint.setTextSize(textSize);
+
+ // Read metrics to get exact pixel dimensions
+ final FontMetrics fm = mTextPaint.getFontMetrics();
+ mCharTop = (int) Math.ceil(fm.top);
+
+ final float[] widths = new float[1];
+ mTextPaint.getTextWidths("X", widths);
+ mCharWidth = (int) Math.ceil(widths[0]);
+ mCharHeight = (int) Math.ceil(fm.descent - fm.top);
+
+ updateTerminalSize();
+ }
+
+ /**
+ * Determine terminal dimensions based on current dimensions and font size,
+ * and request that {@link Terminal} change to that size.
+ */
+ public void updateTerminalSize() {
+ if (getWidth() > 0 && getHeight() > 0) {
+ final int rows = getHeight() / mCharHeight;
+ final int cols = getWidth() / mCharWidth;
+ mTerm.resize(rows, cols);
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ if (changed) {
+ updateTerminalSize();
+ }
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ final long start = SystemClock.elapsedRealtime();
+
+ // Only draw dirty region of console
+ final Rect dirty = canvas.getClipBounds();
+
+ final int startRow = dirty.top / mCharHeight;
+ final int endRow = dirty.bottom / mCharHeight;
+ final int startCol = dirty.left / mCharWidth;
+ final int endCol = dirty.right / mCharWidth;
+
+ final Terminal.Cell cell = new Terminal.Cell();
+
+ for (int row = startRow; row <= endRow; row++) {
+ for (int col = startCol; col <= endCol;) {
+ mTerm.getCell(row, col, cell);
+
+ mBgPaint.setColor(cell.bgColor);
+ mTextPaint.setColor(cell.fgColor);
+
+ final int y = row * mCharHeight;
+ final int x = col * mCharWidth;
+ final int xEnd = x + (cell.width * mCharWidth);
+
+ canvas.drawRect(x, y, xEnd, y + mCharHeight, mBgPaint);
+ canvas.drawText(cell.chars, 0, cell.chars.length, x, y - mCharTop, mTextPaint);
+
+ col += cell.width;
+ }
+ }
+
+ final long delta = SystemClock.elapsedRealtime() - start;
+ Log.d(TAG, "onDraw() took " + delta + "ms");
+ }
+}