Merged from the latest developing branch.
[MacVim/KaoriYa.git] / src / os_unix.c
blobef73270da924c31079891a0b899db68f0b6aee69
1 /* vi:set ts=8 sts=4 sw=4:
3 * VIM - Vi IMproved by Bram Moolenaar
4 * OS/2 port by Paul Slootman
5 * VMS merge by Zoltan Arpadffy
7 * Do ":help uganda" in Vim to read copying and usage conditions.
8 * Do ":help credits" in Vim to see a list of people who contributed.
9 * See README.txt for an overview of the Vim source code.
13 * os_unix.c -- code for all flavors of Unix (BSD, SYSV, SVR4, POSIX, ...)
14 * Also for OS/2, using the excellent EMX package!!!
15 * Also for BeOS and Atari MiNT.
17 * A lot of this file was originally written by Juergen Weigert and later
18 * changed beyond recognition.
22 * Some systems have a prototype for select() that has (int *) instead of
23 * (fd_set *), which is wrong. This define removes that prototype. We define
24 * our own prototype below.
25 * Don't use it for the Mac, it causes a warning for precompiled headers.
26 * TODO: use a configure check for precompiled headers?
28 #if !defined(__APPLE__) && !defined(__TANDEM)
29 # define select select_declared_wrong
30 #endif
32 #include "vim.h"
34 #ifdef FEAT_MZSCHEME
35 # include "if_mzsch.h"
36 #endif
38 #include "os_unixx.h" /* unix includes for os_unix.c only */
40 #ifdef USE_XSMP
41 # include <X11/SM/SMlib.h>
42 #endif
44 #ifdef HAVE_SELINUX
45 # include <selinux/selinux.h>
46 static int selinux_enabled = -1;
47 #endif
50 * Use this prototype for select, some include files have a wrong prototype
52 #ifndef __TANDEM
53 # undef select
54 # ifdef __BEOS__
55 # define select beos_select
56 # endif
57 #endif
59 #ifdef __CYGWIN__
60 # ifndef WIN32
61 # include <sys/cygwin.h> /* for cygwin_conv_to_posix_path() */
62 # endif
63 #endif
65 #if defined(HAVE_SELECT)
66 extern int select __ARGS((int, fd_set *, fd_set *, fd_set *, struct timeval *));
67 #endif
69 #ifdef FEAT_MOUSE_GPM
70 # include <gpm.h>
71 /* <linux/keyboard.h> contains defines conflicting with "keymap.h",
72 * I just copied relevant defines here. A cleaner solution would be to put gpm
73 * code into separate file and include there linux/keyboard.h
75 /* #include <linux/keyboard.h> */
76 # define KG_SHIFT 0
77 # define KG_CTRL 2
78 # define KG_ALT 3
79 # define KG_ALTGR 1
80 # define KG_SHIFTL 4
81 # define KG_SHIFTR 5
82 # define KG_CTRLL 6
83 # define KG_CTRLR 7
84 # define KG_CAPSSHIFT 8
86 static void gpm_close __ARGS((void));
87 static int gpm_open __ARGS((void));
88 static int mch_gpm_process __ARGS((void));
89 #endif
91 #ifdef FEAT_SYSMOUSE
92 # include <sys/consio.h>
93 # include <sys/fbio.h>
95 static int sysmouse_open __ARGS((void));
96 static void sysmouse_close __ARGS((void));
97 static RETSIGTYPE sig_sysmouse __ARGS(SIGPROTOARG);
98 #endif
101 * end of autoconf section. To be extended...
104 /* Are the following #ifdefs still required? And why? Is that for X11? */
106 #if defined(ESIX) || defined(M_UNIX) && !defined(SCO)
107 # ifdef SIGWINCH
108 # undef SIGWINCH
109 # endif
110 # ifdef TIOCGWINSZ
111 # undef TIOCGWINSZ
112 # endif
113 #endif
115 #if defined(SIGWINDOW) && !defined(SIGWINCH) /* hpux 9.01 has it */
116 # define SIGWINCH SIGWINDOW
117 #endif
119 #ifdef FEAT_X11
120 # include <X11/Xlib.h>
121 # include <X11/Xutil.h>
122 # include <X11/Xatom.h>
123 # ifdef FEAT_XCLIPBOARD
124 # include <X11/Intrinsic.h>
125 # include <X11/Shell.h>
126 # include <X11/StringDefs.h>
127 static Widget xterm_Shell = (Widget)0;
128 static void xterm_update __ARGS((void));
129 # endif
131 # if defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE)
132 Window x11_window = 0;
133 # endif
134 Display *x11_display = NULL;
136 # ifdef FEAT_TITLE
137 static int get_x11_windis __ARGS((void));
138 static void set_x11_title __ARGS((char_u *));
139 static void set_x11_icon __ARGS((char_u *));
140 # endif
141 #endif
143 #ifdef FEAT_TITLE
144 static int get_x11_title __ARGS((int));
145 static int get_x11_icon __ARGS((int));
147 static char_u *oldtitle = NULL;
148 static int did_set_title = FALSE;
149 static char_u *oldicon = NULL;
150 static int did_set_icon = FALSE;
151 #endif
153 static void may_core_dump __ARGS((void));
155 static int WaitForChar __ARGS((long));
156 #if defined(__BEOS__)
157 int RealWaitForChar __ARGS((int, long, int *));
158 #else
159 static int RealWaitForChar __ARGS((int, long, int *));
160 #endif
162 #ifdef FEAT_XCLIPBOARD
163 static int do_xterm_trace __ARGS((void));
164 # define XT_TRACE_DELAY 50 /* delay for xterm tracing */
165 #endif
167 static void handle_resize __ARGS((void));
169 #if defined(SIGWINCH)
170 static RETSIGTYPE sig_winch __ARGS(SIGPROTOARG);
171 #endif
172 #if defined(SIGINT)
173 static RETSIGTYPE catch_sigint __ARGS(SIGPROTOARG);
174 #endif
175 #if defined(SIGPWR)
176 static RETSIGTYPE catch_sigpwr __ARGS(SIGPROTOARG);
177 #endif
178 #if defined(SIGALRM) && defined(FEAT_X11) \
179 && defined(FEAT_TITLE) && !defined(FEAT_GUI_GTK)
180 # define SET_SIG_ALARM
181 static RETSIGTYPE sig_alarm __ARGS(SIGPROTOARG);
182 static int sig_alarm_called;
183 #endif
184 static RETSIGTYPE deathtrap __ARGS(SIGPROTOARG);
186 static void catch_int_signal __ARGS((void));
187 static void set_signals __ARGS((void));
188 static void catch_signals __ARGS((RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)()));
189 #ifndef __EMX__
190 static int have_wildcard __ARGS((int, char_u **));
191 static int have_dollars __ARGS((int, char_u **));
192 #endif
194 #ifndef __EMX__
195 static int save_patterns __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file));
196 #endif
198 #ifndef SIG_ERR
199 # define SIG_ERR ((RETSIGTYPE (*)())-1)
200 #endif
202 static int do_resize = FALSE;
203 #ifndef __EMX__
204 static char_u *extra_shell_arg = NULL;
205 static int show_shell_mess = TRUE;
206 #endif
207 static int deadly_signal = 0; /* The signal we caught */
208 static int in_mch_delay = FALSE; /* sleeping in mch_delay() */
210 static int curr_tmode = TMODE_COOK; /* contains current terminal mode */
212 #ifdef USE_XSMP
213 typedef struct
215 SmcConn smcconn; /* The SM connection ID */
216 IceConn iceconn; /* The ICE connection ID */
217 char *clientid; /* The client ID for the current smc session */
218 Bool save_yourself; /* If we're in the middle of a save_yourself */
219 Bool shutdown; /* If we're in shutdown mode */
220 } xsmp_config_T;
222 static xsmp_config_T xsmp;
223 #endif
225 #ifdef SYS_SIGLIST_DECLARED
227 * I have seen
228 * extern char *_sys_siglist[NSIG];
229 * on Irix, Linux, NetBSD and Solaris. It contains a nice list of strings
230 * that describe the signals. That is nearly what we want here. But
231 * autoconf does only check for sys_siglist (without the underscore), I
232 * do not want to change everything today.... jw.
233 * This is why AC_DECL_SYS_SIGLIST is commented out in configure.in
235 #endif
237 static struct signalinfo
239 int sig; /* Signal number, eg. SIGSEGV etc */
240 char *name; /* Signal name (not char_u!). */
241 char deadly; /* Catch as a deadly signal? */
242 } signal_info[] =
244 #ifdef SIGHUP
245 {SIGHUP, "HUP", TRUE},
246 #endif
247 #ifdef SIGQUIT
248 {SIGQUIT, "QUIT", TRUE},
249 #endif
250 #ifdef SIGILL
251 {SIGILL, "ILL", TRUE},
252 #endif
253 #ifdef SIGTRAP
254 {SIGTRAP, "TRAP", TRUE},
255 #endif
256 #ifdef SIGABRT
257 {SIGABRT, "ABRT", TRUE},
258 #endif
259 #ifdef SIGEMT
260 {SIGEMT, "EMT", TRUE},
261 #endif
262 #ifdef SIGFPE
263 {SIGFPE, "FPE", TRUE},
264 #endif
265 #ifdef SIGBUS
266 {SIGBUS, "BUS", TRUE},
267 #endif
268 #ifdef SIGSEGV
269 {SIGSEGV, "SEGV", TRUE},
270 #endif
271 #ifdef SIGSYS
272 {SIGSYS, "SYS", TRUE},
273 #endif
274 #ifdef SIGALRM
275 {SIGALRM, "ALRM", FALSE}, /* Perl's alarm() can trigger it */
276 #endif
277 #ifdef SIGTERM
278 {SIGTERM, "TERM", TRUE},
279 #endif
280 #ifdef SIGVTALRM
281 {SIGVTALRM, "VTALRM", TRUE},
282 #endif
283 #if defined(SIGPROF) && !defined(FEAT_MZSCHEME) && !defined(WE_ARE_PROFILING)
284 /* MzScheme uses SIGPROF for its own needs; On Linux with profiling
285 * this makes Vim exit. WE_ARE_PROFILING is defined in Makefile. */
286 {SIGPROF, "PROF", TRUE},
287 #endif
288 #ifdef SIGXCPU
289 {SIGXCPU, "XCPU", TRUE},
290 #endif
291 #ifdef SIGXFSZ
292 {SIGXFSZ, "XFSZ", TRUE},
293 #endif
294 #ifdef SIGUSR1
295 {SIGUSR1, "USR1", TRUE},
296 #endif
297 #if defined(SIGUSR2) && !defined(FEAT_SYSMOUSE)
298 /* Used for sysmouse handling */
299 {SIGUSR2, "USR2", TRUE},
300 #endif
301 #ifdef SIGINT
302 {SIGINT, "INT", FALSE},
303 #endif
304 #ifdef SIGWINCH
305 {SIGWINCH, "WINCH", FALSE},
306 #endif
307 #ifdef SIGTSTP
308 {SIGTSTP, "TSTP", FALSE},
309 #endif
310 #ifdef SIGPIPE
311 {SIGPIPE, "PIPE", FALSE},
312 #endif
313 {-1, "Unknown!", FALSE}
316 void
317 mch_write(s, len)
318 char_u *s;
319 int len;
321 write(1, (char *)s, len);
322 if (p_wd) /* Unix is too fast, slow down a bit more */
323 RealWaitForChar(read_cmd_fd, p_wd, NULL);
327 * mch_inchar(): low level input function.
328 * Get a characters from the keyboard.
329 * Return the number of characters that are available.
330 * If wtime == 0 do not wait for characters.
331 * If wtime == n wait a short time for characters.
332 * If wtime == -1 wait forever for characters.
335 mch_inchar(buf, maxlen, wtime, tb_change_cnt)
336 char_u *buf;
337 int maxlen;
338 long wtime; /* don't use "time", MIPS cannot handle it */
339 int tb_change_cnt;
341 int len;
343 /* Check if window changed size while we were busy, perhaps the ":set
344 * columns=99" command was used. */
345 while (do_resize)
346 handle_resize();
348 if (wtime >= 0)
350 while (WaitForChar(wtime) == 0) /* no character available */
352 if (!do_resize) /* return if not interrupted by resize */
353 return 0;
354 handle_resize();
357 else /* wtime == -1 */
360 * If there is no character available within 'updatetime' seconds
361 * flush all the swap files to disk.
362 * Also done when interrupted by SIGWINCH.
364 if (WaitForChar(p_ut) == 0)
366 #ifdef FEAT_AUTOCMD
367 if (trigger_cursorhold() && maxlen >= 3
368 && !typebuf_changed(tb_change_cnt))
370 buf[0] = K_SPECIAL;
371 buf[1] = KS_EXTRA;
372 buf[2] = (int)KE_CURSORHOLD;
373 return 3;
375 #endif
376 before_blocking();
380 for (;;) /* repeat until we got a character */
382 while (do_resize) /* window changed size */
383 handle_resize();
385 * we want to be interrupted by the winch signal
387 WaitForChar(-1L);
388 if (do_resize) /* interrupted by SIGWINCH signal */
389 continue;
391 /* If input was put directly in typeahead buffer bail out here. */
392 if (typebuf_changed(tb_change_cnt))
393 return 0;
396 * For some terminals we only get one character at a time.
397 * We want the get all available characters, so we could keep on
398 * trying until none is available
399 * For some other terminals this is quite slow, that's why we don't do
400 * it.
402 len = read_from_input_buf(buf, (long)maxlen);
403 if (len > 0)
405 #ifdef OS2
406 int i;
408 for (i = 0; i < len; i++)
409 if (buf[i] == 0)
410 buf[i] = K_NUL;
411 #endif
412 return len;
417 static void
418 handle_resize()
420 do_resize = FALSE;
421 shell_resized();
425 * return non-zero if a character is available
428 mch_char_avail()
430 return WaitForChar(0L);
433 #if defined(HAVE_TOTAL_MEM) || defined(PROTO)
434 # ifdef HAVE_SYS_RESOURCE_H
435 # include <sys/resource.h>
436 # endif
437 # if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTL)
438 # include <sys/sysctl.h>
439 # endif
440 # if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
441 # include <sys/sysinfo.h>
442 # endif
445 * Return total amount of memory available in Kbyte.
446 * Doesn't change when memory has been allocated.
448 /* ARGSUSED */
449 long_u
450 mch_total_mem(special)
451 int special;
453 # ifdef __EMX__
454 return ulimit(3, 0L) >> 10; /* always 32MB? */
455 # else
456 long_u mem = 0;
457 long_u shiftright = 10; /* how much to shift "mem" right for Kbyte */
459 # ifdef HAVE_SYSCTL
460 int mib[2], physmem;
461 size_t len;
463 /* BSD way of getting the amount of RAM available. */
464 mib[0] = CTL_HW;
465 mib[1] = HW_USERMEM;
466 len = sizeof(physmem);
467 if (sysctl(mib, 2, &physmem, &len, NULL, 0) == 0)
468 mem = (long_u)physmem;
469 # endif
471 # if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
472 if (mem == 0)
474 struct sysinfo sinfo;
476 /* Linux way of getting amount of RAM available */
477 if (sysinfo(&sinfo) == 0)
479 # ifdef HAVE_SYSINFO_MEM_UNIT
480 /* avoid overflow as much as possible */
481 while (shiftright > 0 && (sinfo.mem_unit & 1) == 0)
483 sinfo.mem_unit = sinfo.mem_unit >> 1;
484 --shiftright;
486 mem = sinfo.totalram * sinfo.mem_unit;
487 # else
488 mem = sinfo.totalram;
489 # endif
492 # endif
494 # ifdef HAVE_SYSCONF
495 if (mem == 0)
497 long pagesize, pagecount;
499 /* Solaris way of getting amount of RAM available */
500 pagesize = sysconf(_SC_PAGESIZE);
501 pagecount = sysconf(_SC_PHYS_PAGES);
502 if (pagesize > 0 && pagecount > 0)
504 /* avoid overflow as much as possible */
505 while (shiftright > 0 && (pagesize & 1) == 0)
507 pagesize = (long_u)pagesize >> 1;
508 --shiftright;
510 mem = (long_u)pagesize * pagecount;
513 # endif
515 /* Return the minimum of the physical memory and the user limit, because
516 * using more than the user limit may cause Vim to be terminated. */
517 # if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT)
519 struct rlimit rlp;
521 if (getrlimit(RLIMIT_DATA, &rlp) == 0
522 && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
523 # ifdef RLIM_INFINITY
524 && rlp.rlim_cur != RLIM_INFINITY
525 # endif
526 && ((long_u)rlp.rlim_cur >> 10) < (mem >> shiftright)
529 mem = (long_u)rlp.rlim_cur;
530 shiftright = 10;
533 # endif
535 if (mem > 0)
536 return mem >> shiftright;
537 return (long_u)0x1fffff;
538 # endif
540 #endif
542 void
543 mch_delay(msec, ignoreinput)
544 long msec;
545 int ignoreinput;
547 int old_tmode;
548 #ifdef FEAT_MZSCHEME
549 long total = msec; /* remember original value */
550 #endif
552 if (ignoreinput)
554 /* Go to cooked mode without echo, to allow SIGINT interrupting us
555 * here. But we don't want QUIT to kill us (CTRL-\ used in a
556 * shell may produce SIGQUIT). */
557 in_mch_delay = TRUE;
558 old_tmode = curr_tmode;
559 if (curr_tmode == TMODE_RAW)
560 settmode(TMODE_SLEEP);
563 * Everybody sleeps in a different way...
564 * Prefer nanosleep(), some versions of usleep() can only sleep up to
565 * one second.
567 #ifdef FEAT_MZSCHEME
570 /* if total is large enough, wait by portions in p_mzq */
571 if (total > p_mzq)
572 msec = p_mzq;
573 else
574 msec = total;
575 total -= msec;
576 #endif
577 #ifdef HAVE_NANOSLEEP
579 struct timespec ts;
581 ts.tv_sec = msec / 1000;
582 ts.tv_nsec = (msec % 1000) * 1000000;
583 (void)nanosleep(&ts, NULL);
585 #else
586 # ifdef HAVE_USLEEP
587 while (msec >= 1000)
589 usleep((unsigned int)(999 * 1000));
590 msec -= 999;
592 usleep((unsigned int)(msec * 1000));
593 # else
594 # ifndef HAVE_SELECT
595 poll(NULL, 0, (int)msec);
596 # else
597 # ifdef __EMX__
598 _sleep2(msec);
599 # else
601 struct timeval tv;
603 tv.tv_sec = msec / 1000;
604 tv.tv_usec = (msec % 1000) * 1000;
606 * NOTE: Solaris 2.6 has a bug that makes select() hang here. Get
607 * a patch from Sun to fix this. Reported by Gunnar Pedersen.
609 select(0, NULL, NULL, NULL, &tv);
611 # endif /* __EMX__ */
612 # endif /* HAVE_SELECT */
613 # endif /* HAVE_NANOSLEEP */
614 #endif /* HAVE_USLEEP */
615 #ifdef FEAT_MZSCHEME
617 while (total > 0);
618 #endif
620 settmode(old_tmode);
621 in_mch_delay = FALSE;
623 else
624 WaitForChar(msec);
627 #if 0 /* disabled, no longer needed now that regmatch() is not recursive */
628 # if defined(HAVE_GETRLIMIT)
629 # define HAVE_STACK_LIMIT
630 # endif
631 #endif
633 #if defined(HAVE_STACK_LIMIT) \
634 || (!defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGSTACK))
635 # define HAVE_CHECK_STACK_GROWTH
637 * Support for checking for an almost-out-of-stack-space situation.
641 * Return a pointer to an item on the stack. Used to find out if the stack
642 * grows up or down.
644 static void check_stack_growth __ARGS((char *p));
645 static int stack_grows_downwards;
648 * Find out if the stack grows upwards or downwards.
649 * "p" points to a variable on the stack of the caller.
651 static void
652 check_stack_growth(p)
653 char *p;
655 int i;
657 stack_grows_downwards = (p > (char *)&i);
659 #endif
661 #if defined(HAVE_STACK_LIMIT) || defined(PROTO)
662 static char *stack_limit = NULL;
664 #if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
665 # include <pthread.h>
666 # include <pthread_np.h>
667 #endif
670 * Find out until how var the stack can grow without getting into trouble.
671 * Called when starting up and when switching to the signal stack in
672 * deathtrap().
674 static void
675 get_stack_limit()
677 struct rlimit rlp;
678 int i;
679 long lim;
681 /* Set the stack limit to 15/16 of the allowable size. Skip this when the
682 * limit doesn't fit in a long (rlim_cur might be "long long"). */
683 if (getrlimit(RLIMIT_STACK, &rlp) == 0
684 && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
685 # ifdef RLIM_INFINITY
686 && rlp.rlim_cur != RLIM_INFINITY
687 # endif
690 lim = (long)rlp.rlim_cur;
691 #if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
693 pthread_attr_t attr;
694 size_t size;
696 /* On FreeBSD the initial thread always has a fixed stack size, no
697 * matter what the limits are set to. Normally it's 1 Mbyte. */
698 pthread_attr_init(&attr);
699 if (pthread_attr_get_np(pthread_self(), &attr) == 0)
701 pthread_attr_getstacksize(&attr, &size);
702 if (lim > (long)size)
703 lim = (long)size;
705 pthread_attr_destroy(&attr);
707 #endif
708 if (stack_grows_downwards)
710 stack_limit = (char *)((long)&i - (lim / 16L * 15L));
711 if (stack_limit >= (char *)&i)
712 /* overflow, set to 1/16 of current stack position */
713 stack_limit = (char *)((long)&i / 16L);
715 else
717 stack_limit = (char *)((long)&i + (lim / 16L * 15L));
718 if (stack_limit <= (char *)&i)
719 stack_limit = NULL; /* overflow */
725 * Return FAIL when running out of stack space.
726 * "p" must point to any variable local to the caller that's on the stack.
729 mch_stackcheck(p)
730 char *p;
732 if (stack_limit != NULL)
734 if (stack_grows_downwards)
736 if (p < stack_limit)
737 return FAIL;
739 else if (p > stack_limit)
740 return FAIL;
742 return OK;
744 #endif
746 #if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
748 * Support for using the signal stack.
749 * This helps when we run out of stack space, which causes a SIGSEGV. The
750 * signal handler then must run on another stack, since the normal stack is
751 * completely full.
754 #ifndef SIGSTKSZ
755 # define SIGSTKSZ 8000 /* just a guess of how much stack is needed... */
756 #endif
758 # ifdef HAVE_SIGALTSTACK
759 static stack_t sigstk; /* for sigaltstack() */
760 # else
761 static struct sigstack sigstk; /* for sigstack() */
762 # endif
764 static void init_signal_stack __ARGS((void));
765 static char *signal_stack;
767 static void
768 init_signal_stack()
770 if (signal_stack != NULL)
772 # ifdef HAVE_SIGALTSTACK
773 # if defined(__APPLE__) && (!defined(MAC_OS_X_VERSION_MAX_ALLOWED) \
774 || MAC_OS_X_VERSION_MAX_ALLOWED <= 1040)
775 /* missing prototype. Adding it to osdef?.h.in doesn't work, because
776 * "struct sigaltstack" needs to be declared. */
777 extern int sigaltstack __ARGS((const struct sigaltstack *ss, struct sigaltstack *oss));
778 # endif
780 # ifdef HAVE_SS_BASE
781 sigstk.ss_base = signal_stack;
782 # else
783 sigstk.ss_sp = signal_stack;
784 # endif
785 sigstk.ss_size = SIGSTKSZ;
786 sigstk.ss_flags = 0;
787 (void)sigaltstack(&sigstk, NULL);
788 # else
789 sigstk.ss_sp = signal_stack;
790 if (stack_grows_downwards)
791 sigstk.ss_sp += SIGSTKSZ - 1;
792 sigstk.ss_onstack = 0;
793 (void)sigstack(&sigstk, NULL);
794 # endif
797 #endif
800 * We need correct potatotypes for a signal function, otherwise mean compilers
801 * will barf when the second argument to signal() is ``wrong''.
802 * Let me try it with a few tricky defines from my own osdef.h (jw).
804 #if defined(SIGWINCH)
805 /* ARGSUSED */
806 static RETSIGTYPE
807 sig_winch SIGDEFARG(sigarg)
809 /* this is not required on all systems, but it doesn't hurt anybody */
810 signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
811 do_resize = TRUE;
812 SIGRETURN;
814 #endif
816 #if defined(SIGINT)
817 /* ARGSUSED */
818 static RETSIGTYPE
819 catch_sigint SIGDEFARG(sigarg)
821 /* this is not required on all systems, but it doesn't hurt anybody */
822 signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
823 got_int = TRUE;
824 SIGRETURN;
826 #endif
828 #if defined(SIGPWR)
829 /* ARGSUSED */
830 static RETSIGTYPE
831 catch_sigpwr SIGDEFARG(sigarg)
833 /* this is not required on all systems, but it doesn't hurt anybody */
834 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
836 * I'm not sure we get the SIGPWR signal when the system is really going
837 * down or when the batteries are almost empty. Just preserve the swap
838 * files and don't exit, that can't do any harm.
840 ml_sync_all(FALSE, FALSE);
841 SIGRETURN;
843 #endif
845 #ifdef SET_SIG_ALARM
847 * signal function for alarm().
849 /* ARGSUSED */
850 static RETSIGTYPE
851 sig_alarm SIGDEFARG(sigarg)
853 /* doesn't do anything, just to break a system call */
854 sig_alarm_called = TRUE;
855 SIGRETURN;
857 #endif
859 #if (defined(HAVE_SETJMP_H) \
860 && ((defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) \
861 || defined(FEAT_LIBCALL))) \
862 || defined(PROTO)
864 * A simplistic version of setjmp() that only allows one level of using.
865 * Don't call twice before calling mch_endjmp()!.
866 * Usage:
867 * mch_startjmp();
868 * if (SETJMP(lc_jump_env) != 0)
870 * mch_didjmp();
871 * EMSG("crash!");
873 * else
875 * do_the_work;
876 * mch_endjmp();
878 * Note: Can't move SETJMP() here, because a function calling setjmp() must
879 * not return before the saved environment is used.
880 * Returns OK for normal return, FAIL when the protected code caused a
881 * problem and LONGJMP() was used.
883 void
884 mch_startjmp()
886 #ifdef SIGHASARG
887 lc_signal = 0;
888 #endif
889 lc_active = TRUE;
892 void
893 mch_endjmp()
895 lc_active = FALSE;
898 void
899 mch_didjmp()
901 # if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
902 /* On FreeBSD the signal stack has to be reset after using siglongjmp(),
903 * otherwise catching the signal only works once. */
904 init_signal_stack();
905 # endif
907 #endif
910 * This function handles deadly signals.
911 * It tries to preserve any swap file and exit properly.
912 * (partly from Elvis).
914 static RETSIGTYPE
915 deathtrap SIGDEFARG(sigarg)
917 static int entered = 0; /* count the number of times we got here.
918 Note: when memory has been corrupted
919 this may get an arbitrary value! */
920 #ifdef SIGHASARG
921 int i;
922 #endif
924 #if defined(HAVE_SETJMP_H)
926 * Catch a crash in protected code.
927 * Restores the environment saved in lc_jump_env, which looks like
928 * SETJMP() returns 1.
930 if (lc_active)
932 # if defined(SIGHASARG)
933 lc_signal = sigarg;
934 # endif
935 lc_active = FALSE; /* don't jump again */
936 LONGJMP(lc_jump_env, 1);
937 /* NOTREACHED */
939 #endif
941 #ifdef SIGHASARG
942 # ifdef SIGQUIT
943 /* While in mch_delay() we go to cooked mode to allow a CTRL-C to
944 * interrupt us. But in cooked mode we may also get SIGQUIT, e.g., when
945 * pressing CTRL-\, but we don't want Vim to exit then. */
946 if (in_mch_delay && sigarg == SIGQUIT)
947 SIGRETURN;
948 # endif
950 /* When SIGHUP, SIGQUIT, etc. are blocked: postpone the effect and return
951 * here. This avoids that a non-reentrant function is interrupted, e.g.,
952 * free(). Calling free() again may then cause a crash. */
953 if (entered == 0
954 && (0
955 # ifdef SIGHUP
956 || sigarg == SIGHUP
957 # endif
958 # ifdef SIGQUIT
959 || sigarg == SIGQUIT
960 # endif
961 # ifdef SIGTERM
962 || sigarg == SIGTERM
963 # endif
964 # ifdef SIGPWR
965 || sigarg == SIGPWR
966 # endif
967 # ifdef SIGUSR1
968 || sigarg == SIGUSR1
969 # endif
970 # ifdef SIGUSR2
971 || sigarg == SIGUSR2
972 # endif
974 && !vim_handle_signal(sigarg))
975 SIGRETURN;
976 #endif
978 /* Remember how often we have been called. */
979 ++entered;
981 #ifdef FEAT_EVAL
982 /* Set the v:dying variable. */
983 set_vim_var_nr(VV_DYING, (long)entered);
984 #endif
986 #ifdef HAVE_STACK_LIMIT
987 /* Since we are now using the signal stack, need to reset the stack
988 * limit. Otherwise using a regexp will fail. */
989 get_stack_limit();
990 #endif
992 #if 0
993 /* This is for opening gdb the moment Vim crashes.
994 * You need to manually adjust the file name and Vim executable name.
995 * Suggested by SungHyun Nam. */
997 # define VI_GDB_FILE "/tmp/vimgdb"
998 # define VIM_NAME "/usr/bin/vim"
999 FILE *fp = fopen(VI_GDB_FILE, "w");
1000 if (fp)
1002 fprintf(fp,
1003 "file %s\n"
1004 "attach %d\n"
1005 "set height 1000\n"
1006 "bt full\n"
1007 , VIM_NAME, getpid());
1008 fclose(fp);
1009 system("xterm -e gdb -x "VI_GDB_FILE);
1010 unlink(VI_GDB_FILE);
1013 #endif
1015 #ifdef SIGHASARG
1016 /* try to find the name of this signal */
1017 for (i = 0; signal_info[i].sig != -1; i++)
1018 if (sigarg == signal_info[i].sig)
1019 break;
1020 deadly_signal = sigarg;
1021 #endif
1023 full_screen = FALSE; /* don't write message to the GUI, it might be
1024 * part of the problem... */
1026 * If something goes wrong after entering here, we may get here again.
1027 * When this happens, give a message and try to exit nicely (resetting the
1028 * terminal mode, etc.)
1029 * When this happens twice, just exit, don't even try to give a message,
1030 * stack may be corrupt or something weird.
1031 * When this still happens again (or memory was corrupted in such a way
1032 * that "entered" was clobbered) use _exit(), don't try freeing resources.
1034 if (entered >= 3)
1036 reset_signals(); /* don't catch any signals anymore */
1037 may_core_dump();
1038 if (entered >= 4)
1039 _exit(8);
1040 exit(7);
1042 if (entered == 2)
1044 OUT_STR(_("Vim: Double signal, exiting\n"));
1045 out_flush();
1046 getout(1);
1049 #ifdef SIGHASARG
1050 sprintf((char *)IObuff, _("Vim: Caught deadly signal %s\n"),
1051 signal_info[i].name);
1052 #else
1053 sprintf((char *)IObuff, _("Vim: Caught deadly signal\n"));
1054 #endif
1055 preserve_exit(); /* preserve files and exit */
1057 #ifdef NBDEBUG
1058 reset_signals();
1059 may_core_dump();
1060 abort();
1061 #endif
1063 SIGRETURN;
1066 #ifdef _REENTRANT
1068 * On Solaris with multi-threading, suspending might not work immediately.
1069 * Catch the SIGCONT signal, which will be used as an indication whether the
1070 * suspending has been done or not.
1072 static int sigcont_received;
1073 static RETSIGTYPE sigcont_handler __ARGS(SIGPROTOARG);
1076 * signal handler for SIGCONT
1078 /* ARGSUSED */
1079 static RETSIGTYPE
1080 sigcont_handler SIGDEFARG(sigarg)
1082 sigcont_received = TRUE;
1083 SIGRETURN;
1085 #endif
1088 * If the machine has job control, use it to suspend the program,
1089 * otherwise fake it by starting a new shell.
1091 void
1092 mch_suspend()
1094 /* BeOS does have SIGTSTP, but it doesn't work. */
1095 #if defined(SIGTSTP) && !defined(__BEOS__)
1096 out_flush(); /* needed to make cursor visible on some systems */
1097 settmode(TMODE_COOK);
1098 out_flush(); /* needed to disable mouse on some systems */
1100 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
1101 /* Since we are going to sleep, we can't respond to requests for the X
1102 * selections. Lose them, otherwise other applications will hang. But
1103 * first copy the text to cut buffer 0. */
1104 if (clip_star.owned || clip_plus.owned)
1106 x11_export_final_selection();
1107 if (clip_star.owned)
1108 clip_lose_selection(&clip_star);
1109 if (clip_plus.owned)
1110 clip_lose_selection(&clip_plus);
1111 if (x11_display != NULL)
1112 XFlush(x11_display);
1114 # endif
1116 # ifdef _REENTRANT
1117 sigcont_received = FALSE;
1118 # endif
1119 kill(0, SIGTSTP); /* send ourselves a STOP signal */
1120 # ifdef _REENTRANT
1121 /* When we didn't suspend immediately in the kill(), do it now. Happens
1122 * on multi-threaded Solaris. */
1123 if (!sigcont_received)
1124 pause();
1125 # endif
1127 # ifdef FEAT_TITLE
1129 * Set oldtitle to NULL, so the current title is obtained again.
1131 vim_free(oldtitle);
1132 oldtitle = NULL;
1133 # endif
1134 settmode(TMODE_RAW);
1135 need_check_timestamps = TRUE;
1136 did_check_timestamps = FALSE;
1137 #else
1138 suspend_shell();
1139 #endif
1142 void
1143 mch_init()
1145 Columns = 80;
1146 Rows = 24;
1148 out_flush();
1149 set_signals();
1151 #ifdef MACOS_CONVERT
1152 mac_conv_init();
1153 #endif
1156 static void
1157 set_signals()
1159 #if defined(SIGWINCH)
1161 * WINDOW CHANGE signal is handled with sig_winch().
1163 signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
1164 #endif
1167 * We want the STOP signal to work, to make mch_suspend() work.
1168 * For "rvim" the STOP signal is ignored.
1170 #ifdef SIGTSTP
1171 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
1172 #endif
1173 #ifdef _REENTRANT
1174 signal(SIGCONT, sigcont_handler);
1175 #endif
1178 * We want to ignore breaking of PIPEs.
1180 #ifdef SIGPIPE
1181 signal(SIGPIPE, SIG_IGN);
1182 #endif
1184 #ifdef SIGINT
1185 catch_int_signal();
1186 #endif
1189 * Ignore alarm signals (Perl's alarm() generates it).
1191 #ifdef SIGALRM
1192 signal(SIGALRM, SIG_IGN);
1193 #endif
1196 * Catch SIGPWR (power failure?) to preserve the swap files, so that no
1197 * work will be lost.
1199 #ifdef SIGPWR
1200 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
1201 #endif
1204 * Arrange for other signals to gracefully shutdown Vim.
1206 catch_signals(deathtrap, SIG_ERR);
1208 #if defined(FEAT_GUI) && defined(SIGHUP)
1210 * When the GUI is running, ignore the hangup signal.
1212 if (gui.in_use)
1213 signal(SIGHUP, SIG_IGN);
1214 #endif
1217 #if defined(SIGINT) || defined(PROTO)
1219 * Catch CTRL-C (only works while in Cooked mode).
1221 static void
1222 catch_int_signal()
1224 signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
1226 #endif
1228 void
1229 reset_signals()
1231 catch_signals(SIG_DFL, SIG_DFL);
1232 #ifdef _REENTRANT
1233 /* SIGCONT isn't in the list, because its default action is ignore */
1234 signal(SIGCONT, SIG_DFL);
1235 #endif
1238 static void
1239 catch_signals(func_deadly, func_other)
1240 RETSIGTYPE (*func_deadly)();
1241 RETSIGTYPE (*func_other)();
1243 int i;
1245 for (i = 0; signal_info[i].sig != -1; i++)
1246 if (signal_info[i].deadly)
1248 #if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
1249 struct sigaction sa;
1251 /* Setup to use the alternate stack for the signal function. */
1252 sa.sa_handler = func_deadly;
1253 sigemptyset(&sa.sa_mask);
1254 # if defined(__linux__) && defined(_REENTRANT)
1255 /* On Linux, with glibc compiled for kernel 2.2, there is a bug in
1256 * thread handling in combination with using the alternate stack:
1257 * pthread library functions try to use the stack pointer to
1258 * identify the current thread, causing a SEGV signal, which
1259 * recursively calls deathtrap() and hangs. */
1260 sa.sa_flags = 0;
1261 # else
1262 sa.sa_flags = SA_ONSTACK;
1263 # endif
1264 sigaction(signal_info[i].sig, &sa, NULL);
1265 #else
1266 # if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGVEC)
1267 struct sigvec sv;
1269 /* Setup to use the alternate stack for the signal function. */
1270 sv.sv_handler = func_deadly;
1271 sv.sv_mask = 0;
1272 sv.sv_flags = SV_ONSTACK;
1273 sigvec(signal_info[i].sig, &sv, NULL);
1274 # else
1275 signal(signal_info[i].sig, func_deadly);
1276 # endif
1277 #endif
1279 else if (func_other != SIG_ERR)
1280 signal(signal_info[i].sig, func_other);
1284 * Handling of SIGHUP, SIGQUIT and SIGTERM:
1285 * "when" == a signal: when busy, postpone and return FALSE, otherwise
1286 * return TRUE
1287 * "when" == SIGNAL_BLOCK: Going to be busy, block signals
1288 * "when" == SIGNAL_UNBLOCK: Going to wait, unblock signals, use postponed
1289 * signal
1290 * Returns TRUE when Vim should exit.
1293 vim_handle_signal(sig)
1294 int sig;
1296 static int got_signal = 0;
1297 static int blocked = TRUE;
1299 switch (sig)
1301 case SIGNAL_BLOCK: blocked = TRUE;
1302 break;
1304 case SIGNAL_UNBLOCK: blocked = FALSE;
1305 if (got_signal != 0)
1307 kill(getpid(), got_signal);
1308 got_signal = 0;
1310 break;
1312 default: if (!blocked)
1313 return TRUE; /* exit! */
1314 got_signal = sig;
1315 #ifdef SIGPWR
1316 if (sig != SIGPWR)
1317 #endif
1318 got_int = TRUE; /* break any loops */
1319 break;
1321 return FALSE;
1325 * Check_win checks whether we have an interactive stdout.
1327 /* ARGSUSED */
1329 mch_check_win(argc, argv)
1330 int argc;
1331 char **argv;
1333 #ifdef OS2
1335 * Store argv[0], may be used for $VIM. Only use it if it is an absolute
1336 * name, mostly it's just "vim" and found in the path, which is unusable.
1338 if (mch_isFullName(argv[0]))
1339 exe_name = vim_strsave((char_u *)argv[0]);
1340 #endif
1341 if (isatty(1))
1342 return OK;
1343 return FAIL;
1347 * Return TRUE if the input comes from a terminal, FALSE otherwise.
1350 mch_input_isatty()
1352 if (isatty(read_cmd_fd))
1353 return TRUE;
1354 return FALSE;
1357 #ifdef FEAT_X11
1359 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) \
1360 && (defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE))
1362 static void xopen_message __ARGS((struct timeval *tvp));
1365 * Give a message about the elapsed time for opening the X window.
1367 static void
1368 xopen_message(tvp)
1369 struct timeval *tvp; /* must contain start time */
1371 struct timeval end_tv;
1373 /* Compute elapsed time. */
1374 gettimeofday(&end_tv, NULL);
1375 smsg((char_u *)_("Opening the X display took %ld msec"),
1376 (end_tv.tv_sec - tvp->tv_sec) * 1000L
1377 + (end_tv.tv_usec - tvp->tv_usec) / 1000L);
1379 # endif
1380 #endif
1382 #if defined(FEAT_X11) && (defined(FEAT_TITLE) || defined(FEAT_XCLIPBOARD))
1384 * A few functions shared by X11 title and clipboard code.
1386 static int x_error_handler __ARGS((Display *dpy, XErrorEvent *error_event));
1387 static int x_error_check __ARGS((Display *dpy, XErrorEvent *error_event));
1388 static int x_connect_to_server __ARGS((void));
1389 static int test_x11_window __ARGS((Display *dpy));
1391 static int got_x_error = FALSE;
1394 * X Error handler, otherwise X just exits! (very rude) -- webb
1396 static int
1397 x_error_handler(dpy, error_event)
1398 Display *dpy;
1399 XErrorEvent *error_event;
1401 XGetErrorText(dpy, error_event->error_code, (char *)IObuff, IOSIZE);
1402 STRCAT(IObuff, _("\nVim: Got X error\n"));
1404 /* We cannot print a message and continue, because no X calls are allowed
1405 * here (causes my system to hang). Silently continuing might be an
1406 * alternative... */
1407 preserve_exit(); /* preserve files and exit */
1409 return 0; /* NOTREACHED */
1413 * Another X Error handler, just used to check for errors.
1415 /* ARGSUSED */
1416 static int
1417 x_error_check(dpy, error_event)
1418 Display *dpy;
1419 XErrorEvent *error_event;
1421 got_x_error = TRUE;
1422 return 0;
1425 #if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
1426 # if defined(HAVE_SETJMP_H)
1428 * An X IO Error handler, used to catch error while opening the display.
1430 static int x_IOerror_check __ARGS((Display *dpy));
1432 /* ARGSUSED */
1433 static int
1434 x_IOerror_check(dpy)
1435 Display *dpy;
1437 /* This function should not return, it causes exit(). Longjump instead. */
1438 LONGJMP(lc_jump_env, 1);
1439 /*NOTREACHED*/
1440 return 0;
1442 # endif
1445 * An X IO Error handler, used to catch terminal errors.
1447 static int x_IOerror_handler __ARGS((Display *dpy));
1449 /* ARGSUSED */
1450 static int
1451 x_IOerror_handler(dpy)
1452 Display *dpy;
1454 xterm_dpy = NULL;
1455 x11_window = 0;
1456 x11_display = NULL;
1457 xterm_Shell = (Widget)0;
1459 /* This function should not return, it causes exit(). Longjump instead. */
1460 LONGJMP(x_jump_env, 1);
1461 /*NOTREACHED*/
1462 return 0;
1464 #endif
1467 * Return TRUE when connection to the X server is desired.
1469 static int
1470 x_connect_to_server()
1472 regmatch_T regmatch;
1474 #if defined(FEAT_CLIENTSERVER)
1475 if (x_force_connect)
1476 return TRUE;
1477 #endif
1478 if (x_no_connect)
1479 return FALSE;
1481 /* Check for a match with "exclude:" from 'clipboard'. */
1482 if (clip_exclude_prog != NULL)
1484 regmatch.rm_ic = FALSE; /* Don't ignore case */
1485 regmatch.regprog = clip_exclude_prog;
1486 if (vim_regexec(&regmatch, T_NAME, (colnr_T)0))
1487 return FALSE;
1489 return TRUE;
1493 * Test if "dpy" and x11_window are valid by getting the window title.
1494 * I don't actually want it yet, so there may be a simpler call to use, but
1495 * this will cause the error handler x_error_check() to be called if anything
1496 * is wrong, such as the window pointer being invalid (as can happen when the
1497 * user changes his DISPLAY, but not his WINDOWID) -- webb
1499 static int
1500 test_x11_window(dpy)
1501 Display *dpy;
1503 int (*old_handler)();
1504 XTextProperty text_prop;
1506 old_handler = XSetErrorHandler(x_error_check);
1507 got_x_error = FALSE;
1508 if (XGetWMName(dpy, x11_window, &text_prop))
1509 XFree((void *)text_prop.value);
1510 XSync(dpy, False);
1511 (void)XSetErrorHandler(old_handler);
1513 if (p_verbose > 0 && got_x_error)
1514 verb_msg((char_u *)_("Testing the X display failed"));
1516 return (got_x_error ? FAIL : OK);
1518 #endif
1520 #ifdef FEAT_TITLE
1522 #ifdef FEAT_X11
1524 static int get_x11_thing __ARGS((int get_title, int test_only));
1527 * try to get x11 window and display
1529 * return FAIL for failure, OK otherwise
1531 static int
1532 get_x11_windis()
1534 char *winid;
1535 static int result = -1;
1536 #define XD_NONE 0 /* x11_display not set here */
1537 #define XD_HERE 1 /* x11_display opened here */
1538 #define XD_GUI 2 /* x11_display used from gui.dpy */
1539 #define XD_XTERM 3 /* x11_display used from xterm_dpy */
1540 static int x11_display_from = XD_NONE;
1541 static int did_set_error_handler = FALSE;
1543 if (!did_set_error_handler)
1545 /* X just exits if it finds an error otherwise! */
1546 (void)XSetErrorHandler(x_error_handler);
1547 did_set_error_handler = TRUE;
1550 #if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
1551 if (gui.in_use)
1554 * If the X11 display was opened here before, for the window where Vim
1555 * was started, close that one now to avoid a memory leak.
1557 if (x11_display_from == XD_HERE && x11_display != NULL)
1559 XCloseDisplay(x11_display);
1560 x11_display_from = XD_NONE;
1562 if (gui_get_x11_windis(&x11_window, &x11_display) == OK)
1564 x11_display_from = XD_GUI;
1565 return OK;
1567 x11_display = NULL;
1568 return FAIL;
1570 else if (x11_display_from == XD_GUI)
1572 /* GUI must have stopped somehow, clear x11_display */
1573 x11_window = 0;
1574 x11_display = NULL;
1575 x11_display_from = XD_NONE;
1577 #endif
1579 /* When started with the "-X" argument, don't try connecting. */
1580 if (!x_connect_to_server())
1581 return FAIL;
1584 * If WINDOWID not set, should try another method to find out
1585 * what the current window number is. The only code I know for
1586 * this is very complicated.
1587 * We assume that zero is invalid for WINDOWID.
1589 if (x11_window == 0 && (winid = getenv("WINDOWID")) != NULL)
1590 x11_window = (Window)atol(winid);
1592 #ifdef FEAT_XCLIPBOARD
1593 if (xterm_dpy != NULL && x11_window != 0)
1595 /* We may have checked it already, but Gnome terminal can move us to
1596 * another window, so we need to check every time. */
1597 if (x11_display_from != XD_XTERM)
1600 * If the X11 display was opened here before, for the window where
1601 * Vim was started, close that one now to avoid a memory leak.
1603 if (x11_display_from == XD_HERE && x11_display != NULL)
1604 XCloseDisplay(x11_display);
1605 x11_display = xterm_dpy;
1606 x11_display_from = XD_XTERM;
1608 if (test_x11_window(x11_display) == FAIL)
1610 /* probably bad $WINDOWID */
1611 x11_window = 0;
1612 x11_display = NULL;
1613 x11_display_from = XD_NONE;
1614 return FAIL;
1616 return OK;
1618 #endif
1620 if (x11_window == 0 || x11_display == NULL)
1621 result = -1;
1623 if (result != -1) /* Have already been here and set this */
1624 return result; /* Don't do all these X calls again */
1626 if (x11_window != 0 && x11_display == NULL)
1628 #ifdef SET_SIG_ALARM
1629 RETSIGTYPE (*sig_save)();
1630 #endif
1631 #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1632 struct timeval start_tv;
1634 if (p_verbose > 0)
1635 gettimeofday(&start_tv, NULL);
1636 #endif
1638 #ifdef SET_SIG_ALARM
1640 * Opening the Display may hang if the DISPLAY setting is wrong, or
1641 * the network connection is bad. Set an alarm timer to get out.
1643 sig_alarm_called = FALSE;
1644 sig_save = (RETSIGTYPE (*)())signal(SIGALRM,
1645 (RETSIGTYPE (*)())sig_alarm);
1646 alarm(2);
1647 #endif
1648 x11_display = XOpenDisplay(NULL);
1650 #ifdef SET_SIG_ALARM
1651 alarm(0);
1652 signal(SIGALRM, (RETSIGTYPE (*)())sig_save);
1653 if (p_verbose > 0 && sig_alarm_called)
1654 verb_msg((char_u *)_("Opening the X display timed out"));
1655 #endif
1656 if (x11_display != NULL)
1658 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1659 if (p_verbose > 0)
1661 verbose_enter();
1662 xopen_message(&start_tv);
1663 verbose_leave();
1665 # endif
1666 if (test_x11_window(x11_display) == FAIL)
1668 /* Maybe window id is bad */
1669 x11_window = 0;
1670 XCloseDisplay(x11_display);
1671 x11_display = NULL;
1673 else
1674 x11_display_from = XD_HERE;
1677 if (x11_window == 0 || x11_display == NULL)
1678 return (result = FAIL);
1679 return (result = OK);
1683 * Determine original x11 Window Title
1685 static int
1686 get_x11_title(test_only)
1687 int test_only;
1689 return get_x11_thing(TRUE, test_only);
1693 * Determine original x11 Window icon
1695 static int
1696 get_x11_icon(test_only)
1697 int test_only;
1699 int retval = FALSE;
1701 retval = get_x11_thing(FALSE, test_only);
1703 /* could not get old icon, use terminal name */
1704 if (oldicon == NULL && !test_only)
1706 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1707 oldicon = T_NAME + 8;
1708 else
1709 oldicon = T_NAME;
1712 return retval;
1715 static int
1716 get_x11_thing(get_title, test_only)
1717 int get_title; /* get title string */
1718 int test_only;
1720 XTextProperty text_prop;
1721 int retval = FALSE;
1722 Status status;
1724 if (get_x11_windis() == OK)
1726 /* Get window/icon name if any */
1727 if (get_title)
1728 status = XGetWMName(x11_display, x11_window, &text_prop);
1729 else
1730 status = XGetWMIconName(x11_display, x11_window, &text_prop);
1733 * If terminal is xterm, then x11_window may be a child window of the
1734 * outer xterm window that actually contains the window/icon name, so
1735 * keep traversing up the tree until a window with a title/icon is
1736 * found.
1738 /* Previously this was only done for xterm and alikes. I don't see a
1739 * reason why it would fail for other terminal emulators.
1740 * if (term_is_xterm) */
1742 Window root;
1743 Window parent;
1744 Window win = x11_window;
1745 Window *children;
1746 unsigned int num_children;
1748 while (!status || text_prop.value == NULL)
1750 if (!XQueryTree(x11_display, win, &root, &parent, &children,
1751 &num_children))
1752 break;
1753 if (children)
1754 XFree((void *)children);
1755 if (parent == root || parent == 0)
1756 break;
1758 win = parent;
1759 if (get_title)
1760 status = XGetWMName(x11_display, win, &text_prop);
1761 else
1762 status = XGetWMIconName(x11_display, win, &text_prop);
1765 if (status && text_prop.value != NULL)
1767 retval = TRUE;
1768 if (!test_only)
1770 #ifdef FEAT_XFONTSET
1771 if (text_prop.encoding == XA_STRING)
1773 #endif
1774 if (get_title)
1775 oldtitle = vim_strsave((char_u *)text_prop.value);
1776 else
1777 oldicon = vim_strsave((char_u *)text_prop.value);
1778 #ifdef FEAT_XFONTSET
1780 else
1782 char **cl;
1783 Status transform_status;
1784 int n = 0;
1786 transform_status = XmbTextPropertyToTextList(x11_display,
1787 &text_prop,
1788 &cl, &n);
1789 if (transform_status >= Success && n > 0 && cl[0])
1791 if (get_title)
1792 oldtitle = vim_strsave((char_u *) cl[0]);
1793 else
1794 oldicon = vim_strsave((char_u *) cl[0]);
1795 XFreeStringList(cl);
1797 else
1799 if (get_title)
1800 oldtitle = vim_strsave((char_u *)text_prop.value);
1801 else
1802 oldicon = vim_strsave((char_u *)text_prop.value);
1805 #endif
1807 XFree((void *)text_prop.value);
1810 return retval;
1813 /* Are Xutf8 functions available? Avoid error from old compilers. */
1814 #if defined(X_HAVE_UTF8_STRING) && defined(FEAT_MBYTE)
1815 # if X_HAVE_UTF8_STRING
1816 # define USE_UTF8_STRING
1817 # endif
1818 #endif
1821 * Set x11 Window Title
1823 * get_x11_windis() must be called before this and have returned OK
1825 static void
1826 set_x11_title(title)
1827 char_u *title;
1829 /* XmbSetWMProperties() and Xutf8SetWMProperties() should use a STRING
1830 * when possible, COMPOUND_TEXT otherwise. COMPOUND_TEXT isn't
1831 * supported everywhere and STRING doesn't work for multi-byte titles.
1833 #ifdef USE_UTF8_STRING
1834 if (enc_utf8)
1835 Xutf8SetWMProperties(x11_display, x11_window, (const char *)title,
1836 NULL, NULL, 0, NULL, NULL, NULL);
1837 else
1838 #endif
1840 #if XtSpecificationRelease >= 4
1841 # ifdef FEAT_XFONTSET
1842 XmbSetWMProperties(x11_display, x11_window, (const char *)title,
1843 NULL, NULL, 0, NULL, NULL, NULL);
1844 # else
1845 XTextProperty text_prop;
1846 char *c_title = (char *)title;
1848 /* directly from example 3-18 "basicwin" of Xlib Programming Manual */
1849 (void)XStringListToTextProperty(&c_title, 1, &text_prop);
1850 XSetWMProperties(x11_display, x11_window, &text_prop,
1851 NULL, NULL, 0, NULL, NULL, NULL);
1852 # endif
1853 #else
1854 XStoreName(x11_display, x11_window, (char *)title);
1855 #endif
1857 XFlush(x11_display);
1861 * Set x11 Window icon
1863 * get_x11_windis() must be called before this and have returned OK
1865 static void
1866 set_x11_icon(icon)
1867 char_u *icon;
1869 /* See above for comments about using X*SetWMProperties(). */
1870 #ifdef USE_UTF8_STRING
1871 if (enc_utf8)
1872 Xutf8SetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
1873 NULL, 0, NULL, NULL, NULL);
1874 else
1875 #endif
1877 #if XtSpecificationRelease >= 4
1878 # ifdef FEAT_XFONTSET
1879 XmbSetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
1880 NULL, 0, NULL, NULL, NULL);
1881 # else
1882 XTextProperty text_prop;
1883 char *c_icon = (char *)icon;
1885 (void)XStringListToTextProperty(&c_icon, 1, &text_prop);
1886 XSetWMProperties(x11_display, x11_window, NULL, &text_prop,
1887 NULL, 0, NULL, NULL, NULL);
1888 # endif
1889 #else
1890 XSetIconName(x11_display, x11_window, (char *)icon);
1891 #endif
1893 XFlush(x11_display);
1896 #else /* FEAT_X11 */
1898 /*ARGSUSED*/
1899 static int
1900 get_x11_title(test_only)
1901 int test_only;
1903 return FALSE;
1906 static int
1907 get_x11_icon(test_only)
1908 int test_only;
1910 if (!test_only)
1912 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1913 oldicon = T_NAME + 8;
1914 else
1915 oldicon = T_NAME;
1917 return FALSE;
1920 #endif /* FEAT_X11 */
1923 mch_can_restore_title()
1925 return get_x11_title(TRUE);
1929 mch_can_restore_icon()
1931 return get_x11_icon(TRUE);
1935 * Set the window title and icon.
1937 void
1938 mch_settitle(title, icon)
1939 char_u *title;
1940 char_u *icon;
1942 int type = 0;
1943 static int recursive = 0;
1945 if (T_NAME == NULL) /* no terminal name (yet) */
1946 return;
1947 if (title == NULL && icon == NULL) /* nothing to do */
1948 return;
1950 /* When one of the X11 functions causes a deadly signal, we get here again
1951 * recursively. Avoid hanging then (something is probably locked). */
1952 if (recursive)
1953 return;
1954 ++recursive;
1957 * if the window ID and the display is known, we may use X11 calls
1959 #ifdef FEAT_X11
1960 if (get_x11_windis() == OK)
1961 type = 1;
1962 #else
1963 # if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_GTK)
1964 if (gui.in_use)
1965 type = 1;
1966 # endif
1967 #endif
1970 * Note: if "t_TS" is set, title is set with escape sequence rather
1971 * than x11 calls, because the x11 calls don't always work
1973 if ((type || *T_TS != NUL) && title != NULL)
1975 if (oldtitle == NULL
1976 #ifdef FEAT_GUI
1977 && !gui.in_use
1978 #endif
1979 ) /* first call but not in GUI, save title */
1980 (void)get_x11_title(FALSE);
1982 if (*T_TS != NUL) /* it's OK if t_fs is empty */
1983 term_settitle(title);
1984 #ifdef FEAT_X11
1985 else
1986 # ifdef FEAT_GUI_GTK
1987 if (!gui.in_use) /* don't do this if GTK+ is running */
1988 # endif
1989 set_x11_title(title); /* x11 */
1990 #endif
1991 #if defined(FEAT_GUI_GTK) \
1992 || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
1993 else
1994 gui_mch_settitle(title, icon);
1995 #endif
1996 did_set_title = TRUE;
1999 if ((type || *T_CIS != NUL) && icon != NULL)
2001 if (oldicon == NULL
2002 #ifdef FEAT_GUI
2003 && !gui.in_use
2004 #endif
2005 ) /* first call, save icon */
2006 get_x11_icon(FALSE);
2008 if (*T_CIS != NUL)
2010 out_str(T_CIS); /* set icon start */
2011 out_str_nf(icon);
2012 out_str(T_CIE); /* set icon end */
2013 out_flush();
2015 #ifdef FEAT_X11
2016 else
2017 # ifdef FEAT_GUI_GTK
2018 if (!gui.in_use) /* don't do this if GTK+ is running */
2019 # endif
2020 set_x11_icon(icon); /* x11 */
2021 #endif
2022 did_set_icon = TRUE;
2024 --recursive;
2028 * Restore the window/icon title.
2029 * "which" is one of:
2030 * 1 only restore title
2031 * 2 only restore icon
2032 * 3 restore title and icon
2034 void
2035 mch_restore_title(which)
2036 int which;
2038 /* only restore the title or icon when it has been set */
2039 mch_settitle(((which & 1) && did_set_title) ?
2040 (oldtitle ? oldtitle : p_titleold) : NULL,
2041 ((which & 2) && did_set_icon) ? oldicon : NULL);
2044 #endif /* FEAT_TITLE */
2047 * Return TRUE if "name" looks like some xterm name.
2048 * Seiichi Sato mentioned that "mlterm" works like xterm.
2051 vim_is_xterm(name)
2052 char_u *name;
2054 if (name == NULL)
2055 return FALSE;
2056 return (STRNICMP(name, "xterm", 5) == 0
2057 || STRNICMP(name, "nxterm", 6) == 0
2058 || STRNICMP(name, "kterm", 5) == 0
2059 || STRNICMP(name, "mlterm", 6) == 0
2060 || STRNICMP(name, "rxvt", 4) == 0
2061 || STRCMP(name, "builtin_xterm") == 0);
2064 #if defined(FEAT_MOUSE_XTERM) || defined(PROTO)
2066 * Return TRUE if "name" appears to be that of a terminal
2067 * known to support the xterm-style mouse protocol.
2068 * Relies on term_is_xterm having been set to its correct value.
2071 use_xterm_like_mouse(name)
2072 char_u *name;
2074 return (name != NULL
2075 && (term_is_xterm || STRNICMP(name, "screen", 6) == 0));
2077 #endif
2079 #if defined(FEAT_MOUSE_TTY) || defined(PROTO)
2081 * Return non-zero when using an xterm mouse, according to 'ttymouse'.
2082 * Return 1 for "xterm".
2083 * Return 2 for "xterm2".
2086 use_xterm_mouse()
2088 if (ttym_flags == TTYM_XTERM2)
2089 return 2;
2090 if (ttym_flags == TTYM_XTERM)
2091 return 1;
2092 return 0;
2094 #endif
2097 vim_is_iris(name)
2098 char_u *name;
2100 if (name == NULL)
2101 return FALSE;
2102 return (STRNICMP(name, "iris-ansi", 9) == 0
2103 || STRCMP(name, "builtin_iris-ansi") == 0);
2107 vim_is_vt300(name)
2108 char_u *name;
2110 if (name == NULL)
2111 return FALSE; /* actually all ANSI comp. terminals should be here */
2112 /* catch VT100 - VT5xx */
2113 return ((STRNICMP(name, "vt", 2) == 0
2114 && vim_strchr((char_u *)"12345", name[2]) != NULL)
2115 || STRCMP(name, "builtin_vt320") == 0);
2119 * Return TRUE if "name" is a terminal for which 'ttyfast' should be set.
2120 * This should include all windowed terminal emulators.
2123 vim_is_fastterm(name)
2124 char_u *name;
2126 if (name == NULL)
2127 return FALSE;
2128 if (vim_is_xterm(name) || vim_is_vt300(name) || vim_is_iris(name))
2129 return TRUE;
2130 return ( STRNICMP(name, "hpterm", 6) == 0
2131 || STRNICMP(name, "sun-cmd", 7) == 0
2132 || STRNICMP(name, "screen", 6) == 0
2133 || STRNICMP(name, "dtterm", 6) == 0);
2137 * Insert user name in s[len].
2138 * Return OK if a name found.
2141 mch_get_user_name(s, len)
2142 char_u *s;
2143 int len;
2145 #ifdef VMS
2146 vim_strncpy(s, (char_u *)cuserid(NULL), len - 1);
2147 return OK;
2148 #else
2149 return mch_get_uname(getuid(), s, len);
2150 #endif
2154 * Insert user name for "uid" in s[len].
2155 * Return OK if a name found.
2158 mch_get_uname(uid, s, len)
2159 uid_t uid;
2160 char_u *s;
2161 int len;
2163 #if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
2164 struct passwd *pw;
2166 if ((pw = getpwuid(uid)) != NULL
2167 && pw->pw_name != NULL && *(pw->pw_name) != NUL)
2169 vim_strncpy(s, (char_u *)pw->pw_name, len - 1);
2170 return OK;
2172 #endif
2173 sprintf((char *)s, "%d", (int)uid); /* assumes s is long enough */
2174 return FAIL; /* a number is not a name */
2178 * Insert host name is s[len].
2181 #ifdef HAVE_SYS_UTSNAME_H
2182 void
2183 mch_get_host_name(s, len)
2184 char_u *s;
2185 int len;
2187 struct utsname vutsname;
2189 if (uname(&vutsname) < 0)
2190 *s = NUL;
2191 else
2192 vim_strncpy(s, (char_u *)vutsname.nodename, len - 1);
2194 #else /* HAVE_SYS_UTSNAME_H */
2196 # ifdef HAVE_SYS_SYSTEMINFO_H
2197 # define gethostname(nam, len) sysinfo(SI_HOSTNAME, nam, len)
2198 # endif
2200 void
2201 mch_get_host_name(s, len)
2202 char_u *s;
2203 int len;
2205 # ifdef VAXC
2206 vaxc$gethostname((char *)s, len);
2207 # else
2208 gethostname((char *)s, len);
2209 # endif
2210 s[len - 1] = NUL; /* make sure it's terminated */
2212 #endif /* HAVE_SYS_UTSNAME_H */
2215 * return process ID
2217 long
2218 mch_get_pid()
2220 return (long)getpid();
2223 #if !defined(HAVE_STRERROR) && defined(USE_GETCWD)
2224 static char *strerror __ARGS((int));
2226 static char *
2227 strerror(err)
2228 int err;
2230 extern int sys_nerr;
2231 extern char *sys_errlist[];
2232 static char er[20];
2234 if (err > 0 && err < sys_nerr)
2235 return (sys_errlist[err]);
2236 sprintf(er, "Error %d", err);
2237 return er;
2239 #endif
2242 * Get name of current directory into buffer 'buf' of length 'len' bytes.
2243 * Return OK for success, FAIL for failure.
2246 mch_dirname(buf, len)
2247 char_u *buf;
2248 int len;
2250 #if defined(USE_GETCWD)
2251 if (getcwd((char *)buf, len) == NULL)
2253 STRCPY(buf, strerror(errno));
2254 return FAIL;
2256 return OK;
2257 #else
2258 return (getwd((char *)buf) != NULL ? OK : FAIL);
2259 #endif
2262 #if defined(OS2) || defined(PROTO)
2264 * Replace all slashes by backslashes.
2265 * When 'shellslash' set do it the other way around.
2267 void
2268 slash_adjust(p)
2269 char_u *p;
2271 while (*p)
2273 if (*p == psepcN)
2274 *p = psepc;
2275 mb_ptr_adv(p);
2278 #endif
2281 * Get absolute file name into "buf[len]".
2283 * return FAIL for failure, OK for success
2286 mch_FullName(fname, buf, len, force)
2287 char_u *fname, *buf;
2288 int len;
2289 int force; /* also expand when already absolute path */
2291 int l;
2292 #ifdef OS2
2293 int only_drive; /* file name is only a drive letter */
2294 #endif
2295 #ifdef HAVE_FCHDIR
2296 int fd = -1;
2297 static int dont_fchdir = FALSE; /* TRUE when fchdir() doesn't work */
2298 #endif
2299 char_u olddir[MAXPATHL];
2300 char_u *p;
2301 int retval = OK;
2302 #ifdef __CYGWIN__
2303 char_u posix_fname[MAXPATHL]; /* Cygwin docs mention MAX_PATH, but
2304 it's not always defined */
2305 #endif
2307 #ifdef VMS
2308 fname = vms_fixfilename(fname);
2309 #endif
2311 #ifdef __CYGWIN__
2313 * This helps for when "/etc/hosts" is a symlink to "c:/something/hosts".
2315 cygwin_conv_to_posix_path(fname, posix_fname);
2316 fname = posix_fname;
2317 #endif
2319 /* expand it if forced or not an absolute path */
2320 if (force || !mch_isFullName(fname))
2323 * If the file name has a path, change to that directory for a moment,
2324 * and then do the getwd() (and get back to where we were).
2325 * This will get the correct path name with "../" things.
2327 #ifdef OS2
2328 only_drive = 0;
2329 if (((p = vim_strrchr(fname, '/')) != NULL)
2330 || ((p = vim_strrchr(fname, '\\')) != NULL)
2331 || (((p = vim_strchr(fname, ':')) != NULL) && ++only_drive))
2332 #else
2333 if ((p = vim_strrchr(fname, '/')) != NULL)
2334 #endif
2336 #ifdef HAVE_FCHDIR
2338 * Use fchdir() if possible, it's said to be faster and more
2339 * reliable. But on SunOS 4 it might not work. Check this by
2340 * doing a fchdir() right now.
2342 if (!dont_fchdir)
2344 fd = open(".", O_RDONLY | O_EXTRA, 0);
2345 if (fd >= 0 && fchdir(fd) < 0)
2347 close(fd);
2348 fd = -1;
2349 dont_fchdir = TRUE; /* don't try again */
2352 #endif
2354 /* Only change directory when we are sure we can return to where
2355 * we are now. After doing "su" chdir(".") might not work. */
2356 if (
2357 #ifdef HAVE_FCHDIR
2358 fd < 0 &&
2359 #endif
2360 (mch_dirname(olddir, MAXPATHL) == FAIL
2361 || mch_chdir((char *)olddir) != 0))
2363 p = NULL; /* can't get current dir: don't chdir */
2364 retval = FAIL;
2366 else
2368 #ifdef OS2
2370 * compensate for case where ':' from "D:" was the only
2371 * path separator detected in the file name; the _next_
2372 * character has to be removed, and then restored later.
2374 if (only_drive)
2375 p++;
2376 #endif
2377 /* The directory is copied into buf[], to be able to remove
2378 * the file name without changing it (could be a string in
2379 * read-only memory) */
2380 if (p - fname >= len)
2381 retval = FAIL;
2382 else
2384 vim_strncpy(buf, fname, p - fname);
2385 if (mch_chdir((char *)buf))
2386 retval = FAIL;
2387 else
2388 fname = p + 1;
2389 *buf = NUL;
2391 #ifdef OS2
2392 if (only_drive)
2394 p--;
2395 if (retval != FAIL)
2396 fname--;
2398 #endif
2401 if (mch_dirname(buf, len) == FAIL)
2403 retval = FAIL;
2404 *buf = NUL;
2406 if (p != NULL)
2408 #ifdef HAVE_FCHDIR
2409 if (fd >= 0)
2411 l = fchdir(fd);
2412 close(fd);
2414 else
2415 #endif
2416 l = mch_chdir((char *)olddir);
2417 if (l != 0)
2418 EMSG(_(e_prev_dir));
2421 l = STRLEN(buf);
2422 if (l >= len)
2423 retval = FAIL;
2424 #ifndef VMS
2425 else
2427 if (l > 0 && buf[l - 1] != '/' && *fname != NUL
2428 && STRCMP(fname, ".") != 0)
2429 STRCAT(buf, "/");
2431 #endif
2434 /* Catch file names which are too long. */
2435 if (retval == FAIL || STRLEN(buf) + STRLEN(fname) >= len)
2436 return FAIL;
2438 /* Do not append ".", "/dir/." is equal to "/dir". */
2439 if (STRCMP(fname, ".") != 0)
2440 STRCAT(buf, fname);
2442 return OK;
2446 * Return TRUE if "fname" does not depend on the current directory.
2449 mch_isFullName(fname)
2450 char_u *fname;
2452 #ifdef __EMX__
2453 return _fnisabs(fname);
2454 #else
2455 # ifdef VMS
2456 return ( fname[0] == '/' || fname[0] == '.' ||
2457 strchr((char *)fname,':') || strchr((char *)fname,'"') ||
2458 (strchr((char *)fname,'[') && strchr((char *)fname,']'))||
2459 (strchr((char *)fname,'<') && strchr((char *)fname,'>')) );
2460 # else
2461 return (*fname == '/' || *fname == '~');
2462 # endif
2463 #endif
2466 #if defined(USE_FNAME_CASE) || defined(PROTO)
2468 * Set the case of the file name, if it already exists. This will cause the
2469 * file name to remain exactly the same.
2470 * Only required for file systems where case is ignored and preserved.
2472 /*ARGSUSED*/
2473 void
2474 fname_case(name, len)
2475 char_u *name;
2476 int len; /* buffer size, only used when name gets longer */
2478 struct stat st;
2479 char_u *slash, *tail;
2480 DIR *dirp;
2481 struct dirent *dp;
2483 if (lstat((char *)name, &st) >= 0)
2485 /* Open the directory where the file is located. */
2486 slash = vim_strrchr(name, '/');
2487 if (slash == NULL)
2489 dirp = opendir(".");
2490 tail = name;
2492 else
2494 *slash = NUL;
2495 dirp = opendir((char *)name);
2496 *slash = '/';
2497 tail = slash + 1;
2500 if (dirp != NULL)
2502 while ((dp = readdir(dirp)) != NULL)
2504 /* Only accept names that differ in case and are the same byte
2505 * length. TODO: accept different length name. */
2506 if (STRICMP(tail, dp->d_name) == 0
2507 && STRLEN(tail) == STRLEN(dp->d_name))
2509 char_u newname[MAXPATHL + 1];
2510 struct stat st2;
2512 /* Verify the inode is equal. */
2513 vim_strncpy(newname, name, MAXPATHL);
2514 vim_strncpy(newname + (tail - name), (char_u *)dp->d_name,
2515 MAXPATHL - (tail - name));
2516 if (lstat((char *)newname, &st2) >= 0
2517 && st.st_ino == st2.st_ino
2518 && st.st_dev == st2.st_dev)
2520 STRCPY(tail, dp->d_name);
2521 break;
2526 closedir(dirp);
2530 #endif
2533 * Get file permissions for 'name'.
2534 * Returns -1 when it doesn't exist.
2536 long
2537 mch_getperm(name)
2538 char_u *name;
2540 struct stat statb;
2542 /* Keep the #ifdef outside of stat(), it may be a macro. */
2543 #ifdef VMS
2544 if (stat((char *)vms_fixfilename(name), &statb))
2545 #else
2546 if (stat((char *)name, &statb))
2547 #endif
2548 return -1;
2549 #ifdef __INTERIX
2550 /* The top bit makes the value negative, which means the file doesn't
2551 * exist. Remove the bit, we don't use it. */
2552 return statb.st_mode & ~S_ADDACE;
2553 #else
2554 return statb.st_mode;
2555 #endif
2559 * set file permission for 'name' to 'perm'
2561 * return FAIL for failure, OK otherwise
2564 mch_setperm(name, perm)
2565 char_u *name;
2566 long perm;
2568 return (chmod((char *)
2569 #ifdef VMS
2570 vms_fixfilename(name),
2571 #else
2572 name,
2573 #endif
2574 (mode_t)perm) == 0 ? OK : FAIL);
2577 #if defined(HAVE_ACL) || defined(PROTO)
2578 # ifdef HAVE_SYS_ACL_H
2579 # include <sys/acl.h>
2580 # endif
2581 # ifdef HAVE_SYS_ACCESS_H
2582 # include <sys/access.h>
2583 # endif
2585 # ifdef HAVE_SOLARIS_ACL
2586 typedef struct vim_acl_solaris_T {
2587 int acl_cnt;
2588 aclent_t *acl_entry;
2589 } vim_acl_solaris_T;
2590 # endif
2592 #if defined(HAVE_SELINUX) || defined(PROTO)
2594 * Copy security info from "from_file" to "to_file".
2596 void
2597 mch_copy_sec(from_file, to_file)
2598 char_u *from_file;
2599 char_u *to_file;
2601 if (from_file == NULL)
2602 return;
2604 if (selinux_enabled == -1)
2605 selinux_enabled = is_selinux_enabled();
2607 if (selinux_enabled > 0)
2609 security_context_t from_context = NULL;
2610 security_context_t to_context = NULL;
2612 if (getfilecon((char *)from_file, &from_context) < 0)
2614 /* If the filesystem doesn't support extended attributes,
2615 the original had no special security context and the
2616 target cannot have one either. */
2617 if (errno == EOPNOTSUPP)
2618 return;
2620 MSG_PUTS(_("\nCould not get security context for "));
2621 msg_outtrans(from_file);
2622 msg_putchar('\n');
2623 return;
2625 if (getfilecon((char *)to_file, &to_context) < 0)
2627 MSG_PUTS(_("\nCould not get security context for "));
2628 msg_outtrans(to_file);
2629 msg_putchar('\n');
2630 freecon (from_context);
2631 return ;
2633 if (strcmp(from_context, to_context) != 0)
2635 if (setfilecon((char *)to_file, from_context) < 0)
2637 MSG_PUTS(_("\nCould not set security context for "));
2638 msg_outtrans(to_file);
2639 msg_putchar('\n');
2642 freecon(to_context);
2643 freecon(from_context);
2646 #endif /* HAVE_SELINUX */
2649 * Return a pointer to the ACL of file "fname" in allocated memory.
2650 * Return NULL if the ACL is not available for whatever reason.
2652 vim_acl_T
2653 mch_get_acl(fname)
2654 char_u *fname;
2656 vim_acl_T ret = NULL;
2657 #ifdef HAVE_POSIX_ACL
2658 ret = (vim_acl_T)acl_get_file((char *)fname, ACL_TYPE_ACCESS);
2659 #else
2660 #ifdef HAVE_SOLARIS_ACL
2661 vim_acl_solaris_T *aclent;
2663 aclent = malloc(sizeof(vim_acl_solaris_T));
2664 if ((aclent->acl_cnt = acl((char *)fname, GETACLCNT, 0, NULL)) < 0)
2666 free(aclent);
2667 return NULL;
2669 aclent->acl_entry = malloc(aclent->acl_cnt * sizeof(aclent_t));
2670 if (acl((char *)fname, GETACL, aclent->acl_cnt, aclent->acl_entry) < 0)
2672 free(aclent->acl_entry);
2673 free(aclent);
2674 return NULL;
2676 ret = (vim_acl_T)aclent;
2677 #else
2678 #if defined(HAVE_AIX_ACL)
2679 int aclsize;
2680 struct acl *aclent;
2682 aclsize = sizeof(struct acl);
2683 aclent = malloc(aclsize);
2684 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2686 if (errno == ENOSPC)
2688 aclsize = aclent->acl_len;
2689 aclent = realloc(aclent, aclsize);
2690 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2692 free(aclent);
2693 return NULL;
2696 else
2698 free(aclent);
2699 return NULL;
2702 ret = (vim_acl_T)aclent;
2703 #endif /* HAVE_AIX_ACL */
2704 #endif /* HAVE_SOLARIS_ACL */
2705 #endif /* HAVE_POSIX_ACL */
2706 return ret;
2710 * Set the ACL of file "fname" to "acl" (unless it's NULL).
2712 void
2713 mch_set_acl(fname, aclent)
2714 char_u *fname;
2715 vim_acl_T aclent;
2717 if (aclent == NULL)
2718 return;
2719 #ifdef HAVE_POSIX_ACL
2720 acl_set_file((char *)fname, ACL_TYPE_ACCESS, (acl_t)aclent);
2721 #else
2722 #ifdef HAVE_SOLARIS_ACL
2723 acl((char *)fname, SETACL, ((vim_acl_solaris_T *)aclent)->acl_cnt,
2724 ((vim_acl_solaris_T *)aclent)->acl_entry);
2725 #else
2726 #ifdef HAVE_AIX_ACL
2727 chacl((char *)fname, aclent, ((struct acl *)aclent)->acl_len);
2728 #endif /* HAVE_AIX_ACL */
2729 #endif /* HAVE_SOLARIS_ACL */
2730 #endif /* HAVE_POSIX_ACL */
2733 void
2734 mch_free_acl(aclent)
2735 vim_acl_T aclent;
2737 if (aclent == NULL)
2738 return;
2739 #ifdef HAVE_POSIX_ACL
2740 acl_free((acl_t)aclent);
2741 #else
2742 #ifdef HAVE_SOLARIS_ACL
2743 free(((vim_acl_solaris_T *)aclent)->acl_entry);
2744 free(aclent);
2745 #else
2746 #ifdef HAVE_AIX_ACL
2747 free(aclent);
2748 #endif /* HAVE_AIX_ACL */
2749 #endif /* HAVE_SOLARIS_ACL */
2750 #endif /* HAVE_POSIX_ACL */
2752 #endif
2755 * Set hidden flag for "name".
2757 /* ARGSUSED */
2758 void
2759 mch_hide(name)
2760 char_u *name;
2762 /* can't hide a file */
2766 * return TRUE if "name" is a directory
2767 * return FALSE if "name" is not a directory
2768 * return FALSE for error
2771 mch_isdir(name)
2772 char_u *name;
2774 struct stat statb;
2776 if (*name == NUL) /* Some stat()s don't flag "" as an error. */
2777 return FALSE;
2778 if (stat((char *)name, &statb))
2779 return FALSE;
2780 #ifdef _POSIX_SOURCE
2781 return (S_ISDIR(statb.st_mode) ? TRUE : FALSE);
2782 #else
2783 return ((statb.st_mode & S_IFMT) == S_IFDIR ? TRUE : FALSE);
2784 #endif
2787 static int executable_file __ARGS((char_u *name));
2790 * Return 1 if "name" is an executable file, 0 if not or it doesn't exist.
2792 static int
2793 executable_file(name)
2794 char_u *name;
2796 struct stat st;
2798 if (stat((char *)name, &st))
2799 return 0;
2800 return S_ISREG(st.st_mode) && mch_access((char *)name, X_OK) == 0;
2804 * Return 1 if "name" can be found in $PATH and executed, 0 if not.
2805 * Return -1 if unknown.
2808 mch_can_exe(name)
2809 char_u *name;
2811 char_u *buf;
2812 char_u *p, *e;
2813 int retval;
2815 /* If it's an absolute or relative path don't need to use $PATH. */
2816 if (mch_isFullName(name) || (name[0] == '.' && (name[1] == '/'
2817 || (name[1] == '.' && name[2] == '/'))))
2818 return executable_file(name);
2820 p = (char_u *)getenv("PATH");
2821 if (p == NULL || *p == NUL)
2822 return -1;
2823 buf = alloc((unsigned)(STRLEN(name) + STRLEN(p) + 2));
2824 if (buf == NULL)
2825 return -1;
2828 * Walk through all entries in $PATH to check if "name" exists there and
2829 * is an executable file.
2831 for (;;)
2833 e = (char_u *)strchr((char *)p, ':');
2834 if (e == NULL)
2835 e = p + STRLEN(p);
2836 if (e - p <= 1) /* empty entry means current dir */
2837 STRCPY(buf, "./");
2838 else
2840 vim_strncpy(buf, p, e - p);
2841 add_pathsep(buf);
2843 STRCAT(buf, name);
2844 retval = executable_file(buf);
2845 if (retval == 1)
2846 break;
2848 if (*e != ':')
2849 break;
2850 p = e + 1;
2853 vim_free(buf);
2854 return retval;
2858 * Check what "name" is:
2859 * NODE_NORMAL: file or directory (or doesn't exist)
2860 * NODE_WRITABLE: writable device, socket, fifo, etc.
2861 * NODE_OTHER: non-writable things
2864 mch_nodetype(name)
2865 char_u *name;
2867 struct stat st;
2869 if (stat((char *)name, &st))
2870 return NODE_NORMAL;
2871 if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
2872 return NODE_NORMAL;
2873 #ifndef OS2
2874 if (S_ISBLK(st.st_mode)) /* block device isn't writable */
2875 return NODE_OTHER;
2876 #endif
2877 /* Everything else is writable? */
2878 return NODE_WRITABLE;
2881 void
2882 mch_early_init()
2884 #ifdef HAVE_CHECK_STACK_GROWTH
2885 int i;
2887 check_stack_growth((char *)&i);
2889 # ifdef HAVE_STACK_LIMIT
2890 get_stack_limit();
2891 # endif
2893 #endif
2896 * Setup an alternative stack for signals. Helps to catch signals when
2897 * running out of stack space.
2898 * Use of sigaltstack() is preferred, it's more portable.
2899 * Ignore any errors.
2901 #if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2902 signal_stack = malloc(SIGSTKSZ);
2903 init_signal_stack();
2904 #endif
2907 #if defined(EXITFREE) || defined(PROTO)
2908 void
2909 mch_free_mem()
2911 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
2912 if (clip_star.owned)
2913 clip_lose_selection(&clip_star);
2914 if (clip_plus.owned)
2915 clip_lose_selection(&clip_plus);
2916 # endif
2917 # if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
2918 if (xterm_Shell != (Widget)0)
2919 XtDestroyWidget(xterm_Shell);
2920 # ifndef LESSTIF_VERSION
2921 /* Lesstif crashes here, lose some memory */
2922 if (xterm_dpy != NULL)
2923 XtCloseDisplay(xterm_dpy);
2924 if (app_context != (XtAppContext)NULL)
2926 XtDestroyApplicationContext(app_context);
2927 # ifdef FEAT_X11
2928 x11_display = NULL; /* freed by XtDestroyApplicationContext() */
2929 # endif
2931 # endif
2932 # endif
2933 # ifdef FEAT_X11
2934 if (x11_display != NULL
2935 # ifdef FEAT_XCLIPBOARD
2936 && x11_display != xterm_dpy
2937 # endif
2939 XCloseDisplay(x11_display);
2940 # endif
2941 # if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2942 vim_free(signal_stack);
2943 signal_stack = NULL;
2944 # endif
2945 # ifdef FEAT_TITLE
2946 vim_free(oldtitle);
2947 vim_free(oldicon);
2948 # endif
2950 #endif
2952 static void exit_scroll __ARGS((void));
2955 * Output a newline when exiting.
2956 * Make sure the newline goes to the same stream as the text.
2958 static void
2959 exit_scroll()
2961 if (silent_mode)
2962 return;
2963 if (newline_on_exit || msg_didout)
2965 if (msg_use_printf())
2967 if (info_message)
2968 mch_msg("\n");
2969 else
2970 mch_errmsg("\r\n");
2972 else
2973 out_char('\n');
2975 else
2977 restore_cterm_colors(); /* get original colors back */
2978 msg_clr_eos_force(); /* clear the rest of the display */
2979 windgoto((int)Rows - 1, 0); /* may have moved the cursor */
2983 void
2984 mch_exit(r)
2985 int r;
2987 exiting = TRUE;
2989 #if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
2990 x11_export_final_selection();
2991 #endif
2993 #ifdef FEAT_GUI
2994 if (!gui.in_use)
2995 #endif
2997 settmode(TMODE_COOK);
2998 #ifdef FEAT_TITLE
2999 mch_restore_title(3); /* restore xterm title and icon name */
3000 #endif
3002 * When t_ti is not empty but it doesn't cause swapping terminal
3003 * pages, need to output a newline when msg_didout is set. But when
3004 * t_ti does swap pages it should not go to the shell page. Do this
3005 * before stoptermcap().
3007 if (swapping_screen() && !newline_on_exit)
3008 exit_scroll();
3010 /* Stop termcap: May need to check for T_CRV response, which
3011 * requires RAW mode. */
3012 stoptermcap();
3015 * A newline is only required after a message in the alternate screen.
3016 * This is set to TRUE by wait_return().
3018 if (!swapping_screen() || newline_on_exit)
3019 exit_scroll();
3021 /* Cursor may have been switched off without calling starttermcap()
3022 * when doing "vim -u vimrc" and vimrc contains ":q". */
3023 if (full_screen)
3024 cursor_on();
3026 out_flush();
3027 ml_close_all(TRUE); /* remove all memfiles */
3028 may_core_dump();
3029 #ifdef FEAT_GUI
3030 if (gui.in_use)
3031 gui_exit(r);
3032 #endif
3034 #ifdef MACOS_CONVERT
3035 mac_conv_cleanup();
3036 #endif
3038 #ifdef __QNX__
3039 /* A core dump won't be created if the signal handler
3040 * doesn't return, so we can't call exit() */
3041 if (deadly_signal != 0)
3042 return;
3043 #endif
3045 #ifdef FEAT_NETBEANS_INTG
3046 if (usingNetbeans)
3047 netbeans_send_disconnect();
3048 #endif
3050 #ifdef EXITFREE
3051 free_all_mem();
3052 #endif
3054 exit(r);
3057 static void
3058 may_core_dump()
3060 if (deadly_signal != 0)
3062 signal(deadly_signal, SIG_DFL);
3063 kill(getpid(), deadly_signal); /* Die using the signal we caught */
3067 #ifndef VMS
3069 void
3070 mch_settmode(tmode)
3071 int tmode;
3073 static int first = TRUE;
3075 /* Why is NeXT excluded here (and not in os_unixx.h)? */
3076 #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
3078 * for "new" tty systems
3080 # ifdef HAVE_TERMIOS_H
3081 static struct termios told;
3082 struct termios tnew;
3083 # else
3084 static struct termio told;
3085 struct termio tnew;
3086 # endif
3088 if (first)
3090 first = FALSE;
3091 # if defined(HAVE_TERMIOS_H)
3092 tcgetattr(read_cmd_fd, &told);
3093 # else
3094 ioctl(read_cmd_fd, TCGETA, &told);
3095 # endif
3098 tnew = told;
3099 if (tmode == TMODE_RAW)
3102 * ~ICRNL enables typing ^V^M
3104 tnew.c_iflag &= ~ICRNL;
3105 tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE
3106 # if defined(IEXTEN) && !defined(__MINT__)
3107 | IEXTEN /* IEXTEN enables typing ^V on SOLARIS */
3108 /* but it breaks function keys on MINT */
3109 # endif
3111 # ifdef ONLCR /* don't map NL -> CR NL, we do it ourselves */
3112 tnew.c_oflag &= ~ONLCR;
3113 # endif
3114 tnew.c_cc[VMIN] = 1; /* return after 1 char */
3115 tnew.c_cc[VTIME] = 0; /* don't wait */
3117 else if (tmode == TMODE_SLEEP)
3118 tnew.c_lflag &= ~(ECHO);
3120 # if defined(HAVE_TERMIOS_H)
3122 int n = 10;
3124 /* A signal may cause tcsetattr() to fail (e.g., SIGCONT). Retry a
3125 * few times. */
3126 while (tcsetattr(read_cmd_fd, TCSANOW, &tnew) == -1
3127 && errno == EINTR && n > 0)
3128 --n;
3130 # else
3131 ioctl(read_cmd_fd, TCSETA, &tnew);
3132 # endif
3134 #else
3137 * for "old" tty systems
3139 # ifndef TIOCSETN
3140 # define TIOCSETN TIOCSETP /* for hpux 9.0 */
3141 # endif
3142 static struct sgttyb ttybold;
3143 struct sgttyb ttybnew;
3145 if (first)
3147 first = FALSE;
3148 ioctl(read_cmd_fd, TIOCGETP, &ttybold);
3151 ttybnew = ttybold;
3152 if (tmode == TMODE_RAW)
3154 ttybnew.sg_flags &= ~(CRMOD | ECHO);
3155 ttybnew.sg_flags |= RAW;
3157 else if (tmode == TMODE_SLEEP)
3158 ttybnew.sg_flags &= ~(ECHO);
3159 ioctl(read_cmd_fd, TIOCSETN, &ttybnew);
3160 #endif
3161 curr_tmode = tmode;
3165 * Try to get the code for "t_kb" from the stty setting
3167 * Even if termcap claims a backspace key, the user's setting *should*
3168 * prevail. stty knows more about reality than termcap does, and if
3169 * somebody's usual erase key is DEL (which, for most BSD users, it will
3170 * be), they're going to get really annoyed if their erase key starts
3171 * doing forward deletes for no reason. (Eric Fischer)
3173 void
3174 get_stty()
3176 char_u buf[2];
3177 char_u *p;
3179 /* Why is NeXT excluded here (and not in os_unixx.h)? */
3180 #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
3181 /* for "new" tty systems */
3182 # ifdef HAVE_TERMIOS_H
3183 struct termios keys;
3184 # else
3185 struct termio keys;
3186 # endif
3188 # if defined(HAVE_TERMIOS_H)
3189 if (tcgetattr(read_cmd_fd, &keys) != -1)
3190 # else
3191 if (ioctl(read_cmd_fd, TCGETA, &keys) != -1)
3192 # endif
3194 buf[0] = keys.c_cc[VERASE];
3195 intr_char = keys.c_cc[VINTR];
3196 #else
3197 /* for "old" tty systems */
3198 struct sgttyb keys;
3200 if (ioctl(read_cmd_fd, TIOCGETP, &keys) != -1)
3202 buf[0] = keys.sg_erase;
3203 intr_char = keys.sg_kill;
3204 #endif
3205 buf[1] = NUL;
3206 add_termcode((char_u *)"kb", buf, FALSE);
3209 * If <BS> and <DEL> are now the same, redefine <DEL>.
3211 p = find_termcode((char_u *)"kD");
3212 if (p != NULL && p[0] == buf[0] && p[1] == buf[1])
3213 do_fixdel(NULL);
3215 #if 0
3216 } /* to keep cindent happy */
3217 #endif
3220 #endif /* VMS */
3222 #if defined(FEAT_MOUSE_TTY) || defined(PROTO)
3224 * Set mouse clicks on or off.
3226 void
3227 mch_setmouse(on)
3228 int on;
3230 static int ison = FALSE;
3231 int xterm_mouse_vers;
3233 if (on == ison) /* return quickly if nothing to do */
3234 return;
3236 xterm_mouse_vers = use_xterm_mouse();
3237 if (xterm_mouse_vers > 0)
3239 if (on) /* enable mouse events, use mouse tracking if available */
3240 out_str_nf((char_u *)
3241 (xterm_mouse_vers > 1
3242 ? IF_EB("\033[?1002h", ESC_STR "[?1002h")
3243 : IF_EB("\033[?1000h", ESC_STR "[?1000h")));
3244 else /* disable mouse events, could probably always send the same */
3245 out_str_nf((char_u *)
3246 (xterm_mouse_vers > 1
3247 ? IF_EB("\033[?1002l", ESC_STR "[?1002l")
3248 : IF_EB("\033[?1000l", ESC_STR "[?1000l")));
3249 ison = on;
3252 # ifdef FEAT_MOUSE_DEC
3253 else if (ttym_flags == TTYM_DEC)
3255 if (on) /* enable mouse events */
3256 out_str_nf((char_u *)"\033[1;2'z\033[1;3'{");
3257 else /* disable mouse events */
3258 out_str_nf((char_u *)"\033['z");
3259 ison = on;
3261 # endif
3263 # ifdef FEAT_MOUSE_GPM
3264 else
3266 if (on)
3268 if (gpm_open())
3269 ison = TRUE;
3271 else
3273 gpm_close();
3274 ison = FALSE;
3277 # endif
3279 # ifdef FEAT_SYSMOUSE
3280 else
3282 if (on)
3284 if (sysmouse_open() == OK)
3285 ison = TRUE;
3287 else
3289 sysmouse_close();
3290 ison = FALSE;
3293 # endif
3295 # ifdef FEAT_MOUSE_JSB
3296 else
3298 if (on)
3300 /* D - Enable Mouse up/down messages
3301 * L - Enable Left Button Reporting
3302 * M - Enable Middle Button Reporting
3303 * R - Enable Right Button Reporting
3304 * K - Enable SHIFT and CTRL key Reporting
3305 * + - Enable Advanced messaging of mouse moves and up/down messages
3306 * Q - Quiet No Ack
3307 * # - Numeric value of mouse pointer required
3308 * 0 = Multiview 2000 cursor, used as standard
3309 * 1 = Windows Arrow
3310 * 2 = Windows I Beam
3311 * 3 = Windows Hour Glass
3312 * 4 = Windows Cross Hair
3313 * 5 = Windows UP Arrow
3315 #ifdef JSBTERM_MOUSE_NONADVANCED /* Disables full feedback of pointer movements */
3316 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK1Q\033\\",
3317 ESC_STR "[0~ZwLMRK1Q" ESC_STR "\\"));
3318 #else
3319 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK+1Q\033\\",
3320 ESC_STR "[0~ZwLMRK+1Q" ESC_STR "\\"));
3321 #endif
3322 ison = TRUE;
3324 else
3326 out_str_nf((char_u *)IF_EB("\033[0~ZwQ\033\\",
3327 ESC_STR "[0~ZwQ" ESC_STR "\\"));
3328 ison = FALSE;
3331 # endif
3332 # ifdef FEAT_MOUSE_PTERM
3333 else
3335 /* 1 = button press, 6 = release, 7 = drag, 1h...9l = right button */
3336 if (on)
3337 out_str_nf("\033[>1h\033[>6h\033[>7h\033[>1h\033[>9l");
3338 else
3339 out_str_nf("\033[>1l\033[>6l\033[>7l\033[>1l\033[>9h");
3340 ison = on;
3342 # endif
3346 * Set the mouse termcode, depending on the 'term' and 'ttymouse' options.
3348 void
3349 check_mouse_termcode()
3351 # ifdef FEAT_MOUSE_XTERM
3352 if (use_xterm_mouse()
3353 # ifdef FEAT_GUI
3354 && !gui.in_use
3355 # endif
3358 set_mouse_termcode(KS_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3359 ? IF_EB("\233M", CSI_STR "M")
3360 : IF_EB("\033[M", ESC_STR "[M")));
3361 if (*p_mouse != NUL)
3363 /* force mouse off and maybe on to send possibly new mouse
3364 * activation sequence to the xterm, with(out) drag tracing. */
3365 mch_setmouse(FALSE);
3366 setmouse();
3369 else
3370 del_mouse_termcode(KS_MOUSE);
3371 # endif
3373 # ifdef FEAT_MOUSE_GPM
3374 if (!use_xterm_mouse()
3375 # ifdef FEAT_GUI
3376 && !gui.in_use
3377 # endif
3379 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MG", ESC_STR "MG"));
3380 # endif
3382 # ifdef FEAT_SYSMOUSE
3383 if (!use_xterm_mouse()
3384 # ifdef FEAT_GUI
3385 && !gui.in_use
3386 # endif
3388 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MS", ESC_STR "MS"));
3389 # endif
3391 # ifdef FEAT_MOUSE_JSB
3392 /* conflicts with xterm mouse: "\033[" and "\033[M" ??? */
3393 if (!use_xterm_mouse()
3394 # ifdef FEAT_GUI
3395 && !gui.in_use
3396 # endif
3398 set_mouse_termcode(KS_JSBTERM_MOUSE,
3399 (char_u *)IF_EB("\033[0~zw", ESC_STR "[0~zw"));
3400 else
3401 del_mouse_termcode(KS_JSBTERM_MOUSE);
3402 # endif
3404 # ifdef FEAT_MOUSE_NET
3405 /* There is no conflict, but one may type "ESC }" from Insert mode. Don't
3406 * define it in the GUI or when using an xterm. */
3407 if (!use_xterm_mouse()
3408 # ifdef FEAT_GUI
3409 && !gui.in_use
3410 # endif
3412 set_mouse_termcode(KS_NETTERM_MOUSE,
3413 (char_u *)IF_EB("\033}", ESC_STR "}"));
3414 else
3415 del_mouse_termcode(KS_NETTERM_MOUSE);
3416 # endif
3418 # ifdef FEAT_MOUSE_DEC
3419 /* conflicts with xterm mouse: "\033[" and "\033[M" */
3420 if (!use_xterm_mouse()
3421 # ifdef FEAT_GUI
3422 && !gui.in_use
3423 # endif
3425 set_mouse_termcode(KS_DEC_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3426 ? IF_EB("\233", CSI_STR) : IF_EB("\033[", ESC_STR "[")));
3427 else
3428 del_mouse_termcode(KS_DEC_MOUSE);
3429 # endif
3430 # ifdef FEAT_MOUSE_PTERM
3431 /* same as the dec mouse */
3432 if (!use_xterm_mouse()
3433 # ifdef FEAT_GUI
3434 && !gui.in_use
3435 # endif
3437 set_mouse_termcode(KS_PTERM_MOUSE,
3438 (char_u *) IF_EB("\033[", ESC_STR "["));
3439 else
3440 del_mouse_termcode(KS_PTERM_MOUSE);
3441 # endif
3443 #endif
3446 * set screen mode, always fails.
3448 /* ARGSUSED */
3450 mch_screenmode(arg)
3451 char_u *arg;
3453 EMSG(_(e_screenmode));
3454 return FAIL;
3457 #ifndef VMS
3460 * Try to get the current window size:
3461 * 1. with an ioctl(), most accurate method
3462 * 2. from the environment variables LINES and COLUMNS
3463 * 3. from the termcap
3464 * 4. keep using the old values
3465 * Return OK when size could be determined, FAIL otherwise.
3468 mch_get_shellsize()
3470 long rows = 0;
3471 long columns = 0;
3472 char_u *p;
3475 * For OS/2 use _scrsize().
3477 # ifdef __EMX__
3479 int s[2];
3481 _scrsize(s);
3482 columns = s[0];
3483 rows = s[1];
3485 # endif
3488 * 1. try using an ioctl. It is the most accurate method.
3490 * Try using TIOCGWINSZ first, some systems that have it also define
3491 * TIOCGSIZE but don't have a struct ttysize.
3493 # ifdef TIOCGWINSZ
3495 struct winsize ws;
3496 int fd = 1;
3498 /* When stdout is not a tty, use stdin for the ioctl(). */
3499 if (!isatty(fd) && isatty(read_cmd_fd))
3500 fd = read_cmd_fd;
3501 if (ioctl(fd, TIOCGWINSZ, &ws) == 0)
3503 columns = ws.ws_col;
3504 rows = ws.ws_row;
3507 # else /* TIOCGWINSZ */
3508 # ifdef TIOCGSIZE
3510 struct ttysize ts;
3511 int fd = 1;
3513 /* When stdout is not a tty, use stdin for the ioctl(). */
3514 if (!isatty(fd) && isatty(read_cmd_fd))
3515 fd = read_cmd_fd;
3516 if (ioctl(fd, TIOCGSIZE, &ts) == 0)
3518 columns = ts.ts_cols;
3519 rows = ts.ts_lines;
3522 # endif /* TIOCGSIZE */
3523 # endif /* TIOCGWINSZ */
3526 * 2. get size from environment
3527 * When being POSIX compliant ('|' flag in 'cpoptions') this overrules
3528 * the ioctl() values!
3530 if (columns == 0 || rows == 0 || vim_strchr(p_cpo, CPO_TSIZE) != NULL)
3532 if ((p = (char_u *)getenv("LINES")))
3533 rows = atoi((char *)p);
3534 if ((p = (char_u *)getenv("COLUMNS")))
3535 columns = atoi((char *)p);
3538 #ifdef HAVE_TGETENT
3540 * 3. try reading "co" and "li" entries from termcap
3542 if (columns == 0 || rows == 0)
3543 getlinecol(&columns, &rows);
3544 #endif
3547 * 4. If everything fails, use the old values
3549 if (columns <= 0 || rows <= 0)
3550 return FAIL;
3552 Rows = rows;
3553 Columns = columns;
3554 return OK;
3558 * Try to set the window size to Rows and Columns.
3560 void
3561 mch_set_shellsize()
3563 if (*T_CWS)
3566 * NOTE: if you get an error here that term_set_winsize() is
3567 * undefined, check the output of configure. It could probably not
3568 * find a ncurses, termcap or termlib library.
3570 term_set_winsize((int)Rows, (int)Columns);
3571 out_flush();
3572 screen_start(); /* don't know where cursor is now */
3576 #endif /* VMS */
3579 * Rows and/or Columns has changed.
3581 void
3582 mch_new_shellsize()
3584 /* Nothing to do. */
3587 #ifndef USE_SYSTEM
3588 static void append_ga_line __ARGS((garray_T *gap));
3591 * Append the text in "gap" below the cursor line and clear "gap".
3593 static void
3594 append_ga_line(gap)
3595 garray_T *gap;
3597 /* Remove trailing CR. */
3598 if (gap->ga_len > 0
3599 && !curbuf->b_p_bin
3600 && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR)
3601 --gap->ga_len;
3602 ga_append(gap, NUL);
3603 ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE);
3604 gap->ga_len = 0;
3606 #endif
3609 mch_call_shell(cmd, options)
3610 char_u *cmd;
3611 int options; /* SHELL_*, see vim.h */
3613 #ifdef VMS
3614 char *ifn = NULL;
3615 char *ofn = NULL;
3616 #endif
3617 int tmode = cur_tmode;
3618 #ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
3619 int x;
3620 # ifndef __EMX__
3621 char_u *newcmd; /* only needed for unix */
3622 # else
3624 * Set the preferred shell in the EMXSHELL environment variable (but
3625 * only if it is different from what is already in the environment).
3626 * Emx then takes care of whether to use "/c" or "-c" in an
3627 * intelligent way. Simply pass the whole thing to emx's system() call.
3628 * Emx also starts an interactive shell if system() is passed an empty
3629 * string.
3631 char_u *p, *old;
3633 if (((old = (char_u *)getenv("EMXSHELL")) == NULL) || STRCMP(old, p_sh))
3635 /* should check HAVE_SETENV, but I know we don't have it. */
3636 p = alloc(10 + strlen(p_sh));
3637 if (p)
3639 sprintf((char *)p, "EMXSHELL=%s", p_sh);
3640 putenv((char *)p); /* don't free the pointer! */
3643 # endif
3645 out_flush();
3647 if (options & SHELL_COOKED)
3648 settmode(TMODE_COOK); /* set to normal mode */
3650 # ifdef __EMX__
3651 if (cmd == NULL)
3652 x = system(""); /* this starts an interactive shell in emx */
3653 else
3654 x = system((char *)cmd);
3655 /* system() returns -1 when error occurs in starting shell */
3656 if (x == -1 && !emsg_silent)
3658 MSG_PUTS(_("\nCannot execute shell "));
3659 msg_outtrans(p_sh);
3660 msg_putchar('\n');
3662 # else /* not __EMX__ */
3663 if (cmd == NULL)
3664 x = system((char *)p_sh);
3665 else
3667 # ifdef VMS
3668 if (ofn = strchr((char *)cmd, '>'))
3669 *ofn++ = '\0';
3670 if (ifn = strchr((char *)cmd, '<'))
3672 char *p;
3674 *ifn++ = '\0';
3675 p = strchr(ifn,' '); /* chop off any trailing spaces */
3676 if (p)
3677 *p = '\0';
3679 if (ofn)
3680 x = vms_sys((char *)cmd, ofn, ifn);
3681 else
3682 x = system((char *)cmd);
3683 # else
3684 newcmd = lalloc(STRLEN(p_sh)
3685 + (extra_shell_arg == NULL ? 0 : STRLEN(extra_shell_arg))
3686 + STRLEN(p_shcf) + STRLEN(cmd) + 4, TRUE);
3687 if (newcmd == NULL)
3688 x = 0;
3689 else
3691 sprintf((char *)newcmd, "%s %s %s %s", p_sh,
3692 extra_shell_arg == NULL ? "" : (char *)extra_shell_arg,
3693 (char *)p_shcf,
3694 (char *)cmd);
3695 x = system((char *)newcmd);
3696 vim_free(newcmd);
3698 # endif
3700 # ifdef VMS
3701 x = vms_sys_status(x);
3702 # endif
3703 if (emsg_silent)
3705 else if (x == 127)
3706 MSG_PUTS(_("\nCannot execute shell sh\n"));
3707 # endif /* __EMX__ */
3708 else if (x && !(options & SHELL_SILENT))
3710 MSG_PUTS(_("\nshell returned "));
3711 msg_outnum((long)x);
3712 msg_putchar('\n');
3715 if (tmode == TMODE_RAW)
3716 settmode(TMODE_RAW); /* set to raw mode */
3717 # ifdef FEAT_TITLE
3718 resettitle();
3719 # endif
3720 return x;
3722 #else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
3724 # define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
3725 127, some shells use that already */
3727 char_u *newcmd = NULL;
3728 pid_t pid;
3729 pid_t wpid = 0;
3730 pid_t wait_pid = 0;
3731 # ifdef HAVE_UNION_WAIT
3732 union wait status;
3733 # else
3734 int status = -1;
3735 # endif
3736 int retval = -1;
3737 char **argv = NULL;
3738 int argc;
3739 int i;
3740 char_u *p;
3741 int inquote;
3742 int pty_master_fd = -1; /* for pty's */
3743 # ifdef FEAT_GUI
3744 int pty_slave_fd = -1;
3745 char *tty_name;
3746 # endif
3747 int fd_toshell[2]; /* for pipes */
3748 int fd_fromshell[2];
3749 int pipe_error = FALSE;
3750 # ifdef HAVE_SETENV
3751 char envbuf[50];
3752 # else
3753 static char envbuf_Rows[20];
3754 static char envbuf_Columns[20];
3755 # endif
3756 int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
3758 out_flush();
3759 if (options & SHELL_COOKED)
3760 settmode(TMODE_COOK); /* set to normal mode */
3762 newcmd = vim_strsave(p_sh);
3763 if (newcmd == NULL) /* out of memory */
3764 goto error;
3767 * Do this loop twice:
3768 * 1: find number of arguments
3769 * 2: separate them and build argv[]
3771 for (i = 0; i < 2; ++i)
3773 p = newcmd;
3774 inquote = FALSE;
3775 argc = 0;
3776 for (;;)
3778 if (i == 1)
3779 argv[argc] = (char *)p;
3780 ++argc;
3781 while (*p && (inquote || (*p != ' ' && *p != TAB)))
3783 if (*p == '"')
3784 inquote = !inquote;
3785 ++p;
3787 if (*p == NUL)
3788 break;
3789 if (i == 1)
3790 *p++ = NUL;
3791 p = skipwhite(p);
3793 if (argv == NULL)
3795 argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *)));
3796 if (argv == NULL) /* out of memory */
3797 goto error;
3800 if (cmd != NULL)
3802 if (extra_shell_arg != NULL)
3803 argv[argc++] = (char *)extra_shell_arg;
3804 argv[argc++] = (char *)p_shcf;
3805 argv[argc++] = (char *)cmd;
3807 argv[argc] = NULL;
3810 * For the GUI, when writing the output into the buffer and when reading
3811 * input from the buffer: Try using a pseudo-tty to get the stdin/stdout
3812 * of the executed command into the Vim window. Or use a pipe.
3814 if ((options & (SHELL_READ|SHELL_WRITE))
3815 # ifdef FEAT_GUI
3816 || (gui.in_use && show_shell_mess)
3817 # endif
3820 # ifdef FEAT_GUI
3822 * Try to open a master pty.
3823 * If this works, open the slave pty.
3824 * If the slave can't be opened, close the master pty.
3826 if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
3828 pty_master_fd = OpenPTY(&tty_name); /* open pty */
3829 if (pty_master_fd >= 0 && ((pty_slave_fd =
3830 open(tty_name, O_RDWR | O_EXTRA, 0)) < 0))
3832 close(pty_master_fd);
3833 pty_master_fd = -1;
3837 * If not opening a pty or it didn't work, try using pipes.
3839 if (pty_master_fd < 0)
3840 # endif
3842 pipe_error = (pipe(fd_toshell) < 0);
3843 if (!pipe_error) /* pipe create OK */
3845 pipe_error = (pipe(fd_fromshell) < 0);
3846 if (pipe_error) /* pipe create failed */
3848 close(fd_toshell[0]);
3849 close(fd_toshell[1]);
3852 if (pipe_error)
3854 MSG_PUTS(_("\nCannot create pipes\n"));
3855 out_flush();
3860 if (!pipe_error) /* pty or pipe opened or not used */
3862 # ifdef __BEOS__
3863 beos_cleanup_read_thread();
3864 # endif
3866 if ((pid = fork()) == -1) /* maybe we should use vfork() */
3868 MSG_PUTS(_("\nCannot fork\n"));
3869 if ((options & (SHELL_READ|SHELL_WRITE))
3870 # ifdef FEAT_GUI
3871 || (gui.in_use && show_shell_mess)
3872 # endif
3875 # ifdef FEAT_GUI
3876 if (pty_master_fd >= 0) /* close the pseudo tty */
3878 close(pty_master_fd);
3879 close(pty_slave_fd);
3881 else /* close the pipes */
3882 # endif
3884 close(fd_toshell[0]);
3885 close(fd_toshell[1]);
3886 close(fd_fromshell[0]);
3887 close(fd_fromshell[1]);
3891 else if (pid == 0) /* child */
3893 reset_signals(); /* handle signals normally */
3895 if (!show_shell_mess || (options & SHELL_EXPAND))
3897 int fd;
3900 * Don't want to show any message from the shell. Can't just
3901 * close stdout and stderr though, because some systems will
3902 * break if you try to write to them after that, so we must
3903 * use dup() to replace them with something else -- webb
3904 * Connect stdin to /dev/null too, so ":n `cat`" doesn't hang,
3905 * waiting for input.
3907 fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
3908 fclose(stdin);
3909 fclose(stdout);
3910 fclose(stderr);
3913 * If any of these open()'s and dup()'s fail, we just continue
3914 * anyway. It's not fatal, and on most systems it will make
3915 * no difference at all. On a few it will cause the execvp()
3916 * to exit with a non-zero status even when the completion
3917 * could be done, which is nothing too serious. If the open()
3918 * or dup() failed we'd just do the same thing ourselves
3919 * anyway -- webb
3921 if (fd >= 0)
3923 dup(fd); /* To replace stdin (file descriptor 0) */
3924 dup(fd); /* To replace stdout (file descriptor 1) */
3925 dup(fd); /* To replace stderr (file descriptor 2) */
3927 /* Don't need this now that we've duplicated it */
3928 close(fd);
3931 else if ((options & (SHELL_READ|SHELL_WRITE))
3932 # ifdef FEAT_GUI
3933 || gui.in_use
3934 # endif
3938 # ifdef HAVE_SETSID
3939 /* Create our own process group, so that the child and all its
3940 * children can be kill()ed. Don't do this when using pipes,
3941 * because stdin is not a tty, we would loose /dev/tty. */
3942 if (p_stmp)
3943 (void)setsid();
3944 # endif
3945 # ifdef FEAT_GUI
3946 if (pty_slave_fd >= 0)
3948 /* push stream discipline modules */
3949 if (options & SHELL_COOKED)
3950 SetupSlavePTY(pty_slave_fd);
3951 # ifdef TIOCSCTTY
3952 /* Try to become controlling tty (probably doesn't work,
3953 * unless run by root) */
3954 ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
3955 # endif
3957 # endif
3958 /* Simulate to have a dumb terminal (for now) */
3959 # ifdef HAVE_SETENV
3960 setenv("TERM", "dumb", 1);
3961 sprintf((char *)envbuf, "%ld", Rows);
3962 setenv("ROWS", (char *)envbuf, 1);
3963 sprintf((char *)envbuf, "%ld", Rows);
3964 setenv("LINES", (char *)envbuf, 1);
3965 sprintf((char *)envbuf, "%ld", Columns);
3966 setenv("COLUMNS", (char *)envbuf, 1);
3967 # else
3969 * Putenv does not copy the string, it has to remain valid.
3970 * Use a static array to avoid loosing allocated memory.
3972 putenv("TERM=dumb");
3973 sprintf(envbuf_Rows, "ROWS=%ld", Rows);
3974 putenv(envbuf_Rows);
3975 sprintf(envbuf_Rows, "LINES=%ld", Rows);
3976 putenv(envbuf_Rows);
3977 sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
3978 putenv(envbuf_Columns);
3979 # endif
3982 * stderr is only redirected when using the GUI, so that a
3983 * program like gpg can still access the terminal to get a
3984 * passphrase using stderr.
3986 # ifdef FEAT_GUI
3987 if (pty_master_fd >= 0)
3989 close(pty_master_fd); /* close master side of pty */
3991 /* set up stdin/stdout/stderr for the child */
3992 close(0);
3993 dup(pty_slave_fd);
3994 close(1);
3995 dup(pty_slave_fd);
3996 if (gui.in_use)
3998 close(2);
3999 dup(pty_slave_fd);
4002 close(pty_slave_fd); /* has been dupped, close it now */
4004 else
4005 # endif
4007 /* set up stdin for the child */
4008 close(fd_toshell[1]);
4009 close(0);
4010 dup(fd_toshell[0]);
4011 close(fd_toshell[0]);
4013 /* set up stdout for the child */
4014 close(fd_fromshell[0]);
4015 close(1);
4016 dup(fd_fromshell[1]);
4017 close(fd_fromshell[1]);
4019 # ifdef FEAT_GUI
4020 if (gui.in_use)
4022 /* set up stderr for the child */
4023 close(2);
4024 dup(1);
4026 # endif
4031 * There is no type cast for the argv, because the type may be
4032 * different on different machines. This may cause a warning
4033 * message with strict compilers, don't worry about it.
4034 * Call _exit() instead of exit() to avoid closing the connection
4035 * to the X server (esp. with GTK, which uses atexit()).
4037 execvp(argv[0], argv);
4038 _exit(EXEC_FAILED); /* exec failed, return failure code */
4040 else /* parent */
4043 * While child is running, ignore terminating signals.
4044 * Do catch CTRL-C, so that "got_int" is set.
4046 catch_signals(SIG_IGN, SIG_ERR);
4047 catch_int_signal();
4050 * For the GUI we redirect stdin, stdout and stderr to our window.
4051 * This is also used to pipe stdin/stdout to/from the external
4052 * command.
4054 if ((options & (SHELL_READ|SHELL_WRITE))
4055 # ifdef FEAT_GUI
4056 || (gui.in_use && show_shell_mess)
4057 # endif
4060 # define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
4061 char_u buffer[BUFLEN + 1];
4062 # ifdef FEAT_MBYTE
4063 int buffer_off = 0; /* valid bytes in buffer[] */
4064 # endif
4065 char_u ta_buf[BUFLEN + 1]; /* TypeAHead */
4066 int ta_len = 0; /* valid bytes in ta_buf[] */
4067 int len;
4068 int p_more_save;
4069 int old_State;
4070 int c;
4071 int toshell_fd;
4072 int fromshell_fd;
4073 garray_T ga;
4074 int noread_cnt;
4076 # ifdef FEAT_GUI
4077 if (pty_master_fd >= 0)
4079 close(pty_slave_fd); /* close slave side of pty */
4080 fromshell_fd = pty_master_fd;
4081 toshell_fd = dup(pty_master_fd);
4083 else
4084 # endif
4086 close(fd_toshell[0]);
4087 close(fd_fromshell[1]);
4088 toshell_fd = fd_toshell[1];
4089 fromshell_fd = fd_fromshell[0];
4093 * Write to the child if there are typed characters.
4094 * Read from the child if there are characters available.
4095 * Repeat the reading a few times if more characters are
4096 * available. Need to check for typed keys now and then, but
4097 * not too often (delays when no chars are available).
4098 * This loop is quit if no characters can be read from the pty
4099 * (WaitForChar detected special condition), or there are no
4100 * characters available and the child has exited.
4101 * Only check if the child has exited when there is no more
4102 * output. The child may exit before all the output has
4103 * been printed.
4105 * Currently this busy loops!
4106 * This can probably dead-lock when the write blocks!
4108 p_more_save = p_more;
4109 p_more = FALSE;
4110 old_State = State;
4111 State = EXTERNCMD; /* don't redraw at window resize */
4113 if ((options & SHELL_WRITE) && toshell_fd >= 0)
4115 /* Fork a process that will write the lines to the
4116 * external program. */
4117 if ((wpid = fork()) == -1)
4119 MSG_PUTS(_("\nCannot fork\n"));
4121 else if (wpid == 0)
4123 linenr_T lnum = curbuf->b_op_start.lnum;
4124 int written = 0;
4125 char_u *lp = ml_get(lnum);
4126 char_u *s;
4127 size_t l;
4129 /* child */
4130 close(fromshell_fd);
4131 for (;;)
4133 l = STRLEN(lp + written);
4134 if (l == 0)
4135 len = 0;
4136 else if (lp[written] == NL)
4137 /* NL -> NUL translation */
4138 len = write(toshell_fd, "", (size_t)1);
4139 else
4141 s = vim_strchr(lp + written, NL);
4142 len = write(toshell_fd, (char *)lp + written,
4143 s == NULL ? l : s - (lp + written));
4145 if (len == l)
4147 /* Finished a line, add a NL, unless this line
4148 * should not have one. */
4149 if (lnum != curbuf->b_op_end.lnum
4150 || !curbuf->b_p_bin
4151 || (lnum != write_no_eol_lnum
4152 && (lnum !=
4153 curbuf->b_ml.ml_line_count
4154 || curbuf->b_p_eol)))
4155 write(toshell_fd, "\n", (size_t)1);
4156 ++lnum;
4157 if (lnum > curbuf->b_op_end.lnum)
4159 /* finished all the lines, close pipe */
4160 close(toshell_fd);
4161 toshell_fd = -1;
4162 break;
4164 lp = ml_get(lnum);
4165 written = 0;
4167 else if (len > 0)
4168 written += len;
4170 _exit(0);
4172 else
4174 close(toshell_fd);
4175 toshell_fd = -1;
4179 if (options & SHELL_READ)
4180 ga_init2(&ga, 1, BUFLEN);
4182 noread_cnt = 0;
4184 for (;;)
4187 * Check if keys have been typed, write them to the child
4188 * if there are any.
4189 * Don't do this if we are expanding wild cards (would eat
4190 * typeahead).
4191 * Don't do this when filtering and terminal is in cooked
4192 * mode, the shell command will handle the I/O. Avoids
4193 * that a typed password is echoed for ssh or gpg command.
4194 * Don't get characters when the child has already
4195 * finished (wait_pid == 0).
4196 * Don't get extra characters when we already have one.
4197 * Don't read characters unless we didn't get output for a
4198 * while, avoids that ":r !ls" eats typeahead.
4200 len = 0;
4201 if (!(options & SHELL_EXPAND)
4202 && ((options &
4203 (SHELL_READ|SHELL_WRITE|SHELL_COOKED))
4204 != (SHELL_READ|SHELL_WRITE|SHELL_COOKED)
4205 #ifdef FEAT_GUI
4206 || gui.in_use
4207 #endif
4209 && wait_pid == 0
4210 && (ta_len > 0
4211 || (noread_cnt > 4
4212 && (len = ui_inchar(ta_buf,
4213 BUFLEN, 10L, 0)) > 0)))
4216 * For pipes:
4217 * Check for CTRL-C: send interrupt signal to child.
4218 * Check for CTRL-D: EOF, close pipe to child.
4220 if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
4222 # ifdef SIGINT
4224 * Send SIGINT to the child's group or all
4225 * processes in our group.
4227 if (ta_buf[ta_len] == Ctrl_C
4228 || ta_buf[ta_len] == intr_char)
4230 # ifdef HAVE_SETSID
4231 kill(-pid, SIGINT);
4232 # else
4233 kill(0, SIGINT);
4234 # endif
4235 if (wpid > 0)
4236 kill(wpid, SIGINT);
4238 # endif
4239 if (pty_master_fd < 0 && toshell_fd >= 0
4240 && ta_buf[ta_len] == Ctrl_D)
4242 close(toshell_fd);
4243 toshell_fd = -1;
4247 /* replace K_BS by <BS> and K_DEL by <DEL> */
4248 for (i = ta_len; i < ta_len + len; ++i)
4250 if (ta_buf[i] == CSI && len - i > 2)
4252 c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]);
4253 if (c == K_DEL || c == K_KDEL || c == K_BS)
4255 mch_memmove(ta_buf + i + 1, ta_buf + i + 3,
4256 (size_t)(len - i - 2));
4257 if (c == K_DEL || c == K_KDEL)
4258 ta_buf[i] = DEL;
4259 else
4260 ta_buf[i] = Ctrl_H;
4261 len -= 2;
4264 else if (ta_buf[i] == '\r')
4265 ta_buf[i] = '\n';
4266 # ifdef FEAT_MBYTE
4267 if (has_mbyte)
4268 i += (*mb_ptr2len)(ta_buf + i) - 1;
4269 # endif
4273 * For pipes: echo the typed characters.
4274 * For a pty this does not seem to work.
4276 if (pty_master_fd < 0)
4278 for (i = ta_len; i < ta_len + len; ++i)
4280 if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
4281 msg_putchar(ta_buf[i]);
4282 # ifdef FEAT_MBYTE
4283 else if (has_mbyte)
4285 int l = (*mb_ptr2len)(ta_buf + i);
4287 msg_outtrans_len(ta_buf + i, l);
4288 i += l - 1;
4290 # endif
4291 else
4292 msg_outtrans_len(ta_buf + i, 1);
4294 windgoto(msg_row, msg_col);
4295 out_flush();
4298 ta_len += len;
4301 * Write the characters to the child, unless EOF has
4302 * been typed for pipes. Write one character at a
4303 * time, to avoid loosing too much typeahead.
4304 * When writing buffer lines, drop the typed
4305 * characters (only check for CTRL-C).
4307 if (options & SHELL_WRITE)
4308 ta_len = 0;
4309 else if (toshell_fd >= 0)
4311 len = write(toshell_fd, (char *)ta_buf, (size_t)1);
4312 if (len > 0)
4314 ta_len -= len;
4315 mch_memmove(ta_buf, ta_buf + len, ta_len);
4316 noread_cnt = 0;
4321 if (got_int)
4323 /* CTRL-C sends a signal to the child, we ignore it
4324 * ourselves */
4325 # ifdef HAVE_SETSID
4326 kill(-pid, SIGINT);
4327 # else
4328 kill(0, SIGINT);
4329 # endif
4330 if (wpid > 0)
4331 kill(wpid, SIGINT);
4332 got_int = FALSE;
4336 * Check if the child has any characters to be printed.
4337 * Read them and write them to our window. Repeat this as
4338 * long as there is something to do, avoid the 10ms wait
4339 * for mch_inchar(), or sending typeahead characters to
4340 * the external process.
4341 * TODO: This should handle escape sequences, compatible
4342 * to some terminal (vt52?).
4344 ++noread_cnt;
4345 while (RealWaitForChar(fromshell_fd, 10L, NULL))
4347 len = read(fromshell_fd, (char *)buffer
4348 # ifdef FEAT_MBYTE
4349 + buffer_off, (size_t)(BUFLEN - buffer_off)
4350 # else
4351 , (size_t)BUFLEN
4352 # endif
4354 if (len <= 0) /* end of file or error */
4355 goto finished;
4357 noread_cnt = 0;
4358 if (options & SHELL_READ)
4360 /* Do NUL -> NL translation, append NL separated
4361 * lines to the current buffer. */
4362 for (i = 0; i < len; ++i)
4364 if (buffer[i] == NL)
4365 append_ga_line(&ga);
4366 else if (buffer[i] == NUL)
4367 ga_append(&ga, NL);
4368 else
4369 ga_append(&ga, buffer[i]);
4372 # ifdef FEAT_MBYTE
4373 else if (has_mbyte)
4375 int l;
4377 len += buffer_off;
4378 buffer[len] = NUL;
4380 /* Check if the last character in buffer[] is
4381 * incomplete, keep these bytes for the next
4382 * round. */
4383 for (p = buffer; p < buffer + len; p += l)
4385 l = mb_cptr2len(p);
4386 if (l == 0)
4387 l = 1; /* NUL byte? */
4388 else if (MB_BYTE2LEN(*p) != l)
4389 break;
4391 if (p == buffer) /* no complete character */
4393 /* avoid getting stuck at an illegal byte */
4394 if (len >= 12)
4395 ++p;
4396 else
4398 buffer_off = len;
4399 continue;
4402 c = *p;
4403 *p = NUL;
4404 msg_puts(buffer);
4405 if (p < buffer + len)
4407 *p = c;
4408 buffer_off = (buffer + len) - p;
4409 mch_memmove(buffer, p, buffer_off);
4410 continue;
4412 buffer_off = 0;
4414 # endif /* FEAT_MBYTE */
4415 else
4417 buffer[len] = NUL;
4418 msg_puts(buffer);
4421 windgoto(msg_row, msg_col);
4422 cursor_on();
4423 out_flush();
4424 if (got_int)
4425 break;
4428 /* If we already detected the child has finished break the
4429 * loop now. */
4430 if (wait_pid == pid)
4431 break;
4434 * Check if the child still exists, before checking for
4435 * typed characters (otherwise we would loose typeahead).
4437 # ifdef __NeXT__
4438 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *) 0);
4439 # else
4440 wait_pid = waitpid(pid, &status, WNOHANG);
4441 # endif
4442 if ((wait_pid == (pid_t)-1 && errno == ECHILD)
4443 || (wait_pid == pid && WIFEXITED(status)))
4445 /* Don't break the loop yet, try reading more
4446 * characters from "fromshell_fd" first. When using
4447 * pipes there might still be something to read and
4448 * then we'll break the loop at the "break" above. */
4449 wait_pid = pid;
4451 else
4452 wait_pid = 0;
4454 finished:
4455 p_more = p_more_save;
4456 if (options & SHELL_READ)
4458 if (ga.ga_len > 0)
4460 append_ga_line(&ga);
4461 /* remember that the NL was missing */
4462 write_no_eol_lnum = curwin->w_cursor.lnum;
4464 else
4465 write_no_eol_lnum = 0;
4466 ga_clear(&ga);
4470 * Give all typeahead that wasn't used back to ui_inchar().
4472 if (ta_len)
4473 ui_inchar_undo(ta_buf, ta_len);
4474 State = old_State;
4475 if (toshell_fd >= 0)
4476 close(toshell_fd);
4477 close(fromshell_fd);
4481 * Wait until our child has exited.
4482 * Ignore wait() returning pids of other children and returning
4483 * because of some signal like SIGWINCH.
4484 * Don't wait if wait_pid was already set above, indicating the
4485 * child already exited.
4487 while (wait_pid != pid)
4489 # ifdef _THREAD_SAFE
4490 /* Ugly hack: when compiled with Python threads are probably
4491 * used, in which case wait() sometimes hangs for no obvious
4492 * reason. Use waitpid() instead and loop (like the GUI). */
4493 # ifdef __NeXT__
4494 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0);
4495 # else
4496 wait_pid = waitpid(pid, &status, WNOHANG);
4497 # endif
4498 if (wait_pid == 0)
4500 /* Wait for 1/100 sec before trying again. */
4501 mch_delay(10L, TRUE);
4502 continue;
4504 # else
4505 wait_pid = wait(&status);
4506 # endif
4507 if (wait_pid <= 0
4508 # ifdef ECHILD
4509 && errno == ECHILD
4510 # endif
4512 break;
4515 /* Make sure the child that writes to the external program is
4516 * dead. */
4517 if (wpid > 0)
4518 kill(wpid, SIGKILL);
4521 * Set to raw mode right now, otherwise a CTRL-C after
4522 * catch_signals() will kill Vim.
4524 if (tmode == TMODE_RAW)
4525 settmode(TMODE_RAW);
4526 did_settmode = TRUE;
4527 set_signals();
4529 if (WIFEXITED(status))
4531 /* LINTED avoid "bitwise operation on signed value" */
4532 retval = WEXITSTATUS(status);
4533 if (retval && !emsg_silent)
4535 if (retval == EXEC_FAILED)
4537 MSG_PUTS(_("\nCannot execute shell "));
4538 msg_outtrans(p_sh);
4539 msg_putchar('\n');
4541 else if (!(options & SHELL_SILENT))
4543 MSG_PUTS(_("\nshell returned "));
4544 msg_outnum((long)retval);
4545 msg_putchar('\n');
4549 else
4550 MSG_PUTS(_("\nCommand terminated\n"));
4553 vim_free(argv);
4555 error:
4556 if (!did_settmode)
4557 if (tmode == TMODE_RAW)
4558 settmode(TMODE_RAW); /* set to raw mode */
4559 # ifdef FEAT_TITLE
4560 resettitle();
4561 # endif
4562 vim_free(newcmd);
4564 return retval;
4566 #endif /* USE_SYSTEM */
4570 * Check for CTRL-C typed by reading all available characters.
4571 * In cooked mode we should get SIGINT, no need to check.
4573 void
4574 mch_breakcheck()
4576 if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL))
4577 fill_input_buf(FALSE);
4581 * Wait "msec" msec until a character is available from the keyboard or from
4582 * inbuf[]. msec == -1 will block forever.
4583 * When a GUI is being used, this will never get called -- webb
4585 static int
4586 WaitForChar(msec)
4587 long msec;
4589 #ifdef FEAT_MOUSE_GPM
4590 int gpm_process_wanted;
4591 #endif
4592 #ifdef FEAT_XCLIPBOARD
4593 int rest;
4594 #endif
4595 int avail;
4597 if (input_available()) /* something in inbuf[] */
4598 return 1;
4600 #if defined(FEAT_MOUSE_DEC)
4601 /* May need to query the mouse position. */
4602 if (WantQueryMouse)
4604 WantQueryMouse = FALSE;
4605 mch_write((char_u *)IF_EB("\033[1'|", ESC_STR "[1'|"), 5);
4607 #endif
4610 * For FEAT_MOUSE_GPM and FEAT_XCLIPBOARD we loop here to process mouse
4611 * events. This is a bit complicated, because they might both be defined.
4613 #if defined(FEAT_MOUSE_GPM) || defined(FEAT_XCLIPBOARD)
4614 # ifdef FEAT_XCLIPBOARD
4615 rest = 0;
4616 if (do_xterm_trace())
4617 rest = msec;
4618 # endif
4621 # ifdef FEAT_XCLIPBOARD
4622 if (rest != 0)
4624 msec = XT_TRACE_DELAY;
4625 if (rest >= 0 && rest < XT_TRACE_DELAY)
4626 msec = rest;
4627 if (rest >= 0)
4628 rest -= msec;
4630 # endif
4631 # ifdef FEAT_MOUSE_GPM
4632 gpm_process_wanted = 0;
4633 avail = RealWaitForChar(read_cmd_fd, msec, &gpm_process_wanted);
4634 # else
4635 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4636 # endif
4637 if (!avail)
4639 if (input_available())
4640 return 1;
4641 # ifdef FEAT_XCLIPBOARD
4642 if (rest == 0 || !do_xterm_trace())
4643 # endif
4644 break;
4647 while (FALSE
4648 # ifdef FEAT_MOUSE_GPM
4649 || (gpm_process_wanted && mch_gpm_process() == 0)
4650 # endif
4651 # ifdef FEAT_XCLIPBOARD
4652 || (!avail && rest != 0)
4653 # endif
4656 #else
4657 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4658 #endif
4659 return avail;
4663 * Wait "msec" msec until a character is available from file descriptor "fd".
4664 * Time == -1 will block forever.
4665 * When a GUI is being used, this will not be used for input -- webb
4666 * Returns also, when a request from Sniff is waiting -- toni.
4667 * Or when a Linux GPM mouse event is waiting.
4669 /* ARGSUSED */
4670 #if defined(__BEOS__)
4672 #else
4673 static int
4674 #endif
4675 RealWaitForChar(fd, msec, check_for_gpm)
4676 int fd;
4677 long msec;
4678 int *check_for_gpm;
4680 int ret;
4681 #if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4682 static int busy = FALSE;
4684 /* May retry getting characters after an event was handled. */
4685 # define MAY_LOOP
4687 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4688 /* Remember at what time we started, so that we know how much longer we
4689 * should wait after being interrupted. */
4690 # define USE_START_TV
4691 struct timeval start_tv;
4693 if (msec > 0 && (
4694 # ifdef FEAT_XCLIPBOARD
4695 xterm_Shell != (Widget)0
4696 # if defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4698 # endif
4699 # endif
4700 # ifdef USE_XSMP
4701 xsmp_icefd != -1
4702 # ifdef FEAT_MZSCHEME
4704 # endif
4705 # endif
4706 # ifdef FEAT_MZSCHEME
4707 (mzthreads_allowed() && p_mzq > 0)
4708 # endif
4710 gettimeofday(&start_tv, NULL);
4711 # endif
4713 /* Handle being called recursively. This may happen for the session
4714 * manager stuff, it may save the file, which does a breakcheck. */
4715 if (busy)
4716 return 0;
4717 #endif
4719 #ifdef MAY_LOOP
4720 for (;;)
4721 #endif
4723 #ifdef MAY_LOOP
4724 int finished = TRUE; /* default is to 'loop' just once */
4725 # ifdef FEAT_MZSCHEME
4726 int mzquantum_used = FALSE;
4727 # endif
4728 #endif
4729 #ifndef HAVE_SELECT
4730 struct pollfd fds[5];
4731 int nfd;
4732 # ifdef FEAT_XCLIPBOARD
4733 int xterm_idx = -1;
4734 # endif
4735 # ifdef FEAT_MOUSE_GPM
4736 int gpm_idx = -1;
4737 # endif
4738 # ifdef USE_XSMP
4739 int xsmp_idx = -1;
4740 # endif
4741 int towait = (int)msec;
4743 # ifdef FEAT_MZSCHEME
4744 mzvim_check_threads();
4745 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4747 towait = (int)p_mzq; /* don't wait longer than 'mzquantum' */
4748 mzquantum_used = TRUE;
4750 # endif
4751 fds[0].fd = fd;
4752 fds[0].events = POLLIN;
4753 nfd = 1;
4755 # ifdef FEAT_SNIFF
4756 # define SNIFF_IDX 1
4757 if (want_sniff_request)
4759 fds[SNIFF_IDX].fd = fd_from_sniff;
4760 fds[SNIFF_IDX].events = POLLIN;
4761 nfd++;
4763 # endif
4764 # ifdef FEAT_XCLIPBOARD
4765 if (xterm_Shell != (Widget)0)
4767 xterm_idx = nfd;
4768 fds[nfd].fd = ConnectionNumber(xterm_dpy);
4769 fds[nfd].events = POLLIN;
4770 nfd++;
4772 # endif
4773 # ifdef FEAT_MOUSE_GPM
4774 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4776 gpm_idx = nfd;
4777 fds[nfd].fd = gpm_fd;
4778 fds[nfd].events = POLLIN;
4779 nfd++;
4781 # endif
4782 # ifdef USE_XSMP
4783 if (xsmp_icefd != -1)
4785 xsmp_idx = nfd;
4786 fds[nfd].fd = xsmp_icefd;
4787 fds[nfd].events = POLLIN;
4788 nfd++;
4790 # endif
4792 ret = poll(fds, nfd, towait);
4793 # ifdef FEAT_MZSCHEME
4794 if (ret == 0 && mzquantum_used)
4795 /* MzThreads scheduling is required and timeout occurred */
4796 finished = FALSE;
4797 # endif
4799 # ifdef FEAT_SNIFF
4800 if (ret < 0)
4801 sniff_disconnect(1);
4802 else if (want_sniff_request)
4804 if (fds[SNIFF_IDX].revents & POLLHUP)
4805 sniff_disconnect(1);
4806 if (fds[SNIFF_IDX].revents & POLLIN)
4807 sniff_request_waiting = 1;
4809 # endif
4810 # ifdef FEAT_XCLIPBOARD
4811 if (xterm_Shell != (Widget)0 && (fds[xterm_idx].revents & POLLIN))
4813 xterm_update(); /* Maybe we should hand out clipboard */
4814 if (--ret == 0 && !input_available())
4815 /* Try again */
4816 finished = FALSE;
4818 # endif
4819 # ifdef FEAT_MOUSE_GPM
4820 if (gpm_idx >= 0 && (fds[gpm_idx].revents & POLLIN))
4822 *check_for_gpm = 1;
4824 # endif
4825 # ifdef USE_XSMP
4826 if (xsmp_idx >= 0 && (fds[xsmp_idx].revents & (POLLIN | POLLHUP)))
4828 if (fds[xsmp_idx].revents & POLLIN)
4830 busy = TRUE;
4831 xsmp_handle_requests();
4832 busy = FALSE;
4834 else if (fds[xsmp_idx].revents & POLLHUP)
4836 if (p_verbose > 0)
4837 verb_msg((char_u *)_("XSMP lost ICE connection"));
4838 xsmp_close();
4840 if (--ret == 0)
4841 finished = FALSE; /* Try again */
4843 # endif
4846 #else /* HAVE_SELECT */
4848 struct timeval tv;
4849 struct timeval *tvp;
4850 fd_set rfds, efds;
4851 int maxfd;
4852 long towait = msec;
4854 # ifdef FEAT_MZSCHEME
4855 mzvim_check_threads();
4856 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4858 towait = p_mzq; /* don't wait longer than 'mzquantum' */
4859 mzquantum_used = TRUE;
4861 # endif
4862 # ifdef __EMX__
4863 /* don't check for incoming chars if not in raw mode, because select()
4864 * always returns TRUE then (in some version of emx.dll) */
4865 if (curr_tmode != TMODE_RAW)
4866 return 0;
4867 # endif
4869 if (towait >= 0)
4871 tv.tv_sec = towait / 1000;
4872 tv.tv_usec = (towait % 1000) * (1000000/1000);
4873 tvp = &tv;
4875 else
4876 tvp = NULL;
4879 * Select on ready for reading and exceptional condition (end of file).
4881 FD_ZERO(&rfds); /* calls bzero() on a sun */
4882 FD_ZERO(&efds);
4883 FD_SET(fd, &rfds);
4884 # if !defined(__QNX__) && !defined(__CYGWIN32__)
4885 /* For QNX select() always returns 1 if this is set. Why? */
4886 FD_SET(fd, &efds);
4887 # endif
4888 maxfd = fd;
4890 # ifdef FEAT_SNIFF
4891 if (want_sniff_request)
4893 FD_SET(fd_from_sniff, &rfds);
4894 FD_SET(fd_from_sniff, &efds);
4895 if (maxfd < fd_from_sniff)
4896 maxfd = fd_from_sniff;
4898 # endif
4899 # ifdef FEAT_XCLIPBOARD
4900 if (xterm_Shell != (Widget)0)
4902 FD_SET(ConnectionNumber(xterm_dpy), &rfds);
4903 if (maxfd < ConnectionNumber(xterm_dpy))
4904 maxfd = ConnectionNumber(xterm_dpy);
4906 # endif
4907 # ifdef FEAT_MOUSE_GPM
4908 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4910 FD_SET(gpm_fd, &rfds);
4911 FD_SET(gpm_fd, &efds);
4912 if (maxfd < gpm_fd)
4913 maxfd = gpm_fd;
4915 # endif
4916 # ifdef USE_XSMP
4917 if (xsmp_icefd != -1)
4919 FD_SET(xsmp_icefd, &rfds);
4920 FD_SET(xsmp_icefd, &efds);
4921 if (maxfd < xsmp_icefd)
4922 maxfd = xsmp_icefd;
4924 # endif
4926 # ifdef OLD_VMS
4927 /* Old VMS as v6.2 and older have broken select(). It waits more than
4928 * required. Should not be used */
4929 ret = 0;
4930 # else
4931 ret = select(maxfd + 1, &rfds, NULL, &efds, tvp);
4932 # endif
4933 # ifdef __TANDEM
4934 if (ret == -1 && errno == ENOTSUP)
4936 FD_ZERO(&rfds);
4937 FD_ZERO(&efds);
4938 ret = 0;
4940 #endif
4941 # ifdef FEAT_MZSCHEME
4942 if (ret == 0 && mzquantum_used)
4943 /* loop if MzThreads must be scheduled and timeout occurred */
4944 finished = FALSE;
4945 # endif
4947 # ifdef FEAT_SNIFF
4948 if (ret < 0 )
4949 sniff_disconnect(1);
4950 else if (ret > 0 && want_sniff_request)
4952 if (FD_ISSET(fd_from_sniff, &efds))
4953 sniff_disconnect(1);
4954 if (FD_ISSET(fd_from_sniff, &rfds))
4955 sniff_request_waiting = 1;
4957 # endif
4958 # ifdef FEAT_XCLIPBOARD
4959 if (ret > 0 && xterm_Shell != (Widget)0
4960 && FD_ISSET(ConnectionNumber(xterm_dpy), &rfds))
4962 xterm_update(); /* Maybe we should hand out clipboard */
4963 /* continue looping when we only got the X event and the input
4964 * buffer is empty */
4965 if (--ret == 0 && !input_available())
4967 /* Try again */
4968 finished = FALSE;
4971 # endif
4972 # ifdef FEAT_MOUSE_GPM
4973 if (ret > 0 && gpm_flag && check_for_gpm != NULL && gpm_fd >= 0)
4975 if (FD_ISSET(gpm_fd, &efds))
4976 gpm_close();
4977 else if (FD_ISSET(gpm_fd, &rfds))
4978 *check_for_gpm = 1;
4980 # endif
4981 # ifdef USE_XSMP
4982 if (ret > 0 && xsmp_icefd != -1)
4984 if (FD_ISSET(xsmp_icefd, &efds))
4986 if (p_verbose > 0)
4987 verb_msg((char_u *)_("XSMP lost ICE connection"));
4988 xsmp_close();
4989 if (--ret == 0)
4990 finished = FALSE; /* keep going if event was only one */
4992 else if (FD_ISSET(xsmp_icefd, &rfds))
4994 busy = TRUE;
4995 xsmp_handle_requests();
4996 busy = FALSE;
4997 if (--ret == 0)
4998 finished = FALSE; /* keep going if event was only one */
5001 # endif
5003 #endif /* HAVE_SELECT */
5005 #ifdef MAY_LOOP
5006 if (finished || msec == 0)
5007 break;
5009 /* We're going to loop around again, find out for how long */
5010 if (msec > 0)
5012 # ifdef USE_START_TV
5013 struct timeval mtv;
5015 /* Compute remaining wait time. */
5016 gettimeofday(&mtv, NULL);
5017 msec -= (mtv.tv_sec - start_tv.tv_sec) * 1000L
5018 + (mtv.tv_usec - start_tv.tv_usec) / 1000L;
5019 # else
5020 /* Guess we got interrupted halfway. */
5021 msec = msec / 2;
5022 # endif
5023 if (msec <= 0)
5024 break; /* waited long enough */
5026 #endif
5029 return (ret > 0);
5032 #ifndef VMS
5034 #ifndef NO_EXPANDPATH
5036 * Expand a path into all matching files and/or directories. Handles "*",
5037 * "?", "[a-z]", "**", etc.
5038 * "path" has backslashes before chars that are not to be expanded.
5039 * Returns the number of matches found.
5042 mch_expandpath(gap, path, flags)
5043 garray_T *gap;
5044 char_u *path;
5045 int flags; /* EW_* flags */
5047 return unix_expandpath(gap, path, 0, flags, FALSE);
5049 #endif
5052 * mch_expand_wildcards() - this code does wild-card pattern matching using
5053 * the shell
5055 * return OK for success, FAIL for error (you may lose some memory) and put
5056 * an error message in *file.
5058 * num_pat is number of input patterns
5059 * pat is array of pointers to input patterns
5060 * num_file is pointer to number of matched file names
5061 * file is pointer to array of pointers to matched file names
5064 #ifndef SEEK_SET
5065 # define SEEK_SET 0
5066 #endif
5067 #ifndef SEEK_END
5068 # define SEEK_END 2
5069 #endif
5071 #define SHELL_SPECIAL (char_u *)"\t \"&'$;<>()\\|"
5073 /* ARGSUSED */
5075 mch_expand_wildcards(num_pat, pat, num_file, file, flags)
5076 int num_pat;
5077 char_u **pat;
5078 int *num_file;
5079 char_u ***file;
5080 int flags; /* EW_* flags */
5082 int i;
5083 size_t len;
5084 char_u *p;
5085 int dir;
5086 #ifdef __EMX__
5088 * This is the OS/2 implementation.
5090 # define EXPL_ALLOC_INC 16
5091 char_u **expl_files;
5092 size_t files_alloced, files_free;
5093 char_u *buf;
5094 int has_wildcard;
5096 *num_file = 0; /* default: no files found */
5097 files_alloced = EXPL_ALLOC_INC; /* how much space is allocated */
5098 files_free = EXPL_ALLOC_INC; /* how much space is not used */
5099 *file = (char_u **)alloc(sizeof(char_u **) * files_alloced);
5100 if (*file == NULL)
5101 return FAIL;
5103 for (; num_pat > 0; num_pat--, pat++)
5105 expl_files = NULL;
5106 if (vim_strchr(*pat, '$') || vim_strchr(*pat, '~'))
5107 /* expand environment var or home dir */
5108 buf = expand_env_save(*pat);
5109 else
5110 buf = vim_strsave(*pat);
5111 expl_files = NULL;
5112 has_wildcard = mch_has_exp_wildcard(buf); /* (still) wildcards? */
5113 if (has_wildcard) /* yes, so expand them */
5114 expl_files = (char_u **)_fnexplode(buf);
5117 * return value of buf if no wildcards left,
5118 * OR if no match AND EW_NOTFOUND is set.
5120 if ((!has_wildcard && ((flags & EW_NOTFOUND) || mch_getperm(buf) >= 0))
5121 || (expl_files == NULL && (flags & EW_NOTFOUND)))
5122 { /* simply save the current contents of *buf */
5123 expl_files = (char_u **)alloc(sizeof(char_u **) * 2);
5124 if (expl_files != NULL)
5126 expl_files[0] = vim_strsave(buf);
5127 expl_files[1] = NULL;
5130 vim_free(buf);
5133 * Count number of names resulting from expansion,
5134 * At the same time add a backslash to the end of names that happen to
5135 * be directories, and replace slashes with backslashes.
5137 if (expl_files)
5139 for (i = 0; (p = expl_files[i]) != NULL; i++)
5141 dir = mch_isdir(p);
5142 /* If we don't want dirs and this is one, skip it */
5143 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5144 continue;
5146 /* Skip files that are not executable if we check for that. */
5147 if (!dir && (flags & EW_EXEC) && !mch_can_exe(p))
5148 continue;
5150 if (--files_free == 0)
5152 /* need more room in table of pointers */
5153 files_alloced += EXPL_ALLOC_INC;
5154 *file = (char_u **)vim_realloc(*file,
5155 sizeof(char_u **) * files_alloced);
5156 if (*file == NULL)
5158 EMSG(_(e_outofmem));
5159 *num_file = 0;
5160 return FAIL;
5162 files_free = EXPL_ALLOC_INC;
5164 slash_adjust(p);
5165 if (dir)
5167 /* For a directory we add a '/', unless it's already
5168 * there. */
5169 len = STRLEN(p);
5170 if (((*file)[*num_file] = alloc(len + 2)) != NULL)
5172 STRCPY((*file)[*num_file], p);
5173 if (!after_pathsep((*file)[*num_file],
5174 (*file)[*num_file] + len))
5176 (*file)[*num_file][len] = psepc;
5177 (*file)[*num_file][len + 1] = NUL;
5181 else
5183 (*file)[*num_file] = vim_strsave(p);
5187 * Error message already given by either alloc or vim_strsave.
5188 * Should return FAIL, but returning OK works also.
5190 if ((*file)[*num_file] == NULL)
5191 break;
5192 (*num_file)++;
5194 _fnexplodefree((char **)expl_files);
5197 return OK;
5199 #else /* __EMX__ */
5201 * This is the non-OS/2 implementation (really Unix).
5203 int j;
5204 char_u *tempname;
5205 char_u *command;
5206 FILE *fd;
5207 char_u *buffer;
5208 #define STYLE_ECHO 0 /* use "echo", the default */
5209 #define STYLE_GLOB 1 /* use "glob", for csh */
5210 #define STYLE_VIMGLOB 2 /* use "vimglob", for Posix sh */
5211 #define STYLE_PRINT 3 /* use "print -N", for zsh */
5212 #define STYLE_BT 4 /* `cmd` expansion, execute the pattern
5213 * directly */
5214 int shell_style = STYLE_ECHO;
5215 int check_spaces;
5216 static int did_find_nul = FALSE;
5217 int ampersent = FALSE;
5218 /* vimglob() function to define for Posix shell */
5219 static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >";
5221 *num_file = 0; /* default: no files found */
5222 *file = NULL;
5225 * If there are no wildcards, just copy the names to allocated memory.
5226 * Saves a lot of time, because we don't have to start a new shell.
5228 if (!have_wildcard(num_pat, pat))
5229 return save_patterns(num_pat, pat, num_file, file);
5231 # ifdef HAVE_SANDBOX
5232 /* Don't allow any shell command in the sandbox. */
5233 if (sandbox != 0 && check_secure())
5234 return FAIL;
5235 # endif
5238 * Don't allow the use of backticks in secure and restricted mode.
5240 if (secure || restricted)
5241 for (i = 0; i < num_pat; ++i)
5242 if (vim_strchr(pat[i], '`') != NULL
5243 && (check_restricted() || check_secure()))
5244 return FAIL;
5247 * get a name for the temp file
5249 if ((tempname = vim_tempname('o')) == NULL)
5251 EMSG(_(e_notmp));
5252 return FAIL;
5256 * Let the shell expand the patterns and write the result into the temp
5257 * file.
5258 * STYLE_BT: NL separated
5259 * If expanding `cmd` execute it directly.
5260 * STYLE_GLOB: NUL separated
5261 * If we use *csh, "glob" will work better than "echo".
5262 * STYLE_PRINT: NL or NUL separated
5263 * If we use *zsh, "print -N" will work better than "glob".
5264 * STYLE_VIMGLOB: NL separated
5265 * If we use *sh*, we define "vimglob()".
5266 * STYLE_ECHO: space separated.
5267 * A shell we don't know, stay safe and use "echo".
5269 if (num_pat == 1 && *pat[0] == '`'
5270 && (len = STRLEN(pat[0])) > 2
5271 && *(pat[0] + len - 1) == '`')
5272 shell_style = STYLE_BT;
5273 else if ((len = STRLEN(p_sh)) >= 3)
5275 if (STRCMP(p_sh + len - 3, "csh") == 0)
5276 shell_style = STYLE_GLOB;
5277 else if (STRCMP(p_sh + len - 3, "zsh") == 0)
5278 shell_style = STYLE_PRINT;
5280 if (shell_style == STYLE_ECHO && strstr((char *)gettail(p_sh),
5281 "sh") != NULL)
5282 shell_style = STYLE_VIMGLOB;
5284 /* Compute the length of the command. We need 2 extra bytes: for the
5285 * optional '&' and for the NUL.
5286 * Worst case: "unset nonomatch; print -N >" plus two is 29 */
5287 len = STRLEN(tempname) + 29;
5288 if (shell_style == STYLE_VIMGLOB)
5289 len += STRLEN(sh_vimglob_func);
5291 for (i = 0; i < num_pat; ++i)
5293 /* Count the length of the patterns in the same way as they are put in
5294 * "command" below. */
5295 #ifdef USE_SYSTEM
5296 len += STRLEN(pat[i]) + 3; /* add space and two quotes */
5297 #else
5298 ++len; /* add space */
5299 for (j = 0; pat[i][j] != NUL; ++j)
5301 if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL)
5302 ++len; /* may add a backslash */
5303 ++len;
5305 #endif
5307 command = alloc(len);
5308 if (command == NULL)
5310 /* out of memory */
5311 vim_free(tempname);
5312 return FAIL;
5316 * Build the shell command:
5317 * - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell
5318 * recognizes this).
5319 * - Add the shell command to print the expanded names.
5320 * - Add the temp file name.
5321 * - Add the file name patterns.
5323 if (shell_style == STYLE_BT)
5325 /* change `command; command& ` to (command; command ) */
5326 STRCPY(command, "(");
5327 STRCAT(command, pat[0] + 1); /* exclude first backtick */
5328 p = command + STRLEN(command) - 1;
5329 *p-- = ')'; /* remove last backtick */
5330 while (p > command && vim_iswhite(*p))
5331 --p;
5332 if (*p == '&') /* remove trailing '&' */
5334 ampersent = TRUE;
5335 *p = ' ';
5337 STRCAT(command, ">");
5339 else
5341 if (flags & EW_NOTFOUND)
5342 STRCPY(command, "set nonomatch; ");
5343 else
5344 STRCPY(command, "unset nonomatch; ");
5345 if (shell_style == STYLE_GLOB)
5346 STRCAT(command, "glob >");
5347 else if (shell_style == STYLE_PRINT)
5348 STRCAT(command, "print -N >");
5349 else if (shell_style == STYLE_VIMGLOB)
5350 STRCAT(command, sh_vimglob_func);
5351 else
5352 STRCAT(command, "echo >");
5355 STRCAT(command, tempname);
5357 if (shell_style != STYLE_BT)
5358 for (i = 0; i < num_pat; ++i)
5360 /* When using system() always add extra quotes, because the shell
5361 * is started twice. Otherwise put a backslash before special
5362 * characters, except inside ``. */
5363 #ifdef USE_SYSTEM
5364 STRCAT(command, " \"");
5365 STRCAT(command, pat[i]);
5366 STRCAT(command, "\"");
5367 #else
5368 int intick = FALSE;
5370 p = command + STRLEN(command);
5371 *p++ = ' ';
5372 for (j = 0; pat[i][j] != NUL; ++j)
5374 if (pat[i][j] == '`')
5375 intick = !intick;
5376 else if (pat[i][j] == '\\' && pat[i][j + 1] != NUL)
5378 /* Remove a backslash, take char literally. But keep
5379 * backslash inside backticks, before a special character
5380 * and before a backtick. */
5381 if (intick
5382 || vim_strchr(SHELL_SPECIAL, pat[i][j + 1]) != NULL
5383 || pat[i][j + 1] == '`')
5384 *p++ = '\\';
5385 ++j;
5387 else if (!intick && vim_strchr(SHELL_SPECIAL,
5388 pat[i][j]) != NULL)
5389 /* Put a backslash before a special character, but not
5390 * when inside ``. */
5391 *p++ = '\\';
5393 /* Copy one character. */
5394 *p++ = pat[i][j];
5396 *p = NUL;
5397 #endif
5399 if (flags & EW_SILENT)
5400 show_shell_mess = FALSE;
5401 if (ampersent)
5402 STRCAT(command, "&"); /* put the '&' after the redirection */
5405 * Using zsh -G: If a pattern has no matches, it is just deleted from
5406 * the argument list, otherwise zsh gives an error message and doesn't
5407 * expand any other pattern.
5409 if (shell_style == STYLE_PRINT)
5410 extra_shell_arg = (char_u *)"-G"; /* Use zsh NULL_GLOB option */
5413 * If we use -f then shell variables set in .cshrc won't get expanded.
5414 * vi can do it, so we will too, but it is only necessary if there is a "$"
5415 * in one of the patterns, otherwise we can still use the fast option.
5417 else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat))
5418 extra_shell_arg = (char_u *)"-f"; /* Use csh fast option */
5421 * execute the shell command
5423 i = call_shell(command, SHELL_EXPAND | SHELL_SILENT);
5425 /* When running in the background, give it some time to create the temp
5426 * file, but don't wait for it to finish. */
5427 if (ampersent)
5428 mch_delay(10L, TRUE);
5430 extra_shell_arg = NULL; /* cleanup */
5431 show_shell_mess = TRUE;
5432 vim_free(command);
5434 if (i != 0) /* mch_call_shell() failed */
5436 mch_remove(tempname);
5437 vim_free(tempname);
5439 * With interactive completion, the error message is not printed.
5440 * However with USE_SYSTEM, I don't know how to turn off error messages
5441 * from the shell, so screen may still get messed up -- webb.
5443 #ifndef USE_SYSTEM
5444 if (!(flags & EW_SILENT))
5445 #endif
5447 redraw_later_clear(); /* probably messed up screen */
5448 msg_putchar('\n'); /* clear bottom line quickly */
5449 cmdline_row = Rows - 1; /* continue on last line */
5450 #ifdef USE_SYSTEM
5451 if (!(flags & EW_SILENT))
5452 #endif
5454 MSG(_(e_wildexpand));
5455 msg_start(); /* don't overwrite this message */
5458 /* If a `cmd` expansion failed, don't list `cmd` as a match, even when
5459 * EW_NOTFOUND is given */
5460 if (shell_style == STYLE_BT)
5461 return FAIL;
5462 goto notfound;
5466 * read the names from the file into memory
5468 fd = fopen((char *)tempname, READBIN);
5469 if (fd == NULL)
5471 /* Something went wrong, perhaps a file name with a special char. */
5472 if (!(flags & EW_SILENT))
5474 MSG(_(e_wildexpand));
5475 msg_start(); /* don't overwrite this message */
5477 vim_free(tempname);
5478 goto notfound;
5480 fseek(fd, 0L, SEEK_END);
5481 len = ftell(fd); /* get size of temp file */
5482 fseek(fd, 0L, SEEK_SET);
5483 buffer = alloc(len + 1);
5484 if (buffer == NULL)
5486 /* out of memory */
5487 mch_remove(tempname);
5488 vim_free(tempname);
5489 fclose(fd);
5490 return FAIL;
5492 i = fread((char *)buffer, 1, len, fd);
5493 fclose(fd);
5494 mch_remove(tempname);
5495 if (i != len)
5497 /* unexpected read error */
5498 EMSG2(_(e_notread), tempname);
5499 vim_free(tempname);
5500 vim_free(buffer);
5501 return FAIL;
5503 vim_free(tempname);
5505 # if defined(__CYGWIN__) || defined(__CYGWIN32__)
5506 /* Translate <CR><NL> into <NL>. Caution, buffer may contain NUL. */
5507 p = buffer;
5508 for (i = 0; i < len; ++i)
5509 if (!(buffer[i] == CAR && buffer[i + 1] == NL))
5510 *p++ = buffer[i];
5511 len = p - buffer;
5512 # endif
5515 /* file names are separated with Space */
5516 if (shell_style == STYLE_ECHO)
5518 buffer[len] = '\n'; /* make sure the buffer ends in NL */
5519 p = buffer;
5520 for (i = 0; *p != '\n'; ++i) /* count number of entries */
5522 while (*p != ' ' && *p != '\n')
5523 ++p;
5524 p = skipwhite(p); /* skip to next entry */
5527 /* file names are separated with NL */
5528 else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB)
5530 buffer[len] = NUL; /* make sure the buffer ends in NUL */
5531 p = buffer;
5532 for (i = 0; *p != NUL; ++i) /* count number of entries */
5534 while (*p != '\n' && *p != NUL)
5535 ++p;
5536 if (*p != NUL)
5537 ++p;
5538 p = skipwhite(p); /* skip leading white space */
5541 /* file names are separated with NUL */
5542 else
5545 * Some versions of zsh use spaces instead of NULs to separate
5546 * results. Only do this when there is no NUL before the end of the
5547 * buffer, otherwise we would never be able to use file names with
5548 * embedded spaces when zsh does use NULs.
5549 * When we found a NUL once, we know zsh is OK, set did_find_nul and
5550 * don't check for spaces again.
5552 check_spaces = FALSE;
5553 if (shell_style == STYLE_PRINT && !did_find_nul)
5555 /* If there is a NUL, set did_find_nul, else set check_spaces */
5556 if (len && (int)STRLEN(buffer) < len - 1)
5557 did_find_nul = TRUE;
5558 else
5559 check_spaces = TRUE;
5563 * Make sure the buffer ends with a NUL. For STYLE_PRINT there
5564 * already is one, for STYLE_GLOB it needs to be added.
5566 if (len && buffer[len - 1] == NUL)
5567 --len;
5568 else
5569 buffer[len] = NUL;
5570 i = 0;
5571 for (p = buffer; p < buffer + len; ++p)
5572 if (*p == NUL || (*p == ' ' && check_spaces)) /* count entry */
5574 ++i;
5575 *p = NUL;
5577 if (len)
5578 ++i; /* count last entry */
5580 if (i == 0)
5583 * Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I".
5584 * /bin/sh will happily expand it to nothing rather than returning an
5585 * error; and hey, it's good to check anyway -- webb.
5587 vim_free(buffer);
5588 goto notfound;
5590 *num_file = i;
5591 *file = (char_u **)alloc(sizeof(char_u *) * i);
5592 if (*file == NULL)
5594 /* out of memory */
5595 vim_free(buffer);
5596 return FAIL;
5600 * Isolate the individual file names.
5602 p = buffer;
5603 for (i = 0; i < *num_file; ++i)
5605 (*file)[i] = p;
5606 /* Space or NL separates */
5607 if (shell_style == STYLE_ECHO || shell_style == STYLE_BT
5608 || shell_style == STYLE_VIMGLOB)
5610 while (!(shell_style == STYLE_ECHO && *p == ' ')
5611 && *p != '\n' && *p != NUL)
5612 ++p;
5613 if (p == buffer + len) /* last entry */
5614 *p = NUL;
5615 else
5617 *p++ = NUL;
5618 p = skipwhite(p); /* skip to next entry */
5621 else /* NUL separates */
5623 while (*p && p < buffer + len) /* skip entry */
5624 ++p;
5625 ++p; /* skip NUL */
5630 * Move the file names to allocated memory.
5632 for (j = 0, i = 0; i < *num_file; ++i)
5634 /* Require the files to exist. Helps when using /bin/sh */
5635 if (!(flags & EW_NOTFOUND) && mch_getperm((*file)[i]) < 0)
5636 continue;
5638 /* check if this entry should be included */
5639 dir = (mch_isdir((*file)[i]));
5640 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5641 continue;
5643 /* Skip files that are not executable if we check for that. */
5644 if (!dir && (flags & EW_EXEC) && !mch_can_exe((*file)[i]))
5645 continue;
5647 p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir));
5648 if (p)
5650 STRCPY(p, (*file)[i]);
5651 if (dir)
5652 add_pathsep(p); /* add '/' to a directory name */
5653 (*file)[j++] = p;
5656 vim_free(buffer);
5657 *num_file = j;
5659 if (*num_file == 0) /* rejected all entries */
5661 vim_free(*file);
5662 *file = NULL;
5663 goto notfound;
5666 return OK;
5668 notfound:
5669 if (flags & EW_NOTFOUND)
5670 return save_patterns(num_pat, pat, num_file, file);
5671 return FAIL;
5673 #endif /* __EMX__ */
5676 #endif /* VMS */
5678 #ifndef __EMX__
5679 static int
5680 save_patterns(num_pat, pat, num_file, file)
5681 int num_pat;
5682 char_u **pat;
5683 int *num_file;
5684 char_u ***file;
5686 int i;
5687 char_u *s;
5689 *file = (char_u **)alloc(num_pat * sizeof(char_u *));
5690 if (*file == NULL)
5691 return FAIL;
5692 for (i = 0; i < num_pat; i++)
5694 s = vim_strsave(pat[i]);
5695 if (s != NULL)
5696 /* Be compatible with expand_filename(): halve the number of
5697 * backslashes. */
5698 backslash_halve(s);
5699 (*file)[i] = s;
5701 *num_file = num_pat;
5702 return OK;
5704 #endif
5708 * Return TRUE if the string "p" contains a wildcard that mch_expandpath() can
5709 * expand.
5712 mch_has_exp_wildcard(p)
5713 char_u *p;
5715 for ( ; *p; mb_ptr_adv(p))
5717 #ifndef OS2
5718 if (*p == '\\' && p[1] != NUL)
5719 ++p;
5720 else
5721 #endif
5722 if (vim_strchr((char_u *)
5723 #ifdef VMS
5724 "*?%"
5725 #else
5726 # ifdef OS2
5727 "*?"
5728 # else
5729 "*?[{'"
5730 # endif
5731 #endif
5732 , *p) != NULL)
5733 return TRUE;
5735 return FALSE;
5739 * Return TRUE if the string "p" contains a wildcard.
5740 * Don't recognize '~' at the end as a wildcard.
5743 mch_has_wildcard(p)
5744 char_u *p;
5746 for ( ; *p; mb_ptr_adv(p))
5748 #ifndef OS2
5749 if (*p == '\\' && p[1] != NUL)
5750 ++p;
5751 else
5752 #endif
5753 if (vim_strchr((char_u *)
5754 #ifdef VMS
5755 "*?%$"
5756 #else
5757 # ifdef OS2
5758 # ifdef VIM_BACKTICK
5759 "*?$`"
5760 # else
5761 "*?$"
5762 # endif
5763 # else
5764 "*?[{`'$"
5765 # endif
5766 #endif
5767 , *p) != NULL
5768 || (*p == '~' && p[1] != NUL))
5769 return TRUE;
5771 return FALSE;
5774 #ifndef __EMX__
5775 static int
5776 have_wildcard(num, file)
5777 int num;
5778 char_u **file;
5780 int i;
5782 for (i = 0; i < num; i++)
5783 if (mch_has_wildcard(file[i]))
5784 return 1;
5785 return 0;
5788 static int
5789 have_dollars(num, file)
5790 int num;
5791 char_u **file;
5793 int i;
5795 for (i = 0; i < num; i++)
5796 if (vim_strchr(file[i], '$') != NULL)
5797 return TRUE;
5798 return FALSE;
5800 #endif /* ifndef __EMX__ */
5802 #ifndef HAVE_RENAME
5804 * Scaled-down version of rename(), which is missing in Xenix.
5805 * This version can only move regular files and will fail if the
5806 * destination exists.
5809 mch_rename(src, dest)
5810 const char *src, *dest;
5812 struct stat st;
5814 if (stat(dest, &st) >= 0) /* fail if destination exists */
5815 return -1;
5816 if (link(src, dest) != 0) /* link file to new name */
5817 return -1;
5818 if (mch_remove(src) == 0) /* delete link to old name */
5819 return 0;
5820 return -1;
5822 #endif /* !HAVE_RENAME */
5824 #ifdef FEAT_MOUSE_GPM
5826 * Initializes connection with gpm (if it isn't already opened)
5827 * Return 1 if succeeded (or connection already opened), 0 if failed
5829 static int
5830 gpm_open()
5832 static Gpm_Connect gpm_connect; /* Must it be kept till closing ? */
5834 if (!gpm_flag)
5836 gpm_connect.eventMask = (GPM_UP | GPM_DRAG | GPM_DOWN);
5837 gpm_connect.defaultMask = ~GPM_HARD;
5838 /* Default handling for mouse move*/
5839 gpm_connect.minMod = 0; /* Handle any modifier keys */
5840 gpm_connect.maxMod = 0xffff;
5841 if (Gpm_Open(&gpm_connect, 0) > 0)
5843 /* gpm library tries to handling TSTP causes
5844 * problems. Anyways, we close connection to Gpm whenever
5845 * we are going to suspend or starting an external process
5846 * so we shouldn't have problem with this
5848 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
5849 return 1; /* succeed */
5851 if (gpm_fd == -2)
5852 Gpm_Close(); /* We don't want to talk to xterm via gpm */
5853 return 0;
5855 return 1; /* already open */
5859 * Closes connection to gpm
5861 static void
5862 gpm_close()
5864 if (gpm_flag && gpm_fd >= 0) /* if Open */
5865 Gpm_Close();
5868 /* Reads gpm event and adds special keys to input buf. Returns length of
5869 * generated key sequence.
5870 * This function is made after gui_send_mouse_event
5872 static int
5873 mch_gpm_process()
5875 int button;
5876 static Gpm_Event gpm_event;
5877 char_u string[6];
5878 int_u vim_modifiers;
5879 int row,col;
5880 unsigned char buttons_mask;
5881 unsigned char gpm_modifiers;
5882 static unsigned char old_buttons = 0;
5884 Gpm_GetEvent(&gpm_event);
5886 #ifdef FEAT_GUI
5887 /* Don't put events in the input queue now. */
5888 if (hold_gui_events)
5889 return 0;
5890 #endif
5892 row = gpm_event.y - 1;
5893 col = gpm_event.x - 1;
5895 string[0] = ESC; /* Our termcode */
5896 string[1] = 'M';
5897 string[2] = 'G';
5898 switch (GPM_BARE_EVENTS(gpm_event.type))
5900 case GPM_DRAG:
5901 string[3] = MOUSE_DRAG;
5902 break;
5903 case GPM_DOWN:
5904 buttons_mask = gpm_event.buttons & ~old_buttons;
5905 old_buttons = gpm_event.buttons;
5906 switch (buttons_mask)
5908 case GPM_B_LEFT:
5909 button = MOUSE_LEFT;
5910 break;
5911 case GPM_B_MIDDLE:
5912 button = MOUSE_MIDDLE;
5913 break;
5914 case GPM_B_RIGHT:
5915 button = MOUSE_RIGHT;
5916 break;
5917 default:
5918 return 0;
5919 /*Don't know what to do. Can more than one button be
5920 * reported in one event? */
5922 string[3] = (char_u)(button | 0x20);
5923 SET_NUM_MOUSE_CLICKS(string[3], gpm_event.clicks + 1);
5924 break;
5925 case GPM_UP:
5926 string[3] = MOUSE_RELEASE;
5927 old_buttons &= ~gpm_event.buttons;
5928 break;
5929 default:
5930 return 0;
5932 /*This code is based on gui_x11_mouse_cb in gui_x11.c */
5933 gpm_modifiers = gpm_event.modifiers;
5934 vim_modifiers = 0x0;
5935 /* I ignore capslock stats. Aren't we all just hate capslock mixing with
5936 * Vim commands ? Besides, gpm_event.modifiers is unsigned char, and
5937 * K_CAPSSHIFT is defined 8, so it probably isn't even reported
5939 if (gpm_modifiers & ((1 << KG_SHIFT) | (1 << KG_SHIFTR) | (1 << KG_SHIFTL)))
5940 vim_modifiers |= MOUSE_SHIFT;
5942 if (gpm_modifiers & ((1 << KG_CTRL) | (1 << KG_CTRLR) | (1 << KG_CTRLL)))
5943 vim_modifiers |= MOUSE_CTRL;
5944 if (gpm_modifiers & ((1 << KG_ALT) | (1 << KG_ALTGR)))
5945 vim_modifiers |= MOUSE_ALT;
5946 string[3] |= vim_modifiers;
5947 string[4] = (char_u)(col + ' ' + 1);
5948 string[5] = (char_u)(row + ' ' + 1);
5949 add_to_input_buf(string, 6);
5950 return 6;
5952 #endif /* FEAT_MOUSE_GPM */
5954 #ifdef FEAT_SYSMOUSE
5956 * Initialize connection with sysmouse.
5957 * Let virtual console inform us with SIGUSR2 for pending sysmouse
5958 * output, any sysmouse output than will be processed via sig_sysmouse().
5959 * Return OK if succeeded, FAIL if failed.
5961 static int
5962 sysmouse_open()
5964 struct mouse_info mouse;
5966 mouse.operation = MOUSE_MODE;
5967 mouse.u.mode.mode = 0;
5968 mouse.u.mode.signal = SIGUSR2;
5969 if (ioctl(1, CONS_MOUSECTL, &mouse) != -1)
5971 signal(SIGUSR2, (RETSIGTYPE (*)())sig_sysmouse);
5972 mouse.operation = MOUSE_SHOW;
5973 ioctl(1, CONS_MOUSECTL, &mouse);
5974 return OK;
5976 return FAIL;
5980 * Stop processing SIGUSR2 signals, and also make sure that
5981 * virtual console do not send us any sysmouse related signal.
5983 static void
5984 sysmouse_close()
5986 struct mouse_info mouse;
5988 signal(SIGUSR2, restricted ? SIG_IGN : SIG_DFL);
5989 mouse.operation = MOUSE_MODE;
5990 mouse.u.mode.mode = 0;
5991 mouse.u.mode.signal = 0;
5992 ioctl(1, CONS_MOUSECTL, &mouse);
5996 * Gets info from sysmouse and adds special keys to input buf.
5998 /* ARGSUSED */
5999 static RETSIGTYPE
6000 sig_sysmouse SIGDEFARG(sigarg)
6002 struct mouse_info mouse;
6003 struct video_info video;
6004 char_u string[6];
6005 int row, col;
6006 int button;
6007 int buttons;
6008 static int oldbuttons = 0;
6010 #ifdef FEAT_GUI
6011 /* Don't put events in the input queue now. */
6012 if (hold_gui_events)
6013 return;
6014 #endif
6016 mouse.operation = MOUSE_GETINFO;
6017 if (ioctl(1, FBIO_GETMODE, &video.vi_mode) != -1
6018 && ioctl(1, FBIO_MODEINFO, &video) != -1
6019 && ioctl(1, CONS_MOUSECTL, &mouse) != -1
6020 && video.vi_cheight > 0 && video.vi_cwidth > 0)
6022 row = mouse.u.data.y / video.vi_cheight;
6023 col = mouse.u.data.x / video.vi_cwidth;
6024 buttons = mouse.u.data.buttons;
6025 string[0] = ESC; /* Our termcode */
6026 string[1] = 'M';
6027 string[2] = 'S';
6028 if (oldbuttons == buttons && buttons != 0)
6030 button = MOUSE_DRAG;
6032 else
6034 switch (buttons)
6036 case 0:
6037 button = MOUSE_RELEASE;
6038 break;
6039 case 1:
6040 button = MOUSE_LEFT;
6041 break;
6042 case 2:
6043 button = MOUSE_MIDDLE;
6044 break;
6045 case 4:
6046 button = MOUSE_RIGHT;
6047 break;
6048 default:
6049 return;
6051 oldbuttons = buttons;
6053 string[3] = (char_u)(button);
6054 string[4] = (char_u)(col + ' ' + 1);
6055 string[5] = (char_u)(row + ' ' + 1);
6056 add_to_input_buf(string, 6);
6058 return;
6060 #endif /* FEAT_SYSMOUSE */
6062 #if defined(FEAT_LIBCALL) || defined(PROTO)
6063 typedef char_u * (*STRPROCSTR)__ARGS((char_u *));
6064 typedef char_u * (*INTPROCSTR)__ARGS((int));
6065 typedef int (*STRPROCINT)__ARGS((char_u *));
6066 typedef int (*INTPROCINT)__ARGS((int));
6069 * Call a DLL routine which takes either a string or int param
6070 * and returns an allocated string.
6073 mch_libcall(libname, funcname, argstring, argint, string_result, number_result)
6074 char_u *libname;
6075 char_u *funcname;
6076 char_u *argstring; /* NULL when using a argint */
6077 int argint;
6078 char_u **string_result;/* NULL when using number_result */
6079 int *number_result;
6081 # if defined(USE_DLOPEN)
6082 void *hinstLib;
6083 char *dlerr = NULL;
6084 # else
6085 shl_t hinstLib;
6086 # endif
6087 STRPROCSTR ProcAdd;
6088 INTPROCSTR ProcAddI;
6089 char_u *retval_str = NULL;
6090 int retval_int = 0;
6091 int success = FALSE;
6094 * Get a handle to the DLL module.
6096 # if defined(USE_DLOPEN)
6097 /* First clear any error, it's not cleared by the dlopen() call. */
6098 (void)dlerror();
6100 hinstLib = dlopen((char *)libname, RTLD_LAZY
6101 # ifdef RTLD_LOCAL
6102 | RTLD_LOCAL
6103 # endif
6105 if (hinstLib == NULL)
6107 /* "dlerr" must be used before dlclose() */
6108 dlerr = (char *)dlerror();
6109 if (dlerr != NULL)
6110 EMSG2(_("dlerror = \"%s\""), dlerr);
6112 # else
6113 hinstLib = shl_load((const char*)libname, BIND_IMMEDIATE|BIND_VERBOSE, 0L);
6114 # endif
6116 /* If the handle is valid, try to get the function address. */
6117 if (hinstLib != NULL)
6119 # ifdef HAVE_SETJMP_H
6121 * Catch a crash when calling the library function. For example when
6122 * using a number where a string pointer is expected.
6124 mch_startjmp();
6125 if (SETJMP(lc_jump_env) != 0)
6127 success = FALSE;
6128 # if defined(USE_DLOPEN)
6129 dlerr = NULL;
6130 # endif
6131 mch_didjmp();
6133 else
6134 # endif
6136 retval_str = NULL;
6137 retval_int = 0;
6139 if (argstring != NULL)
6141 # if defined(USE_DLOPEN)
6142 ProcAdd = (STRPROCSTR)dlsym(hinstLib, (const char *)funcname);
6143 dlerr = (char *)dlerror();
6144 # else
6145 if (shl_findsym(&hinstLib, (const char *)funcname,
6146 TYPE_PROCEDURE, (void *)&ProcAdd) < 0)
6147 ProcAdd = NULL;
6148 # endif
6149 if ((success = (ProcAdd != NULL
6150 # if defined(USE_DLOPEN)
6151 && dlerr == NULL
6152 # endif
6155 if (string_result == NULL)
6156 retval_int = ((STRPROCINT)ProcAdd)(argstring);
6157 else
6158 retval_str = (ProcAdd)(argstring);
6161 else
6163 # if defined(USE_DLOPEN)
6164 ProcAddI = (INTPROCSTR)dlsym(hinstLib, (const char *)funcname);
6165 dlerr = (char *)dlerror();
6166 # else
6167 if (shl_findsym(&hinstLib, (const char *)funcname,
6168 TYPE_PROCEDURE, (void *)&ProcAddI) < 0)
6169 ProcAddI = NULL;
6170 # endif
6171 if ((success = (ProcAddI != NULL
6172 # if defined(USE_DLOPEN)
6173 && dlerr == NULL
6174 # endif
6177 if (string_result == NULL)
6178 retval_int = ((INTPROCINT)ProcAddI)(argint);
6179 else
6180 retval_str = (ProcAddI)(argint);
6184 /* Save the string before we free the library. */
6185 /* Assume that a "1" or "-1" result is an illegal pointer. */
6186 if (string_result == NULL)
6187 *number_result = retval_int;
6188 else if (retval_str != NULL
6189 && retval_str != (char_u *)1
6190 && retval_str != (char_u *)-1)
6191 *string_result = vim_strsave(retval_str);
6194 # ifdef HAVE_SETJMP_H
6195 mch_endjmp();
6196 # ifdef SIGHASARG
6197 if (lc_signal != 0)
6199 int i;
6201 /* try to find the name of this signal */
6202 for (i = 0; signal_info[i].sig != -1; i++)
6203 if (lc_signal == signal_info[i].sig)
6204 break;
6205 EMSG2("E368: got SIG%s in libcall()", signal_info[i].name);
6207 # endif
6208 # endif
6210 # if defined(USE_DLOPEN)
6211 /* "dlerr" must be used before dlclose() */
6212 if (dlerr != NULL)
6213 EMSG2(_("dlerror = \"%s\""), dlerr);
6215 /* Free the DLL module. */
6216 (void)dlclose(hinstLib);
6217 # else
6218 (void)shl_unload(hinstLib);
6219 # endif
6222 if (!success)
6224 EMSG2(_(e_libcall), funcname);
6225 return FAIL;
6228 return OK;
6230 #endif
6232 #if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
6233 static int xterm_trace = -1; /* default: disabled */
6234 static int xterm_button;
6237 * Setup a dummy window for X selections in a terminal.
6239 void
6240 setup_term_clip()
6242 int z = 0;
6243 char *strp = "";
6244 Widget AppShell;
6246 if (!x_connect_to_server())
6247 return;
6249 open_app_context();
6250 if (app_context != NULL && xterm_Shell == (Widget)0)
6252 int (*oldhandler)();
6253 #if defined(HAVE_SETJMP_H)
6254 int (*oldIOhandler)();
6255 #endif
6256 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
6257 struct timeval start_tv;
6259 if (p_verbose > 0)
6260 gettimeofday(&start_tv, NULL);
6261 # endif
6263 /* Ignore X errors while opening the display */
6264 oldhandler = XSetErrorHandler(x_error_check);
6266 #if defined(HAVE_SETJMP_H)
6267 /* Ignore X IO errors while opening the display */
6268 oldIOhandler = XSetIOErrorHandler(x_IOerror_check);
6269 mch_startjmp();
6270 if (SETJMP(lc_jump_env) != 0)
6272 mch_didjmp();
6273 xterm_dpy = NULL;
6275 else
6276 #endif
6278 xterm_dpy = XtOpenDisplay(app_context, xterm_display,
6279 "vim_xterm", "Vim_xterm", NULL, 0, &z, &strp);
6280 #if defined(HAVE_SETJMP_H)
6281 mch_endjmp();
6282 #endif
6285 #if defined(HAVE_SETJMP_H)
6286 /* Now handle X IO errors normally. */
6287 (void)XSetIOErrorHandler(oldIOhandler);
6288 #endif
6289 /* Now handle X errors normally. */
6290 (void)XSetErrorHandler(oldhandler);
6292 if (xterm_dpy == NULL)
6294 if (p_verbose > 0)
6295 verb_msg((char_u *)_("Opening the X display failed"));
6296 return;
6299 /* Catch terminating error of the X server connection. */
6300 (void)XSetIOErrorHandler(x_IOerror_handler);
6302 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
6303 if (p_verbose > 0)
6305 verbose_enter();
6306 xopen_message(&start_tv);
6307 verbose_leave();
6309 # endif
6311 /* Create a Shell to make converters work. */
6312 AppShell = XtVaAppCreateShell("vim_xterm", "Vim_xterm",
6313 applicationShellWidgetClass, xterm_dpy,
6314 NULL);
6315 if (AppShell == (Widget)0)
6316 return;
6317 xterm_Shell = XtVaCreatePopupShell("VIM",
6318 topLevelShellWidgetClass, AppShell,
6319 XtNmappedWhenManaged, 0,
6320 XtNwidth, 1,
6321 XtNheight, 1,
6322 NULL);
6323 if (xterm_Shell == (Widget)0)
6324 return;
6326 x11_setup_atoms(xterm_dpy);
6327 if (x11_display == NULL)
6328 x11_display = xterm_dpy;
6330 XtRealizeWidget(xterm_Shell);
6331 XSync(xterm_dpy, False);
6332 xterm_update();
6334 if (xterm_Shell != (Widget)0)
6336 clip_init(TRUE);
6337 if (x11_window == 0 && (strp = getenv("WINDOWID")) != NULL)
6338 x11_window = (Window)atol(strp);
6339 /* Check if $WINDOWID is valid. */
6340 if (test_x11_window(xterm_dpy) == FAIL)
6341 x11_window = 0;
6342 if (x11_window != 0)
6343 xterm_trace = 0;
6347 void
6348 start_xterm_trace(button)
6349 int button;
6351 if (x11_window == 0 || xterm_trace < 0 || xterm_Shell == (Widget)0)
6352 return;
6353 xterm_trace = 1;
6354 xterm_button = button;
6355 do_xterm_trace();
6359 void
6360 stop_xterm_trace()
6362 if (xterm_trace < 0)
6363 return;
6364 xterm_trace = 0;
6368 * Query the xterm pointer and generate mouse termcodes if necessary
6369 * return TRUE if dragging is active, else FALSE
6371 static int
6372 do_xterm_trace()
6374 Window root, child;
6375 int root_x, root_y;
6376 int win_x, win_y;
6377 int row, col;
6378 int_u mask_return;
6379 char_u buf[50];
6380 char_u *strp;
6381 long got_hints;
6382 static char_u *mouse_code;
6383 static char_u mouse_name[2] = {KS_MOUSE, KE_FILLER};
6384 static int prev_row = 0, prev_col = 0;
6385 static XSizeHints xterm_hints;
6387 if (xterm_trace <= 0)
6388 return FALSE;
6390 if (xterm_trace == 1)
6392 /* Get the hints just before tracking starts. The font size might
6393 * have changed recently. */
6394 if (!XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints)
6395 || !(got_hints & PResizeInc)
6396 || xterm_hints.width_inc <= 1
6397 || xterm_hints.height_inc <= 1)
6399 xterm_trace = -1; /* Not enough data -- disable tracing */
6400 return FALSE;
6403 /* Rely on the same mouse code for the duration of this */
6404 mouse_code = find_termcode(mouse_name);
6405 prev_row = mouse_row;
6406 prev_row = mouse_col;
6407 xterm_trace = 2;
6409 /* Find the offset of the chars, there might be a scrollbar on the
6410 * left of the window and/or a menu on the top (eterm etc.) */
6411 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
6412 &win_x, &win_y, &mask_return);
6413 xterm_hints.y = win_y - (xterm_hints.height_inc * mouse_row)
6414 - (xterm_hints.height_inc / 2);
6415 if (xterm_hints.y <= xterm_hints.height_inc / 2)
6416 xterm_hints.y = 2;
6417 xterm_hints.x = win_x - (xterm_hints.width_inc * mouse_col)
6418 - (xterm_hints.width_inc / 2);
6419 if (xterm_hints.x <= xterm_hints.width_inc / 2)
6420 xterm_hints.x = 2;
6421 return TRUE;
6423 if (mouse_code == NULL)
6425 xterm_trace = 0;
6426 return FALSE;
6429 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
6430 &win_x, &win_y, &mask_return);
6432 row = check_row((win_y - xterm_hints.y) / xterm_hints.height_inc);
6433 col = check_col((win_x - xterm_hints.x) / xterm_hints.width_inc);
6434 if (row == prev_row && col == prev_col)
6435 return TRUE;
6437 STRCPY(buf, mouse_code);
6438 strp = buf + STRLEN(buf);
6439 *strp++ = (xterm_button | MOUSE_DRAG) & ~0x20;
6440 *strp++ = (char_u)(col + ' ' + 1);
6441 *strp++ = (char_u)(row + ' ' + 1);
6442 *strp = 0;
6443 add_to_input_buf(buf, STRLEN(buf));
6445 prev_row = row;
6446 prev_col = col;
6447 return TRUE;
6450 # if defined(FEAT_GUI) || defined(PROTO)
6452 * Destroy the display, window and app_context. Required for GTK.
6454 void
6455 clear_xterm_clip()
6457 if (xterm_Shell != (Widget)0)
6459 XtDestroyWidget(xterm_Shell);
6460 xterm_Shell = (Widget)0;
6462 if (xterm_dpy != NULL)
6464 # if 0
6465 /* Lesstif and Solaris crash here, lose some memory */
6466 XtCloseDisplay(xterm_dpy);
6467 # endif
6468 if (x11_display == xterm_dpy)
6469 x11_display = NULL;
6470 xterm_dpy = NULL;
6472 # if 0
6473 if (app_context != (XtAppContext)NULL)
6475 /* Lesstif and Solaris crash here, lose some memory */
6476 XtDestroyApplicationContext(app_context);
6477 app_context = (XtAppContext)NULL;
6479 # endif
6481 # endif
6484 * Catch up with any queued X events. This may put keyboard input into the
6485 * input buffer, call resize call-backs, trigger timers etc. If there is
6486 * nothing in the X event queue (& no timers pending), then we return
6487 * immediately.
6489 static void
6490 xterm_update()
6492 XEvent event;
6494 while (XtAppPending(app_context) && !vim_is_input_buf_full())
6496 XtAppNextEvent(app_context, &event);
6497 #ifdef FEAT_CLIENTSERVER
6499 XPropertyEvent *e = (XPropertyEvent *)&event;
6501 if (e->type == PropertyNotify && e->window == commWindow
6502 && e->atom == commProperty && e->state == PropertyNewValue)
6503 serverEventProc(xterm_dpy, &event);
6505 #endif
6506 XtDispatchEvent(&event);
6511 clip_xterm_own_selection(cbd)
6512 VimClipboard *cbd;
6514 if (xterm_Shell != (Widget)0)
6515 return clip_x11_own_selection(xterm_Shell, cbd);
6516 return FAIL;
6519 void
6520 clip_xterm_lose_selection(cbd)
6521 VimClipboard *cbd;
6523 if (xterm_Shell != (Widget)0)
6524 clip_x11_lose_selection(xterm_Shell, cbd);
6527 void
6528 clip_xterm_request_selection(cbd)
6529 VimClipboard *cbd;
6531 if (xterm_Shell != (Widget)0)
6532 clip_x11_request_selection(xterm_Shell, xterm_dpy, cbd);
6535 void
6536 clip_xterm_set_selection(cbd)
6537 VimClipboard *cbd;
6539 clip_x11_set_selection(cbd);
6541 #endif
6544 #if defined(USE_XSMP) || defined(PROTO)
6546 * Code for X Session Management Protocol.
6548 static void xsmp_handle_save_yourself __ARGS((SmcConn smc_conn, SmPointer client_data, int save_type, Bool shutdown, int interact_style, Bool fast));
6549 static void xsmp_die __ARGS((SmcConn smc_conn, SmPointer client_data));
6550 static void xsmp_save_complete __ARGS((SmcConn smc_conn, SmPointer client_data));
6551 static void xsmp_shutdown_cancelled __ARGS((SmcConn smc_conn, SmPointer client_data));
6552 static void xsmp_ice_connection __ARGS((IceConn iceConn, IcePointer clientData, Bool opening, IcePointer *watchData));
6555 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6556 static void xsmp_handle_interaction __ARGS((SmcConn smc_conn, SmPointer client_data));
6559 * This is our chance to ask the user if they want to save,
6560 * or abort the logout
6562 /*ARGSUSED*/
6563 static void
6564 xsmp_handle_interaction(smc_conn, client_data)
6565 SmcConn smc_conn;
6566 SmPointer client_data;
6568 cmdmod_T save_cmdmod;
6569 int cancel_shutdown = False;
6571 save_cmdmod = cmdmod;
6572 cmdmod.confirm = TRUE;
6573 if (check_changed_any(FALSE))
6574 /* Mustn't logout */
6575 cancel_shutdown = True;
6576 cmdmod = save_cmdmod;
6577 setcursor(); /* position cursor */
6578 out_flush();
6580 /* Done interaction */
6581 SmcInteractDone(smc_conn, cancel_shutdown);
6583 /* Finish off
6584 * Only end save-yourself here if we're not cancelling shutdown;
6585 * we'll get a cancelled callback later in which we'll end it.
6586 * Hopefully get around glitchy SMs (like GNOME-1)
6588 if (!cancel_shutdown)
6590 xsmp.save_yourself = False;
6591 SmcSaveYourselfDone(smc_conn, True);
6594 # endif
6597 * Callback that starts save-yourself.
6599 /*ARGSUSED*/
6600 static void
6601 xsmp_handle_save_yourself(smc_conn, client_data, save_type,
6602 shutdown, interact_style, fast)
6603 SmcConn smc_conn;
6604 SmPointer client_data;
6605 int save_type;
6606 Bool shutdown;
6607 int interact_style;
6608 Bool fast;
6610 /* Handle already being in saveyourself */
6611 if (xsmp.save_yourself)
6612 SmcSaveYourselfDone(smc_conn, True);
6613 xsmp.save_yourself = True;
6614 xsmp.shutdown = shutdown;
6616 /* First up, preserve all files */
6617 out_flush();
6618 ml_sync_all(FALSE, FALSE); /* preserve all swap files */
6620 if (p_verbose > 0)
6621 verb_msg((char_u *)_("XSMP handling save-yourself request"));
6623 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6624 /* Now see if we can ask about unsaved files */
6625 if (shutdown && !fast && gui.in_use)
6626 /* Need to interact with user, but need SM's permission */
6627 SmcInteractRequest(smc_conn, SmDialogError,
6628 xsmp_handle_interaction, client_data);
6629 else
6630 # endif
6632 /* Can stop the cycle here */
6633 SmcSaveYourselfDone(smc_conn, True);
6634 xsmp.save_yourself = False;
6640 * Callback to warn us of imminent death.
6642 /*ARGSUSED*/
6643 static void
6644 xsmp_die(smc_conn, client_data)
6645 SmcConn smc_conn;
6646 SmPointer client_data;
6648 xsmp_close();
6650 /* quit quickly leaving swapfiles for modified buffers behind */
6651 getout_preserve_modified(0);
6656 * Callback to tell us that save-yourself has completed.
6658 /*ARGSUSED*/
6659 static void
6660 xsmp_save_complete(smc_conn, client_data)
6661 SmcConn smc_conn;
6662 SmPointer client_data;
6664 xsmp.save_yourself = False;
6669 * Callback to tell us that an instigated shutdown was cancelled
6670 * (maybe even by us)
6672 /*ARGSUSED*/
6673 static void
6674 xsmp_shutdown_cancelled(smc_conn, client_data)
6675 SmcConn smc_conn;
6676 SmPointer client_data;
6678 if (xsmp.save_yourself)
6679 SmcSaveYourselfDone(smc_conn, True);
6680 xsmp.save_yourself = False;
6681 xsmp.shutdown = False;
6686 * Callback to tell us that a new ICE connection has been established.
6688 /*ARGSUSED*/
6689 static void
6690 xsmp_ice_connection(iceConn, clientData, opening, watchData)
6691 IceConn iceConn;
6692 IcePointer clientData;
6693 Bool opening;
6694 IcePointer *watchData;
6696 /* Intercept creation of ICE connection fd */
6697 if (opening)
6699 xsmp_icefd = IceConnectionNumber(iceConn);
6700 IceRemoveConnectionWatch(xsmp_ice_connection, NULL);
6705 /* Handle any ICE processing that's required; return FAIL if SM lost */
6707 xsmp_handle_requests()
6709 Bool rep;
6711 if (IceProcessMessages(xsmp.iceconn, NULL, &rep)
6712 == IceProcessMessagesIOError)
6714 /* Lost ICE */
6715 if (p_verbose > 0)
6716 verb_msg((char_u *)_("XSMP lost ICE connection"));
6717 xsmp_close();
6718 return FAIL;
6720 else
6721 return OK;
6724 static int dummy;
6726 /* Set up X Session Management Protocol */
6727 void
6728 xsmp_init(void)
6730 char errorstring[80];
6731 SmcCallbacks smcallbacks;
6732 #if 0
6733 SmPropValue smname;
6734 SmProp smnameprop;
6735 SmProp *smprops[1];
6736 #endif
6738 if (p_verbose > 0)
6739 verb_msg((char_u *)_("XSMP opening connection"));
6741 xsmp.save_yourself = xsmp.shutdown = False;
6743 /* Set up SM callbacks - must have all, even if they're not used */
6744 smcallbacks.save_yourself.callback = xsmp_handle_save_yourself;
6745 smcallbacks.save_yourself.client_data = NULL;
6746 smcallbacks.die.callback = xsmp_die;
6747 smcallbacks.die.client_data = NULL;
6748 smcallbacks.save_complete.callback = xsmp_save_complete;
6749 smcallbacks.save_complete.client_data = NULL;
6750 smcallbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
6751 smcallbacks.shutdown_cancelled.client_data = NULL;
6753 /* Set up a watch on ICE connection creations. The "dummy" argument is
6754 * apparently required for FreeBSD (we get a BUS error when using NULL). */
6755 if (IceAddConnectionWatch(xsmp_ice_connection, &dummy) == 0)
6757 if (p_verbose > 0)
6758 verb_msg((char_u *)_("XSMP ICE connection watch failed"));
6759 return;
6762 /* Create an SM connection */
6763 xsmp.smcconn = SmcOpenConnection(
6764 NULL,
6765 NULL,
6766 SmProtoMajor,
6767 SmProtoMinor,
6768 SmcSaveYourselfProcMask | SmcDieProcMask
6769 | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
6770 &smcallbacks,
6771 NULL,
6772 &xsmp.clientid,
6773 sizeof(errorstring),
6774 errorstring);
6775 if (xsmp.smcconn == NULL)
6777 char errorreport[132];
6779 if (p_verbose > 0)
6781 vim_snprintf(errorreport, sizeof(errorreport),
6782 _("XSMP SmcOpenConnection failed: %s"), errorstring);
6783 verb_msg((char_u *)errorreport);
6785 return;
6787 xsmp.iceconn = SmcGetIceConnection(xsmp.smcconn);
6789 #if 0
6790 /* ID ourselves */
6791 smname.value = "vim";
6792 smname.length = 3;
6793 smnameprop.name = "SmProgram";
6794 smnameprop.type = "SmARRAY8";
6795 smnameprop.num_vals = 1;
6796 smnameprop.vals = &smname;
6798 smprops[0] = &smnameprop;
6799 SmcSetProperties(xsmp.smcconn, 1, smprops);
6800 #endif
6804 /* Shut down XSMP comms. */
6805 void
6806 xsmp_close()
6808 if (xsmp_icefd != -1)
6810 SmcCloseConnection(xsmp.smcconn, 0, NULL);
6811 vim_free(xsmp.clientid);
6812 xsmp.clientid = NULL;
6813 xsmp_icefd = -1;
6816 #endif /* USE_XSMP */
6819 #ifdef EBCDIC
6820 /* Translate character to its CTRL- value */
6821 char CtrlTable[] =
6823 /* 00 - 5E */
6824 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6825 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6826 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6827 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6828 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6829 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6830 /* ^ */ 0x1E,
6831 /* - */ 0x1F,
6832 /* 61 - 6C */
6833 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6834 /* _ */ 0x1F,
6835 /* 6E - 80 */
6836 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6837 /* a */ 0x01,
6838 /* b */ 0x02,
6839 /* c */ 0x03,
6840 /* d */ 0x37,
6841 /* e */ 0x2D,
6842 /* f */ 0x2E,
6843 /* g */ 0x2F,
6844 /* h */ 0x16,
6845 /* i */ 0x05,
6846 /* 8A - 90 */
6847 0, 0, 0, 0, 0, 0, 0,
6848 /* j */ 0x15,
6849 /* k */ 0x0B,
6850 /* l */ 0x0C,
6851 /* m */ 0x0D,
6852 /* n */ 0x0E,
6853 /* o */ 0x0F,
6854 /* p */ 0x10,
6855 /* q */ 0x11,
6856 /* r */ 0x12,
6857 /* 9A - A1 */
6858 0, 0, 0, 0, 0, 0, 0, 0,
6859 /* s */ 0x13,
6860 /* t */ 0x3C,
6861 /* u */ 0x3D,
6862 /* v */ 0x32,
6863 /* w */ 0x26,
6864 /* x */ 0x18,
6865 /* y */ 0x19,
6866 /* z */ 0x3F,
6867 /* AA - AC */
6868 0, 0, 0,
6869 /* [ */ 0x27,
6870 /* AE - BC */
6871 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6872 /* ] */ 0x1D,
6873 /* BE - C0 */ 0, 0, 0,
6874 /* A */ 0x01,
6875 /* B */ 0x02,
6876 /* C */ 0x03,
6877 /* D */ 0x37,
6878 /* E */ 0x2D,
6879 /* F */ 0x2E,
6880 /* G */ 0x2F,
6881 /* H */ 0x16,
6882 /* I */ 0x05,
6883 /* CA - D0 */ 0, 0, 0, 0, 0, 0, 0,
6884 /* J */ 0x15,
6885 /* K */ 0x0B,
6886 /* L */ 0x0C,
6887 /* M */ 0x0D,
6888 /* N */ 0x0E,
6889 /* O */ 0x0F,
6890 /* P */ 0x10,
6891 /* Q */ 0x11,
6892 /* R */ 0x12,
6893 /* DA - DF */ 0, 0, 0, 0, 0, 0,
6894 /* \ */ 0x1C,
6895 /* E1 */ 0,
6896 /* S */ 0x13,
6897 /* T */ 0x3C,
6898 /* U */ 0x3D,
6899 /* V */ 0x32,
6900 /* W */ 0x26,
6901 /* X */ 0x18,
6902 /* Y */ 0x19,
6903 /* Z */ 0x3F,
6904 /* EA - FF*/ 0, 0, 0, 0, 0, 0,
6905 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6908 char MetaCharTable[]=
6909 {/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6910 0, 0, 0, 0,'\\', 0,'F', 0,'W','M','N', 0, 0, 0, 0, 0,
6911 0, 0, 0, 0,']', 0, 0,'G', 0, 0,'R','O', 0, 0, 0, 0,
6912 '@','A','B','C','D','E', 0, 0,'H','I','J','K','L', 0, 0, 0,
6913 'P','Q', 0,'S','T','U','V', 0,'X','Y','Z','[', 0, 0,'^', 0
6917 /* TODO: Use characters NOT numbers!!! */
6918 char CtrlCharTable[]=
6919 {/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6920 124,193,194,195, 0,201, 0, 0, 0, 0, 0,210,211,212,213,214,
6921 215,216,217,226, 0,209,200, 0,231,232, 0, 0,224,189, 95,109,
6922 0, 0, 0, 0, 0, 0,230,173, 0, 0, 0, 0, 0,197,198,199,
6923 0, 0,229, 0, 0, 0, 0,196, 0, 0, 0, 0,227,228, 0,233,
6927 #endif