summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--jni/com_android_terminal_Terminal.cpp72
-rw-r--r--src/com/android/terminal/Terminal.java17
-rw-r--r--src/com/android/terminal/TerminalView.java42
3 files changed, 92 insertions, 39 deletions
diff --git a/jni/com_android_terminal_Terminal.cpp b/jni/com_android_terminal_Terminal.cpp
index 31589aa..4a3fecb 100644
--- a/jni/com_android_terminal_Terminal.cpp
+++ b/jni/com_android_terminal_Terminal.cpp
@@ -60,15 +60,15 @@ static jmethodID bellMethod;
static jmethodID resizeMethod;
/*
- * Cell class
+ * CellRun class
*/
-static jclass cellClass;
-static jfieldID cellCharsField;
-
+static jclass cellRunClass;
+static jfieldID cellRunDataField;
+static jfieldID cellRunDataSizeField;
+static jfieldID cellRunColSizeField;
/*
* Terminal session
*/
-
class Terminal {
public:
Terminal(jobject callbacks, int rows, int cols);
@@ -344,6 +344,7 @@ int Terminal::readLoop() {
int Terminal::resize(short unsigned int rows, short unsigned int cols) {
ALOGD("resize(%d, %d)", rows, cols);
+ // TODO: wait for resize event to propegate back from shell?
mRows = rows;
mCols = cols;
struct winsize size = { rows, cols, 0, 0 };
@@ -395,29 +396,52 @@ static jint com_android_terminal_Terminal_nativeResize(JNIEnv* env,
return term->resize(rows, cols);
}
-static jint com_android_terminal_Terminal_nativeGetCell(JNIEnv* env,
- jclass clazz, jint ptr, jint row, jint col, jobject cell) {
+static jint com_android_terminal_Terminal_nativeGetCellRun(JNIEnv* env,
+ jclass clazz, jint ptr, jint row, jint col, jobject run) {
Terminal* term = reinterpret_cast<Terminal*>(ptr);
+ jcharArray dataArray = (jcharArray) env->GetObjectField(run, cellRunDataField);
+ jchar* data = env->GetCharArrayElements(dataArray, 0);
+ int dataLen = env->GetArrayLength(dataArray);
+
+ VTermScreenCell cell;
+ memset(&cell, 0, sizeof(VTermScreenCell));
+
VTermPos pos = {
.row = row,
.col = col,
};
- VTermScreenCell termCell;
- memset(&termCell, 0, sizeof(VTermScreenCell));
- int res = term->getCell(pos, &termCell);
+ int dataSize = 0;
+ int colSize = 0;
+ while (pos.col < term->getCols()) {
+ int res = term->getCell(pos, &cell);
- //ALOGD("getCell(%d, %d, %s)", row, col, termCell.chars);
+ // TODO: terminate this loop once text style changes
- // TODO: support full UTF-32 characters
- // for testing, 0x00020000 should become 0xD840 0xDC00
+ // TODO: remove this once terminal is resized
+ if (cell.width == 0) {
+ cell.width = 1;
+ }
+
+ // TODO: support full UTF-32 characters
+ // for testing, 0x00020000 should become 0xD840 0xDC00
+ int size = 1;
+
+ // Only include cell chars if they fit into run
+ if (dataSize + size <= dataLen) {
+ data[dataSize] = cell.chars[0];
+ dataSize += size;
+ colSize += cell.width;
+ pos.col += cell.width;
+ } else {
+ break;
+ }
+ }
- jintArray charsArray = (jintArray)env->GetObjectField(cell, cellCharsField);
- jint *chars = env->GetIntArrayElements(charsArray, 0);
- chars[0] = termCell.chars[0];
- chars[1] = 0x00;
- env->ReleaseIntArrayElements(charsArray, chars, 0);
+ env->ReleaseCharArrayElements(dataArray, data, 0);
+ env->SetIntField(run, cellRunDataSizeField, dataSize);
+ env->SetIntField(run, cellRunColSizeField, colSize);
return 0;
}
@@ -436,7 +460,7 @@ static JNINativeMethod gMethods[] = {
{ "nativeInit", "(Lcom/android/terminal/TerminalCallbacks;II)I", (void*)com_android_terminal_Terminal_nativeInit },
{ "nativeReadLoop", "(I)I", (void*)com_android_terminal_Terminal_nativeReadLoop },
{ "nativeResize", "(III)I", (void*)com_android_terminal_Terminal_nativeResize },
- { "nativeGetCell", "(IIILcom/android/terminal/Terminal$Cell;)I", (void*)com_android_terminal_Terminal_nativeGetCell },
+ { "nativeGetCellRun", "(IIILcom/android/terminal/Terminal$CellRun;)I", (void*)com_android_terminal_Terminal_nativeGetCellRun },
{ "nativeGetRows", "(I)I", (void*)com_android_terminal_Terminal_nativeGetRows },
{ "nativeGetCols", "(I)I", (void*)com_android_terminal_Terminal_nativeGetCols },
};
@@ -463,10 +487,12 @@ int register_com_android_terminal_Terminal(JNIEnv* env) {
android::bellMethod = env->GetMethodID(terminalCallbacksClass, "bell", "()I");
android::resizeMethod = env->GetMethodID(terminalCallbacksClass, "resize", "(II)I");
- ScopedLocalRef<jclass> cellLocal(env,
- env->FindClass("com/android/terminal/Terminal$Cell"));
- cellClass = reinterpret_cast<jclass>(env->NewGlobalRef(cellLocal.get()));
- cellCharsField = env->GetFieldID(cellClass, "chars", "[C");
+ ScopedLocalRef<jclass> cellRunLocal(env,
+ env->FindClass("com/android/terminal/Terminal$CellRun"));
+ cellRunClass = reinterpret_cast<jclass>(env->NewGlobalRef(cellRunLocal.get()));
+ cellRunDataField = env->GetFieldID(cellRunClass, "data", "[C");
+ cellRunDataSizeField = env->GetFieldID(cellRunClass, "dataSize", "I");
+ cellRunColSizeField = env->GetFieldID(cellRunClass, "colSize", "I");
env->GetJavaVM(&gJavaVM);
diff --git a/src/com/android/terminal/Terminal.java b/src/com/android/terminal/Terminal.java
index 7d4197c..dfd370b 100644
--- a/src/com/android/terminal/Terminal.java
+++ b/src/com/android/terminal/Terminal.java
@@ -26,9 +26,14 @@ public class Terminal {
System.loadLibrary("jni_terminal");
}
- public static class Cell {
- char[] chars = new char[2];
- int width = 1;
+ /**
+ * Represents a run of one or more {@code VTermScreenCell} which all have
+ * the same formatting.
+ */
+ public static class CellRun {
+ char[] data;
+ int dataSize;
+ int colSize;
boolean bold;
int underline;
@@ -97,8 +102,8 @@ public class Terminal {
return nativeGetCols(mNativePtr);
}
- public void getCell(int row, int col, Cell cell) {
- if (nativeGetCell(mNativePtr, row, col, cell) != 0) {
+ public void getCellRun(int row, int col, CellRun run) {
+ if (nativeGetCellRun(mNativePtr, row, col, run) != 0) {
throw new IllegalStateException("getCell failed");
}
}
@@ -106,7 +111,7 @@ public class Terminal {
private static native int nativeInit(TerminalCallbacks callbacks, int rows, int cols);
private static native int nativeReadLoop(int ptr);
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 nativeGetCellRun(int ptr, int row, int col, CellRun run);
private static native int nativeGetRows(int ptr);
private static native int nativeGetCols(int ptr);
}
diff --git a/src/com/android/terminal/TerminalView.java b/src/com/android/terminal/TerminalView.java
index adbb0a7..33b651b 100644
--- a/src/com/android/terminal/TerminalView.java
+++ b/src/com/android/terminal/TerminalView.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.Typeface;
import android.graphics.Paint.FontMetrics;
import android.graphics.Rect;
import android.view.View;
@@ -93,6 +94,7 @@ public class TerminalView extends View {
}
public void setTextSize(float textSize) {
+ mTextPaint.setTypeface(Typeface.MONOSPACE);
mTextPaint.setTextSize(textSize);
// Read metrics to get exact pixel dimensions
@@ -126,6 +128,8 @@ public class TerminalView extends View {
updateTerminalSize();
}
}
+
+ private static final int MAX_RUN_LENGTH = 128;
@Override
protected void onDraw(Canvas canvas) {
@@ -136,28 +140,46 @@ public class TerminalView extends View {
// Only draw dirty region of console
final Rect dirty = canvas.getClipBounds();
+ final int rows = mTerm.getRows();
+ final int cols = mTerm.getCols();
+
final int startRow = dirty.top / mCharHeight;
- final int endRow = dirty.bottom / mCharHeight;
+ final int endRow = Math.min(dirty.bottom / mCharHeight, rows - 1);
final int startCol = dirty.left / mCharWidth;
- final int endCol = dirty.right / mCharWidth;
+ final int endCol = Math.min(dirty.right / mCharWidth, cols - 1);
+
+ final Terminal.CellRun run = new Terminal.CellRun();
+ run.data = new char[MAX_RUN_LENGTH];
- final Terminal.Cell cell = new Terminal.Cell();
+ // Positions of each possible cell
+ // TODO: make sure this works with surrogate pairs
+ final float[] pos = new float[MAX_RUN_LENGTH * 2];
+ for (int i = 0; i < MAX_RUN_LENGTH; i++) {
+ pos[i * 2] = i * mCharWidth;
+ pos[(i * 2) + 1] = -mCharTop;
+ }
for (int row = startRow; row <= endRow; row++) {
for (int col = startCol; col <= endCol;) {
- mTerm.getCell(row, col, cell);
+ mTerm.getCellRun(row, col, run);
- mBgPaint.setColor(cell.bgColor);
- mTextPaint.setColor(cell.fgColor);
+ mBgPaint.setColor(run.bgColor);
+ mTextPaint.setColor(run.fgColor);
final int y = row * mCharHeight;
final int x = col * mCharWidth;
- final int xEnd = x + (cell.width * mCharWidth);
+ final int xEnd = x + (run.colSize * mCharWidth);
+
+ canvas.save(Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG);
+ canvas.translate(x, y);
+ canvas.clipRect(0, 0, run.colSize * mCharWidth, mCharHeight);
+
+ canvas.drawPaint(mBgPaint);
+ canvas.drawPosText(run.data, 0, run.dataSize, pos, mTextPaint);
- canvas.drawRect(x, y, xEnd, y + mCharHeight, mBgPaint);
- canvas.drawText(cell.chars, 0, cell.chars.length, x, y - mCharTop, mTextPaint);
+ canvas.restore();
- col += cell.width;
+ col += run.colSize;
}
}