aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenny Root <kenny@the-b.org>2009-08-02 12:35:57 +0000
committerKenny Root <kenny@the-b.org>2009-08-02 12:35:57 +0000
commit4738e1afc28356df2100a145c6226732ccee365a (patch)
tree7b26db408f5961e6703cebc50711543ced1ddd8a
parent1afdbb9858fbc300261afc8187634ba15082acf3 (diff)
downloadconnectbot-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.xml2
-rw-r--r--src/de/mud/terminal/VDUBuffer.java16
-rw-r--r--src/de/mud/terminal/vt320.java67
-rw-r--r--src/org/connectbot/TerminalView.java10
-rw-r--r--src/org/connectbot/service/Relay.java12
-rw-r--r--src/org/connectbot/service/TerminalBridge.java28
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++;
}
}