<classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="lib" path="jars/icu4j-4_2_1-src/icu4j.jar"/>
- <classpathentry combineaccessrules="false" kind="src" path="/Util"/>
+ <classpathentry combineaccessrules="false" exported="true" kind="src" path="/Util"/>
<classpathentry kind="output" path="bin"/>
</classpath>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hughes.android.dictionary"
- android:versionCode="1"
- android:versionName="1.0">
+ android:versionCode="8"
+ android:versionName="1.8">
+
+ <uses-sdk android:minSdkVersion="4" />
+
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application android:icon="@drawable/icon" android:label="@string/app_name">
</intent-filter>
</activity>
+ <activity android:name="AboutActivity"/>
+ <activity android:name="PreferenceActivity"/>
+ <activity android:name="DownloadActivity"/>
+ <activity android:name="NoDictionaryActivity"/>
+
</application>
</manifest>
\ No newline at end of file
# Indicates whether an apk should be generated for each density.
split.density=false
# Project target.
-target=android-4
+target=android-3
<string name="failedAddingToWordList">Fehler bei Wortliste hinzufugen: %s</string>
<!-- About. -->
- <string name="thadHughes">Thad Hughes</string>
<string name="contactMe">Wenn QuickDic dir gefällt, würde ich gern von dir hören. Bitte schicke Bemerkungen, Aufforderungen, oder Programmfehler an:</string>
- <string name="myEmail">thad.hughes+quickdic@gmail.com</string>
<string name="currentDictInfo">Wörterbuch Info:</string>
<string name="noDictLoaded">Kein Wörterbuch geöffnet.</string>
<string name="aboutText"><![CDATA[%s\n
<string name="wordListFileKey">wordListFile</string>
<string name="wordListFileTitle">Wortliste Datei</string>
<string name="wordListFileSummary">Die Datei, in der neue Worte hinzugefügt werden.</string>
- <string name="wordListFileDefault">/sdcard/wordList.txt</string>
+ <string name="wordListFileDefault">/sdcard/quickdic/wordList.txt</string>
<string name="saveOnlyFirstSubentryKey">saveOnlyFirstSubentry</string>
<string name="saveOnlyFirstSubentryTitle">Save only first sub-entry</string>
<string name="dictFileKey">dictFile</string>
<string name="dictFileTitle">Wörterbuch Datei</string>
<string name="dictFileSummary">Die Datei, die das Wörterbuch enthält (und worein das Wörterbuch heruntergeladen wird).</string>
- <string name="dictFileDefault">/sdcard/de-en.dict</string>
+ <string name="dictFileDefault">/sdcard/quickdic/de-en.dict</string>
<string name="dictFetchUrlKey">dictFetchUrl</string>
<string name="dictFetchUrlTitle">Wörterbuch URL</string>
<string name="dictFetchUrlSummary">Das URL, wovon das Wörterbuch heruntergeladen wird.</string>
- <string name="dictFetchUrlDefault">http://www.stanford.edu/~egirard/dict/de-en.dict</string>
+ <string name="dictFetchUrlDefault">http://www.stanford.edu/~egirard/dict/de-en_2.0.dict</string>
</resources>
<string name="failedAddingToWordList">Failure adding to word list: %s</string>
<!-- About. -->
- <string name="titleWithVersion">QuickDic 1.8</string>
+ <string name="titleWithVersion">QuickDic 2.0</string>
<string name="thadHughes">Thad Hughes</string>
<string name="contactMe">If you\'re using QuickDic, I\'d love to hear from you. Please send comments, suggestions, bug reports, or just a quick hello to:</string>
- <string name="myEmail">thad.hughes+quickdic@gmail.com</string>
+ <string name="myEmail">thad.hughes\+quickdic@gmail.com</string>
<string name="currentDictInfo">Current dictionary info:</string>
<string name="noDictLoaded">No dictionary loaded.</string>
<string name="aboutText"><![CDATA[%s\n
\r
public final class Dictionary implements RAFSerializable<Dictionary> {\r
\r
- private static final String VERSION_CODE = "DictionaryVersion=1.5";\r
+ private static final String VERSION_CODE = "DictionaryVersion=2.0";\r
\r
- static final RAFSerializer<Entry> ENTRY_SERIALIZER = new RAFSerializableSerializer<Entry>(\r
- Entry.RAF_FACTORY);\r
+ static final RAFSerializer<SimpleEntry> ENTRY_SERIALIZER = new RAFSerializableSerializer<SimpleEntry>(\r
+ SimpleEntry.RAF_FACTORY);\r
static final RAFSerializer<Row> ROW_SERIALIZER = new RAFSerializableSerializer<Row>(\r
Row.RAF_FACTORY);\r
static final RAFSerializer<IndexEntry> INDEX_ENTRY_SERIALIZER = new RAFSerializableSerializer<IndexEntry>(\r
IndexEntry.RAF_FACTORY);\r
\r
final String dictionaryInfo;\r
+ final List<String> sources;\r
final List<Entry> entries;\r
final LanguageData[] languageDatas = new LanguageData[2];\r
\r
public Dictionary(final String dictionaryInfo, final Language language0, final Language language1) {\r
this.dictionaryInfo = dictionaryInfo;\r
- languageDatas[0] = new LanguageData(this, language0, Entry.LANG1);\r
- languageDatas[1] = new LanguageData(this, language1, Entry.LANG2);\r
+ sources = new ArrayList<String>();\r
+ languageDatas[0] = new LanguageData(this, language0, SimpleEntry.LANG1);\r
+ languageDatas[1] = new LanguageData(this, language1, SimpleEntry.LANG2);\r
entries = new ArrayList<Entry>();\r
}\r
\r
public Dictionary(final RandomAccessFile raf) throws IOException {\r
dictionaryInfo = raf.readUTF();\r
+ sources = new ArrayList<String>(FileList.create(raf, RAFSerializer.STRING, raf.getFilePointer()));\r
entries = CachingList.create(FileList.create(raf, ENTRY_SERIALIZER, raf\r
.getFilePointer()), 10000);\r
- languageDatas[0] = new LanguageData(this, raf, Entry.LANG1);\r
- languageDatas[1] = new LanguageData(this, raf, Entry.LANG2);\r
- if (!VERSION_CODE.equals(raf.readUTF())) {\r
- throw new IOException("Invalid dictionary version, expected: " + VERSION_CODE);\r
+ languageDatas[0] = new LanguageData(this, raf, SimpleEntry.LANG1);\r
+ languageDatas[1] = new LanguageData(this, raf, SimpleEntry.LANG2);\r
+ final String version = raf.readUTF();\r
+ if (!VERSION_CODE.equals(version)) {\r
+ throw new IOException("Invalid dictionary version, found " + version + ", expected: " + VERSION_CODE);\r
}\r
}\r
\r
public void write(RandomAccessFile raf) throws IOException {\r
raf.writeUTF(dictionaryInfo);\r
+ FileList.write(raf, sources, RAFSerializer.STRING);\r
FileList.write(raf, entries, ENTRY_SERIALIZER);\r
languageDatas[0].write(raf);\r
languageDatas[1].write(raf);\r
throw new Exception(e);
}
- final byte lang = prefs.getInt(PREF_DICT_ACTIVE_LANG, Entry.LANG1) == Entry.LANG1 ? Entry.LANG1
- : Entry.LANG2;
+ final byte lang = prefs.getInt(PREF_DICT_ACTIVE_LANG, SimpleEntry.LANG1) == SimpleEntry.LANG1 ? SimpleEntry.LANG1
+ : SimpleEntry.LANG2;
languageList = new LanguageListAdapter(dictionary.languageDatas[lang]);
setListAdapter(languageList);
@Override
public boolean onPrepareOptionsMenu(final Menu menu) {
switchLanguageMenuItem.setTitle(getString(R.string.switchToLanguage,
- dictionary.languageDatas[Entry
+ dictionary.languageDatas[SimpleEntry
.otherLang(languageList.languageData.lang)].language.symbol));
return super.onPrepareOptionsMenu(menu);
}
// Entry row(s).
final TableLayout result = new TableLayout(parent.getContext());
- final Entry entry = dictionary.entries.get(row.getIndex());
+ final SimpleEntry entry = dictionary.entries.get(row.getIndex());
final int rowCount = entry.getRowCount();
for (int r = 0; r < rowCount; ++r) {
final TableRow tableRow = new TableRow(result.getContext());
if (r > 0) {
final TextView spacer = new TextView(tableRow.getContext());
- spacer.setText(r == 0 ? "\95 " : " \95 ");
+ spacer.setText(r == 0 ? "� " : " � ");
tableRow.addView(spacer);
}
tableRow.addView(column1, layoutParams);
if (r > 0) {
final TextView spacer = new TextView(tableRow.getContext());
- spacer.setText(r == 0 ? "\95 " : " \95 ");
+ spacer.setText(r == 0 ? "� " : " � ");
tableRow.addView(spacer);
}
tableRow.addView(column2, layoutParams);
}
column2.setText(
- entry.getAllText(Entry.otherLang(languageData.lang))[r],
+ entry.getAllText(SimpleEntry.otherLang(languageData.lang))[r],
TextView.BufferType.NORMAL);
result.addView(tableRow);
public void resetDictionary() throws Exception {\r
final DictionaryActivity dict = getActivity();\r
\r
- if (dict.languageList.languageData.language == Language.EN) {\r
+ if (dict.languageList.languageData.language == Language.en) {\r
postAndWait(switchLangRunnable());\r
}\r
- assertEquals(Language.DE, dict.languageList.languageData.language);\r
+ assertEquals(Language.de, dict.languageList.languageData.language);\r
\r
postAndWait(new NotifyRunnable() {\r
protected void run2() {\r
final NotifyRunnable switchLang = switchLangRunnable();\r
\r
postAndWait(switchLang);\r
- assertEquals(Language.EN, dict.languageList.languageData.language);\r
+ assertEquals(Language.en, dict.languageList.languageData.language);\r
assertEquals("EN", dict.langButton.getText().toString());\r
\r
postAndWait(switchLang);\r
- assertEquals(Language.DE, dict.languageList.languageData.language);\r
+ assertEquals(Language.de, dict.languageList.languageData.language);\r
assertEquals("DE", dict.langButton.getText().toString());\r
\r
dict.finish();\r
-package com.hughes.android.dictionary;\r
-\r
-import java.io.IOException;\r
-import java.io.RandomAccessFile;\r
-import java.util.ArrayList;\r
-import java.util.Arrays;\r
-import java.util.LinkedHashMap;\r
-import java.util.LinkedHashSet;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-import java.util.regex.Matcher;\r
-import java.util.regex.Pattern;\r
-\r
-import com.hughes.util.raf.RAFFactory;\r
-import com.hughes.util.raf.RAFSerializable;\r
-\r
-public final class Entry implements RAFSerializable<Entry> {\r
-\r
- static final byte LANG1 = 0;\r
- static final byte LANG2 = 1;\r
-\r
- static final Pattern lineSplitPattern = Pattern.compile("\\s::\\s");\r
- static final Pattern sublineSplitPattern = Pattern.compile("\\s\\|\\s");\r
-\r
- final String[] lang1;\r
- final String[] lang2;\r
- \r
-// public Entry(final String lang1, final String lang2) {\r
-// this.lang1 = new String[] {lang1};\r
-// this.lang2 = new String[] {lang2};\r
-// }\r
-\r
- Entry(final String[] lang1, final String[] lang2) {\r
- this.lang1 = lang1;\r
- this.lang2 = lang2;\r
- }\r
-\r
- public static final RAFFactory<Entry> RAF_FACTORY = new RAFFactory<Entry>() {\r
- public Entry create(RandomAccessFile raf) throws IOException {\r
- final int rows = raf.readByte();\r
- final String[] lang1 = new String[rows];\r
- final String[] lang2 = new String[rows];\r
- for (int i = 0; i < lang1.length; ++i) {\r
- lang1[i] = raf.readUTF();\r
- lang2[i] = raf.readUTF();\r
- }\r
- return new Entry(lang1, lang2);\r
- }};\r
- public void write(RandomAccessFile raf) throws IOException {\r
- assert lang1.length == (byte) lang1.length;\r
- raf.writeByte(lang1.length);\r
- for (int i = 0; i < lang1.length; ++i) {\r
- raf.writeUTF(lang1[i]);\r
- raf.writeUTF(lang2[i]);\r
- }\r
- }\r
-\r
- @Override\r
- public boolean equals(Object o) {\r
- if (!(o instanceof Entry)) {\r
- return false;\r
- }\r
- final Entry that = (Entry) o;\r
- return Arrays.deepEquals(this.lang1, that.lang1) && Arrays.deepEquals(this.lang2, that.lang2); \r
- }\r
-\r
- @Override\r
- public int hashCode() {\r
- return Arrays.deepHashCode(lang1) + Arrays.deepHashCode(lang2);\r
- }\r
-\r
- @Override\r
- public String toString() {\r
- return getRawText(false);\r
- }\r
-\r
- public int getRowCount() {\r
- assert lang1.length == lang2.length;\r
- return lang1.length;\r
- }\r
-\r
- String[] getAllText(final byte lang) {\r
- if (lang == LANG1) {\r
- return lang1;\r
- }\r
- assert lang == LANG2;\r
- return lang2;\r
- }\r
- \r
- String getRawText(boolean onlyFirstSubentry) {\r
- final StringBuilder result = new StringBuilder();\r
- for (int i = 0; i < (onlyFirstSubentry ? 1 : lang1.length); ++i) {\r
- result.append(i == 0 ? "" : " | ").append(lang1[i]);\r
- }\r
- result.append("\t");\r
- for (int i = 0; i < (onlyFirstSubentry ? 1 : lang2.length); ++i) {\r
- result.append(i == 0 ? "" : " | ").append(lang2[i]);\r
- }\r
- return result.toString();\r
- }\r
- \r
- static byte otherLang(final byte lang) {\r
- assert lang == LANG1 || lang == LANG2;\r
- return lang == LANG1 ? LANG2 : LANG1;\r
- }\r
- \r
-/*\r
-Lu Letter, Uppercase\r
-Ll Letter, Lowercase\r
-Lt Letter, Titlecase\r
-Lm Letter, Modifier\r
-Lo Letter, Other\r
-Mn Mark, Nonspacing\r
-Mc Mark, Spacing Combining\r
-Me Mark, Enclosing\r
-Nd Number, Decimal Digit\r
-Nl Number, Letter\r
-No Number, Other\r
-Pc Punctuation, Connector\r
-Pd Punctuation, Dash\r
-Ps Punctuation, Open\r
-Pe Punctuation, Close\r
-Pi Punctuation, Initial quote (may behave like Ps or Pe depending on usage)\r
-Pf Punctuation, Final quote (may behave like Ps or Pe depending on usage)\r
-Po Punctuation, Other\r
-Sm Symbol, Math\r
-Sc Symbol, Currency\r
-Sk Symbol, Modifier\r
-So Symbol, Other\r
-Zs Separator, Space\r
-Zl Separator, Line\r
-Zp Separator, Paragraph\r
-*/\r
-\r
- static Pattern htmlDecimalCode = Pattern.compile("&#([0-9]+);");\r
- static Pattern htmlCode = Pattern.compile("&#[^;]+;");\r
- \r
- static Entry parseFromLine(String line, final boolean hasMultipleSubentries) {\r
- \r
- line = line.replaceAll("<", "<");\r
- line = line.replaceAll(">", ">");\r
- Matcher matcher;\r
- while ((matcher = htmlDecimalCode.matcher(line)).find()) {\r
- final int intVal = Integer.parseInt(matcher.group(1));\r
- final String charCode = "" + ((char) intVal);\r
- System.out.println("Replacing " + matcher.group() + " with " + charCode);\r
- line = matcher.replaceAll(charCode);\r
- }\r
- if ((matcher = htmlCode.matcher(line)).find()) {\r
- System.err.println("HTML code: " + matcher.group());\r
- }\r
- \r
- final String[] parts = lineSplitPattern.split(line);\r
- if (parts.length != 2) {\r
- System.err.println("Entry:" + "Invalid line: " + line);\r
- return null;\r
- }\r
- if (!hasMultipleSubentries) {\r
- return new Entry(new String[] {parts[0].trim()}, new String[] {parts[1].trim()});\r
- }\r
- \r
- final String[] lang1 = sublineSplitPattern.split(" " + parts[0].trim() + " ");\r
- final String[] lang2 = sublineSplitPattern.split(" " + parts[1].trim() + " ");\r
- if (lang1.length != lang2.length) {\r
- System.err.println("Entry:" + "Invalid subline: " + line);\r
- return null;\r
- }\r
- for (int i = 0; i < lang1.length; ++i) {\r
- lang1[i] = lang1[i].trim();\r
- lang2[i] = lang2[i].trim();\r
- }\r
- return new Entry(lang1, lang2);\r
- }\r
- \r
- static final Map<String, String> bracketToClose = new LinkedHashMap<String, String>();\r
- static {\r
- bracketToClose.put("\"", "\"");\r
- bracketToClose.put(" '", "' ");\r
- }\r
- \r
- // This used to be called WHITESPACE.\r
- static final Pattern NON_TOKEN_CHAR = Pattern.compile("\\s+");\r
- \r
- public Set<String> getIndexableTokens(final byte lang) {\r
- final Set<String> result = new LinkedHashSet<String>();\r
- String text = " ";\r
- for (final String subentry : getAllText(lang)) {\r
- text += subentry + " ";\r
- }\r
-\r
- text = text.replaceAll("fig\\.", " ");\r
- text = text.replaceAll("\\{[^\\}]+}", " ");\r
- text = text.replaceAll("\"-", "-");\r
- text = text.replaceAll("-\"", "-");\r
- text = text.replaceAll("[\"/\\()<>\\[\\],;?!.]", " ");\r
- text = text.replaceAll("[-:] ", " ");\r
- text = text.replaceAll(" [-:]", " ");\r
- \r
- // Now be really conservative about what we allow inside a token:\r
- // See: http://unicode.org/Public/UNIDATA/UCD.html#General_Category_Values\r
- text = text.replaceAll("[^-:\\p{L}\\p{N}\\p{S}]", " ");\r
- result.addAll(Arrays.asList(NON_TOKEN_CHAR.split(text)));\r
-\r
- text = text.replaceAll("[-]", " ");\r
- result.addAll(Arrays.asList(NON_TOKEN_CHAR.split(text)));\r
- \r
- final Set<String> result2 = new LinkedHashSet<String>();\r
- for (final String token : result) {\r
- if (isIndexable(token)) {\r
- result2.add(token);\r
- }\r
- }\r
- return result2;\r
- }\r
-\r
- static boolean isIndexable(final String text) {\r
- // Does it have an alpha-numeric anywhere?\r
- return text.matches(".*\\w.*");\r
- }\r
- \r
- static List<String> getTextInside(final String text, final String start, final String end) {\r
- final List<String> result = new ArrayList<String>();\r
- int startPos = 0;\r
- while ((startPos = text.indexOf(start)) != -1) {\r
- final int endPos = text.indexOf(end, startPos + 1);\r
- result.add(text.substring(startPos + 1, endPos));\r
- startPos = endPos + 1;\r
- }\r
- return result;\r
- }\r
-\r
-}
\ No newline at end of file
+package com.hughes.android.dictionary;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+
+import com.hughes.util.raf.RAFFactory;
+import com.hughes.util.raf.RAFSerializable;
+
+public abstract class Entry implements RAFSerializable<Entry> {
+
+ public static final RAFFactory<Entry> RAF_FACTORY = new RAFFactory<Entry>() {
+ public Entry create(RandomAccessFile raf) throws IOException {
+ final byte type = raf.readByte();
+ switch (type) {
+ case 0:
+ return SimpleEntry.RAF_FACTORY.create(raf);
+ }
+ throw new RuntimeException("Invalid entry type: " + type);
+ }};
+
+
+}
\r
public class Language {\r
\r
+ static final Map<String, Language> symbolToLangauge = new LinkedHashMap<String, Language>();\r
+\r
+ \r
final String symbol;\r
final Locale locale;\r
\r
private Collator findCollator;\r
final Comparator<String> findComparator;\r
\r
- public Language(final String symbol, final Locale locale) {\r
- this.symbol = symbol;\r
+ public Language(final Locale locale) {\r
+ this.symbol = locale.getLanguage();\r
this.locale = locale;\r
\r
this.sortComparator = new Comparator<String>() {\r
return getFindCollator().compare(textNorm(s1), textNorm(s2));\r
}\r
};\r
-\r
+ \r
+ symbolToLangauge.put(symbol.toLowerCase(), this);\r
}\r
\r
public String textNorm(final String s) {\r
\r
@Override\r
public String toString() {\r
+ return locale.toString();\r
+ }\r
+ \r
+ public String getSymbol() {\r
return symbol;\r
}\r
\r
\r
// ----------------------------------------------------------------\r
\r
- public static final Language EN = new Language("EN", Locale.ENGLISH);\r
+ public static final Language en = new Language(Locale.ENGLISH);\r
+ public static final Language fr = new Language(Locale.FRENCH);\r
+ public static final Language it = new Language(Locale.ITALIAN);\r
\r
- public static final Language DE = new Language("DE", Locale.GERMAN) {\r
+ public static final Language de = new Language(Locale.GERMAN) {\r
@Override\r
public String textNorm(String token) {\r
boolean sub = false;\r
if (!sub) {\r
return token;\r
}\r
- token = token.replaceAll("ae", "ä");\r
- token = token.replaceAll("oe", "ö");\r
- token = token.replaceAll("ue", "ü");\r
-\r
- token = token.replaceAll("Ae", "Ä");\r
- token = token.replaceAll("Oe", "Ö");\r
- token = token.replaceAll("Ue", "Ü");\r
- return token;\r
+ token = token.replaceAll("ae", "ä");\r
+ token = token.replaceAll("oe", "ö");\r
+ token = token.replaceAll("ue", "ü");\r
+\r
+ token = token.replaceAll("Ae", "Ä");\r
+ token = token.replaceAll("Oe", "Ö");\r
+ token = token.replaceAll("Ue", "Ü");\r
+ return token; \r
}\r
};\r
-\r
- // ----------------------------------------------------------------\r
-\r
- private static final Map<String, Language> symbolToLangauge = new LinkedHashMap<String, Language>();\r
-\r
+ \r
static {\r
- symbolToLangauge.put(EN.symbol, EN);\r
- symbolToLangauge.put(DE.symbol, DE);\r
+ for (final String lang : Locale.getISOLanguages()) {\r
+ if (lookup(lang) == null) {\r
+ new Language(new Locale(lang));\r
+ }\r
+ }\r
}\r
\r
+ // ----------------------------------------------------------------\r
+\r
static Language lookup(final String symbol) {\r
- return symbolToLangauge.get(symbol);\r
+ return symbolToLangauge.get(symbol.toLowerCase());\r
}\r
\r
}\r