Mercurial > vim
annotate src/dosinst.h @ 11258:84f71a8a5f2c v8.0.0515
patch 8.0.0515: ml_get errors in silent Ex mode
commit https://github.com/vim/vim/commit/d5d37537d1fa46fd468bd378af2006dd09840f38
Author: Bram Moolenaar <Bram@vim.org>
Date: Mon Mar 27 23:02:07 2017 +0200
patch 8.0.0515: ml_get errors in silent Ex mode
Problem: ml_get errors in silent Ex mode. (Dominique Pelle)
Solution: Clear valid flags when setting the cursor. Set the topline when
not in full screen mode.
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Mon, 27 Mar 2017 23:15:05 +0200 |
parents | 4aead6a9b7a9 |
children | aca41efd888c |
rev | line source |
---|---|
10042
4aead6a9b7a9
commit https://github.com/vim/vim/commit/edf3f97ae2af024708ebb4ac614227327033ca47
Christian Brabandt <cb@256bit.org>
parents:
8212
diff
changeset
|
1 /* vi:set ts=8 sts=4 sw=4 noet: |
7 | 2 * |
3 * VIM - Vi IMproved by Bram Moolenaar | |
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 * See README.txt for an overview of the Vim source code. | |
8 */ | |
9 /* | |
10 * dosinst.h: Common code for dosinst.c and uninstal.c | |
11 */ | |
714 | 12 |
13 /* Visual Studio 2005 has 'deprecated' many of the standard CRT functions */ | |
14 #if _MSC_VER >= 1400 | |
15 # define _CRT_SECURE_NO_DEPRECATE | |
16 # define _CRT_NONSTDC_NO_DEPRECATE | |
17 #endif | |
18 | |
7 | 19 #include <stdio.h> |
20 #include <stdlib.h> | |
21 #include <string.h> | |
22 #include <sys/stat.h> | |
23 #include <fcntl.h> | |
24 | |
25 #ifndef UNIX_LINT | |
714 | 26 # include "vimio.h" |
7 | 27 # include <ctype.h> |
28 | |
29 # ifndef __CYGWIN__ | |
30 # include <direct.h> | |
31 # endif | |
32 | |
33 # if defined(_WIN64) || defined(WIN32) | |
34 # define WIN3264 | |
35 # include <windows.h> | |
36 # include <shlobj.h> | |
37 # else | |
38 # include <dir.h> | |
39 # include <bios.h> | |
40 # include <dos.h> | |
41 # endif | |
42 #endif | |
43 | |
44 #ifdef UNIX_LINT | |
45 /* Running lint on Unix: Some things are missing. */ | |
46 char *searchpath(char *name); | |
47 #endif | |
48 | |
8212
05b88224cea1
commit https://github.com/vim/vim/commit/48e330aff911be1c798c88a973af6437a8141fce
Christian Brabandt <cb@256bit.org>
parents:
8080
diff
changeset
|
49 #if defined(UNIX_LINT) |
7 | 50 # include <unistd.h> |
51 # include <errno.h> | |
52 #endif | |
53 | |
54 #include "version.h" | |
55 | |
8212
05b88224cea1
commit https://github.com/vim/vim/commit/48e330aff911be1c798c88a973af6437a8141fce
Christian Brabandt <cb@256bit.org>
parents:
8080
diff
changeset
|
56 #if defined(UNIX_LINT) |
7 | 57 # define vim_mkdir(x, y) mkdir((char *)(x), y) |
58 #else | |
59 # if defined(WIN3264) && !defined(__BORLANDC__) | |
60 # define vim_mkdir(x, y) _mkdir((char *)(x)) | |
61 # else | |
62 # define vim_mkdir(x, y) mkdir((char *)(x)) | |
63 # endif | |
64 #endif | |
2287
573da4dac306
Make the dos installer work with more compilers.
Bram Moolenaar <bram@vim.org>
parents:
2217
diff
changeset
|
65 |
8212
05b88224cea1
commit https://github.com/vim/vim/commit/48e330aff911be1c798c88a973af6437a8141fce
Christian Brabandt <cb@256bit.org>
parents:
8080
diff
changeset
|
66 #define sleep(n) Sleep((n) * 1000) |
2287
573da4dac306
Make the dos installer work with more compilers.
Bram Moolenaar <bram@vim.org>
parents:
2217
diff
changeset
|
67 |
7 | 68 /* ---------------------------------------- */ |
69 | |
70 | |
71 #define BUFSIZE 512 /* long enough to hold a file name path */ | |
72 #define NUL 0 | |
73 | |
74 #define FAIL 0 | |
75 #define OK 1 | |
76 | |
77 #ifndef FALSE | |
78 # define FALSE 0 | |
79 #endif | |
80 #ifndef TRUE | |
81 # define TRUE 1 | |
82 #endif | |
83 | |
2449
943280505f72
Fix that uninstaller isn't found on 64-bit Windows.
Bram Moolenaar <bram@vim.org>
parents:
2287
diff
changeset
|
84 /* |
943280505f72
Fix that uninstaller isn't found on 64-bit Windows.
Bram Moolenaar <bram@vim.org>
parents:
2287
diff
changeset
|
85 * Modern way of creating registry entries, also works on 64 bit windows when |
943280505f72
Fix that uninstaller isn't found on 64-bit Windows.
Bram Moolenaar <bram@vim.org>
parents:
2287
diff
changeset
|
86 * compiled as a 32 bit program. |
943280505f72
Fix that uninstaller isn't found on 64-bit Windows.
Bram Moolenaar <bram@vim.org>
parents:
2287
diff
changeset
|
87 */ |
943280505f72
Fix that uninstaller isn't found on 64-bit Windows.
Bram Moolenaar <bram@vim.org>
parents:
2287
diff
changeset
|
88 # ifndef KEY_WOW64_64KEY |
943280505f72
Fix that uninstaller isn't found on 64-bit Windows.
Bram Moolenaar <bram@vim.org>
parents:
2287
diff
changeset
|
89 # define KEY_WOW64_64KEY 0x0100 |
943280505f72
Fix that uninstaller isn't found on 64-bit Windows.
Bram Moolenaar <bram@vim.org>
parents:
2287
diff
changeset
|
90 # endif |
943280505f72
Fix that uninstaller isn't found on 64-bit Windows.
Bram Moolenaar <bram@vim.org>
parents:
2287
diff
changeset
|
91 |
7 | 92 #define VIM_STARTMENU "Programs\\Vim " VIM_VERSION_SHORT |
93 | |
94 int interactive; /* non-zero when running interactively */ | |
95 | |
96 /* | |
97 * Call malloc() and exit when out of memory. | |
98 */ | |
99 static void * | |
100 alloc(int len) | |
101 { | |
102 char *s; | |
103 | |
104 s = malloc(len); | |
105 if (s == NULL) | |
106 { | |
107 printf("ERROR: out of memory\n"); | |
108 exit(1); | |
109 } | |
110 return (void *)s; | |
111 } | |
112 | |
113 /* | |
114 * The toupper() in Bcc 5.5 doesn't work, use our own implementation. | |
115 */ | |
116 static int | |
117 mytoupper(int c) | |
118 { | |
119 if (c >= 'a' && c <= 'z') | |
120 return c - 'a' + 'A'; | |
121 return c; | |
122 } | |
123 | |
124 static void | |
125 myexit(int n) | |
126 { | |
127 if (!interactive) | |
128 { | |
129 /* Present a prompt, otherwise error messages can't be read. */ | |
130 printf("Press Enter to continue\n"); | |
131 rewind(stdin); | |
132 (void)getchar(); | |
133 } | |
134 exit(n); | |
135 } | |
136 | |
137 #ifdef WIN3264 | |
138 /* This symbol is not defined in older versions of the SDK or Visual C++ */ | |
139 | |
140 #ifndef VER_PLATFORM_WIN32_WINDOWS | |
141 # define VER_PLATFORM_WIN32_WINDOWS 1 | |
142 #endif | |
143 | |
144 static DWORD g_PlatformId; | |
145 | |
146 /* | |
147 * Set g_PlatformId to VER_PLATFORM_WIN32_NT (NT) or | |
148 * VER_PLATFORM_WIN32_WINDOWS (Win95). | |
149 */ | |
150 static void | |
151 PlatformId(void) | |
152 { | |
153 static int done = FALSE; | |
154 | |
155 if (!done) | |
156 { | |
157 OSVERSIONINFO ovi; | |
158 | |
159 ovi.dwOSVersionInfoSize = sizeof(ovi); | |
160 GetVersionEx(&ovi); | |
161 | |
162 g_PlatformId = ovi.dwPlatformId; | |
163 done = TRUE; | |
164 } | |
165 } | |
166 | |
167 # ifdef __BORLANDC__ | |
168 /* Borland defines its own searchpath() in dir.h */ | |
169 # include <dir.h> | |
170 # else | |
171 static char * | |
172 searchpath(char *name) | |
173 { | |
174 static char widename[2 * BUFSIZE]; | |
175 static char location[2 * BUFSIZE + 2]; | |
176 | |
177 /* There appears to be a bug in FindExecutableA() on Windows NT. | |
178 * Use FindExecutableW() instead... */ | |
179 PlatformId(); | |
180 if (g_PlatformId == VER_PLATFORM_WIN32_NT) | |
181 { | |
182 MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)name, -1, | |
183 (LPWSTR)widename, BUFSIZE); | |
184 if (FindExecutableW((LPCWSTR)widename, (LPCWSTR)"", | |
185 (LPWSTR)location) > (HINSTANCE)32) | |
186 { | |
187 WideCharToMultiByte(CP_ACP, 0, (LPWSTR)location, -1, | |
188 (LPSTR)widename, 2 * BUFSIZE, NULL, NULL); | |
189 return widename; | |
190 } | |
191 } | |
192 else | |
193 { | |
194 if (FindExecutableA((LPCTSTR)name, (LPCTSTR)"", | |
195 (LPTSTR)location) > (HINSTANCE)32) | |
196 return location; | |
197 } | |
198 return NULL; | |
199 } | |
200 # endif | |
201 #endif | |
202 | |
203 /* | |
204 * Call searchpath() and save the result in allocated memory, or return NULL. | |
205 */ | |
206 static char * | |
207 searchpath_save(char *name) | |
208 { | |
209 char *p; | |
210 char *s; | |
211 | |
212 p = searchpath(name); | |
213 if (p == NULL) | |
214 return NULL; | |
215 s = alloc(strlen(p) + 1); | |
216 strcpy(s, p); | |
217 return s; | |
218 } | |
219 | |
220 #ifdef WIN3264 | |
826 | 221 |
222 #ifndef CSIDL_COMMON_PROGRAMS | |
223 # define CSIDL_COMMON_PROGRAMS 0x0017 | |
224 #endif | |
225 #ifndef CSIDL_COMMON_DESKTOPDIRECTORY | |
226 # define CSIDL_COMMON_DESKTOPDIRECTORY 0x0019 | |
227 #endif | |
228 | |
7 | 229 /* |
230 * Get the path to a requested Windows shell folder. | |
231 * | |
232 * Return FAIL on error, OK on success | |
233 */ | |
234 int | |
235 get_shell_folder_path( | |
236 char *shell_folder_path, | |
237 const char *shell_folder_name) | |
238 { | |
239 /* | |
240 * The following code was successfully built with make_mvc.mak. | |
241 * The resulting executable worked on Windows 95, Millennium Edition, and | |
242 * 2000 Professional. But it was changed after testing... | |
243 */ | |
244 LPITEMIDLIST pidl = 0; /* Pointer to an Item ID list allocated below */ | |
245 LPMALLOC pMalloc; /* Pointer to an IMalloc interface */ | |
246 int csidl; | |
247 int alt_csidl = -1; | |
248 static int desktop_csidl = -1; | |
249 static int programs_csidl = -1; | |
250 int *pcsidl; | |
251 int r; | |
252 | |
253 if (strcmp(shell_folder_name, "desktop") == 0) | |
254 { | |
255 pcsidl = &desktop_csidl; | |
256 csidl = CSIDL_COMMON_DESKTOPDIRECTORY; | |
257 alt_csidl = CSIDL_DESKTOP; | |
258 } | |
259 else if (strncmp(shell_folder_name, "Programs", 8) == 0) | |
260 { | |
261 pcsidl = &programs_csidl; | |
262 csidl = CSIDL_COMMON_PROGRAMS; | |
263 alt_csidl = CSIDL_PROGRAMS; | |
264 } | |
265 else | |
266 { | |
267 printf("\nERROR (internal) unrecognised shell_folder_name: \"%s\"\n\n", | |
268 shell_folder_name); | |
269 return FAIL; | |
270 } | |
271 | |
272 /* Did this stuff before, use the same ID again. */ | |
273 if (*pcsidl >= 0) | |
274 { | |
275 csidl = *pcsidl; | |
276 alt_csidl = -1; | |
277 } | |
278 | |
279 retry: | |
280 /* Initialize pointer to IMalloc interface */ | |
281 if (NOERROR != SHGetMalloc(&pMalloc)) | |
282 { | |
283 printf("\nERROR getting interface for shell_folder_name: \"%s\"\n\n", | |
284 shell_folder_name); | |
285 return FAIL; | |
286 } | |
287 | |
288 /* Get an ITEMIDLIST corresponding to the folder code */ | |
289 if (NOERROR != SHGetSpecialFolderLocation(0, csidl, &pidl)) | |
290 { | |
291 if (alt_csidl < 0 || NOERROR != SHGetSpecialFolderLocation(0, | |
292 alt_csidl, &pidl)) | |
293 { | |
294 printf("\nERROR getting ITEMIDLIST for shell_folder_name: \"%s\"\n\n", | |
295 shell_folder_name); | |
296 return FAIL; | |
297 } | |
298 csidl = alt_csidl; | |
299 alt_csidl = -1; | |
300 } | |
301 | |
302 /* Translate that ITEMIDLIST to a string */ | |
303 r = SHGetPathFromIDList(pidl, shell_folder_path); | |
304 | |
305 /* Free the data associated with pidl */ | |
306 pMalloc->lpVtbl->Free(pMalloc, pidl); | |
307 /* Release the IMalloc interface */ | |
308 pMalloc->lpVtbl->Release(pMalloc); | |
309 | |
310 if (!r) | |
311 { | |
312 if (alt_csidl >= 0) | |
313 { | |
314 /* We probably get here for Windows 95: the "all users" | |
315 * desktop/start menu entry doesn't exist. */ | |
316 csidl = alt_csidl; | |
317 alt_csidl = -1; | |
318 goto retry; | |
319 } | |
320 printf("\nERROR translating ITEMIDLIST for shell_folder_name: \"%s\"\n\n", | |
321 shell_folder_name); | |
322 return FAIL; | |
323 } | |
324 | |
325 /* If there is an alternative: verify we can write in this directory. | |
326 * This should cause a retry when the "all users" directory exists but we | |
327 * are a normal user and can't write there. */ | |
328 if (alt_csidl >= 0) | |
329 { | |
330 char tbuf[BUFSIZE]; | |
331 FILE *fd; | |
332 | |
333 strcpy(tbuf, shell_folder_path); | |
334 strcat(tbuf, "\\vim write test"); | |
335 fd = fopen(tbuf, "w"); | |
336 if (fd == NULL) | |
337 { | |
338 csidl = alt_csidl; | |
339 alt_csidl = -1; | |
340 goto retry; | |
341 } | |
342 fclose(fd); | |
343 unlink(tbuf); | |
344 } | |
345 | |
346 /* | |
347 * Keep the found csidl for next time, so that we don't have to do the | |
348 * write test every time. | |
349 */ | |
350 if (*pcsidl < 0) | |
351 *pcsidl = csidl; | |
352 | |
353 if (strncmp(shell_folder_name, "Programs\\", 9) == 0) | |
354 strcat(shell_folder_path, shell_folder_name + 8); | |
355 | |
356 return OK; | |
357 } | |
358 #endif | |
359 | |
360 /* | |
361 * List of targets. The first one (index zero) is used for the default path | |
362 * for the batch files. | |
363 */ | |
782 | 364 #define TARGET_COUNT 9 |
7 | 365 |
366 struct | |
367 { | |
368 char *name; /* Vim exe name (without .exe) */ | |
369 char *batname; /* batch file name */ | |
370 char *lnkname; /* shortcut file name */ | |
371 char *exename; /* exe file name */ | |
372 char *exenamearg; /* exe file name when using exearg */ | |
373 char *exearg; /* argument for vim.exe or gvim.exe */ | |
374 char *oldbat; /* path to existing xxx.bat or NULL */ | |
375 char *oldexe; /* path to existing xxx.exe or NULL */ | |
376 char batpath[BUFSIZE]; /* path of batch file to create; not | |
377 created when it's empty */ | |
378 } targets[TARGET_COUNT] = | |
379 { | |
380 {"all", "batch files"}, | |
381 {"vim", "vim.bat", "Vim.lnk", | |
382 "vim.exe", "vim.exe", ""}, | |
383 {"gvim", "gvim.bat", "gVim.lnk", | |
384 "gvim.exe", "gvim.exe", ""}, | |
385 {"evim", "evim.bat", "gVim Easy.lnk", | |
386 "evim.exe", "gvim.exe", "-y"}, | |
387 {"view", "view.bat", "Vim Read-only.lnk", | |
388 "view.exe", "vim.exe", "-R"}, | |
389 {"gview", "gview.bat", "gVim Read-only.lnk", | |
390 "gview.exe", "gvim.exe", "-R"}, | |
391 {"vimdiff", "vimdiff.bat", "Vim Diff.lnk", | |
392 "vimdiff.exe","vim.exe", "-d"}, | |
393 {"gvimdiff","gvimdiff.bat", "gVim Diff.lnk", | |
394 "gvimdiff.exe","gvim.exe", "-d"}, | |
782 | 395 {"vimtutor","vimtutor.bat", "Vim tutor.lnk", |
396 "vimtutor.bat", "vimtutor.bat", ""}, | |
7 | 397 }; |
398 | |
399 #define ICON_COUNT 3 | |
400 char *(icon_names[ICON_COUNT]) = | |
401 {"gVim " VIM_VERSION_SHORT, | |
402 "gVim Easy " VIM_VERSION_SHORT, | |
403 "gVim Read only " VIM_VERSION_SHORT}; | |
404 char *(icon_link_names[ICON_COUNT]) = | |
405 {"gVim " VIM_VERSION_SHORT ".lnk", | |
406 "gVim Easy " VIM_VERSION_SHORT ".lnk", | |
407 "gVim Read only " VIM_VERSION_SHORT ".lnk"}; | |
408 | |
2287
573da4dac306
Make the dos installer work with more compilers.
Bram Moolenaar <bram@vim.org>
parents:
2217
diff
changeset
|
409 /* This is only used for dosinst.c when WIN3264 is defined and for uninstal.c |
573da4dac306
Make the dos installer work with more compilers.
Bram Moolenaar <bram@vim.org>
parents:
2217
diff
changeset
|
410 * when not being able to directly access registry entries. */ |
573da4dac306
Make the dos installer work with more compilers.
Bram Moolenaar <bram@vim.org>
parents:
2217
diff
changeset
|
411 #if (defined(DOSINST) && defined(WIN3264)) \ |
573da4dac306
Make the dos installer work with more compilers.
Bram Moolenaar <bram@vim.org>
parents:
2217
diff
changeset
|
412 || (!defined(DOSINST) && !defined(WIN3264)) |
7 | 413 /* |
414 * Run an external command and wait for it to finish. | |
415 */ | |
416 static void | |
417 run_command(char *cmd) | |
418 { | |
419 char *cmd_path; | |
420 char cmd_buf[BUFSIZE]; | |
421 char *p; | |
422 | |
423 /* On WinNT, 'start' is a shell built-in for cmd.exe rather than an | |
8212
05b88224cea1
commit https://github.com/vim/vim/commit/48e330aff911be1c798c88a973af6437a8141fce
Christian Brabandt <cb@256bit.org>
parents:
8080
diff
changeset
|
424 * executable (start.exe) like in Win9x. */ |
7 | 425 cmd_path = searchpath_save("cmd.exe"); |
426 if (cmd_path != NULL) | |
427 { | |
428 /* There is a cmd.exe, so this might be Windows NT. If it is, | |
429 * we need to call cmd.exe explicitly. If it is a later OS, | |
430 * calling cmd.exe won't hurt if it is present. | |
2217
120502692d82
Improve the MS-Windows installer.
Bram Moolenaar <bram@vim.org>
parents:
1222
diff
changeset
|
431 * Also, "start" on NT expects a window title argument. |
7 | 432 */ |
433 /* Replace the slashes with backslashes. */ | |
434 while ((p = strchr(cmd_path, '/')) != NULL) | |
435 *p = '\\'; | |
2217
120502692d82
Improve the MS-Windows installer.
Bram Moolenaar <bram@vim.org>
parents:
1222
diff
changeset
|
436 sprintf(cmd_buf, "%s /c start \"vimcmd\" /wait %s", cmd_path, cmd); |
7 | 437 free(cmd_path); |
438 } | |
439 else | |
440 { | |
441 /* No cmd.exe, just make the call and let the system handle it. */ | |
442 sprintf(cmd_buf, "start /w %s", cmd); | |
443 } | |
444 system(cmd_buf); | |
445 } | |
446 #endif | |
447 | |
448 /* | |
449 * Append a backslash to "name" if there isn't one yet. | |
450 */ | |
8080
b6cb94ad97a4
commit https://github.com/vim/vim/commit/6aa2cd4be287f35f95f35c2cec6d5a24f53c4d3c
Christian Brabandt <cb@256bit.org>
parents:
2475
diff
changeset
|
451 void |
7 | 452 add_pathsep(char *name) |
453 { | |
454 int len = strlen(name); | |
455 | |
456 if (len > 0 && name[len - 1] != '\\' && name[len - 1] != '/') | |
457 strcat(name, "\\"); | |
458 } | |
459 | |
460 /* | |
461 * The normal chdir() does not change the default drive. This one does. | |
462 */ | |
463 /*ARGSUSED*/ | |
464 int | |
465 change_drive(int drive) | |
466 { | |
467 #ifdef WIN3264 | |
468 char temp[3] = "-:"; | |
469 temp[0] = (char)(drive + 'A' - 1); | |
470 return !SetCurrentDirectory(temp); | |
471 #else | |
472 # ifndef UNIX_LINT | |
473 union REGS regs; | |
474 | |
475 regs.h.ah = 0x0e; | |
476 regs.h.dl = drive - 1; | |
477 intdos(®s, ®s); /* set default drive */ | |
478 regs.h.ah = 0x19; | |
479 intdos(®s, ®s); /* get default drive */ | |
480 if (regs.h.al == drive - 1) | |
481 return 0; | |
482 # endif | |
483 return -1; | |
484 #endif | |
485 } | |
486 | |
487 /* | |
488 * Change directory to "path". | |
489 * Return 0 for success, -1 for failure. | |
490 */ | |
491 int | |
492 mch_chdir(char *path) | |
493 { | |
494 if (path[0] == NUL) /* just checking... */ | |
495 return 0; | |
496 if (path[1] == ':') /* has a drive name */ | |
497 { | |
498 if (change_drive(mytoupper(path[0]) - 'A' + 1)) | |
499 return -1; /* invalid drive name */ | |
500 path += 2; | |
501 } | |
502 if (*path == NUL) /* drive name only */ | |
503 return 0; | |
504 return chdir(path); /* let the normal chdir() do the rest */ | |
505 } | |
506 | |
507 /* | |
508 * Expand the executable name into a full path name. | |
509 */ | |
510 #if defined(__BORLANDC__) && !defined(WIN3264) | |
511 | |
512 /* Only Borland C++ has this. */ | |
513 # define my_fullpath(b, n, l) _fullpath(b, n, l) | |
514 | |
515 #else | |
516 static char * | |
517 my_fullpath(char *buf, char *fname, int len) | |
518 { | |
519 # ifdef WIN3264 | |
520 /* Only GetModuleFileName() will get the long file name path. | |
521 * GetFullPathName() may still use the short (FAT) name. */ | |
522 DWORD len_read = GetModuleFileName(NULL, buf, (size_t)len); | |
523 | |
524 return (len_read > 0 && len_read < (DWORD)len) ? buf : NULL; | |
525 # else | |
526 char olddir[BUFSIZE]; | |
527 char *p, *q; | |
528 int c; | |
529 char *retval = buf; | |
530 | |
1222 | 531 if (strchr(fname, ':') != NULL) /* already expanded */ |
7 | 532 { |
533 strncpy(buf, fname, len); | |
534 } | |
535 else | |
536 { | |
537 *buf = NUL; | |
538 /* | |
539 * change to the directory for a moment, | |
540 * and then do the getwd() (and get back to where we were). | |
541 * This will get the correct path name with "../" things. | |
542 */ | |
543 p = strrchr(fname, '/'); | |
544 q = strrchr(fname, '\\'); | |
545 if (q != NULL && (p == NULL || q > p)) | |
546 p = q; | |
547 q = strrchr(fname, ':'); | |
548 if (q != NULL && (p == NULL || q > p)) | |
549 p = q; | |
550 if (p != NULL) | |
551 { | |
552 if (getcwd(olddir, BUFSIZE) == NULL) | |
553 { | |
554 p = NULL; /* can't get current dir: don't chdir */ | |
555 retval = NULL; | |
556 } | |
557 else | |
558 { | |
559 if (p == fname) /* /fname */ | |
560 q = p + 1; /* -> / */ | |
561 else if (q + 1 == p) /* ... c:\foo */ | |
562 q = p + 1; /* -> c:\ */ | |
563 else /* but c:\foo\bar */ | |
564 q = p; /* -> c:\foo */ | |
565 | |
566 c = *q; /* truncate at start of fname */ | |
567 *q = NUL; | |
568 if (mch_chdir(fname)) /* change to the directory */ | |
569 retval = NULL; | |
570 else | |
571 { | |
572 fname = q; | |
573 if (c == '\\') /* if we cut the name at a */ | |
574 fname++; /* '\', don't add it again */ | |
575 } | |
576 *q = c; | |
577 } | |
578 } | |
579 if (getcwd(buf, len) == NULL) | |
580 { | |
581 retval = NULL; | |
582 *buf = NUL; | |
583 } | |
584 /* | |
585 * Concatenate the file name to the path. | |
586 */ | |
587 if (strlen(buf) + strlen(fname) >= len - 1) | |
588 { | |
589 printf("ERROR: File name too long!\n"); | |
590 myexit(1); | |
591 } | |
592 add_pathsep(buf); | |
593 strcat(buf, fname); | |
594 if (p) | |
595 mch_chdir(olddir); | |
596 } | |
597 | |
598 /* Replace forward slashes with backslashes, required for the path to a | |
599 * command. */ | |
600 while ((p = strchr(buf, '/')) != NULL) | |
601 *p = '\\'; | |
602 | |
603 return retval; | |
604 # endif | |
605 } | |
606 #endif | |
607 | |
608 /* | |
609 * Remove the tail from a file or directory name. | |
610 * Puts a NUL on the last '/' or '\'. | |
611 */ | |
612 static void | |
613 remove_tail(char *path) | |
614 { | |
615 int i; | |
616 | |
617 for (i = strlen(path) - 1; i > 0; --i) | |
618 if (path[i] == '/' || path[i] == '\\') | |
619 { | |
620 path[i] = NUL; | |
621 break; | |
622 } | |
623 } | |
624 | |
625 | |
626 char installdir[BUFSIZE]; /* top of the installation dir, where the | |
627 install.exe is located, E.g.: | |
628 "c:\vim\vim60" */ | |
629 int runtimeidx; /* index in installdir[] where "vim60" starts */ | |
630 char *sysdrive; /* system drive or "c:\" */ | |
631 | |
632 /* | |
633 * Setup for using this program. | |
634 * Sets "installdir[]". | |
635 */ | |
636 static void | |
637 do_inits(char **argv) | |
638 { | |
639 /* Find out the full path of our executable. */ | |
640 if (my_fullpath(installdir, argv[0], BUFSIZE) == NULL) | |
641 { | |
642 printf("ERROR: Cannot get name of executable\n"); | |
643 myexit(1); | |
644 } | |
645 /* remove the tail, the executable name "install.exe" */ | |
646 remove_tail(installdir); | |
647 | |
648 /* change to the installdir */ | |
649 mch_chdir(installdir); | |
650 | |
651 /* Find the system drive. Only used for searching the Vim executable, not | |
652 * very important. */ | |
653 sysdrive = getenv("SYSTEMDRIVE"); | |
654 if (sysdrive == NULL || *sysdrive == NUL) | |
655 sysdrive = "C:\\"; | |
656 } |