diff --git a/README.txt b/README.txt index 2fff1ce..bef8da5 100644 --- a/README.txt +++ b/README.txt @@ -1,9 +1,9 @@ You will need to have Java (JDK or JRE) 1.5 or above to execute this program. -To start the program, just double-click on the MobiMetaEditorV0.15.jar file. +To start the program, just double-click on the MobiMetaEditorV0.16.jar file. If that doesn't work, type this from the command-line: - java -jar MobiMetaEditorV0.15.jar + java -jar MobiMetaEditorV0.16.jar This was written based on the MOBI file format describe in: http://wiki.mobileread.com/wiki/MOBI @@ -13,6 +13,9 @@ This application is licensed under the MIT License (http://www.opensource.org/li ChangeLog +v0.16 +- rewrote the language codes routines + v0.15 - added the ability to add/edit the TTS EXTH record - fixed issues with ConcurrentModificationExceptions thrown @@ -27,7 +30,7 @@ v0.13 - added a Header Info dialog, which details various fields in the PDB header, PalmDOC header, and MOBI header - added in provisions to invoke debug and safe modes from the command line - added in WhisperPrep, which lets users set ASINs and sets the CDEType to EBOK - (to invoke, type "java -cp MobiMetaEditorV0.13.jar cli.WhisperPrep + (to invoke, type "java -cp MobiMetaEditorV0.16.jar cli.WhisperPrep ") v0.12 diff --git a/src/gui/LanguageCodes.java b/src/gui/LanguageCodes.java index 2883f81..4e96dad 100644 --- a/src/gui/LanguageCodes.java +++ b/src/gui/LanguageCodes.java @@ -1,74 +1,76 @@ package gui; +import java.io.IOException; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Properties; +import java.util.Vector; + public class LanguageCodes { - // these codes are taken from: - // http://www.autoitscript.com/autoit3/docs/appendix/OSLangCodes.htm - // - public final static int[] code = - { 0, 1078, 1052, 1025, 2049, 3073, 4097, 5121, 6145, 7169, 8193, 9217, - 10241, 11265, 12289, 13313, 14337, 15361, 16385, 1067, 1068, 2092, - 1069, 1059, 1026, 1027, 4, 1028, 2052, 3076, 4100, 5124, 1050, 1029, - 1030, 19, 1043, 2067, 9, 1033, 2057, 3081, 4105, 5129, 6153, 7177, - 8201, 9225, 10249, 11273, 12297, 13321, 1061, 1080, 1073, 1035, 12, - 1036, 2060, 3084, 4108, 5132, 6156, 1079, 7, 1031, 2055, 3079, 4103, - 5127, 1032, 1037, 1081, 1038, 1039, 1057, 16, 1040, 2064, 1041, 1087, - 1111, 1042, 1062, 1063, 1071, 1086, 2110, 1102, 1044, 2068, 1045, 22, - 1046, 2070, 1048, 1049, 1103, 2074, 3098, 1051, 1060, 10, 1034, 2058, - 3082, 4106, 5130, 6154, 7178, 8202, 9226, 10250, 11274, 12298, - 13322, 14346, 15370, 16394, 17418, 18442, 19466, 20490, 1089, 29, 1053, - 2077, 1097, 1092, 1054, 1055, 1058, 1056, 1091, 2115, 1066 }; - - public final static String[] description = - { "Unspecified", "Afrikaans", "Albanian", "Arabic - Saudi Arabia", - "Arabic - Iraq", "Arabic - Egypt", "Arabic - Libya", - "Arabic - Algeria", "Arabic - Morocco", "Arabic - Tunisia", - "Arabic - Oman", "Arabic - Yemen", "Arabic - Syria", - "Arabic - Jordan", "Arabic - Lebanon", "Arabic - Kuwait", - "Arabic - UAE", "Arabic - Bahrain", "Arabic - Qatar", "Armenian", - "Azeri - Latin", "Azeri - Cyrillic", "Basque", "Belarusian", - "Bulgarian", "Catalan", "Chinese", "Chinese - Taiwan", "Chinese - PRC", - "Chinese - Hong Kong", "Chinese - Singapore", "Chinese - Macau", - "Croatian", "Czech", "Danish", "Dutch", "Dutch - Standard", - "Dutch - Belgian", "English", "English - United States", - "English Ð United Kingdom", "English - Australian", - "English - Canadian", "English - New Zealand", "English - Irish", - "English - South Africa", "English - Jamaica", - "English - Caribbean", "English - Belize", "English - Trinidad", - "English - Zimbabwe", "English - Philippines", "Estonian", - "Faeroese", "Farsi", "Finnish", "French", "French - Standard", - "French - Belgian", "French - Canadian", "French - Swiss", - "French - Luxembourg", "French - Monaco", "Georgian", "German", - "German - Standard", "German - Swiss", "German - Austrian", - "German - Luxembourg", "German - Liechtenstei", "Greek", "Hebrew", - "Hindi", "Hungarian", "Icelandic", "Indonesian", "Italian", - "Italian - Standard", "Italian - Swiss", "Japanese", "Kazakh", - "Konkani", "Korean", "Latvian", "Lithuanian", "Macedonian", - "Malay - Malaysia", "Malay - Brunei Darussalam", "Marathi", - "Norwegian - Bokmal", "Norwegian - Nynorsk", "Polish", "Portugese", - "Portuguese - Brazilian", "Portuguese - Standard", "Romanian", - "Russian", "Sanskrit", "Serbian - Latin", "Serbian - Cyrillic", - "Slovak", "Slovenian", "Spanish", "Spanish - Traditional Sort", - "Spanish - Mexican", "Spanish - Modern Sort", - "Spanish - Guatemala", "Spanish - Costa Rica", "Spanish - Panama", - "Spanish - Dominican Republic", "Spanish - Venezuela", - "Spanish - Colombia", "Spanish - Peru", "Spanish - Argentina", - "Spanish - Ecuador", "Spanish - Chile", "Spanish - Uruguay", - "Spanish - Paraguay", "Spanish - Bolivia", "Spanish - El Salvador", - "Spanish - Honduras", "Spanish - Nicaragua", - "Spanish - Puerto Rico", "Swahili", "Swedish", "Swedish - Finland", - "Tamil", "Tatar", "Thai", "Turkish", "Ukrainian", "Urdu", - "Uzbek - Latin", "Uzbek - Cyrillic", "Vietnamese" }; - + public final static String PROP_FILENAME = "languagecodes.properties"; + + private HashMap codeHash; + private HashMap descriptionHash; + private String[] descriptions; - public static int codeToIndex(int key) + public LanguageCodes() { - int len = code.length; - for (int i = 0; i < len; i++) + Properties props = new Properties(); + try + { + props.load(ClassLoader.getSystemClassLoader().getResourceAsStream(PROP_FILENAME)); + } + catch (IOException e) { - if (code[i] == key) return i; + // we really have to find a better way to handle this } - return -1; + codeHash = new HashMap(); + descriptionHash = new HashMap(); + Vector vec = new Vector(); + Enumeration keys = props.keys(); + while (keys.hasMoreElements()) + { + String key = (String)keys.nextElement(); + String description = props.getProperty(key) + " (" + key + ")"; + + try + { + Integer code = Integer.valueOf(key); + codeHash.put(code, description); + descriptionHash.put(description, code); + vec.add(description); + } + catch (NumberFormatException e) + { + } + Collections.sort(vec); + descriptions = vec.toArray(new String[vec.size()]); + } + } + + public String[] getDescriptions() + { + return descriptions; + } + + public boolean codeExists(int code) + { + return (codeToDescription(code) != null); + } + + public int descriptionToCode(String description) + { + Integer code = descriptionHash.get(description); + if (code == null) return -1; + + return code.intValue(); + } + + public String codeToDescription(int code) + { + return codeHash.get (Integer.valueOf(code)); } } diff --git a/src/gui/LanguageDialog.java b/src/gui/LanguageDialog.java index d6c2f5b..085def7 100644 --- a/src/gui/LanguageDialog.java +++ b/src/gui/LanguageDialog.java @@ -47,6 +47,7 @@ public class LanguageDialog extends JDialog implements ActionListener private boolean dictOutputExists; private LanguageModel model; + private LanguageCodes langCodes; /** * Create the dialog. @@ -58,48 +59,17 @@ public class LanguageDialog extends JDialog implements ActionListener locale = model.getLocale(); dictInput = model.getDictInput(); dictOutput = model.getDictOutput(); - localeExists = (LanguageCodes.codeToIndex(locale) != -1); - dictInputExists = (LanguageCodes.codeToIndex(dictInput) != -1); - dictOutputExists = (LanguageCodes.codeToIndex(dictOutput) != -1); - - String[] localeChoices; - String[] dictInputChoices; - String[] dictOutputChoices; + langCodes = new LanguageCodes(); + localeExists = langCodes.codeExists(locale); + dictInputExists = langCodes.codeExists(dictInput); + dictOutputExists = langCodes.codeExists(dictOutput); // assemble choices for combo boxes // - if (localeExists) - localeChoices = LanguageCodes.description; - else - { - localeChoices = new String[LanguageCodes.description.length + 1]; - System.arraycopy(LanguageCodes.description, 0, localeChoices, 0, - LanguageCodes.description.length); - localeChoices[localeChoices.length - 1] = "Unknown (" + locale - + ")"; - } + String[] localeChoices = buildChoices(locale); + String[] dictInputChoices = buildChoices(dictInput); + String[] dictOutputChoices = buildChoices(dictOutput); - if (dictInputExists) - dictInputChoices = LanguageCodes.description; - else - { - dictInputChoices = new String[LanguageCodes.description.length + 1]; - System.arraycopy(LanguageCodes.description, 0, dictInputChoices, 0, - LanguageCodes.description.length); - dictInputChoices[dictInputChoices.length - 1] = "Unknown (" - + dictInput + ")"; - } - - if (dictOutputExists) - dictOutputChoices = LanguageCodes.description; - else - { - dictOutputChoices = new String[LanguageCodes.description.length + 1]; - System.arraycopy(LanguageCodes.description, 0, dictOutputChoices, - 0, LanguageCodes.description.length); - dictOutputChoices[dictOutputChoices.length - 1] = "Unknown (" - + dictOutput + ")"; - } setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); setBounds(100, 100, 450, 300); @@ -149,8 +119,11 @@ public class LanguageDialog extends JDialog implements ActionListener } { cbLanguage = new JComboBox(localeChoices); - cbLanguage.setSelectedIndex(localeExists ? LanguageCodes - .codeToIndex(locale) : (localeChoices.length - 1)); + if (localeExists) + cbLanguage.setSelectedItem(langCodes.codeToDescription(locale)); + else + cbLanguage.setSelectedIndex(localeChoices.length - 1); + GridBagConstraints gbc_cbLanguage = new GridBagConstraints(); gbc_cbLanguage.insets = new Insets(0, 0, 5, 0); gbc_cbLanguage.fill = GridBagConstraints.HORIZONTAL; @@ -172,10 +145,11 @@ public class LanguageDialog extends JDialog implements ActionListener } { cbDictInput = new JComboBox(dictInputChoices); - cbDictInput - .setSelectedIndex(dictInputExists ? LanguageCodes - .codeToIndex(dictInput) - : (dictInputChoices.length - 1)); + if (dictInputExists) + cbDictInput.setSelectedItem(langCodes.codeToDescription(dictInput)); + else + cbDictInput.setSelectedIndex(dictInputChoices.length - 1); + GridBagConstraints gbc_cbDictInput = new GridBagConstraints(); gbc_cbDictInput.insets = new Insets(0, 0, 5, 0); gbc_cbDictInput.fill = GridBagConstraints.HORIZONTAL; @@ -198,9 +172,11 @@ public class LanguageDialog extends JDialog implements ActionListener } { cbDictOutput = new JComboBox(dictOutputChoices); - cbDictOutput.setSelectedIndex(dictOutputExists ? LanguageCodes - .codeToIndex(dictOutput) - : (dictOutputChoices.length - 1)); + if (dictOutputExists) + cbDictOutput.setSelectedItem(langCodes.codeToDescription(dictOutput)); + else + cbDictOutput.setSelectedIndex(dictOutputChoices.length - 1); + GridBagConstraints gbc_cbDictOutput = new GridBagConstraints(); gbc_cbDictOutput.fill = GridBagConstraints.HORIZONTAL; gbc_cbDictOutput.gridx = 1; @@ -232,17 +208,16 @@ public class LanguageDialog extends JDialog implements ActionListener if (source == okButton) { - int localeIndex = cbLanguage.getSelectedIndex(); - if ((localeIndex >= 0) && (localeIndex < LanguageCodes.code.length)) - locale = LanguageCodes.code[localeIndex]; + int mappedCode; + + mappedCode = langCodes.descriptionToCode((String)cbLanguage.getSelectedItem()); + if (mappedCode != -1) locale = mappedCode; - int dictInputIndex = cbDictInput.getSelectedIndex(); - if ((dictInputIndex >= 0) && (dictInputIndex < LanguageCodes.code.length)) - dictInput = LanguageCodes.code[dictInputIndex]; + mappedCode = langCodes.descriptionToCode((String)cbDictInput.getSelectedItem()); + if (mappedCode != -1) dictInput = mappedCode; - int dictOutputIndex = cbDictOutput.getSelectedIndex(); - if ((dictOutputIndex >= 0) && (dictOutputIndex < LanguageCodes.code.length)) - dictOutput = LanguageCodes.code[dictOutputIndex]; + mappedCode = langCodes.descriptionToCode((String)cbDictOutput.getSelectedItem()); + if (mappedCode != -1) dictOutput = mappedCode; model.setLanguages(locale, dictInput, dictOutput); @@ -255,4 +230,20 @@ public class LanguageDialog extends JDialog implements ActionListener dispose(); } } + + private String[] buildChoices(int code) + { + if (langCodes.codeExists(code)) + return langCodes.getDescriptions(); + else + { + String[] descriptions = langCodes.getDescriptions(); + String[] choices = new String[descriptions.length + 1]; + System.arraycopy(descriptions, 0, choices, 0, + descriptions.length); + choices[choices.length - 1] = "Unknown (" + code + + ")"; + return choices; + } + } } diff --git a/src/languagecodes.properties b/src/languagecodes.properties new file mode 100644 index 0000000..ce60419 --- /dev/null +++ b/src/languagecodes.properties @@ -0,0 +1,337 @@ +# Many thanks to ixtab on mobileread forums for the complete list! +# + +1=ar +2=bg +3=ca +4=zh +5=cz +6=da +7=de +8=el +9=en +10=es +11=fi +12=fr +13=he +14=hu +15=is +16=it +17=ja +18=ko +19=nl +20=nn +21=pl +22=pt +24=ro +25=ru +26=hr +27=sk +28=sq +29=sv +30=th +31=tr +32=ur +33=in +34=uk +35=be +36=sl +37=et +38=lv +39=lt +40=tg +41=fa +42=vi +43=hy +44=az +45=eu +46=wen +47=mk +49=ts +50=tn +51=ve +52=xh +53=zu +54=af +55=ka +56=fo +57=hi +58=mt +59=se +60=sco +61=yi +62=ms +63=kk +64=ky +65=sw +66=tk +67=uz +68=tt +69=bn +70=pa +71=gu +72=or +73=ta +74=te +75=kn +76=ml +77=as +78=mr +79=sa +80=mn +81=bo +82=cy +83=km +84=lo +85=bu +86=gl +87=knn +88=mni +89=sd +90=syr +91=si +92=chr +93=iu +94=am +95=tjo +96=ks +97=ne +98=fy +99=ps +100=fil +101=dv +102=bin +103=ff +104=ha +105=ibb +106=yo +107=qu +108=nso +112=ig +113=kr +114=om +115=ti +116=gn +117=haw +118=la +119=so +120=ii +128=ug +129=mi +1025=ar +1026=bg +1027=ca +1028=zh-tw +1029=cz +1030=da +1031=de +1032=el +1033=en +1034=es-es +1035=fi +1036=fr +1037=he +1038=hu +1039=is +1040=it-it +1041=ja +1042=ko +1043=nl-nl +1044=nb +1045=pl +1046=pt +1050=hr +1051=sk +1052=sq-al +1053=sv +1054=th +1055=tr +1056=ur +1057=in +1058=uk +1059=be +1060=sl +1061=et +1062=lv +1063=lt +1064=tg +1065=fa +1066=vi +1067=hy-am +1068=az-latn +1069=eu +1070=wen +1071=mk +1073=ts +1074=tn +1075=ve +1076=xh +1077=zu +1078=af-za +1079=ka +1080=fo +1081=hi +1082=mt +1083=se +1084=sco +1085=yi +1086=ms-my +1087=kk +1088=ky-cyrl +1089=sw +1090=tk +1091=uz-latn +1092=tt +1093=bn-in +1094=pa +1095=gu +1096=or +1097=ta +1098=te +1099=kn +1100=ml +1101=as +1102=mr +1103=sa +1104=mn-cyrl +1105=bo +1106=cy +1107=km +1108=lo +1109=bu +1110=gl +1111=knn +1112=mni +1113=sd-in +1114=syr +1115=si-lk +1116=chr-us +1117=iu +1118=am-et +1119=tjo-arab +1120=ks-arab +1121=ne +1122=fy-nl +1123=ps +1124=fil +1125=dv +1126=bin +1127=ff +1128=ha +1129=ibb +1130=yo +1131=qu-bo +1132=nso +1136=ig +1137=kr +1138=om +1139=ti-et +1140=gn +1141=haw +1142=la +1143=so +1144=ii +1152=ug-cn +1153=mi +2049=ar-iq +2052=zh +2055=de-ch +2057=en-gb +2058=es-mx +2060=fr-be +2064=it-ch +2067=nl-be +2068=nn +2070=pt-pt +2072=ro +2073=ru +2074=sr-latn +2077=sv-fi +2080=ur-in +2092=az-cyrl +2108=ga-ie +2110=ms-bn +2115=uz-cyrl +2117=bn-bd +2118=pa-pk +2128=mn-mong +2129=bo-bt +2137=sd-pk +2143=tjo-latn +2144=ks +2145=ne-in +2155=qu-ec +2163=ti-er +3073=ar-eg +3076=zh-hk +3079=de-at +3081=en-au +3084=fr-ca +3098=sr-cyrl +3179=qu-pe +4097=ar-ly +4100=zh-sg +4103=de-lu +4105=en-ca +4106=es-gt +4108=fr-ch +4122=hr-bs +5121=ar-dz +5124=zh-mo +5127=de-li +5129=en-nz +5130=es-cr +5132=fr-lu +5146=bs-bs +6145=ar-ma +6153=en-ie +6154=es-pa +6156=fr-mc +7169=ar-tn +7177=en-za +7178=es-do +7180=fr-419 +8193=ar-om +8201=en-jm +8202=es-ve +8204=fr-re +9217=ar-ye +9225=en-419 +9226=es-co +9228=fr-cd +10241=ar-sy +10249=en-bz +10250=es-pe +10252=fr-sn +11265=ar-jo +11273=en-tt +11274=es-ar +11276=fr-cm +12289=ar-lb +12297=en-zw +12298=es-ec +12300=fr-ci +13313=ar-kw +13321=en-ph +13322=es-cl +13324=fr-ml +14337=ar-ae +14345=en-id +14346=es-uy +14348=fr-ma +15361=ar-bh +15369=en-hk +15370=es-py +15372=fr-ht +16385=ar-qa +16393=en-in +16394=es-bo +17417=en-my +17418=es-sv +18441=en-sg +18442=es-hn +19466=es-ni +20490=es-pr +21514=es-us +22538=es-419 +58380=fr-015