diff options
Diffstat (limited to 'src/org/theb/ssh/JCTerminalView.java')
-rw-r--r-- | src/org/theb/ssh/JCTerminalView.java | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/src/org/theb/ssh/JCTerminalView.java b/src/org/theb/ssh/JCTerminalView.java new file mode 100644 index 0000000..47d12aa --- /dev/null +++ b/src/org/theb/ssh/JCTerminalView.java @@ -0,0 +1,329 @@ +/* + * Copyright (C) 2007 Kenny Root (kenny at the-b.org) + * + * This file is part of Connectbot. + * + * Connectbot is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Connectbot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Connectbot. If not, see <http://www.gnu.org/licenses/>. + */ +package org.theb.ssh; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.PixelXorXfermode; +import android.graphics.Typeface; +import android.graphics.Paint.FontMetricsInt; +import android.util.Log; +import android.view.KeyEvent; +import android.view.View; + +import com.jcraft.jcterm.Emulator; +import com.jcraft.jcterm.EmulatorVT100; +import com.jcraft.jcterm.Term; + +public class JCTerminalView extends View implements Term, Terminal { + private final Paint mPaint; + private Bitmap mBitmap; + private Canvas mCanvas; + + private final Paint mCursorPaint; + + private Emulator emulator = null; + + private boolean mBold = false; + private boolean mUnderline = false; + private boolean mReverse = false; + + private int mDefaultForeground = Color.WHITE; + private int mDefaultBackground = Color.BLACK; + private int mForeground = Color.WHITE; + private int mBackground = Color.BLACK; + + private boolean mAntialias = true; + + private int mTermWidth = 80; + private int mTermHeight = 24; + + private int mCharHeight; + private int mCharWidth; + private int mDescent; + + + // Cursor location + private int x = 0; + private int y = 0; + + private final Object[] mColors = {Color.BLACK, Color.RED, Color.GREEN, Color.YELLOW, + Color.BLUE, Color.MAGENTA, Color.CYAN, Color.WHITE}; + + public JCTerminalView(Context c) { + super(c); + mPaint = new Paint(); + mPaint.setAntiAlias(mAntialias); + mPaint.setColor(mDefaultForeground); + + mCursorPaint = new Paint(); + mCursorPaint.setAntiAlias(mAntialias); + mCursorPaint.setColor(mDefaultForeground); + mCursorPaint.setXfermode(new PixelXorXfermode(mDefaultBackground)); + + setFont(Typeface.MONOSPACE); + } + + @Override + protected void onDraw(Canvas canvas) { + if (mBitmap != null) { + canvas.drawBitmap(mBitmap, 0, 0, null); + + if (mCharHeight > 0 && y > mCharHeight) { + // Invert pixels for cursor position. + canvas.drawRect(x, y - mCharHeight, x + mCharWidth, y, mCursorPaint); + } + } + } + + @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 (mBitmap != null) + newCanvas.drawBitmap(mBitmap, 0, 0, mPaint); + + mBitmap = newBitmap; + mCanvas = newCanvas; + + setSize(w, h); + } + + private void setSize(int w, int h) { + int column = w / getCharWidth(); + int row = h / getCharHeight(); + + mTermWidth = column; + mTermHeight = row; + + if (emulator != null) + emulator.reset(); + + clear_area(0, 0, w, h); + + // TODO: finish this method + } + + private void setFont(Typeface typeface) { + mPaint.setTypeface(typeface); + mPaint.setTextSize(8); + FontMetricsInt fm = mPaint.getFontMetricsInt(); + mDescent = fm.descent; + + float[] widths = new float[1]; + mPaint.getTextWidths("X", widths); + mCharWidth = (int)widths[0]; + + // Is this right? + mCharHeight = Math.abs(fm.top) + Math.abs(fm.descent); + Log.d("SSH", "character height is " + mCharHeight); + // mCharHeight += mLineSpace * 2; + // mDescent += mLineSpace; + } + + public void beep() { + // TODO Auto-generated method stub + + } + + public void clear() { + mPaint.setColor(getBackgroundColor()); + mCanvas.drawRect(0, 0, mCanvas.getBitmapWidth(), + mCanvas.getBitmapHeight(), mPaint); + mPaint.setColor(getForegroundColor()); + } + + private int getBackgroundColor() { + if (mReverse) + return mForeground; + return mBackground; + } + + private int getForegroundColor() { + if (mReverse) + return mBackground; + return mForeground; + } + + public void clear_area(int x1, int y1, int x2, int y2) { + mPaint.setColor(getBackgroundColor()); + if (mCanvas != null) + mCanvas.drawRect(x1, y1, x2, y2, mPaint); + mPaint.setColor(getForegroundColor()); + } + + public void drawBytes(byte[] buf, int s, int len, int x, int y) { + String chars = null; + try { + chars = new String(buf, "ASCII"); + drawString(chars.substring(s, s+len), x, y); + } catch (UnsupportedEncodingException e) { + // TODO Auto-generated catch block + Log.e("SSH", "Can't convert bytes to ASCII"); + } + } + + public void drawString(String str, int x, int y) { + mPaint.setFakeBoldText(mBold); + mPaint.setUnderlineText(mUnderline); + mCanvas.drawText(str, x, y - mDescent, mPaint); + } + + public void draw_cursor() { + postInvalidate(); + } + + public int getCharHeight() { + return mCharHeight; + } + + public int getCharWidth() { + return mCharWidth; + } + + public Object getColor(int index) { + if (mColors == null || index < 0 || mColors.length <= index) + return null; + return mColors[index]; + } + + public int getColumnCount() { + return mTermWidth; + } + + public int getRowCount() { + return mTermHeight; + } + + public int getTermHeight() { + return mTermHeight * mCharHeight; + } + + public int getTermWidth() { + return mTermWidth * mCharWidth; + } + + public void redraw(int x, int y, int width, int height) { + //invalidate(x, y, x+width, y+height); + postInvalidate(); + } + + public void resetAllAttributes() { + mBold = false; + mUnderline = false; + mReverse = false; + + mBackground = mDefaultBackground; + mForeground = mDefaultForeground; + + if (mPaint != null) + mPaint.setColor(mForeground); + } + + public void scroll_area(int x, int y, int w, int h, int dx, int dy) { + // TODO: make scrolling more efficient (memory-wise) + mCanvas.drawBitmap(Bitmap.createBitmap(mBitmap, x, y, w, h), x+dx, y+dy, null); + } + + private int toColor(Object o) { + if (o instanceof Integer) { + return ((Integer)o).intValue(); + } + + if (o instanceof String) { + return Color.parseColor((String)o); + } + + return Color.WHITE; + } + + public void setBackGround(Object background) { + mBackground = toColor(background); + } + + public void setBold() { + mBold = true; + } + + public void setCursor(int x, int y) { + // Make sure we don't go outside the bounds of the window. + this.x = Math.max( + Math.min(x, getWidth() - mCharWidth), + 0); + this.y = Math.max( + Math.min(y, getHeight()), + mCharHeight); + } + + public void setDefaultBackGround(Object background) { + mDefaultBackground = toColor(background); + } + + public void setDefaultForeGround(Object foreground) { + mDefaultForeground = toColor(foreground); + } + + public void setForeGround(Object foreground) { + mForeground = toColor(foreground); + } + + public void setReverse() { + mReverse = true; + if (mPaint != null) + mPaint.setColor(getForegroundColor()); + } + + public void setUnderline() { + mUnderline = true; + } + + public void start(InputStream in, OutputStream out) { + emulator = new EmulatorVT100(this, in); + emulator.reset(); + emulator.start(); + + clear(); + } + + public byte[] getKeyCode(int keyCode, int meta) { + if (keyCode == KeyEvent.KEYCODE_NEWLINE) + return emulator.getCodeENTER(); + else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) + return emulator.getCodeLEFT(); + else if (keyCode == KeyEvent.KEYCODE_DPAD_UP) + return emulator.getCodeUP(); + else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) + return emulator.getCodeDOWN(); + else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) + return emulator.getCodeRIGHT(); + else + return null; + } +} |