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