OmegaT のメニューバーにフォルダーツリー参照用のメニューを追加します。
拡張子 .docx の MS Word への関連付け判定を実装
@@ -17,6 +17,8 @@ | ||
17 | 17 | package org.omegat.plugin.foldermenu.filepreview; |
18 | 18 | |
19 | 19 | import java.io.File; |
20 | +import java.io.IOException; | |
21 | +import java.util.HashMap; | |
20 | 22 | import org.omegat.core.CoreEvents; |
21 | 23 | import org.omegat.core.events.IProjectEventListener; |
22 | 24 | import org.omegat.core.events.IProjectEventListener.PROJECT_CHANGE_TYPE; |
@@ -31,22 +33,36 @@ | ||
31 | 33 | |
32 | 34 | public class FilePreview { |
33 | 35 | |
34 | - public static void init() { | |
36 | + private static final HashMap<String, IPreview> previews = new HashMap<String, IPreview>(); | |
37 | + | |
38 | + static { | |
35 | 39 | WordPreview.init(); |
36 | 40 | } |
41 | + | |
42 | + public static void init() { | |
43 | + // force executing static initializer | |
44 | + } | |
37 | 45 | |
38 | - public static boolean open(File file) { | |
39 | - if (available(file)) { | |
40 | - return false; //@@ temporary | |
41 | - } else { | |
46 | + public static boolean open(File file) throws IOException { | |
47 | + // file type or environment is not supported | |
48 | + if (! available(file)) | |
42 | 49 | return false; |
50 | + | |
51 | + // Preview instance is already there? | |
52 | + String key = file.getCanonicalPath(); | |
53 | + if (previews.containsKey(key)) { | |
54 | + previews.get(key).activate(); | |
55 | + return true; | |
43 | 56 | } |
57 | + | |
58 | + IPreview p = new WordPreview(file); | |
59 | + previews.put(key, p); | |
60 | + | |
61 | + return true; | |
44 | 62 | } |
45 | 63 | |
46 | 64 | private static boolean available(File file) { |
47 | - return file.isFile() && | |
48 | - file.getName().toLowerCase().endsWith(".docx") && | |
49 | - WordPreview.isAvailable(); | |
65 | + return WordPreview.isAvailable(file); | |
50 | 66 | } |
51 | 67 | |
52 | 68 | /** hook project change event */ |
@@ -23,7 +23,7 @@ | ||
23 | 23 | public interface IPreview { |
24 | 24 | |
25 | 25 | /** called to execute static initializer */ |
26 | - //public void init(); | |
26 | + public boolean activate(); | |
27 | 27 | |
28 | 28 | //public boolean isAvailable(); |
29 | 29 |
@@ -16,8 +16,12 @@ | ||
16 | 16 | |
17 | 17 | package org.omegat.plugin.foldermenu.filepreview; |
18 | 18 | |
19 | +import java.io.File; | |
19 | 20 | import java.io.IOException; |
20 | 21 | import java.io.InputStream; |
22 | +import java.util.ArrayList; | |
23 | +import java.util.Arrays; | |
24 | +import java.util.List; | |
21 | 25 | import org.omegat.util.Log; |
22 | 26 | import static org.omegat.util.Platform.OsType.WIN32; |
23 | 27 | import static org.omegat.util.Platform.OsType.WIN64; |
@@ -31,6 +35,12 @@ | ||
31 | 35 | |
32 | 36 | private static boolean _isMSWordAvailable; |
33 | 37 | |
38 | + private File originalFile; | |
39 | + | |
40 | + public WordPreview(File originalFile) { | |
41 | + this.originalFile = originalFile; | |
42 | + } | |
43 | + | |
34 | 44 | static { |
35 | 45 | // _isMSWordAvailable |
36 | 46 | switch (getOsType()) { |
@@ -40,6 +50,7 @@ | ||
40 | 50 | @Override |
41 | 51 | public void run() { |
42 | 52 | _isMSWordAvailable = getMSWordAvailable(); |
53 | + Log.log("_isMSWordAvailable = " + _isMSWordAvailable); | |
43 | 54 | } |
44 | 55 | }.start(); |
45 | 56 | break; |
@@ -49,31 +60,99 @@ | ||
49 | 60 | } |
50 | 61 | } |
51 | 62 | |
63 | + public static boolean isAvailable(File file) { | |
64 | + return isAvailable() && | |
65 | + file.isFile() && | |
66 | + file.getName().toLowerCase().endsWith(".docx"); | |
67 | + } | |
68 | + | |
52 | 69 | public static boolean isAvailable() { |
53 | 70 | return _isMSWordAvailable; |
54 | 71 | } |
55 | 72 | |
56 | 73 | public static void init() { |
57 | - // | |
74 | + // force executing static initializer | |
58 | 75 | } |
59 | 76 | |
60 | 77 | private static boolean getMSWordAvailable() { |
78 | + final int RET_OK = 0; | |
61 | 79 | try { |
62 | - ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", "assoc", ".docx"); | |
63 | - pb.redirectErrorStream(true); | |
64 | - Process process; | |
65 | - process = pb.start(); | |
66 | - InputStream is = process.getInputStream(); | |
67 | - int size = 0; | |
68 | - byte[] b = new byte[1024]; | |
69 | - if ((size = is.read(b)) > 0) { | |
70 | - String result = new String(b, 0, size); | |
71 | - Log.log(".docx extension associations: " + result); | |
72 | - return result.startsWith(".docx=Word.Document."); | |
80 | + DOSCommand command = new DOSCommand(); | |
81 | + String s; | |
82 | + if (RET_OK == command.exec("assoc", ".docx")) { | |
83 | + s = command.getStdout(); // ex) ".docx=Word.Document.12" | |
84 | + if (s.toLowerCase().startsWith(".docx=word.document.")) { | |
85 | + String classString = s.substring(".docx=".length()); | |
86 | + classString = classString.replaceAll("\\r\\n", ""); | |
87 | + if (RET_OK == command.exec("reg", "query", "HKCR\\" + classString + "\\shell\\open\\command", "/ve")) { | |
88 | + s = command.getStdout(); | |
89 | + // データ例) | |
90 | + // | |
91 | + //HKEY_CLASSES_ROOT\Word.document.12\shell\open\command | |
92 | + //(既定) REG_SZ "C:\PROGRA~2\MICROS~4\OFFICE11\WINWORD.EXE" /n /dde | |
93 | + // | |
94 | + // 前後に空行が入るので注意。 | |
95 | + return s.toUpperCase().indexOf("\\WINWORD.EXE") > -1; | |
96 | + } | |
97 | + } | |
73 | 98 | } |
74 | - } catch (IOException ex) { | |
99 | + } catch (Exception ex) { | |
75 | 100 | Log.log(ex); |
76 | 101 | } |
77 | 102 | return false; |
78 | 103 | } |
104 | + | |
105 | + @Override | |
106 | + public boolean activate() { | |
107 | + | |
108 | + | |
109 | + | |
110 | + return true; | |
111 | + } | |
112 | + | |
113 | + // バッファあふれ非対応のため、少量のテキストが予想される場合のみ利用してください。 | |
114 | + protected static class DOSCommand { | |
115 | + | |
116 | + private int exitCode = 0; | |
117 | + private String stdout = ""; | |
118 | + private String stderr = ""; | |
119 | + | |
120 | + public int getExitCode() { | |
121 | + return exitCode; | |
122 | + } | |
123 | + | |
124 | + public String getStdout() { | |
125 | + return stdout; | |
126 | + } | |
127 | + | |
128 | + public String getStderr() { | |
129 | + return stderr; | |
130 | + } | |
131 | + | |
132 | + public int exec(String... command) throws IOException, | |
133 | + InterruptedException { | |
134 | + List<String> commands = new ArrayList<String>(command.length + 2); | |
135 | + commands.add("cmd.exe"); | |
136 | + commands.add("/c"); | |
137 | + commands.addAll(Arrays.asList(command)); | |
138 | + | |
139 | + ProcessBuilder pb = new ProcessBuilder(commands); | |
140 | + Process process = pb.start(); | |
141 | + exitCode = process.waitFor(); // 0: succeed | |
142 | + stdout = getString(process.getInputStream()); | |
143 | + stderr = getString(process.getErrorStream()); | |
144 | + return exitCode; | |
145 | + } | |
146 | + | |
147 | + private String getString(InputStream is) throws IOException { | |
148 | + byte[] b = new byte[1024]; | |
149 | + int size = is.read(b); | |
150 | + if (size > 0) { | |
151 | + return new String(b, 0, size); | |
152 | + } else { | |
153 | + return ""; | |
154 | + } | |
155 | + } | |
156 | + } | |
157 | + | |
79 | 158 | } |
@@ -24,6 +24,7 @@ | ||
24 | 24 | import static org.omegat.plugin.foldermenu.MenuHelper.getActionListener; |
25 | 25 | import static org.omegat.plugin.foldermenu.MenuHelper.getIcon; |
26 | 26 | import org.omegat.plugin.foldermenu.filepreview.FilePreview; |
27 | +import org.omegat.util.Log; | |
27 | 28 | import static org.omegat.util.Platform.OsType.MAC32; |
28 | 29 | import static org.omegat.util.Platform.OsType.MAC64; |
29 | 30 | import static org.omegat.util.Platform.OsType.WIN32; |
@@ -85,6 +86,7 @@ | ||
85 | 86 | break; |
86 | 87 | } |
87 | 88 | } catch (IOException ex) { |
89 | + Log.log(ex); | |
88 | 90 | Core.getMainWindow().showMessageDialog(StaticUtils.format( |
89 | 91 | L10n.getErrMsgFileHasNoAssoc(), path)); |
90 | 92 | } |