Mercurial > vim
annotate src/GvimExt/gvimext.cpp @ 16250:aeb340e0e485
Added tag v8.1.1129 for changeset 67e43b01497f1780bac0c7d3ca2b9bf394d6bed6
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 06 Apr 2019 21:00:06 +0200 |
parents | 4b2de998ebd6 |
children | 7e733046db1d |
rev | line source |
---|---|
10 | 1 /* vi:set ts=8 sts=4 sw=4: |
2 * | |
3 * VIM - Vi IMproved gvimext by Tianmiao Hu | |
4 * | |
5 * Do ":help uganda" in Vim to read copying and usage conditions. | |
6 * Do ":help credits" in Vim to see a list of people who contributed. | |
7 */ | |
8 | |
9 /* | |
10 * gvimext is a DLL which is used for the "Edit with Vim" context menu | |
11 * extension. It implements a MS defined interface with the Shell. | |
12 * | |
13 * If you have any questions or any suggestions concerning gvimext, please | |
14 * contact Tianmiao Hu: tianmiao@acm.org. | |
15 */ | |
16 | |
17 #include "gvimext.h" | |
18 | |
19 #ifdef __BORLANDC__ | |
20 # include <dir.h> | |
21 # ifndef _strnicmp | |
22 # define _strnicmp(a, b, c) strnicmp((a), (b), (c)) | |
23 # endif | |
24 #else | |
25 static char *searchpath(char *name); | |
26 #endif | |
27 | |
28 // Always get an error while putting the following stuff to the | |
29 // gvimext.h file as class protected variables, give up and | |
30 // declare them as global stuff | |
31 FORMATETC fmte = {CF_HDROP, | |
32 (DVTARGETDEVICE FAR *)NULL, | |
33 DVASPECT_CONTENT, | |
34 -1, | |
35 TYMED_HGLOBAL | |
36 }; | |
37 STGMEDIUM medium; | |
38 HRESULT hres = 0; | |
39 UINT cbFiles = 0; | |
40 | |
12626
aca41efd888c
patch 8.0.1191: MS-Windows: missing 32 and 64 bit files in installer
Christian Brabandt <cb@256bit.org>
parents:
8180
diff
changeset
|
41 /* The buffers size used to be MAX_PATH (260 bytes), but that's not always |
415 | 42 * enough */ |
43 #define BUFSIZE 1100 | |
44 | |
10 | 45 // |
46 // Get the name of the Gvim executable to use, with the path. | |
47 // When "runtime" is non-zero, we were called to find the runtime directory. | |
415 | 48 // Returns the path in name[BUFSIZE]. It's empty when it fails. |
10 | 49 // |
50 static void | |
51 getGvimName(char *name, int runtime) | |
52 { | |
53 HKEY keyhandle; | |
54 DWORD hlen; | |
55 | |
56 // Get the location of gvim from the registry. | |
57 name[0] = 0; | |
58 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim", 0, | |
59 KEY_READ, &keyhandle) == ERROR_SUCCESS) | |
60 { | |
415 | 61 hlen = BUFSIZE; |
10 | 62 if (RegQueryValueEx(keyhandle, "path", 0, NULL, (BYTE *)name, &hlen) |
63 != ERROR_SUCCESS) | |
64 name[0] = 0; | |
65 else | |
66 name[hlen] = 0; | |
67 RegCloseKey(keyhandle); | |
68 } | |
69 | |
70 // Registry didn't work, use the search path. | |
71 if (name[0] == 0) | |
1366 | 72 strcpy(name, searchpath((char *)"gvim.exe")); |
10 | 73 |
74 if (!runtime) | |
75 { | |
76 // Only when looking for the executable, not the runtime dir, we can | |
77 // search for the batch file or a name without a path. | |
78 if (name[0] == 0) | |
1366 | 79 strcpy(name, searchpath((char *)"gvim.bat")); |
10 | 80 if (name[0] == 0) |
81 strcpy(name, "gvim"); // finds gvim.bat or gvim.exe | |
82 } | |
83 } | |
84 | |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
85 static void |
6805 | 86 getGvimInvocation(char *name, int runtime) |
87 { | |
88 getGvimName(name, runtime); | |
89 // avoid that Vim tries to expand wildcards in the file names | |
90 strcat(name, " --literal"); | |
91 } | |
92 | |
93 static void | |
94 getGvimInvocationW(wchar_t *nameW) | |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
95 { |
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
96 char *name; |
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
97 |
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
98 name = (char *)malloc(BUFSIZE); |
6805 | 99 getGvimInvocation(name, 0); |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
100 mbstowcs(nameW, name, BUFSIZE); |
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
101 free(name); |
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
102 } |
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
103 |
10 | 104 // |
415 | 105 // Get the Vim runtime directory into buf[BUFSIZE]. |
10 | 106 // The result is empty when it failed. |
107 // When it works, the path ends in a slash or backslash. | |
108 // | |
109 static void | |
110 getRuntimeDir(char *buf) | |
111 { | |
112 int idx; | |
113 | |
114 getGvimName(buf, 1); | |
115 if (buf[0] != 0) | |
116 { | |
117 // When no path found, use the search path to expand it. | |
118 if (strchr(buf, '/') == NULL && strchr(buf, '\\') == NULL) | |
119 strcpy(buf, searchpath(buf)); | |
120 | |
121 // remove "gvim.exe" from the end | |
835 | 122 for (idx = (int)strlen(buf) - 1; idx >= 0; idx--) |
10 | 123 if (buf[idx] == '\\' || buf[idx] == '/') |
124 { | |
125 buf[idx + 1] = 0; | |
126 break; | |
127 } | |
128 } | |
129 } | |
130 | |
6805 | 131 HBITMAP IconToBitmap(HICON hIcon, HBRUSH hBackground, int width, int height) |
132 { | |
133 HDC hDC = GetDC(NULL); | |
134 HDC hMemDC = CreateCompatibleDC(hDC); | |
135 HBITMAP hMemBmp = CreateCompatibleBitmap(hDC, width, height); | |
136 HBITMAP hResultBmp = NULL; | |
137 HGDIOBJ hOrgBMP = SelectObject(hMemDC, hMemBmp); | |
138 | |
139 DrawIconEx(hMemDC, 0, 0, hIcon, width, height, 0, hBackground, DI_NORMAL); | |
140 | |
141 hResultBmp = hMemBmp; | |
142 hMemBmp = NULL; | |
143 | |
144 SelectObject(hMemDC, hOrgBMP); | |
145 DeleteDC(hMemDC); | |
146 ReleaseDC(NULL, hDC); | |
147 DestroyIcon(hIcon); | |
148 return hResultBmp; | |
149 } | |
150 | |
10 | 151 // |
152 // GETTEXT: translated messages and menu entries | |
153 // | |
154 #ifndef FEAT_GETTEXT | |
155 # define _(x) x | |
156 #else | |
157 # define _(x) (*dyn_libintl_gettext)(x) | |
158 # define VIMPACKAGE "vim" | |
159 # ifndef GETTEXT_DLL | |
160 # define GETTEXT_DLL "libintl.dll" | |
8180
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
161 # define GETTEXT_DLL_ALT "libintl-8.dll" |
10 | 162 # endif |
163 | |
164 // Dummy functions | |
165 static char *null_libintl_gettext(const char *); | |
166 static char *null_libintl_textdomain(const char *); | |
167 static char *null_libintl_bindtextdomain(const char *, const char *); | |
168 static int dyn_libintl_init(char *dir); | |
169 static void dyn_libintl_end(void); | |
170 | |
3008 | 171 static wchar_t *oldenv = NULL; |
10 | 172 static HINSTANCE hLibintlDLL = 0; |
173 static char *(*dyn_libintl_gettext)(const char *) = null_libintl_gettext; | |
174 static char *(*dyn_libintl_textdomain)(const char *) = null_libintl_textdomain; | |
175 static char *(*dyn_libintl_bindtextdomain)(const char *, const char *) | |
176 = null_libintl_bindtextdomain; | |
177 | |
178 // | |
179 // Attempt to load libintl.dll. If it doesn't work, use dummy functions. | |
180 // "dir" is the directory where the libintl.dll might be. | |
181 // Return 1 for success, 0 for failure. | |
182 // | |
183 static int | |
184 dyn_libintl_init(char *dir) | |
185 { | |
186 int i; | |
187 static struct | |
188 { | |
189 char *name; | |
190 FARPROC *ptr; | |
191 } libintl_entry[] = | |
192 { | |
1366 | 193 {(char *)"gettext", (FARPROC*)&dyn_libintl_gettext}, |
194 {(char *)"textdomain", (FARPROC*)&dyn_libintl_textdomain}, | |
195 {(char *)"bindtextdomain", (FARPROC*)&dyn_libintl_bindtextdomain}, | |
10 | 196 {NULL, NULL} |
197 }; | |
8180
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
198 DWORD len, len2; |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
199 LPWSTR buf = NULL; |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
200 LPWSTR buf2 = NULL; |
10 | 201 |
202 // No need to initialize twice. | |
203 if (hLibintlDLL) | |
204 return 1; | |
205 | |
12626
aca41efd888c
patch 8.0.1191: MS-Windows: missing 32 and 64 bit files in installer
Christian Brabandt <cb@256bit.org>
parents:
8180
diff
changeset
|
206 // Load gettext library from $VIMRUNTIME\GvimExt{64,32} directory. |
8180
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
207 // Add the directory to $PATH temporarily. |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
208 len = GetEnvironmentVariableW(L"PATH", NULL, 0); |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
209 len2 = MAX_PATH + 1 + len; |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
210 buf = (LPWSTR)malloc(len * sizeof(WCHAR)); |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
211 buf2 = (LPWSTR)malloc(len2 * sizeof(WCHAR)); |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
212 if (buf != NULL && buf2 != NULL) |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
213 { |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
214 GetEnvironmentVariableW(L"PATH", buf, len); |
12626
aca41efd888c
patch 8.0.1191: MS-Windows: missing 32 and 64 bit files in installer
Christian Brabandt <cb@256bit.org>
parents:
8180
diff
changeset
|
215 #ifdef _WIN64 |
aca41efd888c
patch 8.0.1191: MS-Windows: missing 32 and 64 bit files in installer
Christian Brabandt <cb@256bit.org>
parents:
8180
diff
changeset
|
216 _snwprintf(buf2, len2, L"%S\\GvimExt64;%s", dir, buf); |
aca41efd888c
patch 8.0.1191: MS-Windows: missing 32 and 64 bit files in installer
Christian Brabandt <cb@256bit.org>
parents:
8180
diff
changeset
|
217 #else |
aca41efd888c
patch 8.0.1191: MS-Windows: missing 32 and 64 bit files in installer
Christian Brabandt <cb@256bit.org>
parents:
8180
diff
changeset
|
218 _snwprintf(buf2, len2, L"%S\\GvimExt32;%s", dir, buf); |
aca41efd888c
patch 8.0.1191: MS-Windows: missing 32 and 64 bit files in installer
Christian Brabandt <cb@256bit.org>
parents:
8180
diff
changeset
|
219 #endif |
8180
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
220 SetEnvironmentVariableW(L"PATH", buf2); |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
221 hLibintlDLL = LoadLibrary(GETTEXT_DLL); |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
222 #ifdef GETTEXT_DLL_ALT |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
223 if (!hLibintlDLL) |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
224 hLibintlDLL = LoadLibrary(GETTEXT_DLL_ALT); |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
225 #endif |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
226 SetEnvironmentVariableW(L"PATH", buf); |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
227 } |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
228 free(buf); |
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
229 free(buf2); |
10 | 230 if (!hLibintlDLL) |
8180
1e48ffa2d697
commit https://github.com/vim/vim/commit/271273c39f2150ecdaa67fe1a2a8e9cdc63db545
Christian Brabandt <cb@256bit.org>
parents:
6805
diff
changeset
|
231 return 0; |
10 | 232 |
233 // Get the addresses of the functions we need. | |
234 for (i = 0; libintl_entry[i].name != NULL | |
235 && libintl_entry[i].ptr != NULL; ++i) | |
236 { | |
237 if ((*libintl_entry[i].ptr = GetProcAddress(hLibintlDLL, | |
238 libintl_entry[i].name)) == NULL) | |
239 { | |
240 dyn_libintl_end(); | |
241 return 0; | |
242 } | |
243 } | |
244 return 1; | |
245 } | |
246 | |
247 static void | |
248 dyn_libintl_end(void) | |
249 { | |
250 if (hLibintlDLL) | |
251 FreeLibrary(hLibintlDLL); | |
252 hLibintlDLL = NULL; | |
253 dyn_libintl_gettext = null_libintl_gettext; | |
254 dyn_libintl_textdomain = null_libintl_textdomain; | |
255 dyn_libintl_bindtextdomain = null_libintl_bindtextdomain; | |
256 } | |
257 | |
258 static char * | |
259 null_libintl_gettext(const char *msgid) | |
260 { | |
261 return (char *)msgid; | |
262 } | |
263 | |
264 static char * | |
1686 | 265 null_libintl_bindtextdomain(const char * /* domainname */, const char * /* dirname */) |
10 | 266 { |
267 return NULL; | |
268 } | |
269 | |
270 static char * | |
1686 | 271 null_libintl_textdomain(const char* /* domainname */) |
10 | 272 { |
273 return NULL; | |
274 } | |
275 | |
276 // | |
277 // Setup for translating strings. | |
278 // | |
279 static void | |
280 dyn_gettext_load(void) | |
281 { | |
415 | 282 char szBuff[BUFSIZE]; |
283 char szLang[BUFSIZE]; | |
10 | 284 DWORD len; |
285 HKEY keyhandle; | |
286 int gotlang = 0; | |
287 | |
288 strcpy(szLang, "LANG="); | |
289 | |
290 // First try getting the language from the registry, this can be | |
291 // used to overrule the system language. | |
292 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim", 0, | |
293 KEY_READ, &keyhandle) == ERROR_SUCCESS) | |
294 { | |
415 | 295 len = BUFSIZE; |
10 | 296 if (RegQueryValueEx(keyhandle, "lang", 0, NULL, (BYTE*)szBuff, &len) |
297 == ERROR_SUCCESS) | |
298 { | |
299 szBuff[len] = 0; | |
300 strcat(szLang, szBuff); | |
301 gotlang = 1; | |
302 } | |
303 RegCloseKey(keyhandle); | |
304 } | |
305 | |
306 if (!gotlang && getenv("LANG") == NULL) | |
307 { | |
308 // Get the language from the system. | |
309 // Could use LOCALE_SISO639LANGNAME, but it's not in Win95. | |
310 // LOCALE_SABBREVLANGNAME gives us three letters, like "enu", we use | |
311 // only the first two. | |
312 len = GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SABBREVLANGNAME, | |
415 | 313 (LPTSTR)szBuff, BUFSIZE); |
10 | 314 if (len >= 2 && _strnicmp(szBuff, "en", 2) != 0) |
315 { | |
316 // There are a few exceptions (probably more) | |
317 if (_strnicmp(szBuff, "cht", 3) == 0 | |
318 || _strnicmp(szBuff, "zht", 3) == 0) | |
319 strcpy(szBuff, "zh_TW"); | |
320 else if (_strnicmp(szBuff, "chs", 3) == 0 | |
321 || _strnicmp(szBuff, "zhc", 3) == 0) | |
322 strcpy(szBuff, "zh_CN"); | |
323 else if (_strnicmp(szBuff, "jp", 2) == 0) | |
324 strcpy(szBuff, "ja"); | |
325 else | |
326 szBuff[2] = 0; // truncate to two-letter code | |
327 strcat(szLang, szBuff); | |
328 gotlang = 1; | |
329 } | |
330 } | |
331 if (gotlang) | |
332 putenv(szLang); | |
333 | |
334 // Try to locate the runtime files. The path is used to find libintl.dll | |
335 // and the vim.mo files. | |
336 getRuntimeDir(szBuff); | |
337 if (szBuff[0] != 0) | |
338 { | |
835 | 339 len = (DWORD)strlen(szBuff); |
10 | 340 if (dyn_libintl_init(szBuff)) |
341 { | |
342 strcpy(szBuff + len, "lang"); | |
343 | |
344 (*dyn_libintl_bindtextdomain)(VIMPACKAGE, szBuff); | |
345 (*dyn_libintl_textdomain)(VIMPACKAGE); | |
346 } | |
347 } | |
348 } | |
349 | |
350 static void | |
351 dyn_gettext_free(void) | |
352 { | |
353 dyn_libintl_end(); | |
354 } | |
355 #endif // FEAT_GETTEXT | |
356 | |
357 // | |
358 // Global variables | |
359 // | |
360 UINT g_cRefThisDll = 0; // Reference count of this DLL. | |
361 HINSTANCE g_hmodThisDll = NULL; // Handle to this DLL itself. | |
362 | |
363 | |
364 //--------------------------------------------------------------------------- | |
365 // DllMain | |
366 //--------------------------------------------------------------------------- | |
367 extern "C" int APIENTRY | |
1686 | 368 DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /* lpReserved */) |
10 | 369 { |
370 switch (dwReason) | |
371 { | |
372 case DLL_PROCESS_ATTACH: | |
373 // Extension DLL one-time initialization | |
374 g_hmodThisDll = hInstance; | |
375 break; | |
376 | |
377 case DLL_PROCESS_DETACH: | |
378 break; | |
379 } | |
380 | |
381 return 1; // ok | |
382 } | |
383 | |
384 static void | |
385 inc_cRefThisDLL() | |
386 { | |
387 #ifdef FEAT_GETTEXT | |
3008 | 388 if (g_cRefThisDll == 0) { |
10 | 389 dyn_gettext_load(); |
3008 | 390 oldenv = GetEnvironmentStringsW(); |
391 } | |
10 | 392 #endif |
393 InterlockedIncrement((LPLONG)&g_cRefThisDll); | |
394 } | |
395 | |
396 static void | |
397 dec_cRefThisDLL() | |
398 { | |
399 #ifdef FEAT_GETTEXT | |
3008 | 400 if (InterlockedDecrement((LPLONG)&g_cRefThisDll) == 0) { |
10 | 401 dyn_gettext_free(); |
3008 | 402 if (oldenv != NULL) { |
403 FreeEnvironmentStringsW(oldenv); | |
404 oldenv = NULL; | |
405 } | |
406 } | |
10 | 407 #else |
408 InterlockedDecrement((LPLONG)&g_cRefThisDll); | |
409 #endif | |
410 } | |
411 | |
412 //--------------------------------------------------------------------------- | |
413 // DllCanUnloadNow | |
414 //--------------------------------------------------------------------------- | |
415 | |
416 STDAPI DllCanUnloadNow(void) | |
417 { | |
418 return (g_cRefThisDll == 0 ? S_OK : S_FALSE); | |
419 } | |
420 | |
421 STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut) | |
422 { | |
423 *ppvOut = NULL; | |
424 | |
425 if (IsEqualIID(rclsid, CLSID_ShellExtension)) | |
426 { | |
427 CShellExtClassFactory *pcf = new CShellExtClassFactory; | |
428 | |
429 return pcf->QueryInterface(riid, ppvOut); | |
430 } | |
431 | |
432 return CLASS_E_CLASSNOTAVAILABLE; | |
433 } | |
434 | |
435 CShellExtClassFactory::CShellExtClassFactory() | |
436 { | |
437 m_cRef = 0L; | |
438 | |
439 inc_cRefThisDLL(); | |
440 } | |
441 | |
442 CShellExtClassFactory::~CShellExtClassFactory() | |
443 { | |
444 dec_cRefThisDLL(); | |
445 } | |
446 | |
447 STDMETHODIMP CShellExtClassFactory::QueryInterface(REFIID riid, | |
448 LPVOID FAR *ppv) | |
449 { | |
450 *ppv = NULL; | |
451 | |
6805 | 452 // any interface on this object is the object pointer |
10 | 453 |
454 if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory)) | |
455 { | |
456 *ppv = (LPCLASSFACTORY)this; | |
457 | |
458 AddRef(); | |
459 | |
460 return NOERROR; | |
461 } | |
462 | |
463 return E_NOINTERFACE; | |
464 } | |
465 | |
466 STDMETHODIMP_(ULONG) CShellExtClassFactory::AddRef() | |
467 { | |
468 return InterlockedIncrement((LPLONG)&m_cRef); | |
469 } | |
470 | |
471 STDMETHODIMP_(ULONG) CShellExtClassFactory::Release() | |
472 { | |
473 if (InterlockedDecrement((LPLONG)&m_cRef)) | |
474 return m_cRef; | |
475 | |
476 delete this; | |
477 | |
478 return 0L; | |
479 } | |
480 | |
481 STDMETHODIMP CShellExtClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, | |
482 REFIID riid, | |
483 LPVOID *ppvObj) | |
484 { | |
485 *ppvObj = NULL; | |
486 | |
487 // Shell extensions typically don't support aggregation (inheritance) | |
488 | |
489 if (pUnkOuter) | |
490 return CLASS_E_NOAGGREGATION; | |
491 | |
492 // Create the main shell extension object. The shell will then call | |
493 // QueryInterface with IID_IShellExtInit--this is how shell extensions are | |
494 // initialized. | |
495 | |
6805 | 496 LPCSHELLEXT pShellExt = new CShellExt(); // create the CShellExt object |
10 | 497 |
498 if (NULL == pShellExt) | |
499 return E_OUTOFMEMORY; | |
500 | |
501 return pShellExt->QueryInterface(riid, ppvObj); | |
502 } | |
503 | |
504 | |
1686 | 505 STDMETHODIMP CShellExtClassFactory::LockServer(BOOL /* fLock */) |
10 | 506 { |
507 return NOERROR; | |
508 } | |
509 | |
510 // *********************** CShellExt ************************* | |
511 CShellExt::CShellExt() | |
512 { | |
513 m_cRef = 0L; | |
514 m_pDataObj = NULL; | |
515 | |
516 inc_cRefThisDLL(); | |
6805 | 517 |
518 LoadMenuIcon(); | |
10 | 519 } |
520 | |
521 CShellExt::~CShellExt() | |
522 { | |
523 if (m_pDataObj) | |
524 m_pDataObj->Release(); | |
525 | |
526 dec_cRefThisDLL(); | |
6805 | 527 |
528 if (m_hVimIconBitmap) | |
529 DeleteObject(m_hVimIconBitmap); | |
10 | 530 } |
531 | |
532 STDMETHODIMP CShellExt::QueryInterface(REFIID riid, LPVOID FAR *ppv) | |
533 { | |
534 *ppv = NULL; | |
535 | |
536 if (IsEqualIID(riid, IID_IShellExtInit) || IsEqualIID(riid, IID_IUnknown)) | |
537 { | |
538 *ppv = (LPSHELLEXTINIT)this; | |
539 } | |
540 else if (IsEqualIID(riid, IID_IContextMenu)) | |
541 { | |
542 *ppv = (LPCONTEXTMENU)this; | |
543 } | |
544 | |
545 if (*ppv) | |
546 { | |
547 AddRef(); | |
548 | |
549 return NOERROR; | |
550 } | |
551 | |
552 return E_NOINTERFACE; | |
553 } | |
554 | |
555 STDMETHODIMP_(ULONG) CShellExt::AddRef() | |
556 { | |
557 return InterlockedIncrement((LPLONG)&m_cRef); | |
558 } | |
559 | |
560 STDMETHODIMP_(ULONG) CShellExt::Release() | |
561 { | |
562 | |
563 if (InterlockedDecrement((LPLONG)&m_cRef)) | |
564 return m_cRef; | |
565 | |
566 delete this; | |
567 | |
568 return 0L; | |
569 } | |
570 | |
571 | |
572 // | |
573 // FUNCTION: CShellExt::Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY) | |
574 // | |
575 // PURPOSE: Called by the shell when initializing a context menu or property | |
576 // sheet extension. | |
577 // | |
578 // PARAMETERS: | |
579 // pIDFolder - Specifies the parent folder | |
4352 | 580 // pDataObj - Specifies the set of items selected in that folder. |
10 | 581 // hRegKey - Specifies the type of the focused item in the selection. |
582 // | |
583 // RETURN VALUE: | |
584 // | |
585 // NOERROR in all cases. | |
586 // | |
587 // COMMENTS: Note that at the time this function is called, we don't know | |
588 // (or care) what type of shell extension is being initialized. | |
589 // It could be a context menu or a property sheet. | |
590 // | |
591 | |
1686 | 592 STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST /* pIDFolder */, |
10 | 593 LPDATAOBJECT pDataObj, |
1686 | 594 HKEY /* hRegKey */) |
10 | 595 { |
596 // Initialize can be called more than once | |
597 if (m_pDataObj) | |
598 m_pDataObj->Release(); | |
599 | |
600 // duplicate the object pointer and registry handle | |
601 | |
602 if (pDataObj) | |
603 { | |
604 m_pDataObj = pDataObj; | |
605 pDataObj->AddRef(); | |
606 } | |
607 | |
608 return NOERROR; | |
609 } | |
610 | |
611 | |
612 // | |
613 // FUNCTION: CShellExt::QueryContextMenu(HMENU, UINT, UINT, UINT, UINT) | |
614 // | |
615 // PURPOSE: Called by the shell just before the context menu is displayed. | |
616 // This is where you add your specific menu items. | |
617 // | |
618 // PARAMETERS: | |
619 // hMenu - Handle to the context menu | |
620 // indexMenu - Index of where to begin inserting menu items | |
621 // idCmdFirst - Lowest value for new menu ID's | |
622 // idCmtLast - Highest value for new menu ID's | |
623 // uFlags - Specifies the context of the menu event | |
624 // | |
625 // RETURN VALUE: | |
626 // | |
627 // | |
628 // COMMENTS: | |
629 // | |
630 | |
631 STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu, | |
632 UINT indexMenu, | |
633 UINT idCmdFirst, | |
1686 | 634 UINT /* idCmdLast */, |
635 UINT /* uFlags */) | |
10 | 636 { |
637 UINT idCmd = idCmdFirst; | |
638 | |
639 hres = m_pDataObj->GetData(&fmte, &medium); | |
640 if (medium.hGlobal) | |
641 cbFiles = DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, 0, 0); | |
642 | |
643 // InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL); | |
644 | |
645 // Initialize m_cntOfHWnd to 0 | |
646 m_cntOfHWnd = 0; | |
2972 | 647 |
648 HKEY keyhandle; | |
649 bool showExisting = true; | |
6805 | 650 bool showIcons = true; |
2972 | 651 |
652 // Check whether "Edit with existing Vim" entries are disabled. | |
653 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim", 0, | |
654 KEY_READ, &keyhandle) == ERROR_SUCCESS) | |
655 { | |
656 if (RegQueryValueEx(keyhandle, "DisableEditWithExisting", 0, NULL, | |
657 NULL, NULL) == ERROR_SUCCESS) | |
658 showExisting = false; | |
6805 | 659 if (RegQueryValueEx(keyhandle, "DisableContextMenuIcons", 0, NULL, |
660 NULL, NULL) == ERROR_SUCCESS) | |
661 showIcons = false; | |
2972 | 662 RegCloseKey(keyhandle); |
663 } | |
664 | |
665 // Retrieve all the vim instances, unless disabled. | |
666 if (showExisting) | |
667 EnumWindows(EnumWindowsProc, (LPARAM)this); | |
10 | 668 |
6805 | 669 MENUITEMINFO mii = { sizeof(MENUITEMINFO) }; |
670 mii.fMask = MIIM_STRING | MIIM_ID; | |
671 if (showIcons) | |
672 { | |
673 mii.fMask |= MIIM_BITMAP; | |
674 mii.hbmpItem = m_hVimIconBitmap; | |
675 } | |
676 | |
10 | 677 if (cbFiles > 1) |
678 { | |
6805 | 679 mii.wID = idCmd++; |
680 mii.dwTypeData = _("Edit with &multiple Vims"); | |
681 mii.cch = lstrlen(mii.dwTypeData); | |
682 InsertMenuItem(hMenu, indexMenu++, TRUE, &mii); | |
10 | 683 |
6805 | 684 mii.wID = idCmd++; |
685 mii.dwTypeData = _("Edit with single &Vim"); | |
686 mii.cch = lstrlen(mii.dwTypeData); | |
687 InsertMenuItem(hMenu, indexMenu++, TRUE, &mii); | |
10 | 688 |
689 if (cbFiles <= 4) | |
690 { | |
691 // Can edit up to 4 files in diff mode | |
6805 | 692 mii.wID = idCmd++; |
693 mii.dwTypeData = _("Diff with Vim"); | |
694 mii.cch = lstrlen(mii.dwTypeData); | |
695 InsertMenuItem(hMenu, indexMenu++, TRUE, &mii); | |
10 | 696 m_edit_existing_off = 3; |
697 } | |
698 else | |
699 m_edit_existing_off = 2; | |
700 | |
701 } | |
702 else | |
703 { | |
6805 | 704 mii.wID = idCmd++; |
705 mii.dwTypeData = _("Edit with &Vim"); | |
706 mii.cch = lstrlen(mii.dwTypeData); | |
707 InsertMenuItem(hMenu, indexMenu++, TRUE, &mii); | |
10 | 708 m_edit_existing_off = 1; |
709 } | |
710 | |
14962
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
711 HMENU hSubMenu = NULL; |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
712 if (m_cntOfHWnd > 1) |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
713 { |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
714 hSubMenu = CreatePopupMenu(); |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
715 mii.fMask |= MIIM_SUBMENU; |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
716 mii.wID = idCmd; |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
717 mii.dwTypeData = _("Edit with existing Vim"); |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
718 mii.cch = lstrlen(mii.dwTypeData); |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
719 mii.hSubMenu = hSubMenu; |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
720 InsertMenuItem(hMenu, indexMenu++, TRUE, &mii); |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
721 mii.fMask = mii.fMask & ~MIIM_SUBMENU; |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
722 mii.hSubMenu = NULL; |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
723 } |
10 | 724 // Now display all the vim instances |
725 for (int i = 0; i < m_cntOfHWnd; i++) | |
726 { | |
415 | 727 char title[BUFSIZE]; |
728 char temp[BUFSIZE]; | |
14962
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
729 int index; |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
730 HMENU hmenu; |
10 | 731 |
732 // Obtain window title, continue if can not | |
415 | 733 if (GetWindowText(m_hWnd[i], title, BUFSIZE - 1) == 0) |
10 | 734 continue; |
735 // Truncate the title before the path, keep the file name | |
736 char *pos = strchr(title, '('); | |
737 if (pos != NULL) | |
738 { | |
739 if (pos > title && pos[-1] == ' ') | |
740 --pos; | |
741 *pos = 0; | |
742 } | |
743 // Now concatenate | |
14962
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
744 if (m_cntOfHWnd > 1) |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
745 temp[0] = '\0'; |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
746 else |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
747 { |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
748 strncpy(temp, _("Edit with existing Vim - "), BUFSIZE - 1); |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
749 temp[BUFSIZE - 1] = '\0'; |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
750 } |
1953 | 751 strncat(temp, title, BUFSIZE - 1 - strlen(temp)); |
752 temp[BUFSIZE - 1] = '\0'; | |
6805 | 753 |
754 mii.wID = idCmd++; | |
755 mii.dwTypeData = temp; | |
756 mii.cch = lstrlen(mii.dwTypeData); | |
14962
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
757 if (m_cntOfHWnd > 1) |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
758 { |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
759 hmenu = hSubMenu; |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
760 index = i; |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
761 } |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
762 else |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
763 { |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
764 hmenu = hMenu; |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
765 index = indexMenu++; |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
766 } |
013b70517b1a
patch 8.1.0492: "Edit with existing Vim" list can get long
Bram Moolenaar <Bram@vim.org>
parents:
12626
diff
changeset
|
767 InsertMenuItem(hmenu, index, TRUE, &mii); |
10 | 768 } |
769 // InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL); | |
770 | |
771 // Must return number of menu items we added. | |
772 return ResultFromShort(idCmd-idCmdFirst); | |
773 } | |
774 | |
775 // | |
776 // FUNCTION: CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO) | |
777 // | |
778 // PURPOSE: Called by the shell after the user has selected on of the | |
779 // menu items that was added in QueryContextMenu(). | |
780 // | |
781 // PARAMETERS: | |
782 // lpcmi - Pointer to an CMINVOKECOMMANDINFO structure | |
783 // | |
784 // RETURN VALUE: | |
785 // | |
786 // | |
787 // COMMENTS: | |
788 // | |
789 | |
790 STDMETHODIMP CShellExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpcmi) | |
791 { | |
792 HRESULT hr = E_INVALIDARG; | |
793 | |
794 // If HIWORD(lpcmi->lpVerb) then we have been called programmatically | |
795 // and lpVerb is a command that should be invoked. Otherwise, the shell | |
796 // has called us, and LOWORD(lpcmi->lpVerb) is the menu ID the user has | |
797 // selected. Actually, it's (menu ID - idCmdFirst) from QueryContextMenu(). | |
798 if (!HIWORD(lpcmi->lpVerb)) | |
799 { | |
800 UINT idCmd = LOWORD(lpcmi->lpVerb); | |
801 | |
802 if (idCmd >= m_edit_existing_off) | |
803 { | |
804 // Existing with vim instance | |
805 hr = PushToWindow(lpcmi->hwnd, | |
806 lpcmi->lpDirectory, | |
807 lpcmi->lpVerb, | |
808 lpcmi->lpParameters, | |
809 lpcmi->nShow, | |
810 idCmd - m_edit_existing_off); | |
811 } | |
812 else | |
813 { | |
814 switch (idCmd) | |
815 { | |
816 case 0: | |
817 hr = InvokeGvim(lpcmi->hwnd, | |
818 lpcmi->lpDirectory, | |
819 lpcmi->lpVerb, | |
820 lpcmi->lpParameters, | |
821 lpcmi->nShow); | |
822 break; | |
823 case 1: | |
824 hr = InvokeSingleGvim(lpcmi->hwnd, | |
825 lpcmi->lpDirectory, | |
826 lpcmi->lpVerb, | |
827 lpcmi->lpParameters, | |
828 lpcmi->nShow, | |
829 0); | |
830 break; | |
831 case 2: | |
832 hr = InvokeSingleGvim(lpcmi->hwnd, | |
833 lpcmi->lpDirectory, | |
834 lpcmi->lpVerb, | |
835 lpcmi->lpParameters, | |
836 lpcmi->nShow, | |
837 1); | |
838 break; | |
839 } | |
840 } | |
841 } | |
842 return hr; | |
843 } | |
844 | |
1686 | 845 STDMETHODIMP CShellExt::PushToWindow(HWND /* hParent */, |
846 LPCSTR /* pszWorkingDir */, | |
847 LPCSTR /* pszCmd */, | |
848 LPCSTR /* pszParam */, | |
849 int /* iShowCmd */, | |
10 | 850 int idHWnd) |
851 { | |
852 HWND hWnd = m_hWnd[idHWnd]; | |
853 | |
854 // Show and bring vim instance to foreground | |
855 if (IsIconic(hWnd) != 0) | |
856 ShowWindow(hWnd, SW_RESTORE); | |
857 else | |
858 ShowWindow(hWnd, SW_SHOW); | |
859 SetForegroundWindow(hWnd); | |
860 | |
861 // Post the selected files to the vim instance | |
862 PostMessage(hWnd, WM_DROPFILES, (WPARAM)medium.hGlobal, 0); | |
863 | |
864 return NOERROR; | |
865 } | |
866 | |
1686 | 867 STDMETHODIMP CShellExt::GetCommandString(UINT_PTR /* idCmd */, |
10 | 868 UINT uFlags, |
1686 | 869 UINT FAR * /* reserved */, |
10 | 870 LPSTR pszName, |
871 UINT cchMax) | |
872 { | |
873 if (uFlags == GCS_HELPTEXT && cchMax > 35) | |
874 lstrcpy(pszName, _("Edits the selected file(s) with Vim")); | |
875 | |
876 return NOERROR; | |
877 } | |
878 | |
879 BOOL CALLBACK CShellExt::EnumWindowsProc(HWND hWnd, LPARAM lParam) | |
880 { | |
415 | 881 char temp[BUFSIZE]; |
10 | 882 |
883 // First do a bunch of check | |
884 // No invisible window | |
885 if (!IsWindowVisible(hWnd)) return TRUE; | |
886 // No child window ??? | |
887 // if (GetParent(hWnd)) return TRUE; | |
888 // Class name should be Vim, if failed to get class name, return | |
889 if (GetClassName(hWnd, temp, sizeof(temp)) == 0) | |
890 return TRUE; | |
891 // Compare class name to that of vim, if not, return | |
892 if (_strnicmp(temp, "vim", sizeof("vim")) != 0) | |
893 return TRUE; | |
894 // First check if the number of vim instance exceeds MAX_HWND | |
895 CShellExt *cs = (CShellExt*) lParam; | |
896 if (cs->m_cntOfHWnd >= MAX_HWND) return TRUE; | |
897 // Now we get the vim window, put it into some kind of array | |
898 cs->m_hWnd[cs->m_cntOfHWnd] = hWnd; | |
899 cs->m_cntOfHWnd ++; | |
900 | |
901 return TRUE; // continue enumeration (otherwise this would be false) | |
902 } | |
903 | |
6805 | 904 BOOL CShellExt::LoadMenuIcon() |
905 { | |
906 char vimExeFile[BUFSIZE]; | |
907 getGvimName(vimExeFile, 1); | |
908 if (vimExeFile[0] == '\0') | |
909 return FALSE; | |
910 HICON hVimIcon; | |
911 if (ExtractIconEx(vimExeFile, 0, NULL, &hVimIcon, 1) == 0) | |
912 return FALSE; | |
913 m_hVimIconBitmap = IconToBitmap(hVimIcon, | |
914 GetSysColorBrush(COLOR_MENU), | |
915 GetSystemMetrics(SM_CXSMICON), | |
916 GetSystemMetrics(SM_CYSMICON)); | |
917 return TRUE; | |
918 } | |
919 | |
12626
aca41efd888c
patch 8.0.1191: MS-Windows: missing 32 and 64 bit files in installer
Christian Brabandt <cb@256bit.org>
parents:
8180
diff
changeset
|
920 #ifndef __BORLANDC__ |
10 | 921 static char * |
922 searchpath(char *name) | |
923 { | |
415 | 924 static char widename[2 * BUFSIZE]; |
925 static char location[2 * BUFSIZE + 2]; | |
10 | 926 |
927 // There appears to be a bug in FindExecutableA() on Windows NT. | |
928 // Use FindExecutableW() instead... | |
12626
aca41efd888c
patch 8.0.1191: MS-Windows: missing 32 and 64 bit files in installer
Christian Brabandt <cb@256bit.org>
parents:
8180
diff
changeset
|
929 MultiByteToWideChar(CP_ACP, 0, (LPCSTR)name, -1, |
aca41efd888c
patch 8.0.1191: MS-Windows: missing 32 and 64 bit files in installer
Christian Brabandt <cb@256bit.org>
parents:
8180
diff
changeset
|
930 (LPWSTR)widename, BUFSIZE); |
aca41efd888c
patch 8.0.1191: MS-Windows: missing 32 and 64 bit files in installer
Christian Brabandt <cb@256bit.org>
parents:
8180
diff
changeset
|
931 if (FindExecutableW((LPCWSTR)widename, (LPCWSTR)"", |
aca41efd888c
patch 8.0.1191: MS-Windows: missing 32 and 64 bit files in installer
Christian Brabandt <cb@256bit.org>
parents:
8180
diff
changeset
|
932 (LPWSTR)location) > (HINSTANCE)32) |
10 | 933 { |
12626
aca41efd888c
patch 8.0.1191: MS-Windows: missing 32 and 64 bit files in installer
Christian Brabandt <cb@256bit.org>
parents:
8180
diff
changeset
|
934 WideCharToMultiByte(CP_ACP, 0, (LPWSTR)location, -1, |
aca41efd888c
patch 8.0.1191: MS-Windows: missing 32 and 64 bit files in installer
Christian Brabandt <cb@256bit.org>
parents:
8180
diff
changeset
|
935 (LPSTR)widename, 2 * BUFSIZE, NULL, NULL); |
aca41efd888c
patch 8.0.1191: MS-Windows: missing 32 and 64 bit files in installer
Christian Brabandt <cb@256bit.org>
parents:
8180
diff
changeset
|
936 return widename; |
10 | 937 } |
1366 | 938 return (char *)""; |
10 | 939 } |
940 #endif | |
941 | |
942 STDMETHODIMP CShellExt::InvokeGvim(HWND hParent, | |
1686 | 943 LPCSTR /* pszWorkingDir */, |
944 LPCSTR /* pszCmd */, | |
945 LPCSTR /* pszParam */, | |
946 int /* iShowCmd */) | |
10 | 947 { |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
948 wchar_t m_szFileUserClickedOn[BUFSIZE]; |
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
949 wchar_t cmdStrW[BUFSIZE]; |
10 | 950 UINT i; |
951 | |
952 for (i = 0; i < cbFiles; i++) | |
953 { | |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
954 DragQueryFileW((HDROP)medium.hGlobal, |
10 | 955 i, |
956 m_szFileUserClickedOn, | |
957 sizeof(m_szFileUserClickedOn)); | |
958 | |
6805 | 959 getGvimInvocationW(cmdStrW); |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
960 wcscat(cmdStrW, L" \""); |
10 | 961 |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
962 if ((wcslen(cmdStrW) + wcslen(m_szFileUserClickedOn) + 2) < BUFSIZE) |
10 | 963 { |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
964 wcscat(cmdStrW, m_szFileUserClickedOn); |
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
965 wcscat(cmdStrW, L"\""); |
10 | 966 |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
967 STARTUPINFOW si; |
10 | 968 PROCESS_INFORMATION pi; |
969 | |
970 ZeroMemory(&si, sizeof(si)); | |
971 si.cb = sizeof(si); | |
972 | |
973 // Start the child process. | |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
974 if (!CreateProcessW(NULL, // No module name (use command line). |
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
975 cmdStrW, // Command line. |
10 | 976 NULL, // Process handle not inheritable. |
977 NULL, // Thread handle not inheritable. | |
978 FALSE, // Set handle inheritance to FALSE. | |
3008 | 979 oldenv == NULL ? 0 : CREATE_UNICODE_ENVIRONMENT, |
980 oldenv, // Use unmodified environment block. | |
10 | 981 NULL, // Use parent's starting directory. |
982 &si, // Pointer to STARTUPINFO structure. | |
983 &pi) // Pointer to PROCESS_INFORMATION structure. | |
984 ) | |
985 { | |
986 MessageBox( | |
987 hParent, | |
988 _("Error creating process: Check if gvim is in your path!"), | |
989 _("gvimext.dll error"), | |
990 MB_OK); | |
991 } | |
992 else | |
993 { | |
994 CloseHandle( pi.hProcess ); | |
995 CloseHandle( pi.hThread ); | |
996 } | |
997 } | |
998 else | |
999 { | |
1000 MessageBox( | |
1001 hParent, | |
1002 _("Path length too long!"), | |
1003 _("gvimext.dll error"), | |
1004 MB_OK); | |
1005 } | |
1006 } | |
1007 | |
1008 return NOERROR; | |
1009 } | |
1010 | |
1011 | |
1012 STDMETHODIMP CShellExt::InvokeSingleGvim(HWND hParent, | |
1686 | 1013 LPCSTR /* pszWorkingDir */, |
1014 LPCSTR /* pszCmd */, | |
1015 LPCSTR /* pszParam */, | |
1016 int /* iShowCmd */, | |
10 | 1017 int useDiff) |
1018 { | |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
1019 wchar_t m_szFileUserClickedOn[BUFSIZE]; |
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
1020 wchar_t *cmdStrW; |
10 | 1021 size_t cmdlen; |
1022 size_t len; | |
1023 UINT i; | |
1024 | |
415 | 1025 cmdlen = BUFSIZE; |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
1026 cmdStrW = (wchar_t *) malloc(cmdlen * sizeof(wchar_t)); |
15154
eb0d8065d3f8
patch 8.1.0587: GvimExt: realloc() failing is not handled properly
Bram Moolenaar <Bram@vim.org>
parents:
14962
diff
changeset
|
1027 if (cmdStrW == NULL) |
15158
a9340baa872f
patch 8.1.0589: compilation error in gvimext.cpp
Bram Moolenaar <Bram@vim.org>
parents:
15154
diff
changeset
|
1028 return E_FAIL; |
6805 | 1029 getGvimInvocationW(cmdStrW); |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
1030 |
10 | 1031 if (useDiff) |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
1032 wcscat(cmdStrW, L" -d"); |
10 | 1033 for (i = 0; i < cbFiles; i++) |
1034 { | |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
1035 DragQueryFileW((HDROP)medium.hGlobal, |
10 | 1036 i, |
1037 m_szFileUserClickedOn, | |
1038 sizeof(m_szFileUserClickedOn)); | |
1039 | |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
1040 len = wcslen(cmdStrW) + wcslen(m_szFileUserClickedOn) + 4; |
10 | 1041 if (len > cmdlen) |
1042 { | |
415 | 1043 cmdlen = len + BUFSIZE; |
15154
eb0d8065d3f8
patch 8.1.0587: GvimExt: realloc() failing is not handled properly
Bram Moolenaar <Bram@vim.org>
parents:
14962
diff
changeset
|
1044 wchar_t *cmdStrW_new = (wchar_t *)realloc(cmdStrW, cmdlen * sizeof(wchar_t)); |
eb0d8065d3f8
patch 8.1.0587: GvimExt: realloc() failing is not handled properly
Bram Moolenaar <Bram@vim.org>
parents:
14962
diff
changeset
|
1045 if (cmdStrW_new == NULL) |
15158
a9340baa872f
patch 8.1.0589: compilation error in gvimext.cpp
Bram Moolenaar <Bram@vim.org>
parents:
15154
diff
changeset
|
1046 { |
a9340baa872f
patch 8.1.0589: compilation error in gvimext.cpp
Bram Moolenaar <Bram@vim.org>
parents:
15154
diff
changeset
|
1047 free(cmdStrW); |
a9340baa872f
patch 8.1.0589: compilation error in gvimext.cpp
Bram Moolenaar <Bram@vim.org>
parents:
15154
diff
changeset
|
1048 return E_FAIL; |
a9340baa872f
patch 8.1.0589: compilation error in gvimext.cpp
Bram Moolenaar <Bram@vim.org>
parents:
15154
diff
changeset
|
1049 } |
15154
eb0d8065d3f8
patch 8.1.0587: GvimExt: realloc() failing is not handled properly
Bram Moolenaar <Bram@vim.org>
parents:
14962
diff
changeset
|
1050 cmdStrW = cmdStrW_new; |
10 | 1051 } |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
1052 wcscat(cmdStrW, L" \""); |
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
1053 wcscat(cmdStrW, m_szFileUserClickedOn); |
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
1054 wcscat(cmdStrW, L"\""); |
10 | 1055 } |
1056 | |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
1057 STARTUPINFOW si; |
10 | 1058 PROCESS_INFORMATION pi; |
1059 | |
1060 ZeroMemory(&si, sizeof(si)); | |
1061 si.cb = sizeof(si); | |
1062 | |
1063 // Start the child process. | |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
1064 if (!CreateProcessW(NULL, // No module name (use command line). |
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
1065 cmdStrW, // Command line. |
10 | 1066 NULL, // Process handle not inheritable. |
1067 NULL, // Thread handle not inheritable. | |
1068 FALSE, // Set handle inheritance to FALSE. | |
3008 | 1069 oldenv == NULL ? 0 : CREATE_UNICODE_ENVIRONMENT, |
1070 oldenv, // Use unmodified environment block. | |
10 | 1071 NULL, // Use parent's starting directory. |
1072 &si, // Pointer to STARTUPINFO structure. | |
1073 &pi) // Pointer to PROCESS_INFORMATION structure. | |
1074 ) | |
1075 { | |
1076 MessageBox( | |
1077 hParent, | |
1078 _("Error creating process: Check if gvim is in your path!"), | |
1079 _("gvimext.dll error"), | |
1080 MB_OK); | |
1081 } | |
1082 else | |
1083 { | |
1084 CloseHandle(pi.hProcess); | |
1085 CloseHandle(pi.hThread); | |
1086 } | |
2295
b9bc9c5df131
Support wide file names in gvimext. (Szabolcs Horvat)
Bram Moolenaar <bram@vim.org>
parents:
1953
diff
changeset
|
1087 free(cmdStrW); |
10 | 1088 |
1089 return NOERROR; | |
1090 } |