]>
Commit | Line | Data |
---|---|---|
a2e11672 AG |
1 | To: vim_dev@googlegroups.com |
2 | Subject: Patch 7.3.240 | |
3 | Fcc: outbox | |
4 | From: Bram Moolenaar <Bram@moolenaar.net> | |
5 | Mime-Version: 1.0 | |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ------------ | |
9 | ||
10 | Note: I haven't verified this works or even compiles. Please send me a | |
11 | patch if you see a problem and can fix it. | |
12 | ||
13 | Patch 7.3.240 | |
14 | Problem: External commands can't use pipes on MS-Windows. | |
15 | Solution: Implement pipes and use them when 'shelltemp' isn't set. (Vincent | |
16 | Berthoux) | |
17 | Files: src/eval.c, src/ex_cmds.c, src/misc2.c, src/os_unix.c, | |
18 | src/os_win32.c, src/proto/misc2.pro, src/ui.c | |
19 | ||
20 | ||
21 | *** ../vim-7.3.239/src/eval.c 2011-06-19 02:55:32.000000000 +0200 | |
22 | --- src/eval.c 2011-07-07 15:44:56.000000000 +0200 | |
23 | *************** | |
24 | *** 11931,11937 **** | |
25 | #ifdef FEAT_SEARCHPATH | |
26 | "file_in_path", | |
27 | #endif | |
28 | ! #if defined(UNIX) && !defined(USE_SYSTEM) | |
29 | "filterpipe", | |
30 | #endif | |
31 | #ifdef FEAT_FIND_ID | |
32 | --- 11931,11937 ---- | |
33 | #ifdef FEAT_SEARCHPATH | |
34 | "file_in_path", | |
35 | #endif | |
36 | ! #if (defined(UNIX) && !defined(USE_SYSTEM)) || defined(WIN3264) | |
37 | "filterpipe", | |
38 | #endif | |
39 | #ifdef FEAT_FIND_ID | |
40 | *** ../vim-7.3.239/src/ex_cmds.c 2011-06-12 22:03:15.000000000 +0200 | |
41 | --- src/ex_cmds.c 2011-07-07 15:44:56.000000000 +0200 | |
42 | *************** | |
43 | *** 1107,1113 **** | |
44 | if (do_out) | |
45 | shell_flags |= SHELL_DOOUT; | |
46 | ||
47 | ! #if !defined(USE_SYSTEM) && defined(UNIX) | |
48 | if (!do_in && do_out && !p_stmp) | |
49 | { | |
50 | /* Use a pipe to fetch stdout of the command, do not use a temp file. */ | |
51 | --- 1107,1113 ---- | |
52 | if (do_out) | |
53 | shell_flags |= SHELL_DOOUT; | |
54 | ||
55 | ! #if (!defined(USE_SYSTEM) && defined(UNIX)) || defined(WIN3264) | |
56 | if (!do_in && do_out && !p_stmp) | |
57 | { | |
58 | /* Use a pipe to fetch stdout of the command, do not use a temp file. */ | |
59 | *** ../vim-7.3.239/src/misc2.c 2011-07-07 15:08:53.000000000 +0200 | |
60 | --- src/misc2.c 2011-07-07 15:55:42.000000000 +0200 | |
61 | *************** | |
62 | *** 2146,2151 **** | |
63 | --- 2146,2170 ---- | |
64 | } | |
65 | } | |
66 | ||
67 | + #if (defined(UNIX) && !defined(USE_SYSTEM)) || defined(WIN3264) | |
68 | + /* | |
69 | + * Append the text in "gap" below the cursor line and clear "gap". | |
70 | + */ | |
71 | + void | |
72 | + append_ga_line(gap) | |
73 | + garray_T *gap; | |
74 | + { | |
75 | + /* Remove trailing CR. */ | |
76 | + if (gap->ga_len > 0 | |
77 | + && !curbuf->b_p_bin | |
78 | + && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR) | |
79 | + --gap->ga_len; | |
80 | + ga_append(gap, NUL); | |
81 | + ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE); | |
82 | + gap->ga_len = 0; | |
83 | + } | |
84 | + #endif | |
85 | + | |
86 | /************************************************************************ | |
87 | * functions that use lookup tables for various things, generally to do with | |
88 | * special key codes. | |
89 | *** ../vim-7.3.239/src/os_unix.c 2011-04-11 16:56:29.000000000 +0200 | |
90 | --- src/os_unix.c 2011-07-07 15:54:58.000000000 +0200 | |
91 | *************** | |
92 | *** 3660,3686 **** | |
93 | /* Nothing to do. */ | |
94 | } | |
95 | ||
96 | - #ifndef USE_SYSTEM | |
97 | - static void append_ga_line __ARGS((garray_T *gap)); | |
98 | - | |
99 | - /* | |
100 | - * Append the text in "gap" below the cursor line and clear "gap". | |
101 | - */ | |
102 | - static void | |
103 | - append_ga_line(gap) | |
104 | - garray_T *gap; | |
105 | - { | |
106 | - /* Remove trailing CR. */ | |
107 | - if (gap->ga_len > 0 | |
108 | - && !curbuf->b_p_bin | |
109 | - && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR) | |
110 | - --gap->ga_len; | |
111 | - ga_append(gap, NUL); | |
112 | - ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE); | |
113 | - gap->ga_len = 0; | |
114 | - } | |
115 | - #endif | |
116 | - | |
117 | int | |
118 | mch_call_shell(cmd, options) | |
119 | char_u *cmd; | |
120 | --- 3660,3665 ---- | |
121 | *** ../vim-7.3.239/src/os_win32.c 2011-05-25 17:06:16.000000000 +0200 | |
122 | --- src/os_win32.c 2011-07-07 16:08:30.000000000 +0200 | |
123 | *************** | |
124 | *** 417,422 **** | |
125 | --- 417,427 ---- | |
126 | static PGNSECINFO pGetNamedSecurityInfo; | |
127 | #endif | |
128 | ||
129 | + typedef BOOL (WINAPI *PSETHANDLEINFORMATION)(HANDLE, DWORD, DWORD); | |
130 | + | |
131 | + static BOOL allowPiping = FALSE; | |
132 | + static PSETHANDLEINFORMATION pSetHandleInformation; | |
133 | + | |
134 | /* | |
135 | * Set g_PlatformId to VER_PLATFORM_WIN32_NT (NT) or | |
136 | * VER_PLATFORM_WIN32_WINDOWS (Win95). | |
137 | *************** | |
138 | *** 467,472 **** | |
139 | --- 472,489 ---- | |
140 | } | |
141 | } | |
142 | #endif | |
143 | + /* | |
144 | + * If we are on windows NT, try to load the pipe functions, only | |
145 | + * available from Win2K. | |
146 | + */ | |
147 | + if (g_PlatformId == VER_PLATFORM_WIN32_NT) | |
148 | + { | |
149 | + HANDLE kernel32 = GetModuleHandle("kernel32"); | |
150 | + pSetHandleInformation = (PSETHANDLEINFORMATION)GetProcAddress( | |
151 | + kernel32, "SetHandleInformation"); | |
152 | + | |
153 | + allowPiping = pSetHandleInformation != NULL; | |
154 | + } | |
155 | done = TRUE; | |
156 | } | |
157 | } | |
158 | *************** | |
159 | *** 1635,1641 **** | |
160 | } | |
161 | ||
162 | #if ((defined(__MINGW32__) || defined (__CYGWIN32__)) && \ | |
163 | ! __MSVCRT_VERSION__ >= 0x800) || (defined(_MSC_VER) && _MSC_VER >= 1400) | |
164 | /* | |
165 | * Bad parameter handler. | |
166 | * | |
167 | --- 1652,1658 ---- | |
168 | } | |
169 | ||
170 | #if ((defined(__MINGW32__) || defined (__CYGWIN32__)) && \ | |
171 | ! __MSVCRT_VERSION__ >= 0x800) || (defined(_MSC_VER) && _MSC_VER >= 1400) | |
172 | /* | |
173 | * Bad parameter handler. | |
174 | * | |
175 | *************** | |
176 | *** 3210,3216 **** | |
177 | * 4. Prompt the user to press a key to close the console window | |
178 | */ | |
179 | static int | |
180 | ! mch_system(char *cmd, int options) | |
181 | { | |
182 | STARTUPINFO si; | |
183 | PROCESS_INFORMATION pi; | |
184 | --- 3227,3233 ---- | |
185 | * 4. Prompt the user to press a key to close the console window | |
186 | */ | |
187 | static int | |
188 | ! mch_system_classic(char *cmd, int options) | |
189 | { | |
190 | STARTUPINFO si; | |
191 | PROCESS_INFORMATION pi; | |
192 | *************** | |
193 | *** 3315,3320 **** | |
194 | --- 3332,3829 ---- | |
195 | ||
196 | return ret; | |
197 | } | |
198 | + | |
199 | + /* | |
200 | + * Thread launched by the gui to send the current buffer data to the | |
201 | + * process. This way avoid to hang up vim totally if the children | |
202 | + * process take a long time to process the lines. | |
203 | + */ | |
204 | + static DWORD WINAPI | |
205 | + sub_process_writer(LPVOID param) | |
206 | + { | |
207 | + HANDLE g_hChildStd_IN_Wr = param; | |
208 | + linenr_T lnum = curbuf->b_op_start.lnum; | |
209 | + DWORD len = 0; | |
210 | + DWORD l; | |
211 | + char_u *lp = ml_get(lnum); | |
212 | + char_u *s; | |
213 | + int written = 0; | |
214 | + | |
215 | + for (;;) | |
216 | + { | |
217 | + l = (DWORD)STRLEN(lp + written); | |
218 | + if (l == 0) | |
219 | + len = 0; | |
220 | + else if (lp[written] == NL) | |
221 | + { | |
222 | + /* NL -> NUL translation */ | |
223 | + WriteFile(g_hChildStd_IN_Wr, "", 1, &len, NULL); | |
224 | + } | |
225 | + else | |
226 | + { | |
227 | + s = vim_strchr(lp + written, NL); | |
228 | + WriteFile(g_hChildStd_IN_Wr, (char *)lp + written, | |
229 | + s == NULL ? l : (DWORD)(s - (lp + written)), | |
230 | + &len, NULL); | |
231 | + } | |
232 | + if (len == (int)l) | |
233 | + { | |
234 | + /* Finished a line, add a NL, unless this line should not have | |
235 | + * one. */ | |
236 | + if (lnum != curbuf->b_op_end.lnum | |
237 | + || !curbuf->b_p_bin | |
238 | + || (lnum != curbuf->b_no_eol_lnum | |
239 | + && (lnum != curbuf->b_ml.ml_line_count | |
240 | + || curbuf->b_p_eol))) | |
241 | + { | |
242 | + WriteFile(g_hChildStd_IN_Wr, "\n", 1, &ignored, NULL); | |
243 | + } | |
244 | + | |
245 | + ++lnum; | |
246 | + if (lnum > curbuf->b_op_end.lnum) | |
247 | + break; | |
248 | + | |
249 | + lp = ml_get(lnum); | |
250 | + written = 0; | |
251 | + } | |
252 | + else if (len > 0) | |
253 | + written += len; | |
254 | + } | |
255 | + | |
256 | + /* finished all the lines, close pipe */ | |
257 | + CloseHandle(g_hChildStd_IN_Wr); | |
258 | + ExitThread(0); | |
259 | + } | |
260 | + | |
261 | + | |
262 | + # define BUFLEN 100 /* length for buffer, stolen from unix version */ | |
263 | + | |
264 | + /* | |
265 | + * This function read from the children's stdout and write the | |
266 | + * data on screen or in the buffer accordingly. | |
267 | + */ | |
268 | + static void | |
269 | + dump_pipe(int options, | |
270 | + HANDLE g_hChildStd_OUT_Rd, | |
271 | + garray_T *ga, | |
272 | + char_u buffer[], | |
273 | + DWORD *buffer_off) | |
274 | + { | |
275 | + DWORD availableBytes = 0; | |
276 | + DWORD i; | |
277 | + int c; | |
278 | + char_u *p; | |
279 | + int ret; | |
280 | + DWORD len; | |
281 | + DWORD toRead; | |
282 | + int repeatCount; | |
283 | + | |
284 | + /* we query the pipe to see if there is any data to read | |
285 | + * to avoid to perform a blocking read */ | |
286 | + ret = PeekNamedPipe(g_hChildStd_OUT_Rd, /* pipe to query */ | |
287 | + NULL, /* optional buffer */ | |
288 | + 0, /* buffe size */ | |
289 | + NULL, /* number of read bytes */ | |
290 | + &availableBytes, /* available bytes total */ | |
291 | + NULL); /* byteLeft */ | |
292 | + | |
293 | + repeatCount = 0; | |
294 | + /* We got real data in the pipe, read it */ | |
295 | + while (ret != 0 && availableBytes > 0 && availableBytes > 0) | |
296 | + { | |
297 | + repeatCount++; | |
298 | + toRead = | |
299 | + # ifdef FEAT_MBYTE | |
300 | + (DWORD)(BUFLEN - *buffer_off); | |
301 | + # else | |
302 | + (DWORD)BUFLEN; | |
303 | + # endif | |
304 | + toRead = availableBytes < toRead ? availableBytes : toRead; | |
305 | + ReadFile(g_hChildStd_OUT_Rd, buffer | |
306 | + # ifdef FEAT_MBYTE | |
307 | + + *buffer_off, toRead | |
308 | + # else | |
309 | + , toRead | |
310 | + # endif | |
311 | + , &len, NULL); | |
312 | + | |
313 | + /* If we haven't read anything, there is a problem */ | |
314 | + if (len == 0) | |
315 | + break; | |
316 | + | |
317 | + availableBytes -= len; | |
318 | + | |
319 | + if (options & SHELL_READ) | |
320 | + { | |
321 | + /* Do NUL -> NL translation, append NL separated | |
322 | + * lines to the current buffer. */ | |
323 | + for (i = 0; i < len; ++i) | |
324 | + { | |
325 | + if (buffer[i] == NL) | |
326 | + append_ga_line(ga); | |
327 | + else if (buffer[i] == NUL) | |
328 | + ga_append(ga, NL); | |
329 | + else | |
330 | + ga_append(ga, buffer[i]); | |
331 | + } | |
332 | + } | |
333 | + # ifdef FEAT_MBYTE | |
334 | + else if (has_mbyte) | |
335 | + { | |
336 | + int l; | |
337 | + | |
338 | + len += *buffer_off; | |
339 | + buffer[len] = NUL; | |
340 | + | |
341 | + /* Check if the last character in buffer[] is | |
342 | + * incomplete, keep these bytes for the next | |
343 | + * round. */ | |
344 | + for (p = buffer; p < buffer + len; p += l) | |
345 | + { | |
346 | + l = mb_cptr2len(p); | |
347 | + if (l == 0) | |
348 | + l = 1; /* NUL byte? */ | |
349 | + else if (MB_BYTE2LEN(*p) != l) | |
350 | + break; | |
351 | + } | |
352 | + if (p == buffer) /* no complete character */ | |
353 | + { | |
354 | + /* avoid getting stuck at an illegal byte */ | |
355 | + if (len >= 12) | |
356 | + ++p; | |
357 | + else | |
358 | + { | |
359 | + *buffer_off = len; | |
360 | + return; | |
361 | + } | |
362 | + } | |
363 | + c = *p; | |
364 | + *p = NUL; | |
365 | + msg_puts(buffer); | |
366 | + if (p < buffer + len) | |
367 | + { | |
368 | + *p = c; | |
369 | + *buffer_off = (DWORD)((buffer + len) - p); | |
370 | + mch_memmove(buffer, p, *buffer_off); | |
371 | + return; | |
372 | + } | |
373 | + *buffer_off = 0; | |
374 | + } | |
375 | + # endif /* FEAT_MBYTE */ | |
376 | + else | |
377 | + { | |
378 | + buffer[len] = NUL; | |
379 | + msg_puts(buffer); | |
380 | + } | |
381 | + | |
382 | + windgoto(msg_row, msg_col); | |
383 | + cursor_on(); | |
384 | + out_flush(); | |
385 | + } | |
386 | + } | |
387 | + | |
388 | + /* | |
389 | + * Version of system to use for windows NT > 5.0 (Win2K), use pipe | |
390 | + * for communication and doesn't open any new window. | |
391 | + */ | |
392 | + static int | |
393 | + mch_system_piped(char *cmd, int options) | |
394 | + { | |
395 | + STARTUPINFO si; | |
396 | + PROCESS_INFORMATION pi; | |
397 | + DWORD ret = 0; | |
398 | + | |
399 | + HANDLE g_hChildStd_IN_Rd = NULL; | |
400 | + HANDLE g_hChildStd_IN_Wr = NULL; | |
401 | + HANDLE g_hChildStd_OUT_Rd = NULL; | |
402 | + HANDLE g_hChildStd_OUT_Wr = NULL; | |
403 | + | |
404 | + char_u buffer[BUFLEN + 1]; /* reading buffer + size */ | |
405 | + DWORD len; | |
406 | + | |
407 | + /* buffer used to receive keys */ | |
408 | + char_u ta_buf[BUFLEN + 1]; /* TypeAHead */ | |
409 | + int ta_len = 0; /* valid bytes in ta_buf[] */ | |
410 | + | |
411 | + DWORD i; | |
412 | + int c; | |
413 | + int noread_cnt = 0; | |
414 | + garray_T ga; | |
415 | + int delay = 1; | |
416 | + # ifdef FEAT_MBYTE | |
417 | + DWORD buffer_off = 0; /* valid bytes in buffer[] */ | |
418 | + # endif | |
419 | + | |
420 | + SECURITY_ATTRIBUTES saAttr; | |
421 | + | |
422 | + /* Set the bInheritHandle flag so pipe handles are inherited. */ | |
423 | + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); | |
424 | + saAttr.bInheritHandle = TRUE; | |
425 | + saAttr.lpSecurityDescriptor = NULL; | |
426 | + | |
427 | + if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) | |
428 | + /* Ensure the read handle to the pipe for STDOUT is not inherited. */ | |
429 | + || ! pSetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) | |
430 | + /* Create a pipe for the child process's STDIN. */ | |
431 | + || ! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0) | |
432 | + /* Ensure the write handle to the pipe for STDIN is not inherited. */ | |
433 | + || ! pSetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) ) | |
434 | + { | |
435 | + CloseHandle(g_hChildStd_IN_Rd); | |
436 | + CloseHandle(g_hChildStd_IN_Wr); | |
437 | + CloseHandle(g_hChildStd_OUT_Rd); | |
438 | + CloseHandle(g_hChildStd_OUT_Wr); | |
439 | + MSG_PUTS(_("\nCannot create pipes\n")); | |
440 | + } | |
441 | + | |
442 | + si.cb = sizeof(si); | |
443 | + si.lpReserved = NULL; | |
444 | + si.lpDesktop = NULL; | |
445 | + si.lpTitle = NULL; | |
446 | + si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; | |
447 | + | |
448 | + /* set-up our file redirection */ | |
449 | + si.hStdError = g_hChildStd_OUT_Wr; | |
450 | + si.hStdOutput = g_hChildStd_OUT_Wr; | |
451 | + si.hStdInput = g_hChildStd_IN_Rd; | |
452 | + si.wShowWindow = SW_HIDE; | |
453 | + si.cbReserved2 = 0; | |
454 | + si.lpReserved2 = NULL; | |
455 | + | |
456 | + if (options & SHELL_READ) | |
457 | + ga_init2(&ga, 1, BUFLEN); | |
458 | + | |
459 | + /* Now, run the command */ | |
460 | + CreateProcess(NULL, /* Executable name */ | |
461 | + cmd, /* Command to execute */ | |
462 | + NULL, /* Process security attributes */ | |
463 | + NULL, /* Thread security attributes */ | |
464 | + | |
465 | + // this command can be litigeous, handle inheritence was | |
466 | + // deactivated for pending temp file, but, if we deactivate | |
467 | + // it, the pipes don't work for some reason. | |
468 | + TRUE, /* Inherit handles, first deactivated, | |
469 | + * but needed */ | |
470 | + CREATE_DEFAULT_ERROR_MODE, /* Creation flags */ | |
471 | + NULL, /* Environment */ | |
472 | + NULL, /* Current directory */ | |
473 | + &si, /* Startup information */ | |
474 | + &pi); /* Process information */ | |
475 | + | |
476 | + | |
477 | + /* Close our unused side of the pipes */ | |
478 | + CloseHandle(g_hChildStd_IN_Rd); | |
479 | + CloseHandle(g_hChildStd_OUT_Wr); | |
480 | + | |
481 | + if (options & SHELL_WRITE) | |
482 | + { | |
483 | + HANDLE thread = | |
484 | + CreateThread(NULL, /* security attributes */ | |
485 | + 0, /* default stack size */ | |
486 | + sub_process_writer, /* function to be executed */ | |
487 | + g_hChildStd_IN_Wr, /* parameter */ | |
488 | + 0, /* creation flag, start immediately */ | |
489 | + NULL); /* we don't care about thread id */ | |
490 | + CloseHandle(thread); | |
491 | + g_hChildStd_IN_Wr = NULL; | |
492 | + } | |
493 | + | |
494 | + /* Keep updating the window while waiting for the shell to finish. */ | |
495 | + for (;;) | |
496 | + { | |
497 | + MSG msg; | |
498 | + | |
499 | + if (PeekMessage(&msg, (HWND)NULL, 0, 0, PM_REMOVE)) | |
500 | + { | |
501 | + TranslateMessage(&msg); | |
502 | + DispatchMessage(&msg); | |
503 | + } | |
504 | + | |
505 | + /* write pipe information in the window */ | |
506 | + if ((options & (SHELL_READ|SHELL_WRITE)) | |
507 | + # ifdef FEAT_GUI | |
508 | + || gui.in_use | |
509 | + # endif | |
510 | + ) | |
511 | + { | |
512 | + len = 0; | |
513 | + if (!(options & SHELL_EXPAND) | |
514 | + && ((options & | |
515 | + (SHELL_READ|SHELL_WRITE|SHELL_COOKED)) | |
516 | + != (SHELL_READ|SHELL_WRITE|SHELL_COOKED) | |
517 | + # ifdef FEAT_GUI | |
518 | + || gui.in_use | |
519 | + # endif | |
520 | + ) | |
521 | + && (ta_len > 0 || noread_cnt > 4)) | |
522 | + { | |
523 | + if (ta_len == 0) | |
524 | + { | |
525 | + /* Get extra characters when we don't have any. Reset the | |
526 | + * counter and timer. */ | |
527 | + noread_cnt = 0; | |
528 | + # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) | |
529 | + gettimeofday(&start_tv, NULL); | |
530 | + # endif | |
531 | + len = ui_inchar(ta_buf, BUFLEN, 10L, 0); | |
532 | + } | |
533 | + if (ta_len > 0 || len > 0) | |
534 | + { | |
535 | + /* | |
536 | + * For pipes: Check for CTRL-C: send interrupt signal to | |
537 | + * child. Check for CTRL-D: EOF, close pipe to child. | |
538 | + */ | |
539 | + if (len == 1 && cmd != NULL) | |
540 | + { | |
541 | + if (ta_buf[ta_len] == Ctrl_C) | |
542 | + { | |
543 | + /* Learn what exit code is expected, for | |
544 | + * now put 9 as SIGKILL */ | |
545 | + TerminateProcess(pi.hProcess, 9); | |
546 | + } | |
547 | + if (ta_buf[ta_len] == Ctrl_D) | |
548 | + { | |
549 | + CloseHandle(g_hChildStd_IN_Wr); | |
550 | + g_hChildStd_IN_Wr = NULL; | |
551 | + } | |
552 | + } | |
553 | + | |
554 | + /* replace K_BS by <BS> and K_DEL by <DEL> */ | |
555 | + for (i = ta_len; i < ta_len + len; ++i) | |
556 | + { | |
557 | + if (ta_buf[i] == CSI && len - i > 2) | |
558 | + { | |
559 | + c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]); | |
560 | + if (c == K_DEL || c == K_KDEL || c == K_BS) | |
561 | + { | |
562 | + mch_memmove(ta_buf + i + 1, ta_buf + i + 3, | |
563 | + (size_t)(len - i - 2)); | |
564 | + if (c == K_DEL || c == K_KDEL) | |
565 | + ta_buf[i] = DEL; | |
566 | + else | |
567 | + ta_buf[i] = Ctrl_H; | |
568 | + len -= 2; | |
569 | + } | |
570 | + } | |
571 | + else if (ta_buf[i] == '\r') | |
572 | + ta_buf[i] = '\n'; | |
573 | + # ifdef FEAT_MBYTE | |
574 | + if (has_mbyte) | |
575 | + i += (*mb_ptr2len_len)(ta_buf + i, | |
576 | + ta_len + len - i) - 1; | |
577 | + # endif | |
578 | + } | |
579 | + | |
580 | + /* | |
581 | + * For pipes: echo the typed characters. For a pty this | |
582 | + * does not seem to work. | |
583 | + */ | |
584 | + for (i = ta_len; i < ta_len + len; ++i) | |
585 | + { | |
586 | + if (ta_buf[i] == '\n' || ta_buf[i] == '\b') | |
587 | + msg_putchar(ta_buf[i]); | |
588 | + # ifdef FEAT_MBYTE | |
589 | + else if (has_mbyte) | |
590 | + { | |
591 | + int l = (*mb_ptr2len)(ta_buf + i); | |
592 | + | |
593 | + msg_outtrans_len(ta_buf + i, l); | |
594 | + i += l - 1; | |
595 | + } | |
596 | + # endif | |
597 | + else | |
598 | + msg_outtrans_len(ta_buf + i, 1); | |
599 | + } | |
600 | + windgoto(msg_row, msg_col); | |
601 | + out_flush(); | |
602 | + | |
603 | + ta_len += len; | |
604 | + | |
605 | + /* | |
606 | + * Write the characters to the child, unless EOF has been | |
607 | + * typed for pipes. Write one character at a time, to | |
608 | + * avoid losing too much typeahead. When writing buffer | |
609 | + * lines, drop the typed characters (only check for | |
610 | + * CTRL-C). | |
611 | + */ | |
612 | + if (options & SHELL_WRITE) | |
613 | + ta_len = 0; | |
614 | + else if (g_hChildStd_IN_Wr != NULL) | |
615 | + { | |
616 | + WriteFile(g_hChildStd_IN_Wr, (char*)ta_buf, | |
617 | + 1, &len, NULL); | |
618 | + // if we are typing in, we want to keep things reactive | |
619 | + delay = 1; | |
620 | + if (len > 0) | |
621 | + { | |
622 | + ta_len -= len; | |
623 | + mch_memmove(ta_buf, ta_buf + len, ta_len); | |
624 | + } | |
625 | + } | |
626 | + } | |
627 | + } | |
628 | + } | |
629 | + | |
630 | + if (ta_len) | |
631 | + ui_inchar_undo(ta_buf, ta_len); | |
632 | + | |
633 | + if (WaitForSingleObject(pi.hProcess, delay) != WAIT_TIMEOUT) | |
634 | + { | |
635 | + dump_pipe(options, g_hChildStd_OUT_Rd, | |
636 | + &ga, buffer, &buffer_off); | |
637 | + break; | |
638 | + } | |
639 | + | |
640 | + ++noread_cnt; | |
641 | + dump_pipe(options, g_hChildStd_OUT_Rd, | |
642 | + &ga, buffer, &buffer_off); | |
643 | + | |
644 | + /* We start waiting for a very short time and then increase it, so | |
645 | + * that we respond quickly when the process is quick, and don't | |
646 | + * consume too much overhead when it's slow. */ | |
647 | + if (delay < 50) | |
648 | + delay += 10; | |
649 | + } | |
650 | + | |
651 | + /* Close the pipe */ | |
652 | + CloseHandle(g_hChildStd_OUT_Rd); | |
653 | + if (g_hChildStd_IN_Wr != NULL) | |
654 | + CloseHandle(g_hChildStd_IN_Wr); | |
655 | + | |
656 | + WaitForSingleObject(pi.hProcess, INFINITE); | |
657 | + | |
658 | + /* Get the command exit code */ | |
659 | + GetExitCodeProcess(pi.hProcess, &ret); | |
660 | + | |
661 | + if (options & SHELL_READ) | |
662 | + { | |
663 | + if (ga.ga_len > 0) | |
664 | + { | |
665 | + append_ga_line(&ga); | |
666 | + /* remember that the NL was missing */ | |
667 | + curbuf->b_no_eol_lnum = curwin->w_cursor.lnum; | |
668 | + } | |
669 | + else | |
670 | + curbuf->b_no_eol_lnum = 0; | |
671 | + ga_clear(&ga); | |
672 | + } | |
673 | + | |
674 | + /* Close the handles to the subprocess, so that it goes away */ | |
675 | + CloseHandle(pi.hThread); | |
676 | + CloseHandle(pi.hProcess); | |
677 | + | |
678 | + return ret; | |
679 | + } | |
680 | + | |
681 | + static int | |
682 | + mch_system(char *cmd, int options) | |
683 | + { | |
684 | + /* if we can pipe and the shelltemp option is off */ | |
685 | + if (allowPiping && !p_stmp) | |
686 | + return mch_system_piped(cmd, options); | |
687 | + else | |
688 | + return mch_system_classic(cmd, options); | |
689 | + } | |
690 | #else | |
691 | ||
692 | # define mch_system(c, o) system(c) | |
693 | *************** | |
694 | *** 3388,3394 **** | |
695 | char_u *newcmd; | |
696 | long_u cmdlen = ( | |
697 | #ifdef FEAT_GUI_W32 | |
698 | ! STRLEN(vimrun_path) + | |
699 | #endif | |
700 | STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10); | |
701 | ||
702 | --- 3897,3903 ---- | |
703 | char_u *newcmd; | |
704 | long_u cmdlen = ( | |
705 | #ifdef FEAT_GUI_W32 | |
706 | ! (allowPiping && !p_stmp ? 0 : STRLEN(vimrun_path)) + | |
707 | #endif | |
708 | STRLEN(p_sh) + STRLEN(p_shcf) + STRLEN(cmd) + 10); | |
709 | ||
710 | *************** | |
711 | *** 3497,3503 **** | |
712 | MB_ICONWARNING); | |
713 | need_vimrun_warning = FALSE; | |
714 | } | |
715 | ! if (!s_dont_use_vimrun) | |
716 | /* Use vimrun to execute the command. It opens a console | |
717 | * window, which can be closed without killing Vim. */ | |
718 | vim_snprintf((char *)newcmd, cmdlen, "%s%s%s %s %s", | |
719 | --- 4006,4012 ---- | |
720 | MB_ICONWARNING); | |
721 | need_vimrun_warning = FALSE; | |
722 | } | |
723 | ! if (!s_dont_use_vimrun && (!allowPiping || p_stmp)) | |
724 | /* Use vimrun to execute the command. It opens a console | |
725 | * window, which can be closed without killing Vim. */ | |
726 | vim_snprintf((char *)newcmd, cmdlen, "%s%s%s %s %s", | |
727 | *************** | |
728 | *** 3521,3527 **** | |
729 | /* Print the return value, unless "vimrun" was used. */ | |
730 | if (x != 0 && !(options & SHELL_SILENT) && !emsg_silent | |
731 | #if defined(FEAT_GUI_W32) | |
732 | ! && ((options & SHELL_DOOUT) || s_dont_use_vimrun) | |
733 | #endif | |
734 | ) | |
735 | { | |
736 | --- 4030,4037 ---- | |
737 | /* Print the return value, unless "vimrun" was used. */ | |
738 | if (x != 0 && !(options & SHELL_SILENT) && !emsg_silent | |
739 | #if defined(FEAT_GUI_W32) | |
740 | ! && ((options & SHELL_DOOUT) || s_dont_use_vimrun | |
741 | ! || (allowPiping && !p_stmp)) | |
742 | #endif | |
743 | ) | |
744 | { | |
745 | *** ../vim-7.3.239/src/proto/misc2.pro 2011-07-07 15:08:53.000000000 +0200 | |
746 | --- src/proto/misc2.pro 2011-07-07 15:56:16.000000000 +0200 | |
747 | *************** | |
748 | *** 58,63 **** | |
749 | --- 58,64 ---- | |
750 | char_u *ga_concat_strings __ARGS((garray_T *gap)); | |
751 | void ga_concat __ARGS((garray_T *gap, char_u *s)); | |
752 | void ga_append __ARGS((garray_T *gap, int c)); | |
753 | + void append_ga_line __ARGS((garray_T *gap)); | |
754 | int name_to_mod_mask __ARGS((int c)); | |
755 | int simplify_key __ARGS((int key, int *modifiers)); | |
756 | int handle_x_keys __ARGS((int key)); | |
757 | *** ../vim-7.3.239/src/ui.c 2011-06-19 01:14:23.000000000 +0200 | |
758 | --- src/ui.c 2011-07-07 15:44:56.000000000 +0200 | |
759 | *************** | |
760 | *** 58,64 **** | |
761 | #endif | |
762 | } | |
763 | ||
764 | ! #if defined(UNIX) || defined(VMS) || defined(PROTO) | |
765 | /* | |
766 | * When executing an external program, there may be some typed characters that | |
767 | * are not consumed by it. Give them back to ui_inchar() and they are stored | |
768 | --- 58,64 ---- | |
769 | #endif | |
770 | } | |
771 | ||
772 | ! #if defined(UNIX) || defined(VMS) || defined(PROTO) || defined(WIN3264) | |
773 | /* | |
774 | * When executing an external program, there may be some typed characters that | |
775 | * are not consumed by it. Give them back to ui_inchar() and they are stored | |
776 | *** ../vim-7.3.239/src/version.c 2011-07-07 15:08:53.000000000 +0200 | |
777 | --- src/version.c 2011-07-07 16:14:20.000000000 +0200 | |
778 | *************** | |
779 | *** 711,712 **** | |
780 | --- 711,714 ---- | |
781 | { /* Add new patch number below this line */ | |
782 | + /**/ | |
783 | + 240, | |
784 | /**/ | |
785 | ||
786 | -- | |
787 | hundred-and-one symptoms of being an internet addict: | |
788 | 257. Your "hundred-and-one" lists include well over 101 items, since you | |
789 | automatically interpret all numbers in hexadecimal notation. | |
790 | (hex 101 = decimal 257) | |
791 | ||
792 | /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ | |
793 | /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ | |
794 | \\\ an exciting new programming language -- http://www.Zimbu.org /// | |
795 | \\\ help me help AIDS victims -- http://ICCF-Holland.org /// |