aboutsummaryrefslogtreecommitdiffstats
path: root/src/org/theb/ssh/JTATerminalView.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/org/theb/ssh/JTATerminalView.java')
-rw-r--r--src/org/theb/ssh/JTATerminalView.java323
1 files changed, 323 insertions, 0 deletions
diff --git a/src/org/theb/ssh/JTATerminalView.java b/src/org/theb/ssh/JTATerminalView.java
new file mode 100644
index 0000000..2238f02
--- /dev/null
+++ b/src/org/theb/ssh/JTATerminalView.java
@@ -0,0 +1,323 @@
+package org.theb.ssh;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import de.mud.terminal.SoftFont;
+import de.mud.terminal.VDUBuffer;
+import de.mud.terminal.VDUDisplay;
+import de.mud.terminal.vt320;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Typeface;
+import android.graphics.Paint.FontMetricsInt;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+
+public class JTATerminalView extends View implements VDUDisplay, Terminal, Runnable {
+ private Paint paint;
+ private Canvas canvas;
+ private Bitmap bitmap;
+
+ protected vt320 emulation;
+ private VDUBuffer buffer;
+
+ private InputStream in;
+ private OutputStream out;
+
+ private String encoding = "ASCII";
+ private SoftFont sf = new SoftFont();
+
+ private Thread reader = null;
+
+ private int charWidth;
+ private int charHeight;
+ private int charDescent;
+
+ private int termWidth;
+ private int termHeight;
+
+ private int color[] = {
+ Color.BLACK,
+ Color.RED,
+ Color.GREEN,
+ Color.YELLOW,
+ Color.BLUE,
+ Color.MAGENTA,
+ Color.CYAN,
+ Color.WHITE,
+ };
+
+ private final static int COLOR_FG_STD = 7;
+ private final static int COLOR_BG_STD = 0;
+
+ public JTATerminalView(Context context) {
+ super(context);
+
+ paint = new Paint();
+ paint.setAntiAlias(true);
+ setFont(Typeface.MONOSPACE, 8);
+
+ emulation = new vt320() {
+ public void write(byte[] b) {
+ try {
+ JTATerminalView.this.write(b);
+ } catch (IOException e) {
+ Log.e("SSH", "couldn't write" + b.toString());
+ reader = null;
+ }
+ }
+
+ public void sendTelnetCommand(byte cmd) {
+ // TODO: implement telnet command sending
+ }
+
+ public void setWindowSize(int c, int r) {
+ // TODO: implement window sizing
+ }
+ };
+
+ setVDUBuffer(emulation);
+ emulation.setDisplay(this);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (bitmap != null) {
+ canvas.drawBitmap(bitmap, 0, 0, null);
+ /*
+ if (charHeight > 0 && y > charHeight) {
+ // Invert pixels for cursor position.
+ Bitmap cursor = Bitmap.createBitmap(mBitmap, x, y - mCharHeight, mCharWidth, mCharHeight);
+ for (int cy = 0; cy < mCharHeight; cy++)
+ for (int cx = 0; cx < mCharWidth; cx++)
+ cursor.setPixel(cx, cy, (~cursor.getPixel(cx, cy) & 0xFFFFFFFF) | 0xFF000000);
+ canvas.drawBitmap(cursor, x, y - mCharHeight, null);
+ cursor = null;
+ }
+ */
+ }
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ Log.d("SSH/TerminalView", "onSizeChanged called");
+ Bitmap newBitmap = Bitmap.createBitmap(w, h, false);
+ Canvas newCanvas = new Canvas();
+
+ newCanvas.setDevice(newBitmap);
+
+ if (bitmap != null)
+ newCanvas.drawBitmap(bitmap, 0, 0, paint);
+
+ bitmap = newBitmap;
+ canvas = newCanvas;
+
+ setSize(w, h);
+ }
+
+ private void setSize(int w, int h) {
+ termWidth = w / charWidth;
+ termHeight = h / charHeight;
+
+ buffer.setScreenSize(termWidth, buffer.height = termHeight, true);
+ }
+
+ private void setFont(Typeface typeface, int size) {
+ paint.setTypeface(typeface);
+ paint.setTextSize(size);
+
+ FontMetricsInt fm = paint.getFontMetricsInt();
+
+ charDescent = fm.descent;
+
+ float[] widths = new float[1];
+ paint.getTextWidths("X", widths);
+ charWidth = (int)widths[0];
+
+ charHeight = Math.abs(fm.top) + Math.abs(fm.descent);
+ }
+
+ public void write(byte[] b) throws IOException {
+ Log.e("SSH/JTATerm/write", "Trying to write" + b.toString());
+ out.write(b);
+ }
+
+ public int getColumnCount() {
+ return termWidth;
+ }
+
+ public InputStream getInput() {
+ return in;
+ }
+
+ public byte[] getKeyCode(int keyCode, int meta) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_NEWLINE:
+ emulation.keyTyped(vt320.KEY_ENTER, ' ', meta);
+ break;
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ emulation.keyPressed(vt320.KEY_LEFT, ' ', meta);
+ break;
+ case KeyEvent.KEYCODE_DPAD_UP:
+ emulation.keyPressed(vt320.KEY_UP, ' ', meta);
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ emulation.keyPressed(vt320.KEY_DOWN, ' ', meta) ;
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ emulation.keyPressed(vt320.KEY_RIGHT, ' ', meta);
+ break;
+ }
+ return null;
+ }
+
+ public OutputStream getOutput() {
+ return out;
+ }
+
+ public int getRowCount() {
+ return termHeight;
+ }
+
+ private int darken(int color) {
+ return Color.argb(0xFF,
+ (int)(Color.red(color) * 0.8),
+ (int)(Color.green(color) * 0.8),
+ (int)(Color.blue(color) * 0.8)
+ );
+ }
+
+ /*
+ private int brighten(int color) {
+ return Color.argb(0xFF,
+ (int)(Color.red(color) * 1.2),
+ (int)(Color.green(color) * 1.2),
+ (int)(Color.blue(color) * 1.2)
+ );
+ }
+ */
+
+ public void redraw() {
+ // Make sure the buffer is in the center of the screen.
+ int xoffset = (getWidth() - buffer.width * charWidth) / 2;
+ int yoffset = (getHeight() - buffer.height * charHeight) / 2;
+
+ // Draw the mouse-selection
+ //int selectStartLine = selectBegin.y - buffer.windowBase;
+ //int selectEndLine = selectEnd.y - buffer.windowBase;
+
+ int fg, bg;
+
+ for (int l = 0; l < buffer.height; l++) {
+ if (!buffer.update[0] && !buffer.update[l + 1]) continue;
+
+ for (int c = 0; c < buffer.width; c++) {
+ int addr = 0;
+ int currAttr = buffer.charAttributes[buffer.windowBase + l][c];
+
+ fg = darken(color[COLOR_FG_STD]);
+ bg = darken(color[COLOR_BG_STD]);
+
+ if ((currAttr & VDUBuffer.COLOR_FG) != 0)
+ fg = darken(color[((currAttr & VDUBuffer.COLOR_FG) >> VDUBuffer.COLOR_FG_SHIFT) - 1]);
+ if ((currAttr & VDUBuffer.COLOR_BG) != 0)
+ bg = darken(darken(color[((currAttr & VDUBuffer.COLOR_BG) >> VDUBuffer.COLOR_BG_SHIFT) - 1]));
+ paint.setFakeBoldText((currAttr & VDUBuffer.BOLD) != 0);
+
+ if ((currAttr & VDUBuffer.LOW) != 0)
+ fg = darken(fg);
+
+ if ((currAttr & VDUBuffer.INVERT) != 0) {
+ int swapc = bg;
+ bg = fg;
+ fg = swapc;
+ }
+
+ // If this character is in the special font, print it and continue to the next character.
+ if (sf.inSoftFont(buffer.charArray[buffer.windowBase + l][c])) {
+ paint.setColor(bg);
+ canvas.drawRect(c * charWidth + xoffset, l * charHeight + yoffset,
+ c * (charWidth + 1) + xoffset, (l+1) * charHeight + yoffset, paint);
+ paint.setColor(fg);
+ paint.setUnderlineText((currAttr & VDUBuffer.UNDERLINE) != 0);
+ if ((currAttr & VDUBuffer.INVISIBLE) == 0)
+ sf.drawChar(canvas, paint, buffer.charArray[buffer.windowBase + l][c], xoffset + c * charWidth, l * charHeight + yoffset, charWidth, charHeight);
+ continue;
+ }
+
+ // Determine the amount of continuous characters with the same settings and print them all at once.
+ while ((c + addr < buffer.width) &&
+ ((buffer.charArray[buffer.windowBase + l][c + addr] < ' ') ||
+ (buffer.charAttributes[buffer.windowBase + l][c + addr] == currAttr)) &&
+ !sf.inSoftFont(buffer.charArray[buffer.windowBase + l][c + addr])) {
+ if (buffer.charArray[buffer.windowBase + l][c + addr] < ' ') {
+ buffer.charArray[buffer.windowBase + l][c + addr] = ' ';
+ buffer.charAttributes[buffer.windowBase + l][c + addr] = 0;
+ continue;
+ }
+ addr++;
+ }
+
+ paint.setColor(bg);
+ canvas.drawRect(c * charWidth + xoffset, l * charHeight + yoffset,
+ addr * (charWidth + 1) + xoffset, (l+1) * charHeight + yoffset, paint);
+ paint.setColor(fg);
+
+ paint.setUnderlineText((currAttr & VDUBuffer.UNDERLINE) != 0);
+ if ((currAttr & VDUBuffer.INVISIBLE) == 0)
+ canvas.drawText(buffer.charArray[buffer.windowBase + l],
+ c, addr,
+ c * charWidth + xoffset,
+ (l + 1) * charHeight - charDescent + yoffset,
+ paint);
+
+ c += addr - 1;
+ }
+ }
+
+ buffer.update[0] = false;
+
+ postInvalidate();
+ }
+
+ public void updateScrollBar() {
+ // TODO Auto-generated method stub
+ }
+
+ public void start(InputStream in, OutputStream out) {
+ this.in = in;
+ this.out = out;
+
+ reader = new Thread(this);
+ reader.start();
+ }
+
+ public VDUBuffer getVDUBuffer() {
+ return buffer;
+ }
+
+ public void setVDUBuffer(VDUBuffer buffer) {
+ this.buffer = buffer;
+ }
+
+ public void run() {
+ byte[] b = new byte[256];
+ int n = 0;
+ while (n >= 0)
+ try {
+ n = in.read(b);
+ if (n > 0) emulation.putString(new String(b, 0, n, encoding));
+ redraw();
+ } catch (IOException e) {
+ reader = null;
+ break;
+ }
+ }
+}