Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.unicode.ime" >
package="macaca.unicode.ime" >

<uses-sdk
android:minSdkVersion="8"
Expand Down
2 changes: 1 addition & 1 deletion lib/android-unicode.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
const path = require('path');

exports.apkPath = path.join(__dirname, '..', 'bin', 'android_unicode_ime-debug.apk');
exports.package = 'android.unicode.ime';
exports.package = 'macaca.unicode.ime';
exports.activity = '.Utf7ImeService';
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "android-unicode",
"version": "1.0.9",
"version": "1.0.11",
"description": "android unicode input apk",
"keywords": [
"unicode",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package android.unicode.ime;
package macaca.unicode.ime;

import java.io.ByteArrayOutputStream;
import java.lang.StringBuilder;
Expand Down Expand Up @@ -98,4 +98,4 @@ public static byte[] decode(String data)
}
return buffer.toByteArray();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package android.unicode.ime;
package macaca.unicode.ime;

import java.nio.charset.*;

Expand All @@ -31,6 +31,8 @@
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;

import macaca.unicode.ime.charsetUtils.*;

/**
* <p>
* Utf7ImeService enables users to input any Unicode character by using only the
Expand All @@ -53,14 +55,14 @@ public class Utf7ImeService extends InputMethodService {
/**
* Expected encoding for hardware key input.
*/
private static final String UTF7 = "UTF-7";
private static final String UTF7 = "X-MODIFIED-UTF-7";

private static final String ASCII = "US-ASCII";

/**
* Special character to shift to Modified BASE64 in modified UTF-7.
*/
private static final char UTF7_SHIFT = '+';
private static final char UTF7_SHIFT = '&';

/**
* Special character to shift back to US-ASCII in modified UTF-7.
Expand Down Expand Up @@ -89,7 +91,7 @@ public void onStartInput(EditorInfo attribute, boolean restarting) {
if (!restarting) {
mMetaState = 0;
mIsShifted = false;
mUtf7Charset = Charset.forName(UTF7);
mUtf7Charset = new CharsetProvider().charsetForName(UTF7);
}
mComposing = null;
}
Expand Down Expand Up @@ -141,9 +143,6 @@ public boolean onKeyDown(int keyCode, KeyEvent event) {
// Shifted State
if (c == UTF7_UNSHIFT) {
toUnshifted();
} else if (!isAlphanumeric(c)) {
toUnshifted();
commitCharacter(c);
} else {
appendComposing(c);
}
Expand Down
40 changes: 40 additions & 0 deletions src/macaca/unicode/ime/charsetUtils/Base64Util.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package macaca.unicode.ime.charsetUtils;

import java.util.Arrays;

class Base64Util {
private static final int ALPHABET_LENGTH = 64;
private final char[] alphabet;
private final int[] inverseAlphabet;

Base64Util(final String alphabet) {
this.alphabet = alphabet.toCharArray();
if (alphabet.length() != ALPHABET_LENGTH)
throw new IllegalArgumentException("alphabet has incorrect length (should be 64, not "
+ alphabet.length() + ")");
inverseAlphabet = new int[128];
Arrays.fill(inverseAlphabet, -1);
for (int i = 0; i < this.alphabet.length; i++) {
final char ch = this.alphabet[i];
if (ch >= 128)
throw new IllegalArgumentException("invalid character in alphabet: " + ch);
inverseAlphabet[ch] = i;
}
}

int getSextet(final byte ch) {
if (ch >= 128)
return -1;
return inverseAlphabet[ch];
}

boolean contains(final char ch) {
if (ch >= 128)
return false;
return inverseAlphabet[ch] >= 0;
}

byte getChar(final int sextet) {
return (byte) alphabet[sextet];
}
}
48 changes: 48 additions & 0 deletions src/macaca/unicode/ime/charsetUtils/CharsetProvider.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package macaca.unicode.ime.charsetUtils;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

public class CharsetProvider extends java.nio.charset.spi.CharsetProvider {
private static final String UTF7_NAME = "UTF-7";
private static final String UTF7_O_NAME = "X-UTF-7-OPTIONAL";
private static final String UTF7_M_NAME = "X-MODIFIED-UTF-7";
private static final String[] UTF7_ALIASES = new String[] { "UNICODE-1-1-UTF-7",
"CSUNICODE11UTF7", "X-RFC2152", "X-RFC-2152" };
private static final String[] UTF7_O_ALIASES = new String[] { "X-RFC2152-OPTIONAL",
"X-RFC-2152-OPTIONAL" };
private static final String[] UTF7_M_ALIASES = new String[] { "X-IMAP-MODIFIED-UTF-7",
"X-IMAP4-MODIFIED-UTF7", "X-IMAP4-MODIFIED-UTF-7", "X-RFC3501", "X-RFC-3501" };
private Charset utf7charset = new UTF7Charset(UTF7_NAME, UTF7_ALIASES, false);
private Charset utf7oCharset = new UTF7Charset(UTF7_O_NAME, UTF7_O_ALIASES, true);
private Charset imap4charset = new ModifiedUTF7Charset(UTF7_M_NAME, UTF7_M_ALIASES);
private List charsets;

public CharsetProvider() {
charsets = Arrays.asList(new Object[] { utf7charset, imap4charset, utf7oCharset });
}

public Charset charsetForName(String charsetName) {
charsetName = charsetName.toUpperCase(Locale.US);
for (Iterator iter = charsets.iterator(); iter.hasNext();) {
Charset charset = (Charset) iter.next();
if (charset.name().equals(charsetName))
return charset;
}
for (Iterator iter = charsets.iterator(); iter.hasNext();) {
Charset charset = (Charset) iter.next();
if (charset.aliases().contains(charsetName))
return charset;
}
return null;
}

public Iterator charsets() {
return charsets.iterator();
}

}
24 changes: 24 additions & 0 deletions src/macaca/unicode/ime/charsetUtils/ModifiedUTF7Charset.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package macaca.unicode.ime.charsetUtils;

class ModifiedUTF7Charset extends UTF7StyleCharset {
private static final String MODIFIED_BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz" + "0123456789+,";

ModifiedUTF7Charset(String name, String[] aliases) {
super(name, aliases, MODIFIED_BASE64_ALPHABET, true);
}

boolean canEncodeDirectly(char ch) {
if (ch == shift())
return false;
return ch >= 0x20 && ch <= 0x7E;
}

byte shift() {
return '&';
}

byte unshift() {
return '-';
}
}
30 changes: 30 additions & 0 deletions src/macaca/unicode/ime/charsetUtils/UTF7Charset.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package macaca.unicode.ime.charsetUtils;

class UTF7Charset extends UTF7StyleCharset {
private static final String BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz" + "0123456789+/";
private static final String SET_D = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'(),-./:?";
private static final String SET_O = "!\"#$%&*;<=>@[]^_`{|}";
private static final String RULE_3 = " \t\r\n";
final String directlyEncoded;

UTF7Charset(String name, String[] aliases, boolean includeOptional) {
super(name, aliases, BASE64_ALPHABET, false);
if (includeOptional)
this.directlyEncoded = SET_D + SET_O + RULE_3;
else
this.directlyEncoded = SET_D + RULE_3;
}

boolean canEncodeDirectly(char ch) {
return directlyEncoded.indexOf(ch) >= 0;
}

byte shift() {
return '+';
}

byte unshift() {
return '-';
}
}
38 changes: 38 additions & 0 deletions src/macaca/unicode/ime/charsetUtils/UTF7StyleCharset.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package macaca.unicode.ime.charsetUtils;

import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.Arrays;
import java.util.List;

abstract class UTF7StyleCharset extends Charset {
private static final List CONTAINED = Arrays.asList(new String[] { "US-ASCII", "ISO-8859-1", "UTF-8", "UTF-16", "UTF-16LE", "UTF-16BE" });
final boolean strict;
Base64Util base64;

protected UTF7StyleCharset(String canonicalName, String[] aliases, String alphabet,
boolean strict) {
super(canonicalName, aliases);
this.base64 = new Base64Util(alphabet);
this.strict = strict;
}

public boolean contains(final Charset cs) {
return CONTAINED.contains(cs.name());
}

public CharsetDecoder newDecoder() {
return new UTF7StyleCharsetDecoder(this, base64, strict);
}

public CharsetEncoder newEncoder() {
return new UTF7StyleCharsetEncoder(this, base64, strict);
}

abstract boolean canEncodeDirectly(char ch);

abstract byte shift();

abstract byte unshift();
}
120 changes: 120 additions & 0 deletions src/macaca/unicode/ime/charsetUtils/UTF7StyleCharsetDecoder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package macaca.unicode.ime.charsetUtils;

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;

class UTF7StyleCharsetDecoder extends CharsetDecoder {
private final Base64Util base64;
private final byte shift;
private final byte unshift;
private final boolean strict;
private boolean base64mode;
private int bitsRead;
private int tempChar;
private boolean justShifted;
private boolean justUnshifted;

UTF7StyleCharsetDecoder(UTF7StyleCharset cs, Base64Util base64, boolean strict) {
super(cs, 0.6f, 1.0f);
this.base64 = base64;
this.strict = strict;
this.shift = cs.shift();
this.unshift = cs.unshift();
}

protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
while (in.hasRemaining()) {
byte b = in.get();
if (base64mode) {
if (b == unshift) {
if (base64bitsWaiting())
return malformed(in);
if (justShifted) {
if (!out.hasRemaining())
return overflow(in);
out.put((char) shift);
} else
justUnshifted = true;
setUnshifted();
} else {
if (!out.hasRemaining())
return overflow(in);
CoderResult result = handleBase64(in, out, b);
if (result != null)
return result;
}
justShifted = false;
} else {
if (b == shift) {
base64mode = true;
if (justUnshifted && strict)
return malformed(in);
justShifted = true;
continue;
}
if (!out.hasRemaining())
return overflow(in);
out.put((char) b);
justUnshifted = false;
}
}
return CoderResult.UNDERFLOW;
}

private CoderResult overflow(ByteBuffer in) {
in.position(in.position() - 1);
return CoderResult.OVERFLOW;
}

private CoderResult handleBase64(ByteBuffer in, CharBuffer out, byte lastRead) {
CoderResult result = null;
int sextet = base64.getSextet(lastRead);
if (sextet >= 0) {
bitsRead += 6;
if (bitsRead < 16) {
tempChar += sextet << (16 - bitsRead);
} else {
bitsRead -= 16;
tempChar += sextet >> (bitsRead);
out.put((char) tempChar);
tempChar = (sextet << (16 - bitsRead)) & 0xFFFF;
}
} else {
if (strict)
return malformed(in);
out.put((char) lastRead);
if (base64bitsWaiting())
result = malformed(in);
setUnshifted();
}
return result;
}

protected CoderResult implFlush(CharBuffer out) {
if ((base64mode && strict) || base64bitsWaiting())
return CoderResult.malformedForLength(1);
return CoderResult.UNDERFLOW;
}

protected void implReset() {
setUnshifted();
justUnshifted = false;
}

private CoderResult malformed(ByteBuffer in) {
in.position(in.position() - 1);
return CoderResult.malformedForLength(1);
}

private boolean base64bitsWaiting() {
return tempChar != 0 || bitsRead >= 6;
}

private void setUnshifted() {
base64mode = false;
bitsRead = 0;
tempChar = 0;
}
}
Loading