From: Kenny Root <kenny@the-b.org>
Date: Thu, 9 Dec 2010 00:44:38 -0800

Rearrange some terminal key logic

Try to support the right keyboard map for the hardware keyboard. Also
try to support dead keys.

diff --git a/src/org/connectbot/TerminalView.java b/src/org/connectbot/TerminalView.java
--- a/src/org/connectbot/TerminalView.java
+++ b/src/org/connectbot/TerminalView.java
@@ -179,6 +179,11 @@
 						bridge.charHeight);
 				canvas.drawPaint(cursorPaint);
 
+				final int deadKey = bridge.getKeyHandler().getDeadKey();
+				if (deadKey != 0) {
+					canvas.drawText(new char[] { (char)deadKey }, 0, 1, 0, 0, cursorStrokePaint);
+				}
+
 				// Make sure we scale our decorations to the correct size.
 				canvas.concat(scaleMatrix);
 
diff --git a/src/org/connectbot/service/TerminalKeyListener.java b/src/org/connectbot/service/TerminalKeyListener.java
--- a/src/org/connectbot/service/TerminalKeyListener.java
+++ b/src/org/connectbot/service/TerminalKeyListener.java
@@ -72,6 +72,8 @@
 
 	private int metaState = 0;
 
+	private int mDeadKey = 0;
+
 	private ClipboardManager clipboard = null;
 	private final SelectionArea selectionArea;
 
@@ -161,33 +163,55 @@
 
 			bridge.resetScrollPosition();
 
-			boolean printing = (keymap.isPrintingKey(keyCode) || keyCode == KeyEvent.KEYCODE_SPACE);
+			if (keyCode == KeyEvent.KEYCODE_UNKNOWN &&
+					event.getAction() == KeyEvent.ACTION_MULTIPLE) {
+				byte[] input = event.getCharacters().getBytes(encoding);
+				bridge.transport.write(input);
+				return true;
+			}
+
+			int curMetaState = event.getMetaState();
+
+			if ((metaState & META_SHIFT_MASK) != 0) {
+				curMetaState |= KeyEvent.META_SHIFT_ON;
+			}
+
+			if ((metaState & META_ALT_MASK) != 0) {
+				curMetaState |= KeyEvent.META_ALT_ON;
+			}
+
+			int key = event.getUnicodeChar(curMetaState);
+
+			if ((key & KeyCharacterMap.COMBINING_ACCENT) != 0) {
+				mDeadKey = key & KeyCharacterMap.COMBINING_ACCENT_MASK;
+				return true;
+			}
+
+			if (mDeadKey != 0) {
+				key = KeyCharacterMap.getDeadChar(mDeadKey, keyCode);
+				mDeadKey = 0;
+			}
+
+			final boolean printing = (key != 0);
 
 			// otherwise pass through to existing session
 			// print normal keys
 			if (printing) {
-				int curMetaState = event.getMetaState();
-
 				metaState &= ~(META_SLASH | META_TAB);
 
-				if ((metaState & META_SHIFT_MASK) != 0) {
-					curMetaState |= KeyEvent.META_SHIFT_ON;
-					metaState &= ~META_SHIFT_ON;
+				// Remove shift and alt modifiers
+				final int lastMetaState = metaState;
+				metaState &= ~(META_SHIFT_ON | META_ALT_ON);
+				if (metaState != lastMetaState) {
 					bridge.redraw();
 				}
 
-				if ((metaState & META_ALT_MASK) != 0) {
-					curMetaState |= KeyEvent.META_ALT_ON;
-					metaState &= ~META_ALT_ON;
-					bridge.redraw();
-				}
-
-				int key = keymap.get(keyCode, curMetaState);
-
 				if ((metaState & META_CTRL_MASK) != 0) {
 					metaState &= ~META_CTRL_ON;
 					bridge.redraw();
 
+					// If there is no hard keyboard or there is a hard keyboard currently hidden,
+					// CTRL-1 through CTRL-9 will send F1 through F9
 					if ((!hardKeyboard || (hardKeyboard && hardKeyboardHidden))
 							&& sendFunctionKey(keyCode))
 						return true;
@@ -198,8 +222,10 @@
 					// Support CTRL-A through CTRL-_
 					else if (key >= 0x41 && key <= 0x5F)
 						key -= 0x40;
+					// CTRL-space sends NULL
 					else if (key == 0x20)
 						key = 0x00;
+					// CTRL-? sends DEL
 					else if (key == 0x3F)
 						key = 0x7F;
 				}
@@ -220,13 +246,6 @@
 				return true;
 			}
 
-			if (keyCode == KeyEvent.KEYCODE_UNKNOWN &&
-					event.getAction() == KeyEvent.ACTION_MULTIPLE) {
-				byte[] input = event.getCharacters().getBytes(encoding);
-				bridge.transport.write(input);
-				return true;
-			}
-
 			// try handling keymode shortcuts
 			if (hardKeyboard && !hardKeyboardHidden &&
 					event.getRepeatCount() == 0) {
@@ -487,6 +506,10 @@
 		return metaState;
 	}
 
+	public int getDeadKey() {
+		return mDeadKey;
+	}
+
 	public void setClipboardManager(ClipboardManager clipboard) {
 		this.clipboard = clipboard;
 	}
