diff options
author | Kenny Root <kenny@the-b.org> | 2009-08-02 12:35:57 +0000 |
---|---|---|
committer | Kenny Root <kenny@the-b.org> | 2009-08-02 12:35:57 +0000 |
commit | 4738e1afc28356df2100a145c6226732ccee365a (patch) | |
tree | 7b26db408f5961e6703cebc50711543ced1ddd8a | |
parent | 1afdbb9858fbc300261afc8187634ba15082acf3 (diff) | |
download | connectbot-4738e1afc28356df2100a145c6226732ccee365a.tar.gz connectbot-4738e1afc28356df2100a145c6226732ccee365a.tar.bz2 connectbot-4738e1afc28356df2100a145c6226732ccee365a.zip |
Support wide characters in drawing and emulation
git-svn-id: https://connectbot.googlecode.com/svn/trunk/connectbot@381 df292f66-193f-0410-a5fc-6d59da041ff2
-rw-r--r-- | AndroidManifest.xml | 2 | ||||
-rw-r--r-- | src/de/mud/terminal/VDUBuffer.java | 16 | ||||
-rw-r--r-- | src/de/mud/terminal/vt320.java | 67 | ||||
-rw-r--r-- | src/org/connectbot/TerminalView.java | 10 | ||||
-rw-r--r-- | src/org/connectbot/service/Relay.java | 12 | ||||
-rw-r--r-- | src/org/connectbot/service/TerminalBridge.java | 28 |
6 files changed, 108 insertions, 27 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index a3fdc41..3c6001f 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2,7 +2,7 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.connectbot" android:versionName="1.6-dev" - android:versionCode="181"> + android:versionCode="182"> <application android:icon="@drawable/icon" diff --git a/src/de/mud/terminal/VDUBuffer.java b/src/de/mud/terminal/VDUBuffer.java index 0f5fda6..93e3ccf 100644 --- a/src/de/mud/terminal/VDUBuffer.java +++ b/src/de/mud/terminal/VDUBuffer.java @@ -65,6 +65,20 @@ public class VDUBuffer { /** Scroll down when inserting a line. */ public final static boolean SCROLL_DOWN = true; + /* Attributes bit-field usage: + * + * 8421 8421 8421 8421 8421 8421 8421 8421 + * |||| |||| |||| |||| |||| |||| |||| |||`- Bold + * |||| |||| |||| |||| |||| |||| |||| ||`-- Underline + * |||| |||| |||| |||| |||| |||| |||| |`--- Invert + * |||| |||| |||| |||| |||| |||| |||| `---- Low + * |||| |||| |||| |||| |||| |||| |||`------ Invisible + * |||| |||| |||| |||| ||`+-++++-+++------- Foreground Color + * |||| |||| |`++-++++-++------------------ Background Color + * |||| |||| `----------------------------- Fullwidth character + * `+++-++++------------------------------- Reserved for future use + */ + /** Make character normal. */ public final static int NORMAL = 0x00; /** Make character bold. */ @@ -77,6 +91,8 @@ public class VDUBuffer { public final static int LOW = 0x08; /** Invisible character. */ public final static int INVISIBLE = 0x10; + /** Unicode full-width character (CJK, et al.) */ + public final static int FULLWIDTH = 0x8000000; /** how much to left shift the foreground color */ public final static int COLOR_FG_SHIFT = 5; diff --git a/src/de/mud/terminal/vt320.java b/src/de/mud/terminal/vt320.java index f628cd4..729b6de 100644 --- a/src/de/mud/terminal/vt320.java +++ b/src/de/mud/terminal/vt320.java @@ -72,10 +72,10 @@ public abstract class vt320 extends VDUBuffer implements VDUInput { * Convenience function for putString(char[], int, int) */ public void putString(String s) { - int len = s.length(); - char[] tmp = new char[len]; - s.getChars(0, len, tmp, 0); - putString(tmp, 0, len); + int len = s.length(); + char[] tmp = new char[len]; + s.getChars(0, len, tmp, 0); + putString(tmp, null, 0, len); } /** @@ -85,36 +85,40 @@ public abstract class vt320 extends VDUBuffer implements VDUInput { * @param start place to start in array * @param len number of characters to process */ - public void putString(char[] s, int start, int len) { + public void putString(char[] s, boolean[] fullwidths, int start, int len) { if (len > 0) { //markLine(R, 1); int lastChar = -1; char c; + boolean isWide = false; for (int i = 0; i < len; i++) { c = s[start + i]; // Shortcut for my favorite ASCII if (c <= 0x7F) { if (lastChar != -1) - putChar((char) lastChar, false); + putChar((char) lastChar, isWide, false); lastChar = c; + isWide = false; } else if (!Character.isLowSurrogate(c) && !Character.isHighSurrogate(c)) { if (Character.getType(c) == Character.NON_SPACING_MARK) { if (lastChar != -1) { char nc = Precomposer.precompose((char) lastChar, c); - putChar(nc, false); + putChar(nc, isWide, false); lastChar = -1; } } else { - if (lastChar != -1) - putChar((char) lastChar, false); + if (lastChar != -1) + putChar((char) lastChar, isWide, false); lastChar = c; + if (fullwidths != null) + isWide = fullwidths[i]; } } } if (lastChar != -1) - putChar((char) lastChar, false); + putChar((char) lastChar, isWide, false); setCursorPosition(C, R); redraw(); @@ -138,6 +142,9 @@ public void setScreenSize(int c, int r, boolean broadcast) { //int oldcols = width; if (debug>2) { + if (debugStr == null) + debugStr = new StringBuilder(); + debugStr.append("setscreensize (") .append(c) .append(',') @@ -167,14 +174,15 @@ public void setScreenSize(int c, int r, boolean broadcast) { */ public vt320(int width, int height) { super(width, height); + + debugStr = new StringBuilder(); + setVMS(false); setIBMCharset(false); setTerminalID("vt320"); setBufferSize(100); //setBorder(2, false); - debugStr = new StringBuilder(); - gx = new char[4]; reset(); @@ -548,8 +556,9 @@ public void setScreenSize(int c, int r, boolean broadcast) { write(s); + // TODO check if character is wide if (doecho) - putChar((char)s, false); + putChar((char)s, false, false); return true; } @@ -1497,7 +1506,7 @@ public void setScreenSize(int c, int r, boolean broadcast) { if (R > maxr) R = maxr; } - private void putChar(char c, boolean doshowcursor) { + private void putChar(char c, boolean isWide, boolean doshowcursor) { int rows = this.height; //statusline int columns = this.width; // byte msg[]; @@ -1754,9 +1763,25 @@ public void setScreenSize(int c, int r, boolean broadcast) { /*if(true || (statusmode == 0)) { */ if (insertmode == 1) { - insertChar(C, R, c, attributes); + if (isWide) { + if (C >= columns - 1) { + C = 0; + R++; + } + insertChar(C++, R, c, attributes | FULLWIDTH); + insertChar(C, R, ' ', attributes | FULLWIDTH); + } else + insertChar(C, R, c, attributes); } else { - putChar(C, R, c, attributes); + if (isWide) { + if (C >= columns - 1) { + C = 0; + R++; + } + putChar(C++, R, c, attributes | FULLWIDTH); + putChar(C, R, ' ', attributes | FULLWIDTH); + } else + putChar(C, R, c, attributes); } /* } else { @@ -2525,9 +2550,10 @@ public void setScreenSize(int c, int r, boolean broadcast) { } case 'C': if (DCEvars[0] == 0) + DCEvars[0] = 1; + while (DCEvars[0]-- > 0) { C++; - else - C += DCEvars[0]; + } if (C >= columns) C = columns - 1; if (debug > 1) @@ -2544,9 +2570,10 @@ public void setScreenSize(int c, int r, boolean broadcast) { break; case 'D': if (DCEvars[0] == 0) + DCEvars[0] = 1; + while (DCEvars[0]-- > 0) { C--; - else - C -= DCEvars[0]; + } if (C < 0) C = 0; if (debug > 1) debug("ESC [ " + DCEvars[0] + " D"); diff --git a/src/org/connectbot/TerminalView.java b/src/org/connectbot/TerminalView.java index de74f7e..5eb7e24 100644 --- a/src/org/connectbot/TerminalView.java +++ b/src/org/connectbot/TerminalView.java @@ -36,6 +36,7 @@ import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.widget.Toast; +import de.mud.terminal.VDUBuffer; /** * User interface {@link View} for showing a TerminalBridge in an @@ -148,6 +149,11 @@ public class TerminalView extends View implements FontSizeChangedListener { // also draw cursor if visible if(bridge.buffer.isCursorVisible()) { + int currentAttribute = bridge.buffer.getAttributes( + bridge.buffer.getCursorColumn(), + bridge.buffer.getCursorRow()); + boolean onWideCharacter = (currentAttribute & VDUBuffer.FULLWIDTH) != 0; + int x = bridge.buffer.getCursorColumn() * bridge.charWidth; int y = (bridge.buffer.getCursorRow() + bridge.buffer.screenBase - bridge.buffer.windowBase) @@ -157,7 +163,9 @@ public class TerminalView extends View implements FontSizeChangedListener { canvas.save(); canvas.translate(x, y); - canvas.clipRect(0, 0, bridge.charWidth, bridge.charHeight); + canvas.clipRect(0, 0, + bridge.charWidth * (onWideCharacter ? 2 : 1), + bridge.charHeight); canvas.drawPaint(cursorPaint); // Make sure we scale our decorations to the correct size. diff --git a/src/org/connectbot/service/Relay.java b/src/org/connectbot/service/Relay.java index 746a915..22b8299 100644 --- a/src/org/connectbot/service/Relay.java +++ b/src/org/connectbot/service/Relay.java @@ -92,6 +92,9 @@ public class Relay implements Runnable { byteBuffer = ByteBuffer.allocate(BUFFER_SIZE); charBuffer = CharBuffer.allocate(BUFFER_SIZE); + float[] widths = new float[BUFFER_SIZE]; + boolean[] fullwidths = new boolean[BUFFER_SIZE]; + byteArray = byteBuffer.array(); charArray = charBuffer.array(); @@ -101,9 +104,11 @@ public class Relay implements Runnable { byteBuffer.limit(0); int bytesToRead; int offset; + int charWidth; try { while (true) { + charWidth = bridge.charWidth; bytesToRead = byteBuffer.capacity() - byteBuffer.limit(); offset = byteBuffer.arrayOffset() + byteBuffer.limit(); bytesRead = transport.read(byteArray, offset, bytesToRead); @@ -122,7 +127,12 @@ public class Relay implements Runnable { byteBuffer.position(0); } - buffer.putString(charArray, 0, charBuffer.position()); + offset = charBuffer.position(); + bridge.defaultPaint.getTextWidths(charArray, 0, offset, widths); + for (int i = 0; i < offset; i++) + fullwidths[i] = (int)widths[i] != charWidth; + + buffer.putString(charArray, fullwidths, 0, charBuffer.position()); charBuffer.clear(); bridge.redraw(); } diff --git a/src/org/connectbot/service/TerminalBridge.java b/src/org/connectbot/service/TerminalBridge.java index 500a821..5cb9613 100644 --- a/src/org/connectbot/service/TerminalBridge.java +++ b/src/org/connectbot/service/TerminalBridge.java @@ -80,7 +80,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener { private AbsTransport transport; - private final Paint defaultPaint; + final Paint defaultPaint; private Relay relay; @@ -1037,6 +1037,7 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener { int fg, bg; synchronized (buffer) { boolean entireDirty = buffer.update[0] || fullRedraw; + boolean isWideCharacter = false; // walk through all lines in the buffer for(int l = 0; l < buffer.height; l++) { @@ -1080,9 +1081,16 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener { // set underlined attributes if requested defaultPaint.setUnderlineText((currAttr & VDUBuffer.UNDERLINE) != 0); - // determine the amount of continuous characters with the same settings and print them all at once - while(c + addr < buffer.width && buffer.charAttributes[buffer.windowBase + l][c + addr] == currAttr) { + isWideCharacter = (currAttr & VDUBuffer.FULLWIDTH) != 0; + + if (isWideCharacter) addr++; + else { + // determine the amount of continuous characters with the same settings and print them all at once + while(c + addr < buffer.width + && buffer.charAttributes[buffer.windowBase + l][c + addr] == currAttr) { + addr++; + } } // Save the current clip region @@ -1090,7 +1098,17 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener { // clear this dirty area with background color defaultPaint.setColor(bg); - canvas.clipRect(c * charWidth, l * charHeight, (c + addr) * charWidth, (l + 1) * charHeight); + if (isWideCharacter) { + canvas.clipRect(c * charWidth, + l * charHeight, + (c + 2) * charWidth, + (l + 1) * charHeight); + } else { + canvas.clipRect(c * charWidth, + l * charHeight, + (c + addr) * charWidth, + (l + 1) * charHeight); + } canvas.drawPaint(defaultPaint); // write the text string starting at 'c' for 'addr' number of characters @@ -1105,6 +1123,8 @@ public class TerminalBridge implements VDUDisplay, OnKeyListener { // advance to the next text block with different characteristics c += addr - 1; + if (isWideCharacter) + c++; } } |