Merge branch 'vim'
[MacVim.git] / src / os_unix.c
blob5c629cdb07e47837244ffc923cdbc11ec923393f
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 <cygwin/version.h>
62 # include <sys/cygwin.h> /* for cygwin_conv_to_posix_path() and/or
63 * for cygwin_conv_path() */
64 # endif
65 #endif
67 #if defined(HAVE_SELECT)
68 extern int select __ARGS((int, fd_set *, fd_set *, fd_set *, struct timeval *));
69 #endif
71 #ifdef FEAT_MOUSE_GPM
72 # include <gpm.h>
73 /* <linux/keyboard.h> contains defines conflicting with "keymap.h",
74 * I just copied relevant defines here. A cleaner solution would be to put gpm
75 * code into separate file and include there linux/keyboard.h
77 /* #include <linux/keyboard.h> */
78 # define KG_SHIFT 0
79 # define KG_CTRL 2
80 # define KG_ALT 3
81 # define KG_ALTGR 1
82 # define KG_SHIFTL 4
83 # define KG_SHIFTR 5
84 # define KG_CTRLL 6
85 # define KG_CTRLR 7
86 # define KG_CAPSSHIFT 8
88 static void gpm_close __ARGS((void));
89 static int gpm_open __ARGS((void));
90 static int mch_gpm_process __ARGS((void));
91 #endif
93 #ifdef FEAT_SYSMOUSE
94 # include <sys/consio.h>
95 # include <sys/fbio.h>
97 static int sysmouse_open __ARGS((void));
98 static void sysmouse_close __ARGS((void));
99 static RETSIGTYPE sig_sysmouse __ARGS(SIGPROTOARG);
100 #endif
103 * end of autoconf section. To be extended...
106 /* Are the following #ifdefs still required? And why? Is that for X11? */
108 #if defined(ESIX) || defined(M_UNIX) && !defined(SCO)
109 # ifdef SIGWINCH
110 # undef SIGWINCH
111 # endif
112 # ifdef TIOCGWINSZ
113 # undef TIOCGWINSZ
114 # endif
115 #endif
117 #if defined(SIGWINDOW) && !defined(SIGWINCH) /* hpux 9.01 has it */
118 # define SIGWINCH SIGWINDOW
119 #endif
121 #ifdef FEAT_X11
122 # include <X11/Xlib.h>
123 # include <X11/Xutil.h>
124 # include <X11/Xatom.h>
125 # ifdef FEAT_XCLIPBOARD
126 # include <X11/Intrinsic.h>
127 # include <X11/Shell.h>
128 # include <X11/StringDefs.h>
129 static Widget xterm_Shell = (Widget)0;
130 static void xterm_update __ARGS((void));
131 # endif
133 # if defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE)
134 Window x11_window = 0;
135 # endif
136 Display *x11_display = NULL;
138 # ifdef FEAT_TITLE
139 static int get_x11_windis __ARGS((void));
140 static void set_x11_title __ARGS((char_u *));
141 static void set_x11_icon __ARGS((char_u *));
142 # endif
143 #endif
145 #ifdef FEAT_TITLE
146 static int get_x11_title __ARGS((int));
147 static int get_x11_icon __ARGS((int));
149 static char_u *oldtitle = NULL;
150 static int did_set_title = FALSE;
151 static char_u *oldicon = NULL;
152 static int did_set_icon = FALSE;
153 #endif
155 static void may_core_dump __ARGS((void));
157 static int WaitForChar __ARGS((long));
158 #if defined(__BEOS__)
159 int RealWaitForChar __ARGS((int, long, int *));
160 #else
161 static int RealWaitForChar __ARGS((int, long, int *));
162 #endif
164 #ifdef FEAT_XCLIPBOARD
165 static int do_xterm_trace __ARGS((void));
166 # define XT_TRACE_DELAY 50 /* delay for xterm tracing */
167 #endif
169 static void handle_resize __ARGS((void));
171 #if defined(SIGWINCH)
172 static RETSIGTYPE sig_winch __ARGS(SIGPROTOARG);
173 #endif
174 #if defined(SIGINT)
175 static RETSIGTYPE catch_sigint __ARGS(SIGPROTOARG);
176 #endif
177 #if defined(SIGPWR)
178 static RETSIGTYPE catch_sigpwr __ARGS(SIGPROTOARG);
179 #endif
180 #if defined(SIGALRM) && defined(FEAT_X11) \
181 && defined(FEAT_TITLE) && !defined(FEAT_GUI_GTK)
182 # define SET_SIG_ALARM
183 static RETSIGTYPE sig_alarm __ARGS(SIGPROTOARG);
184 /* volatile because it is used in signal handler sig_alarm(). */
185 static volatile int sig_alarm_called;
186 #endif
187 static RETSIGTYPE deathtrap __ARGS(SIGPROTOARG);
189 static void catch_int_signal __ARGS((void));
190 static void set_signals __ARGS((void));
191 static void catch_signals __ARGS((RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)()));
192 #ifndef __EMX__
193 static int have_wildcard __ARGS((int, char_u **));
194 static int have_dollars __ARGS((int, char_u **));
195 #endif
197 #ifndef __EMX__
198 static int save_patterns __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file));
199 #endif
201 #ifndef SIG_ERR
202 # define SIG_ERR ((RETSIGTYPE (*)())-1)
203 #endif
205 /* volatile because it is used in signal handler sig_winch(). */
206 static volatile int do_resize = FALSE;
207 #ifndef __EMX__
208 static char_u *extra_shell_arg = NULL;
209 static int show_shell_mess = TRUE;
210 #endif
211 /* volatile because it is used in signal handler deathtrap(). */
212 static volatile int deadly_signal = 0; /* The signal we caught */
213 /* volatile because it is used in signal handler deathtrap(). */
214 static volatile int in_mch_delay = FALSE; /* sleeping in mch_delay() */
216 static int curr_tmode = TMODE_COOK; /* contains current terminal mode */
218 #ifdef USE_XSMP
219 typedef struct
221 SmcConn smcconn; /* The SM connection ID */
222 IceConn iceconn; /* The ICE connection ID */
223 char *clientid; /* The client ID for the current smc session */
224 Bool save_yourself; /* If we're in the middle of a save_yourself */
225 Bool shutdown; /* If we're in shutdown mode */
226 } xsmp_config_T;
228 static xsmp_config_T xsmp;
229 #endif
231 #ifdef SYS_SIGLIST_DECLARED
233 * I have seen
234 * extern char *_sys_siglist[NSIG];
235 * on Irix, Linux, NetBSD and Solaris. It contains a nice list of strings
236 * that describe the signals. That is nearly what we want here. But
237 * autoconf does only check for sys_siglist (without the underscore), I
238 * do not want to change everything today.... jw.
239 * This is why AC_DECL_SYS_SIGLIST is commented out in configure.in
241 #endif
243 static struct signalinfo
245 int sig; /* Signal number, eg. SIGSEGV etc */
246 char *name; /* Signal name (not char_u!). */
247 char deadly; /* Catch as a deadly signal? */
248 } signal_info[] =
250 #ifdef SIGHUP
251 {SIGHUP, "HUP", TRUE},
252 #endif
253 #ifdef SIGQUIT
254 {SIGQUIT, "QUIT", TRUE},
255 #endif
256 #ifdef SIGILL
257 {SIGILL, "ILL", TRUE},
258 #endif
259 #ifdef SIGTRAP
260 {SIGTRAP, "TRAP", TRUE},
261 #endif
262 #ifdef SIGABRT
263 {SIGABRT, "ABRT", TRUE},
264 #endif
265 #ifdef SIGEMT
266 {SIGEMT, "EMT", TRUE},
267 #endif
268 #ifdef SIGFPE
269 {SIGFPE, "FPE", TRUE},
270 #endif
271 #ifdef SIGBUS
272 {SIGBUS, "BUS", TRUE},
273 #endif
274 #ifdef SIGSEGV
275 {SIGSEGV, "SEGV", TRUE},
276 #endif
277 #ifdef SIGSYS
278 {SIGSYS, "SYS", TRUE},
279 #endif
280 #ifdef SIGALRM
281 {SIGALRM, "ALRM", FALSE}, /* Perl's alarm() can trigger it */
282 #endif
283 #ifdef SIGTERM
284 {SIGTERM, "TERM", TRUE},
285 #endif
286 #ifdef SIGVTALRM
287 {SIGVTALRM, "VTALRM", TRUE},
288 #endif
289 #if defined(SIGPROF) && !defined(FEAT_MZSCHEME) && !defined(WE_ARE_PROFILING)
290 /* MzScheme uses SIGPROF for its own needs; On Linux with profiling
291 * this makes Vim exit. WE_ARE_PROFILING is defined in Makefile. */
292 {SIGPROF, "PROF", TRUE},
293 #endif
294 #ifdef SIGXCPU
295 {SIGXCPU, "XCPU", TRUE},
296 #endif
297 #ifdef SIGXFSZ
298 {SIGXFSZ, "XFSZ", TRUE},
299 #endif
300 #ifdef SIGUSR1
301 {SIGUSR1, "USR1", TRUE},
302 #endif
303 #if defined(SIGUSR2) && !defined(FEAT_SYSMOUSE)
304 /* Used for sysmouse handling */
305 {SIGUSR2, "USR2", TRUE},
306 #endif
307 #ifdef SIGINT
308 {SIGINT, "INT", FALSE},
309 #endif
310 #ifdef SIGWINCH
311 {SIGWINCH, "WINCH", FALSE},
312 #endif
313 #ifdef SIGTSTP
314 {SIGTSTP, "TSTP", FALSE},
315 #endif
316 #ifdef SIGPIPE
317 {SIGPIPE, "PIPE", FALSE},
318 #endif
319 {-1, "Unknown!", FALSE}
323 mch_chdir(path)
324 char *path;
326 if (p_verbose >= 5)
328 verbose_enter();
329 smsg((char_u *)"chdir(%s)", path);
330 verbose_leave();
332 # ifdef VMS
333 return chdir(vms_fixfilename(path));
334 # else
335 return chdir(path);
336 # endif
340 * Write s[len] to the screen.
342 void
343 mch_write(s, len)
344 char_u *s;
345 int len;
347 ignored = (int)write(1, (char *)s, len);
348 if (p_wd) /* Unix is too fast, slow down a bit more */
349 RealWaitForChar(read_cmd_fd, p_wd, NULL);
353 * mch_inchar(): low level input function.
354 * Get a characters from the keyboard.
355 * Return the number of characters that are available.
356 * If wtime == 0 do not wait for characters.
357 * If wtime == n wait a short time for characters.
358 * If wtime == -1 wait forever for characters.
361 mch_inchar(buf, maxlen, wtime, tb_change_cnt)
362 char_u *buf;
363 int maxlen;
364 long wtime; /* don't use "time", MIPS cannot handle it */
365 int tb_change_cnt;
367 int len;
369 /* Check if window changed size while we were busy, perhaps the ":set
370 * columns=99" command was used. */
371 while (do_resize)
372 handle_resize();
374 if (wtime >= 0)
376 while (WaitForChar(wtime) == 0) /* no character available */
378 if (!do_resize) /* return if not interrupted by resize */
379 return 0;
380 handle_resize();
383 else /* wtime == -1 */
386 * If there is no character available within 'updatetime' seconds
387 * flush all the swap files to disk.
388 * Also done when interrupted by SIGWINCH.
390 if (WaitForChar(p_ut) == 0)
392 #ifdef FEAT_AUTOCMD
393 if (trigger_cursorhold() && maxlen >= 3
394 && !typebuf_changed(tb_change_cnt))
396 buf[0] = K_SPECIAL;
397 buf[1] = KS_EXTRA;
398 buf[2] = (int)KE_CURSORHOLD;
399 return 3;
401 #endif
402 before_blocking();
406 for (;;) /* repeat until we got a character */
408 while (do_resize) /* window changed size */
409 handle_resize();
411 * we want to be interrupted by the winch signal
413 WaitForChar(-1L);
414 if (do_resize) /* interrupted by SIGWINCH signal */
415 continue;
417 /* If input was put directly in typeahead buffer bail out here. */
418 if (typebuf_changed(tb_change_cnt))
419 return 0;
422 * For some terminals we only get one character at a time.
423 * We want the get all available characters, so we could keep on
424 * trying until none is available
425 * For some other terminals this is quite slow, that's why we don't do
426 * it.
428 len = read_from_input_buf(buf, (long)maxlen);
429 if (len > 0)
431 #ifdef OS2
432 int i;
434 for (i = 0; i < len; i++)
435 if (buf[i] == 0)
436 buf[i] = K_NUL;
437 #endif
438 return len;
443 static void
444 handle_resize()
446 do_resize = FALSE;
447 shell_resized();
451 * return non-zero if a character is available
454 mch_char_avail()
456 return WaitForChar(0L);
459 #if defined(HAVE_TOTAL_MEM) || defined(PROTO)
460 # ifdef HAVE_SYS_RESOURCE_H
461 # include <sys/resource.h>
462 # endif
463 # if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTL)
464 # include <sys/sysctl.h>
465 # endif
466 # if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
467 # include <sys/sysinfo.h>
468 # endif
471 * Return total amount of memory available in Kbyte.
472 * Doesn't change when memory has been allocated.
474 long_u
475 mch_total_mem(special)
476 int special UNUSED;
478 # ifdef __EMX__
479 return ulimit(3, 0L) >> 10; /* always 32MB? */
480 # else
481 long_u mem = 0;
482 long_u shiftright = 10; /* how much to shift "mem" right for Kbyte */
484 # ifdef HAVE_SYSCTL
485 int mib[2], physmem;
486 size_t len;
488 /* BSD way of getting the amount of RAM available. */
489 mib[0] = CTL_HW;
490 mib[1] = HW_USERMEM;
491 len = sizeof(physmem);
492 if (sysctl(mib, 2, &physmem, &len, NULL, 0) == 0)
493 mem = (long_u)physmem;
494 # endif
496 # if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
497 if (mem == 0)
499 struct sysinfo sinfo;
501 /* Linux way of getting amount of RAM available */
502 if (sysinfo(&sinfo) == 0)
504 # ifdef HAVE_SYSINFO_MEM_UNIT
505 /* avoid overflow as much as possible */
506 while (shiftright > 0 && (sinfo.mem_unit & 1) == 0)
508 sinfo.mem_unit = sinfo.mem_unit >> 1;
509 --shiftright;
511 mem = sinfo.totalram * sinfo.mem_unit;
512 # else
513 mem = sinfo.totalram;
514 # endif
517 # endif
519 # ifdef HAVE_SYSCONF
520 if (mem == 0)
522 long pagesize, pagecount;
524 /* Solaris way of getting amount of RAM available */
525 pagesize = sysconf(_SC_PAGESIZE);
526 pagecount = sysconf(_SC_PHYS_PAGES);
527 if (pagesize > 0 && pagecount > 0)
529 /* avoid overflow as much as possible */
530 while (shiftright > 0 && (pagesize & 1) == 0)
532 pagesize = (long_u)pagesize >> 1;
533 --shiftright;
535 mem = (long_u)pagesize * pagecount;
538 # endif
540 /* Return the minimum of the physical memory and the user limit, because
541 * using more than the user limit may cause Vim to be terminated. */
542 # if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT)
544 struct rlimit rlp;
546 if (getrlimit(RLIMIT_DATA, &rlp) == 0
547 && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
548 # ifdef RLIM_INFINITY
549 && rlp.rlim_cur != RLIM_INFINITY
550 # endif
551 && ((long_u)rlp.rlim_cur >> 10) < (mem >> shiftright)
554 mem = (long_u)rlp.rlim_cur;
555 shiftright = 10;
558 # endif
560 if (mem > 0)
561 return mem >> shiftright;
562 return (long_u)0x1fffff;
563 # endif
565 #endif
567 void
568 mch_delay(msec, ignoreinput)
569 long msec;
570 int ignoreinput;
572 int old_tmode;
573 #ifdef FEAT_MZSCHEME
574 long total = msec; /* remember original value */
575 #endif
577 if (ignoreinput)
579 /* Go to cooked mode without echo, to allow SIGINT interrupting us
580 * here. But we don't want QUIT to kill us (CTRL-\ used in a
581 * shell may produce SIGQUIT). */
582 in_mch_delay = TRUE;
583 old_tmode = curr_tmode;
584 if (curr_tmode == TMODE_RAW)
585 settmode(TMODE_SLEEP);
588 * Everybody sleeps in a different way...
589 * Prefer nanosleep(), some versions of usleep() can only sleep up to
590 * one second.
592 #ifdef FEAT_MZSCHEME
595 /* if total is large enough, wait by portions in p_mzq */
596 if (total > p_mzq)
597 msec = p_mzq;
598 else
599 msec = total;
600 total -= msec;
601 #endif
602 #ifdef HAVE_NANOSLEEP
604 struct timespec ts;
606 ts.tv_sec = msec / 1000;
607 ts.tv_nsec = (msec % 1000) * 1000000;
608 (void)nanosleep(&ts, NULL);
610 #else
611 # ifdef HAVE_USLEEP
612 while (msec >= 1000)
614 usleep((unsigned int)(999 * 1000));
615 msec -= 999;
617 usleep((unsigned int)(msec * 1000));
618 # else
619 # ifndef HAVE_SELECT
620 poll(NULL, 0, (int)msec);
621 # else
622 # ifdef __EMX__
623 _sleep2(msec);
624 # else
626 struct timeval tv;
628 tv.tv_sec = msec / 1000;
629 tv.tv_usec = (msec % 1000) * 1000;
631 * NOTE: Solaris 2.6 has a bug that makes select() hang here. Get
632 * a patch from Sun to fix this. Reported by Gunnar Pedersen.
634 select(0, NULL, NULL, NULL, &tv);
636 # endif /* __EMX__ */
637 # endif /* HAVE_SELECT */
638 # endif /* HAVE_NANOSLEEP */
639 #endif /* HAVE_USLEEP */
640 #ifdef FEAT_MZSCHEME
642 while (total > 0);
643 #endif
645 settmode(old_tmode);
646 in_mch_delay = FALSE;
648 else
649 WaitForChar(msec);
652 #if 0 /* disabled, no longer needed now that regmatch() is not recursive */
653 # if defined(HAVE_GETRLIMIT)
654 # define HAVE_STACK_LIMIT
655 # endif
656 #endif
658 #if defined(HAVE_STACK_LIMIT) \
659 || (!defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGSTACK))
660 # define HAVE_CHECK_STACK_GROWTH
662 * Support for checking for an almost-out-of-stack-space situation.
666 * Return a pointer to an item on the stack. Used to find out if the stack
667 * grows up or down.
669 static void check_stack_growth __ARGS((char *p));
670 static int stack_grows_downwards;
673 * Find out if the stack grows upwards or downwards.
674 * "p" points to a variable on the stack of the caller.
676 static void
677 check_stack_growth(p)
678 char *p;
680 int i;
682 stack_grows_downwards = (p > (char *)&i);
684 #endif
686 #if defined(HAVE_STACK_LIMIT) || defined(PROTO)
687 static char *stack_limit = NULL;
689 #if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
690 # include <pthread.h>
691 # include <pthread_np.h>
692 #endif
695 * Find out until how var the stack can grow without getting into trouble.
696 * Called when starting up and when switching to the signal stack in
697 * deathtrap().
699 static void
700 get_stack_limit()
702 struct rlimit rlp;
703 int i;
704 long lim;
706 /* Set the stack limit to 15/16 of the allowable size. Skip this when the
707 * limit doesn't fit in a long (rlim_cur might be "long long"). */
708 if (getrlimit(RLIMIT_STACK, &rlp) == 0
709 && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
710 # ifdef RLIM_INFINITY
711 && rlp.rlim_cur != RLIM_INFINITY
712 # endif
715 lim = (long)rlp.rlim_cur;
716 #if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
718 pthread_attr_t attr;
719 size_t size;
721 /* On FreeBSD the initial thread always has a fixed stack size, no
722 * matter what the limits are set to. Normally it's 1 Mbyte. */
723 pthread_attr_init(&attr);
724 if (pthread_attr_get_np(pthread_self(), &attr) == 0)
726 pthread_attr_getstacksize(&attr, &size);
727 if (lim > (long)size)
728 lim = (long)size;
730 pthread_attr_destroy(&attr);
732 #endif
733 if (stack_grows_downwards)
735 stack_limit = (char *)((long)&i - (lim / 16L * 15L));
736 if (stack_limit >= (char *)&i)
737 /* overflow, set to 1/16 of current stack position */
738 stack_limit = (char *)((long)&i / 16L);
740 else
742 stack_limit = (char *)((long)&i + (lim / 16L * 15L));
743 if (stack_limit <= (char *)&i)
744 stack_limit = NULL; /* overflow */
750 * Return FAIL when running out of stack space.
751 * "p" must point to any variable local to the caller that's on the stack.
754 mch_stackcheck(p)
755 char *p;
757 if (stack_limit != NULL)
759 if (stack_grows_downwards)
761 if (p < stack_limit)
762 return FAIL;
764 else if (p > stack_limit)
765 return FAIL;
767 return OK;
769 #endif
771 #if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
773 * Support for using the signal stack.
774 * This helps when we run out of stack space, which causes a SIGSEGV. The
775 * signal handler then must run on another stack, since the normal stack is
776 * completely full.
779 #ifndef SIGSTKSZ
780 # define SIGSTKSZ 8000 /* just a guess of how much stack is needed... */
781 #endif
783 # ifdef HAVE_SIGALTSTACK
784 static stack_t sigstk; /* for sigaltstack() */
785 # else
786 static struct sigstack sigstk; /* for sigstack() */
787 # endif
789 static void init_signal_stack __ARGS((void));
790 static char *signal_stack;
792 static void
793 init_signal_stack()
795 if (signal_stack != NULL)
797 # ifdef HAVE_SIGALTSTACK
798 # if defined(__APPLE__) && (!defined(MAC_OS_X_VERSION_MAX_ALLOWED) \
799 || MAC_OS_X_VERSION_MAX_ALLOWED <= 1040)
800 /* missing prototype. Adding it to osdef?.h.in doesn't work, because
801 * "struct sigaltstack" needs to be declared. */
802 extern int sigaltstack __ARGS((const struct sigaltstack *ss, struct sigaltstack *oss));
803 # endif
805 # ifdef HAVE_SS_BASE
806 sigstk.ss_base = signal_stack;
807 # else
808 sigstk.ss_sp = signal_stack;
809 # endif
810 sigstk.ss_size = SIGSTKSZ;
811 sigstk.ss_flags = 0;
812 (void)sigaltstack(&sigstk, NULL);
813 # else
814 sigstk.ss_sp = signal_stack;
815 if (stack_grows_downwards)
816 sigstk.ss_sp += SIGSTKSZ - 1;
817 sigstk.ss_onstack = 0;
818 (void)sigstack(&sigstk, NULL);
819 # endif
822 #endif
825 * We need correct prototypes for a signal function, otherwise mean compilers
826 * will barf when the second argument to signal() is ``wrong''.
827 * Let me try it with a few tricky defines from my own osdef.h (jw).
829 #if defined(SIGWINCH)
830 static RETSIGTYPE
831 sig_winch SIGDEFARG(sigarg)
833 /* this is not required on all systems, but it doesn't hurt anybody */
834 signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
835 do_resize = TRUE;
836 SIGRETURN;
838 #endif
840 #if defined(SIGINT)
841 static RETSIGTYPE
842 catch_sigint SIGDEFARG(sigarg)
844 /* this is not required on all systems, but it doesn't hurt anybody */
845 signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
846 got_int = TRUE;
847 SIGRETURN;
849 #endif
851 #if defined(SIGPWR)
852 static RETSIGTYPE
853 catch_sigpwr SIGDEFARG(sigarg)
855 /* this is not required on all systems, but it doesn't hurt anybody */
856 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
858 * I'm not sure we get the SIGPWR signal when the system is really going
859 * down or when the batteries are almost empty. Just preserve the swap
860 * files and don't exit, that can't do any harm.
862 ml_sync_all(FALSE, FALSE);
863 SIGRETURN;
865 #endif
867 #ifdef SET_SIG_ALARM
869 * signal function for alarm().
871 static RETSIGTYPE
872 sig_alarm SIGDEFARG(sigarg)
874 /* doesn't do anything, just to break a system call */
875 sig_alarm_called = TRUE;
876 SIGRETURN;
878 #endif
880 #if (defined(HAVE_SETJMP_H) \
881 && ((defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) \
882 || defined(FEAT_LIBCALL))) \
883 || defined(PROTO)
885 * A simplistic version of setjmp() that only allows one level of using.
886 * Don't call twice before calling mch_endjmp()!.
887 * Usage:
888 * mch_startjmp();
889 * if (SETJMP(lc_jump_env) != 0)
891 * mch_didjmp();
892 * EMSG("crash!");
894 * else
896 * do_the_work;
897 * mch_endjmp();
899 * Note: Can't move SETJMP() here, because a function calling setjmp() must
900 * not return before the saved environment is used.
901 * Returns OK for normal return, FAIL when the protected code caused a
902 * problem and LONGJMP() was used.
904 void
905 mch_startjmp()
907 #ifdef SIGHASARG
908 lc_signal = 0;
909 #endif
910 lc_active = TRUE;
913 void
914 mch_endjmp()
916 lc_active = FALSE;
919 void
920 mch_didjmp()
922 # if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
923 /* On FreeBSD the signal stack has to be reset after using siglongjmp(),
924 * otherwise catching the signal only works once. */
925 init_signal_stack();
926 # endif
928 #endif
931 * This function handles deadly signals.
932 * It tries to preserve any swap file and exit properly.
933 * (partly from Elvis).
935 static RETSIGTYPE
936 deathtrap SIGDEFARG(sigarg)
938 static int entered = 0; /* count the number of times we got here.
939 Note: when memory has been corrupted
940 this may get an arbitrary value! */
941 #ifdef SIGHASARG
942 int i;
943 #endif
945 #if defined(HAVE_SETJMP_H)
947 * Catch a crash in protected code.
948 * Restores the environment saved in lc_jump_env, which looks like
949 * SETJMP() returns 1.
951 if (lc_active)
953 # if defined(SIGHASARG)
954 lc_signal = sigarg;
955 # endif
956 lc_active = FALSE; /* don't jump again */
957 LONGJMP(lc_jump_env, 1);
958 /* NOTREACHED */
960 #endif
962 #ifdef SIGHASARG
963 # ifdef SIGQUIT
964 /* While in mch_delay() we go to cooked mode to allow a CTRL-C to
965 * interrupt us. But in cooked mode we may also get SIGQUIT, e.g., when
966 * pressing CTRL-\, but we don't want Vim to exit then. */
967 if (in_mch_delay && sigarg == SIGQUIT)
968 SIGRETURN;
969 # endif
971 /* When SIGHUP, SIGQUIT, etc. are blocked: postpone the effect and return
972 * here. This avoids that a non-reentrant function is interrupted, e.g.,
973 * free(). Calling free() again may then cause a crash. */
974 if (entered == 0
975 && (0
976 # ifdef SIGHUP
977 || sigarg == SIGHUP
978 # endif
979 # ifdef SIGQUIT
980 || sigarg == SIGQUIT
981 # endif
982 # ifdef SIGTERM
983 || sigarg == SIGTERM
984 # endif
985 # ifdef SIGPWR
986 || sigarg == SIGPWR
987 # endif
988 # ifdef SIGUSR1
989 || sigarg == SIGUSR1
990 # endif
991 # ifdef SIGUSR2
992 || sigarg == SIGUSR2
993 # endif
995 && !vim_handle_signal(sigarg))
996 SIGRETURN;
997 #endif
999 /* Remember how often we have been called. */
1000 ++entered;
1002 #ifdef FEAT_EVAL
1003 /* Set the v:dying variable. */
1004 set_vim_var_nr(VV_DYING, (long)entered);
1005 #endif
1007 #ifdef HAVE_STACK_LIMIT
1008 /* Since we are now using the signal stack, need to reset the stack
1009 * limit. Otherwise using a regexp will fail. */
1010 get_stack_limit();
1011 #endif
1013 #if 0
1014 /* This is for opening gdb the moment Vim crashes.
1015 * You need to manually adjust the file name and Vim executable name.
1016 * Suggested by SungHyun Nam. */
1018 # define VI_GDB_FILE "/tmp/vimgdb"
1019 # define VIM_NAME "/usr/bin/vim"
1020 FILE *fp = fopen(VI_GDB_FILE, "w");
1021 if (fp)
1023 fprintf(fp,
1024 "file %s\n"
1025 "attach %d\n"
1026 "set height 1000\n"
1027 "bt full\n"
1028 , VIM_NAME, getpid());
1029 fclose(fp);
1030 system("xterm -e gdb -x "VI_GDB_FILE);
1031 unlink(VI_GDB_FILE);
1034 #endif
1036 #ifdef SIGHASARG
1037 /* try to find the name of this signal */
1038 for (i = 0; signal_info[i].sig != -1; i++)
1039 if (sigarg == signal_info[i].sig)
1040 break;
1041 deadly_signal = sigarg;
1042 #endif
1044 full_screen = FALSE; /* don't write message to the GUI, it might be
1045 * part of the problem... */
1047 * If something goes wrong after entering here, we may get here again.
1048 * When this happens, give a message and try to exit nicely (resetting the
1049 * terminal mode, etc.)
1050 * When this happens twice, just exit, don't even try to give a message,
1051 * stack may be corrupt or something weird.
1052 * When this still happens again (or memory was corrupted in such a way
1053 * that "entered" was clobbered) use _exit(), don't try freeing resources.
1055 if (entered >= 3)
1057 reset_signals(); /* don't catch any signals anymore */
1058 may_core_dump();
1059 if (entered >= 4)
1060 _exit(8);
1061 exit(7);
1063 if (entered == 2)
1065 OUT_STR(_("Vim: Double signal, exiting\n"));
1066 out_flush();
1067 getout(1);
1070 #ifdef SIGHASARG
1071 sprintf((char *)IObuff, _("Vim: Caught deadly signal %s\n"),
1072 signal_info[i].name);
1073 #else
1074 sprintf((char *)IObuff, _("Vim: Caught deadly signal\n"));
1075 #endif
1076 preserve_exit(); /* preserve files and exit */
1078 #ifdef NBDEBUG
1079 reset_signals();
1080 may_core_dump();
1081 abort();
1082 #endif
1084 SIGRETURN;
1087 #if defined(_REENTRANT) && defined(SIGCONT)
1089 * On Solaris with multi-threading, suspending might not work immediately.
1090 * Catch the SIGCONT signal, which will be used as an indication whether the
1091 * suspending has been done or not.
1093 * On Linux, signal is not always handled immediately either.
1094 * See https://bugs.launchpad.net/bugs/291373
1096 * volatile because it is used in in signal handler sigcont_handler().
1098 static volatile int sigcont_received;
1099 static RETSIGTYPE sigcont_handler __ARGS(SIGPROTOARG);
1102 * signal handler for SIGCONT
1104 static RETSIGTYPE
1105 sigcont_handler SIGDEFARG(sigarg)
1107 sigcont_received = TRUE;
1108 SIGRETURN;
1110 #endif
1113 * If the machine has job control, use it to suspend the program,
1114 * otherwise fake it by starting a new shell.
1116 void
1117 mch_suspend()
1119 /* BeOS does have SIGTSTP, but it doesn't work. */
1120 #if defined(SIGTSTP) && !defined(__BEOS__)
1121 out_flush(); /* needed to make cursor visible on some systems */
1122 settmode(TMODE_COOK);
1123 out_flush(); /* needed to disable mouse on some systems */
1125 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
1126 /* Since we are going to sleep, we can't respond to requests for the X
1127 * selections. Lose them, otherwise other applications will hang. But
1128 * first copy the text to cut buffer 0. */
1129 if (clip_star.owned || clip_plus.owned)
1131 x11_export_final_selection();
1132 if (clip_star.owned)
1133 clip_lose_selection(&clip_star);
1134 if (clip_plus.owned)
1135 clip_lose_selection(&clip_plus);
1136 if (x11_display != NULL)
1137 XFlush(x11_display);
1139 # endif
1141 # if defined(_REENTRANT) && defined(SIGCONT)
1142 sigcont_received = FALSE;
1143 # endif
1144 kill(0, SIGTSTP); /* send ourselves a STOP signal */
1145 # if defined(_REENTRANT) && defined(SIGCONT)
1147 * Wait for the SIGCONT signal to be handled. It generally happens
1148 * immediately, but somehow not all the time. Do not call pause()
1149 * because there would be race condition which would hang Vim if
1150 * signal happened in between the test of sigcont_received and the
1151 * call to pause(). If signal is not yet received, call sleep(0)
1152 * to just yield CPU. Signal should then be received. If somehow
1153 * it's still not received, sleep 1, 2, 3 ms. Don't bother waiting
1154 * further if signal is not received after 1+2+3+4 ms (not expected
1155 * to happen).
1158 long wait_time;
1159 for (wait_time = 0; !sigcont_received && wait_time <= 3L; wait_time++)
1160 /* Loop is not entered most of the time */
1161 mch_delay(wait_time, FALSE);
1163 # endif
1165 # ifdef FEAT_TITLE
1167 * Set oldtitle to NULL, so the current title is obtained again.
1169 vim_free(oldtitle);
1170 oldtitle = NULL;
1171 # endif
1172 settmode(TMODE_RAW);
1173 need_check_timestamps = TRUE;
1174 did_check_timestamps = FALSE;
1175 #else
1176 suspend_shell();
1177 #endif
1180 void
1181 mch_init()
1183 Columns = 80;
1184 Rows = 24;
1186 out_flush();
1187 set_signals();
1189 #ifdef MACOS_CONVERT
1190 mac_conv_init();
1191 #endif
1194 static void
1195 set_signals()
1197 #if defined(SIGWINCH)
1199 * WINDOW CHANGE signal is handled with sig_winch().
1201 signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
1202 #endif
1205 * We want the STOP signal to work, to make mch_suspend() work.
1206 * For "rvim" the STOP signal is ignored.
1208 #ifdef SIGTSTP
1209 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
1210 #endif
1211 #if defined(_REENTRANT) && defined(SIGCONT)
1212 signal(SIGCONT, sigcont_handler);
1213 #endif
1216 * We want to ignore breaking of PIPEs.
1218 #ifdef SIGPIPE
1219 signal(SIGPIPE, SIG_IGN);
1220 #endif
1222 #ifdef SIGINT
1223 catch_int_signal();
1224 #endif
1227 * Ignore alarm signals (Perl's alarm() generates it).
1229 #ifdef SIGALRM
1230 signal(SIGALRM, SIG_IGN);
1231 #endif
1234 * Catch SIGPWR (power failure?) to preserve the swap files, so that no
1235 * work will be lost.
1237 #ifdef SIGPWR
1238 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
1239 #endif
1242 * Arrange for other signals to gracefully shutdown Vim.
1244 catch_signals(deathtrap, SIG_ERR);
1246 #if defined(FEAT_GUI) && defined(SIGHUP)
1248 * When the GUI is running, ignore the hangup signal.
1250 if (gui.in_use)
1251 signal(SIGHUP, SIG_IGN);
1252 #endif
1255 #if defined(SIGINT) || defined(PROTO)
1257 * Catch CTRL-C (only works while in Cooked mode).
1259 static void
1260 catch_int_signal()
1262 signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
1264 #endif
1266 void
1267 reset_signals()
1269 catch_signals(SIG_DFL, SIG_DFL);
1270 #if defined(_REENTRANT) && defined(SIGCONT)
1271 /* SIGCONT isn't in the list, because its default action is ignore */
1272 signal(SIGCONT, SIG_DFL);
1273 #endif
1276 static void
1277 catch_signals(func_deadly, func_other)
1278 RETSIGTYPE (*func_deadly)();
1279 RETSIGTYPE (*func_other)();
1281 int i;
1283 for (i = 0; signal_info[i].sig != -1; i++)
1284 if (signal_info[i].deadly)
1286 #if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
1287 struct sigaction sa;
1289 /* Setup to use the alternate stack for the signal function. */
1290 sa.sa_handler = func_deadly;
1291 sigemptyset(&sa.sa_mask);
1292 # if defined(__linux__) && defined(_REENTRANT)
1293 /* On Linux, with glibc compiled for kernel 2.2, there is a bug in
1294 * thread handling in combination with using the alternate stack:
1295 * pthread library functions try to use the stack pointer to
1296 * identify the current thread, causing a SEGV signal, which
1297 * recursively calls deathtrap() and hangs. */
1298 sa.sa_flags = 0;
1299 # else
1300 sa.sa_flags = SA_ONSTACK;
1301 # endif
1302 sigaction(signal_info[i].sig, &sa, NULL);
1303 #else
1304 # if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGVEC)
1305 struct sigvec sv;
1307 /* Setup to use the alternate stack for the signal function. */
1308 sv.sv_handler = func_deadly;
1309 sv.sv_mask = 0;
1310 sv.sv_flags = SV_ONSTACK;
1311 sigvec(signal_info[i].sig, &sv, NULL);
1312 # else
1313 signal(signal_info[i].sig, func_deadly);
1314 # endif
1315 #endif
1317 else if (func_other != SIG_ERR)
1318 signal(signal_info[i].sig, func_other);
1322 * Handling of SIGHUP, SIGQUIT and SIGTERM:
1323 * "when" == a signal: when busy, postpone and return FALSE, otherwise
1324 * return TRUE
1325 * "when" == SIGNAL_BLOCK: Going to be busy, block signals
1326 * "when" == SIGNAL_UNBLOCK: Going to wait, unblock signals, use postponed
1327 * signal
1328 * Returns TRUE when Vim should exit.
1331 vim_handle_signal(sig)
1332 int sig;
1334 static int got_signal = 0;
1335 static int blocked = TRUE;
1337 switch (sig)
1339 case SIGNAL_BLOCK: blocked = TRUE;
1340 break;
1342 case SIGNAL_UNBLOCK: blocked = FALSE;
1343 if (got_signal != 0)
1345 kill(getpid(), got_signal);
1346 got_signal = 0;
1348 break;
1350 default: if (!blocked)
1351 return TRUE; /* exit! */
1352 got_signal = sig;
1353 #ifdef SIGPWR
1354 if (sig != SIGPWR)
1355 #endif
1356 got_int = TRUE; /* break any loops */
1357 break;
1359 return FALSE;
1363 * Check_win checks whether we have an interactive stdout.
1366 mch_check_win(argc, argv)
1367 int argc UNUSED;
1368 char **argv UNUSED;
1370 #ifdef OS2
1372 * Store argv[0], may be used for $VIM. Only use it if it is an absolute
1373 * name, mostly it's just "vim" and found in the path, which is unusable.
1375 if (mch_isFullName(argv[0]))
1376 exe_name = vim_strsave((char_u *)argv[0]);
1377 #endif
1378 if (isatty(1))
1379 return OK;
1380 return FAIL;
1384 * Return TRUE if the input comes from a terminal, FALSE otherwise.
1387 mch_input_isatty()
1389 if (isatty(read_cmd_fd))
1390 return TRUE;
1391 return FALSE;
1394 #ifdef FEAT_X11
1396 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) \
1397 && (defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE))
1399 static void xopen_message __ARGS((struct timeval *tvp));
1402 * Give a message about the elapsed time for opening the X window.
1404 static void
1405 xopen_message(tvp)
1406 struct timeval *tvp; /* must contain start time */
1408 struct timeval end_tv;
1410 /* Compute elapsed time. */
1411 gettimeofday(&end_tv, NULL);
1412 smsg((char_u *)_("Opening the X display took %ld msec"),
1413 (end_tv.tv_sec - tvp->tv_sec) * 1000L
1414 + (end_tv.tv_usec - tvp->tv_usec) / 1000L);
1416 # endif
1417 #endif
1419 #if defined(FEAT_X11) && (defined(FEAT_TITLE) || defined(FEAT_XCLIPBOARD))
1421 * A few functions shared by X11 title and clipboard code.
1423 static int x_error_handler __ARGS((Display *dpy, XErrorEvent *error_event));
1424 static int x_error_check __ARGS((Display *dpy, XErrorEvent *error_event));
1425 static int x_connect_to_server __ARGS((void));
1426 static int test_x11_window __ARGS((Display *dpy));
1428 static int got_x_error = FALSE;
1431 * X Error handler, otherwise X just exits! (very rude) -- webb
1433 static int
1434 x_error_handler(dpy, error_event)
1435 Display *dpy;
1436 XErrorEvent *error_event;
1438 XGetErrorText(dpy, error_event->error_code, (char *)IObuff, IOSIZE);
1439 STRCAT(IObuff, _("\nVim: Got X error\n"));
1441 /* We cannot print a message and continue, because no X calls are allowed
1442 * here (causes my system to hang). Silently continuing might be an
1443 * alternative... */
1444 preserve_exit(); /* preserve files and exit */
1446 return 0; /* NOTREACHED */
1450 * Another X Error handler, just used to check for errors.
1452 static int
1453 x_error_check(dpy, error_event)
1454 Display *dpy UNUSED;
1455 XErrorEvent *error_event UNUSED;
1457 got_x_error = TRUE;
1458 return 0;
1461 #if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
1462 # if defined(HAVE_SETJMP_H)
1464 * An X IO Error handler, used to catch error while opening the display.
1466 static int x_IOerror_check __ARGS((Display *dpy));
1468 static int
1469 x_IOerror_check(dpy)
1470 Display *dpy UNUSED;
1472 /* This function should not return, it causes exit(). Longjump instead. */
1473 LONGJMP(lc_jump_env, 1);
1474 # ifdef VMS
1475 return 0; /* avoid the compiler complains about missing return value */
1476 # endif
1478 # endif
1481 * An X IO Error handler, used to catch terminal errors.
1483 static int x_IOerror_handler __ARGS((Display *dpy));
1485 static int
1486 x_IOerror_handler(dpy)
1487 Display *dpy UNUSED;
1489 xterm_dpy = NULL;
1490 x11_window = 0;
1491 x11_display = NULL;
1492 xterm_Shell = (Widget)0;
1494 /* This function should not return, it causes exit(). Longjump instead. */
1495 LONGJMP(x_jump_env, 1);
1496 # ifdef VMS
1497 return 0; /* avoid the compiler complains about missing return value */
1498 # endif
1500 #endif
1503 * Return TRUE when connection to the X server is desired.
1505 static int
1506 x_connect_to_server()
1508 regmatch_T regmatch;
1510 #if defined(FEAT_CLIENTSERVER)
1511 if (x_force_connect)
1512 return TRUE;
1513 #endif
1514 if (x_no_connect)
1515 return FALSE;
1517 /* Check for a match with "exclude:" from 'clipboard'. */
1518 if (clip_exclude_prog != NULL)
1520 regmatch.rm_ic = FALSE; /* Don't ignore case */
1521 regmatch.regprog = clip_exclude_prog;
1522 if (vim_regexec(&regmatch, T_NAME, (colnr_T)0))
1523 return FALSE;
1525 return TRUE;
1529 * Test if "dpy" and x11_window are valid by getting the window title.
1530 * I don't actually want it yet, so there may be a simpler call to use, but
1531 * this will cause the error handler x_error_check() to be called if anything
1532 * is wrong, such as the window pointer being invalid (as can happen when the
1533 * user changes his DISPLAY, but not his WINDOWID) -- webb
1535 static int
1536 test_x11_window(dpy)
1537 Display *dpy;
1539 int (*old_handler)();
1540 XTextProperty text_prop;
1542 old_handler = XSetErrorHandler(x_error_check);
1543 got_x_error = FALSE;
1544 if (XGetWMName(dpy, x11_window, &text_prop))
1545 XFree((void *)text_prop.value);
1546 XSync(dpy, False);
1547 (void)XSetErrorHandler(old_handler);
1549 if (p_verbose > 0 && got_x_error)
1550 verb_msg((char_u *)_("Testing the X display failed"));
1552 return (got_x_error ? FAIL : OK);
1554 #endif
1556 #ifdef FEAT_TITLE
1558 #ifdef FEAT_X11
1560 static int get_x11_thing __ARGS((int get_title, int test_only));
1563 * try to get x11 window and display
1565 * return FAIL for failure, OK otherwise
1567 static int
1568 get_x11_windis()
1570 char *winid;
1571 static int result = -1;
1572 #define XD_NONE 0 /* x11_display not set here */
1573 #define XD_HERE 1 /* x11_display opened here */
1574 #define XD_GUI 2 /* x11_display used from gui.dpy */
1575 #define XD_XTERM 3 /* x11_display used from xterm_dpy */
1576 static int x11_display_from = XD_NONE;
1577 static int did_set_error_handler = FALSE;
1579 if (!did_set_error_handler)
1581 /* X just exits if it finds an error otherwise! */
1582 (void)XSetErrorHandler(x_error_handler);
1583 did_set_error_handler = TRUE;
1586 #if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
1587 if (gui.in_use)
1590 * If the X11 display was opened here before, for the window where Vim
1591 * was started, close that one now to avoid a memory leak.
1593 if (x11_display_from == XD_HERE && x11_display != NULL)
1595 XCloseDisplay(x11_display);
1596 x11_display_from = XD_NONE;
1598 if (gui_get_x11_windis(&x11_window, &x11_display) == OK)
1600 x11_display_from = XD_GUI;
1601 return OK;
1603 x11_display = NULL;
1604 return FAIL;
1606 else if (x11_display_from == XD_GUI)
1608 /* GUI must have stopped somehow, clear x11_display */
1609 x11_window = 0;
1610 x11_display = NULL;
1611 x11_display_from = XD_NONE;
1613 #endif
1615 /* When started with the "-X" argument, don't try connecting. */
1616 if (!x_connect_to_server())
1617 return FAIL;
1620 * If WINDOWID not set, should try another method to find out
1621 * what the current window number is. The only code I know for
1622 * this is very complicated.
1623 * We assume that zero is invalid for WINDOWID.
1625 if (x11_window == 0 && (winid = getenv("WINDOWID")) != NULL)
1626 x11_window = (Window)atol(winid);
1628 #ifdef FEAT_XCLIPBOARD
1629 if (xterm_dpy != NULL && x11_window != 0)
1631 /* We may have checked it already, but Gnome terminal can move us to
1632 * another window, so we need to check every time. */
1633 if (x11_display_from != XD_XTERM)
1636 * If the X11 display was opened here before, for the window where
1637 * Vim was started, close that one now to avoid a memory leak.
1639 if (x11_display_from == XD_HERE && x11_display != NULL)
1640 XCloseDisplay(x11_display);
1641 x11_display = xterm_dpy;
1642 x11_display_from = XD_XTERM;
1644 if (test_x11_window(x11_display) == FAIL)
1646 /* probably bad $WINDOWID */
1647 x11_window = 0;
1648 x11_display = NULL;
1649 x11_display_from = XD_NONE;
1650 return FAIL;
1652 return OK;
1654 #endif
1656 if (x11_window == 0 || x11_display == NULL)
1657 result = -1;
1659 if (result != -1) /* Have already been here and set this */
1660 return result; /* Don't do all these X calls again */
1662 if (x11_window != 0 && x11_display == NULL)
1664 #ifdef SET_SIG_ALARM
1665 RETSIGTYPE (*sig_save)();
1666 #endif
1667 #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1668 struct timeval start_tv;
1670 if (p_verbose > 0)
1671 gettimeofday(&start_tv, NULL);
1672 #endif
1674 #ifdef SET_SIG_ALARM
1676 * Opening the Display may hang if the DISPLAY setting is wrong, or
1677 * the network connection is bad. Set an alarm timer to get out.
1679 sig_alarm_called = FALSE;
1680 sig_save = (RETSIGTYPE (*)())signal(SIGALRM,
1681 (RETSIGTYPE (*)())sig_alarm);
1682 alarm(2);
1683 #endif
1684 x11_display = XOpenDisplay(NULL);
1686 #ifdef SET_SIG_ALARM
1687 alarm(0);
1688 signal(SIGALRM, (RETSIGTYPE (*)())sig_save);
1689 if (p_verbose > 0 && sig_alarm_called)
1690 verb_msg((char_u *)_("Opening the X display timed out"));
1691 #endif
1692 if (x11_display != NULL)
1694 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1695 if (p_verbose > 0)
1697 verbose_enter();
1698 xopen_message(&start_tv);
1699 verbose_leave();
1701 # endif
1702 if (test_x11_window(x11_display) == FAIL)
1704 /* Maybe window id is bad */
1705 x11_window = 0;
1706 XCloseDisplay(x11_display);
1707 x11_display = NULL;
1709 else
1710 x11_display_from = XD_HERE;
1713 if (x11_window == 0 || x11_display == NULL)
1714 return (result = FAIL);
1715 return (result = OK);
1719 * Determine original x11 Window Title
1721 static int
1722 get_x11_title(test_only)
1723 int test_only;
1725 return get_x11_thing(TRUE, test_only);
1729 * Determine original x11 Window icon
1731 static int
1732 get_x11_icon(test_only)
1733 int test_only;
1735 int retval = FALSE;
1737 retval = get_x11_thing(FALSE, test_only);
1739 /* could not get old icon, use terminal name */
1740 if (oldicon == NULL && !test_only)
1742 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1743 oldicon = vim_strsave(T_NAME + 8);
1744 else
1745 oldicon = vim_strsave(T_NAME);
1748 return retval;
1751 static int
1752 get_x11_thing(get_title, test_only)
1753 int get_title; /* get title string */
1754 int test_only;
1756 XTextProperty text_prop;
1757 int retval = FALSE;
1758 Status status;
1760 if (get_x11_windis() == OK)
1762 /* Get window/icon name if any */
1763 if (get_title)
1764 status = XGetWMName(x11_display, x11_window, &text_prop);
1765 else
1766 status = XGetWMIconName(x11_display, x11_window, &text_prop);
1769 * If terminal is xterm, then x11_window may be a child window of the
1770 * outer xterm window that actually contains the window/icon name, so
1771 * keep traversing up the tree until a window with a title/icon is
1772 * found.
1774 /* Previously this was only done for xterm and alikes. I don't see a
1775 * reason why it would fail for other terminal emulators.
1776 * if (term_is_xterm) */
1778 Window root;
1779 Window parent;
1780 Window win = x11_window;
1781 Window *children;
1782 unsigned int num_children;
1784 while (!status || text_prop.value == NULL)
1786 if (!XQueryTree(x11_display, win, &root, &parent, &children,
1787 &num_children))
1788 break;
1789 if (children)
1790 XFree((void *)children);
1791 if (parent == root || parent == 0)
1792 break;
1794 win = parent;
1795 if (get_title)
1796 status = XGetWMName(x11_display, win, &text_prop);
1797 else
1798 status = XGetWMIconName(x11_display, win, &text_prop);
1801 if (status && text_prop.value != NULL)
1803 retval = TRUE;
1804 if (!test_only)
1806 #ifdef FEAT_XFONTSET
1807 if (text_prop.encoding == XA_STRING)
1809 #endif
1810 if (get_title)
1811 oldtitle = vim_strsave((char_u *)text_prop.value);
1812 else
1813 oldicon = vim_strsave((char_u *)text_prop.value);
1814 #ifdef FEAT_XFONTSET
1816 else
1818 char **cl;
1819 Status transform_status;
1820 int n = 0;
1822 transform_status = XmbTextPropertyToTextList(x11_display,
1823 &text_prop,
1824 &cl, &n);
1825 if (transform_status >= Success && n > 0 && cl[0])
1827 if (get_title)
1828 oldtitle = vim_strsave((char_u *) cl[0]);
1829 else
1830 oldicon = vim_strsave((char_u *) cl[0]);
1831 XFreeStringList(cl);
1833 else
1835 if (get_title)
1836 oldtitle = vim_strsave((char_u *)text_prop.value);
1837 else
1838 oldicon = vim_strsave((char_u *)text_prop.value);
1841 #endif
1843 XFree((void *)text_prop.value);
1846 return retval;
1849 /* Are Xutf8 functions available? Avoid error from old compilers. */
1850 #if defined(X_HAVE_UTF8_STRING) && defined(FEAT_MBYTE)
1851 # if X_HAVE_UTF8_STRING
1852 # define USE_UTF8_STRING
1853 # endif
1854 #endif
1857 * Set x11 Window Title
1859 * get_x11_windis() must be called before this and have returned OK
1861 static void
1862 set_x11_title(title)
1863 char_u *title;
1865 /* XmbSetWMProperties() and Xutf8SetWMProperties() should use a STRING
1866 * when possible, COMPOUND_TEXT otherwise. COMPOUND_TEXT isn't
1867 * supported everywhere and STRING doesn't work for multi-byte titles.
1869 #ifdef USE_UTF8_STRING
1870 if (enc_utf8)
1871 Xutf8SetWMProperties(x11_display, x11_window, (const char *)title,
1872 NULL, NULL, 0, NULL, NULL, NULL);
1873 else
1874 #endif
1876 #if XtSpecificationRelease >= 4
1877 # ifdef FEAT_XFONTSET
1878 XmbSetWMProperties(x11_display, x11_window, (const char *)title,
1879 NULL, NULL, 0, NULL, NULL, NULL);
1880 # else
1881 XTextProperty text_prop;
1882 char *c_title = (char *)title;
1884 /* directly from example 3-18 "basicwin" of Xlib Programming Manual */
1885 (void)XStringListToTextProperty(&c_title, 1, &text_prop);
1886 XSetWMProperties(x11_display, x11_window, &text_prop,
1887 NULL, NULL, 0, NULL, NULL, NULL);
1888 # endif
1889 #else
1890 XStoreName(x11_display, x11_window, (char *)title);
1891 #endif
1893 XFlush(x11_display);
1897 * Set x11 Window icon
1899 * get_x11_windis() must be called before this and have returned OK
1901 static void
1902 set_x11_icon(icon)
1903 char_u *icon;
1905 /* See above for comments about using X*SetWMProperties(). */
1906 #ifdef USE_UTF8_STRING
1907 if (enc_utf8)
1908 Xutf8SetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
1909 NULL, 0, NULL, NULL, NULL);
1910 else
1911 #endif
1913 #if XtSpecificationRelease >= 4
1914 # ifdef FEAT_XFONTSET
1915 XmbSetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
1916 NULL, 0, NULL, NULL, NULL);
1917 # else
1918 XTextProperty text_prop;
1919 char *c_icon = (char *)icon;
1921 (void)XStringListToTextProperty(&c_icon, 1, &text_prop);
1922 XSetWMProperties(x11_display, x11_window, NULL, &text_prop,
1923 NULL, 0, NULL, NULL, NULL);
1924 # endif
1925 #else
1926 XSetIconName(x11_display, x11_window, (char *)icon);
1927 #endif
1929 XFlush(x11_display);
1932 #else /* FEAT_X11 */
1934 static int
1935 get_x11_title(test_only)
1936 int test_only UNUSED;
1938 return FALSE;
1941 static int
1942 get_x11_icon(test_only)
1943 int test_only;
1945 if (!test_only)
1947 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1948 oldicon = vim_strsave(T_NAME + 8);
1949 else
1950 oldicon = vim_strsave(T_NAME);
1952 return FALSE;
1955 #endif /* FEAT_X11 */
1958 mch_can_restore_title()
1960 return get_x11_title(TRUE);
1964 mch_can_restore_icon()
1966 return get_x11_icon(TRUE);
1970 * Set the window title and icon.
1972 void
1973 mch_settitle(title, icon)
1974 char_u *title;
1975 char_u *icon;
1977 int type = 0;
1978 static int recursive = 0;
1980 if (T_NAME == NULL) /* no terminal name (yet) */
1981 return;
1982 if (title == NULL && icon == NULL) /* nothing to do */
1983 return;
1985 /* When one of the X11 functions causes a deadly signal, we get here again
1986 * recursively. Avoid hanging then (something is probably locked). */
1987 if (recursive)
1988 return;
1989 ++recursive;
1992 * if the window ID and the display is known, we may use X11 calls
1994 #ifdef FEAT_X11
1995 if (get_x11_windis() == OK)
1996 type = 1;
1997 #else
1998 # if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) \
1999 || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MACVIM)
2000 if (gui.in_use)
2001 type = 1;
2002 # endif
2003 #endif
2006 * Note: if "t_TS" is set, title is set with escape sequence rather
2007 * than x11 calls, because the x11 calls don't always work
2009 if ((type || *T_TS != NUL) && title != NULL)
2011 if (oldtitle == NULL
2012 #ifdef FEAT_GUI
2013 && !gui.in_use
2014 #endif
2015 ) /* first call but not in GUI, save title */
2016 (void)get_x11_title(FALSE);
2018 if (*T_TS != NUL) /* it's OK if t_fs is empty */
2019 term_settitle(title);
2020 #ifdef FEAT_X11
2021 else
2022 # ifdef FEAT_GUI_GTK
2023 if (!gui.in_use) /* don't do this if GTK+ is running */
2024 # endif
2025 set_x11_title(title); /* x11 */
2026 #endif
2027 #if defined(FEAT_GUI_GTK) \
2028 || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) \
2029 || defined(FEAT_GUI_MACVIM)
2030 else
2031 gui_mch_settitle(title, icon);
2032 #endif
2033 did_set_title = TRUE;
2036 if ((type || *T_CIS != NUL) && icon != NULL)
2038 if (oldicon == NULL
2039 #ifdef FEAT_GUI
2040 && !gui.in_use
2041 #endif
2042 ) /* first call, save icon */
2043 get_x11_icon(FALSE);
2045 if (*T_CIS != NUL)
2047 out_str(T_CIS); /* set icon start */
2048 out_str_nf(icon);
2049 out_str(T_CIE); /* set icon end */
2050 out_flush();
2052 #ifdef FEAT_X11
2053 else
2054 # ifdef FEAT_GUI_GTK
2055 if (!gui.in_use) /* don't do this if GTK+ is running */
2056 # endif
2057 set_x11_icon(icon); /* x11 */
2058 #endif
2059 did_set_icon = TRUE;
2061 --recursive;
2065 * Restore the window/icon title.
2066 * "which" is one of:
2067 * 1 only restore title
2068 * 2 only restore icon
2069 * 3 restore title and icon
2071 void
2072 mch_restore_title(which)
2073 int which;
2075 /* only restore the title or icon when it has been set */
2076 mch_settitle(((which & 1) && did_set_title) ?
2077 (oldtitle ? oldtitle : p_titleold) : NULL,
2078 ((which & 2) && did_set_icon) ? oldicon : NULL);
2081 #endif /* FEAT_TITLE */
2084 * Return TRUE if "name" looks like some xterm name.
2085 * Seiichi Sato mentioned that "mlterm" works like xterm.
2088 vim_is_xterm(name)
2089 char_u *name;
2091 if (name == NULL)
2092 return FALSE;
2093 return (STRNICMP(name, "xterm", 5) == 0
2094 || STRNICMP(name, "nxterm", 6) == 0
2095 || STRNICMP(name, "kterm", 5) == 0
2096 || STRNICMP(name, "mlterm", 6) == 0
2097 || STRNICMP(name, "rxvt", 4) == 0
2098 || STRCMP(name, "builtin_xterm") == 0);
2101 #if defined(FEAT_MOUSE_XTERM) || defined(PROTO)
2103 * Return TRUE if "name" appears to be that of a terminal
2104 * known to support the xterm-style mouse protocol.
2105 * Relies on term_is_xterm having been set to its correct value.
2108 use_xterm_like_mouse(name)
2109 char_u *name;
2111 return (name != NULL
2112 && (term_is_xterm || STRNICMP(name, "screen", 6) == 0));
2114 #endif
2116 #if defined(FEAT_MOUSE_TTY) || defined(PROTO)
2118 * Return non-zero when using an xterm mouse, according to 'ttymouse'.
2119 * Return 1 for "xterm".
2120 * Return 2 for "xterm2".
2123 use_xterm_mouse()
2125 if (ttym_flags == TTYM_XTERM2)
2126 return 2;
2127 if (ttym_flags == TTYM_XTERM)
2128 return 1;
2129 return 0;
2131 #endif
2134 vim_is_iris(name)
2135 char_u *name;
2137 if (name == NULL)
2138 return FALSE;
2139 return (STRNICMP(name, "iris-ansi", 9) == 0
2140 || STRCMP(name, "builtin_iris-ansi") == 0);
2144 vim_is_vt300(name)
2145 char_u *name;
2147 if (name == NULL)
2148 return FALSE; /* actually all ANSI comp. terminals should be here */
2149 /* catch VT100 - VT5xx */
2150 return ((STRNICMP(name, "vt", 2) == 0
2151 && vim_strchr((char_u *)"12345", name[2]) != NULL)
2152 || STRCMP(name, "builtin_vt320") == 0);
2156 * Return TRUE if "name" is a terminal for which 'ttyfast' should be set.
2157 * This should include all windowed terminal emulators.
2160 vim_is_fastterm(name)
2161 char_u *name;
2163 if (name == NULL)
2164 return FALSE;
2165 if (vim_is_xterm(name) || vim_is_vt300(name) || vim_is_iris(name))
2166 return TRUE;
2167 return ( STRNICMP(name, "hpterm", 6) == 0
2168 || STRNICMP(name, "sun-cmd", 7) == 0
2169 || STRNICMP(name, "screen", 6) == 0
2170 || STRNICMP(name, "dtterm", 6) == 0);
2174 * Insert user name in s[len].
2175 * Return OK if a name found.
2178 mch_get_user_name(s, len)
2179 char_u *s;
2180 int len;
2182 #ifdef VMS
2183 vim_strncpy(s, (char_u *)cuserid(NULL), len - 1);
2184 return OK;
2185 #else
2186 return mch_get_uname(getuid(), s, len);
2187 #endif
2191 * Insert user name for "uid" in s[len].
2192 * Return OK if a name found.
2195 mch_get_uname(uid, s, len)
2196 uid_t uid;
2197 char_u *s;
2198 int len;
2200 #if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
2201 struct passwd *pw;
2203 if ((pw = getpwuid(uid)) != NULL
2204 && pw->pw_name != NULL && *(pw->pw_name) != NUL)
2206 vim_strncpy(s, (char_u *)pw->pw_name, len - 1);
2207 return OK;
2209 #endif
2210 sprintf((char *)s, "%d", (int)uid); /* assumes s is long enough */
2211 return FAIL; /* a number is not a name */
2215 * Insert host name is s[len].
2218 #ifdef HAVE_SYS_UTSNAME_H
2219 void
2220 mch_get_host_name(s, len)
2221 char_u *s;
2222 int len;
2224 struct utsname vutsname;
2226 if (uname(&vutsname) < 0)
2227 *s = NUL;
2228 else
2229 vim_strncpy(s, (char_u *)vutsname.nodename, len - 1);
2231 #else /* HAVE_SYS_UTSNAME_H */
2233 # ifdef HAVE_SYS_SYSTEMINFO_H
2234 # define gethostname(nam, len) sysinfo(SI_HOSTNAME, nam, len)
2235 # endif
2237 void
2238 mch_get_host_name(s, len)
2239 char_u *s;
2240 int len;
2242 # ifdef VAXC
2243 vaxc$gethostname((char *)s, len);
2244 # else
2245 gethostname((char *)s, len);
2246 # endif
2247 s[len - 1] = NUL; /* make sure it's terminated */
2249 #endif /* HAVE_SYS_UTSNAME_H */
2252 * return process ID
2254 long
2255 mch_get_pid()
2257 return (long)getpid();
2260 #if !defined(HAVE_STRERROR) && defined(USE_GETCWD)
2261 static char *strerror __ARGS((int));
2263 static char *
2264 strerror(err)
2265 int err;
2267 extern int sys_nerr;
2268 extern char *sys_errlist[];
2269 static char er[20];
2271 if (err > 0 && err < sys_nerr)
2272 return (sys_errlist[err]);
2273 sprintf(er, "Error %d", err);
2274 return er;
2276 #endif
2279 * Get name of current directory into buffer 'buf' of length 'len' bytes.
2280 * Return OK for success, FAIL for failure.
2283 mch_dirname(buf, len)
2284 char_u *buf;
2285 int len;
2287 #if defined(USE_GETCWD)
2288 if (getcwd((char *)buf, len) == NULL)
2290 STRCPY(buf, strerror(errno));
2291 return FAIL;
2293 return OK;
2294 #else
2295 return (getwd((char *)buf) != NULL ? OK : FAIL);
2296 #endif
2299 #if defined(OS2) || defined(PROTO)
2301 * Replace all slashes by backslashes.
2302 * When 'shellslash' set do it the other way around.
2304 void
2305 slash_adjust(p)
2306 char_u *p;
2308 while (*p)
2310 if (*p == psepcN)
2311 *p = psepc;
2312 mb_ptr_adv(p);
2315 #endif
2318 * Get absolute file name into "buf[len]".
2320 * return FAIL for failure, OK for success
2323 mch_FullName(fname, buf, len, force)
2324 char_u *fname, *buf;
2325 int len;
2326 int force; /* also expand when already absolute path */
2328 int l;
2329 #ifdef OS2
2330 int only_drive; /* file name is only a drive letter */
2331 #endif
2332 #ifdef HAVE_FCHDIR
2333 int fd = -1;
2334 static int dont_fchdir = FALSE; /* TRUE when fchdir() doesn't work */
2335 #endif
2336 char_u olddir[MAXPATHL];
2337 char_u *p;
2338 int retval = OK;
2339 #ifdef __CYGWIN__
2340 char_u posix_fname[MAXPATHL]; /* Cygwin docs mention MAX_PATH, but
2341 it's not always defined */
2342 #endif
2344 #ifdef VMS
2345 fname = vms_fixfilename(fname);
2346 #endif
2348 #ifdef __CYGWIN__
2350 * This helps for when "/etc/hosts" is a symlink to "c:/something/hosts".
2352 # if CYGWIN_VERSION_DLL_MAJOR >= 1007
2353 cygwin_conv_path(CCP_WIN_A_TO_POSIX, fname, posix_fname, MAXPATHL);
2354 # else
2355 cygwin_conv_to_posix_path(fname, posix_fname);
2356 # endif
2357 fname = posix_fname;
2358 #endif
2360 /* expand it if forced or not an absolute path */
2361 if (force || !mch_isFullName(fname))
2364 * If the file name has a path, change to that directory for a moment,
2365 * and then do the getwd() (and get back to where we were).
2366 * This will get the correct path name with "../" things.
2368 #ifdef OS2
2369 only_drive = 0;
2370 if (((p = vim_strrchr(fname, '/')) != NULL)
2371 || ((p = vim_strrchr(fname, '\\')) != NULL)
2372 || (((p = vim_strchr(fname, ':')) != NULL) && ++only_drive))
2373 #else
2374 if ((p = vim_strrchr(fname, '/')) != NULL)
2375 #endif
2377 #ifdef HAVE_FCHDIR
2379 * Use fchdir() if possible, it's said to be faster and more
2380 * reliable. But on SunOS 4 it might not work. Check this by
2381 * doing a fchdir() right now.
2383 if (!dont_fchdir)
2385 fd = open(".", O_RDONLY | O_EXTRA, 0);
2386 if (fd >= 0 && fchdir(fd) < 0)
2388 close(fd);
2389 fd = -1;
2390 dont_fchdir = TRUE; /* don't try again */
2393 #endif
2395 /* Only change directory when we are sure we can return to where
2396 * we are now. After doing "su" chdir(".") might not work. */
2397 if (
2398 #ifdef HAVE_FCHDIR
2399 fd < 0 &&
2400 #endif
2401 (mch_dirname(olddir, MAXPATHL) == FAIL
2402 || mch_chdir((char *)olddir) != 0))
2404 p = NULL; /* can't get current dir: don't chdir */
2405 retval = FAIL;
2407 else
2409 #ifdef OS2
2411 * compensate for case where ':' from "D:" was the only
2412 * path separator detected in the file name; the _next_
2413 * character has to be removed, and then restored later.
2415 if (only_drive)
2416 p++;
2417 #endif
2418 /* The directory is copied into buf[], to be able to remove
2419 * the file name without changing it (could be a string in
2420 * read-only memory) */
2421 if (p - fname >= len)
2422 retval = FAIL;
2423 else
2425 vim_strncpy(buf, fname, p - fname);
2426 if (mch_chdir((char *)buf))
2427 retval = FAIL;
2428 else
2429 fname = p + 1;
2430 *buf = NUL;
2432 #ifdef OS2
2433 if (only_drive)
2435 p--;
2436 if (retval != FAIL)
2437 fname--;
2439 #endif
2442 if (mch_dirname(buf, len) == FAIL)
2444 retval = FAIL;
2445 *buf = NUL;
2447 if (p != NULL)
2449 #ifdef HAVE_FCHDIR
2450 if (fd >= 0)
2452 if (p_verbose >= 5)
2454 verbose_enter();
2455 MSG("fchdir() to previous dir");
2456 verbose_leave();
2458 l = fchdir(fd);
2459 close(fd);
2461 else
2462 #endif
2463 l = mch_chdir((char *)olddir);
2464 if (l != 0)
2465 EMSG(_(e_prev_dir));
2468 l = STRLEN(buf);
2469 if (l >= len)
2470 retval = FAIL;
2471 #ifndef VMS
2472 else
2474 if (l > 0 && buf[l - 1] != '/' && *fname != NUL
2475 && STRCMP(fname, ".") != 0)
2476 STRCAT(buf, "/");
2478 #endif
2481 /* Catch file names which are too long. */
2482 if (retval == FAIL || (int)(STRLEN(buf) + STRLEN(fname)) >= len)
2483 return FAIL;
2485 /* Do not append ".", "/dir/." is equal to "/dir". */
2486 if (STRCMP(fname, ".") != 0)
2487 STRCAT(buf, fname);
2489 return OK;
2493 * Return TRUE if "fname" does not depend on the current directory.
2496 mch_isFullName(fname)
2497 char_u *fname;
2499 #ifdef __EMX__
2500 return _fnisabs(fname);
2501 #else
2502 # ifdef VMS
2503 return ( fname[0] == '/' || fname[0] == '.' ||
2504 strchr((char *)fname,':') || strchr((char *)fname,'"') ||
2505 (strchr((char *)fname,'[') && strchr((char *)fname,']'))||
2506 (strchr((char *)fname,'<') && strchr((char *)fname,'>')) );
2507 # else
2508 return (*fname == '/' || *fname == '~');
2509 # endif
2510 #endif
2513 #if defined(USE_FNAME_CASE) || defined(PROTO)
2515 * Set the case of the file name, if it already exists. This will cause the
2516 * file name to remain exactly the same.
2517 * Only required for file systems where case is ignored and preserved.
2519 void
2520 fname_case(name, len)
2521 char_u *name;
2522 int len UNUSED; /* buffer size, only used when name gets longer */
2524 struct stat st;
2525 char_u *slash, *tail;
2526 DIR *dirp;
2527 struct dirent *dp;
2529 if (lstat((char *)name, &st) >= 0)
2531 /* Open the directory where the file is located. */
2532 slash = vim_strrchr(name, '/');
2533 if (slash == NULL)
2535 dirp = opendir(".");
2536 tail = name;
2538 else
2540 *slash = NUL;
2541 dirp = opendir((char *)name);
2542 *slash = '/';
2543 tail = slash + 1;
2546 if (dirp != NULL)
2548 while ((dp = readdir(dirp)) != NULL)
2550 /* Only accept names that differ in case and are the same byte
2551 * length. TODO: accept different length name. */
2552 if (STRICMP(tail, dp->d_name) == 0
2553 && STRLEN(tail) == STRLEN(dp->d_name))
2555 char_u newname[MAXPATHL + 1];
2556 struct stat st2;
2558 /* Verify the inode is equal. */
2559 vim_strncpy(newname, name, MAXPATHL);
2560 vim_strncpy(newname + (tail - name), (char_u *)dp->d_name,
2561 MAXPATHL - (tail - name));
2562 if (lstat((char *)newname, &st2) >= 0
2563 && st.st_ino == st2.st_ino
2564 && st.st_dev == st2.st_dev)
2566 STRCPY(tail, dp->d_name);
2567 break;
2572 closedir(dirp);
2576 #endif
2579 * Get file permissions for 'name'.
2580 * Returns -1 when it doesn't exist.
2582 long
2583 mch_getperm(name)
2584 char_u *name;
2586 struct stat statb;
2588 /* Keep the #ifdef outside of stat(), it may be a macro. */
2589 #ifdef VMS
2590 if (stat((char *)vms_fixfilename(name), &statb))
2591 #else
2592 if (stat((char *)name, &statb))
2593 #endif
2594 return -1;
2595 #ifdef __INTERIX
2596 /* The top bit makes the value negative, which means the file doesn't
2597 * exist. Remove the bit, we don't use it. */
2598 return statb.st_mode & ~S_ADDACE;
2599 #else
2600 return statb.st_mode;
2601 #endif
2605 * set file permission for 'name' to 'perm'
2607 * return FAIL for failure, OK otherwise
2610 mch_setperm(name, perm)
2611 char_u *name;
2612 long perm;
2614 return (chmod((char *)
2615 #ifdef VMS
2616 vms_fixfilename(name),
2617 #else
2618 name,
2619 #endif
2620 (mode_t)perm) == 0 ? OK : FAIL);
2623 #if defined(HAVE_ACL) || defined(PROTO)
2624 # ifdef HAVE_SYS_ACL_H
2625 # include <sys/acl.h>
2626 # endif
2627 # ifdef HAVE_SYS_ACCESS_H
2628 # include <sys/access.h>
2629 # endif
2631 # ifdef HAVE_SOLARIS_ACL
2632 typedef struct vim_acl_solaris_T {
2633 int acl_cnt;
2634 aclent_t *acl_entry;
2635 } vim_acl_solaris_T;
2636 # endif
2638 #if defined(HAVE_SELINUX) || defined(PROTO)
2640 * Copy security info from "from_file" to "to_file".
2642 void
2643 mch_copy_sec(from_file, to_file)
2644 char_u *from_file;
2645 char_u *to_file;
2647 if (from_file == NULL)
2648 return;
2650 if (selinux_enabled == -1)
2651 selinux_enabled = is_selinux_enabled();
2653 if (selinux_enabled > 0)
2655 security_context_t from_context = NULL;
2656 security_context_t to_context = NULL;
2658 if (getfilecon((char *)from_file, &from_context) < 0)
2660 /* If the filesystem doesn't support extended attributes,
2661 the original had no special security context and the
2662 target cannot have one either. */
2663 if (errno == EOPNOTSUPP)
2664 return;
2666 MSG_PUTS(_("\nCould not get security context for "));
2667 msg_outtrans(from_file);
2668 msg_putchar('\n');
2669 return;
2671 if (getfilecon((char *)to_file, &to_context) < 0)
2673 MSG_PUTS(_("\nCould not get security context for "));
2674 msg_outtrans(to_file);
2675 msg_putchar('\n');
2676 freecon (from_context);
2677 return ;
2679 if (strcmp(from_context, to_context) != 0)
2681 if (setfilecon((char *)to_file, from_context) < 0)
2683 MSG_PUTS(_("\nCould not set security context for "));
2684 msg_outtrans(to_file);
2685 msg_putchar('\n');
2688 freecon(to_context);
2689 freecon(from_context);
2692 #endif /* HAVE_SELINUX */
2695 * Return a pointer to the ACL of file "fname" in allocated memory.
2696 * Return NULL if the ACL is not available for whatever reason.
2698 vim_acl_T
2699 mch_get_acl(fname)
2700 char_u *fname UNUSED;
2702 vim_acl_T ret = NULL;
2703 #ifdef HAVE_POSIX_ACL
2704 ret = (vim_acl_T)acl_get_file((char *)fname, ACL_TYPE_ACCESS);
2705 #else
2706 #ifdef HAVE_SOLARIS_ACL
2707 vim_acl_solaris_T *aclent;
2709 aclent = malloc(sizeof(vim_acl_solaris_T));
2710 if ((aclent->acl_cnt = acl((char *)fname, GETACLCNT, 0, NULL)) < 0)
2712 free(aclent);
2713 return NULL;
2715 aclent->acl_entry = malloc(aclent->acl_cnt * sizeof(aclent_t));
2716 if (acl((char *)fname, GETACL, aclent->acl_cnt, aclent->acl_entry) < 0)
2718 free(aclent->acl_entry);
2719 free(aclent);
2720 return NULL;
2722 ret = (vim_acl_T)aclent;
2723 #else
2724 #if defined(HAVE_AIX_ACL)
2725 int aclsize;
2726 struct acl *aclent;
2728 aclsize = sizeof(struct acl);
2729 aclent = malloc(aclsize);
2730 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2732 if (errno == ENOSPC)
2734 aclsize = aclent->acl_len;
2735 aclent = realloc(aclent, aclsize);
2736 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2738 free(aclent);
2739 return NULL;
2742 else
2744 free(aclent);
2745 return NULL;
2748 ret = (vim_acl_T)aclent;
2749 #endif /* HAVE_AIX_ACL */
2750 #endif /* HAVE_SOLARIS_ACL */
2751 #endif /* HAVE_POSIX_ACL */
2752 return ret;
2756 * Set the ACL of file "fname" to "acl" (unless it's NULL).
2758 void
2759 mch_set_acl(fname, aclent)
2760 char_u *fname UNUSED;
2761 vim_acl_T aclent;
2763 if (aclent == NULL)
2764 return;
2765 #ifdef HAVE_POSIX_ACL
2766 acl_set_file((char *)fname, ACL_TYPE_ACCESS, (acl_t)aclent);
2767 #else
2768 #ifdef HAVE_SOLARIS_ACL
2769 acl((char *)fname, SETACL, ((vim_acl_solaris_T *)aclent)->acl_cnt,
2770 ((vim_acl_solaris_T *)aclent)->acl_entry);
2771 #else
2772 #ifdef HAVE_AIX_ACL
2773 chacl((char *)fname, aclent, ((struct acl *)aclent)->acl_len);
2774 #endif /* HAVE_AIX_ACL */
2775 #endif /* HAVE_SOLARIS_ACL */
2776 #endif /* HAVE_POSIX_ACL */
2779 void
2780 mch_free_acl(aclent)
2781 vim_acl_T aclent;
2783 if (aclent == NULL)
2784 return;
2785 #ifdef HAVE_POSIX_ACL
2786 acl_free((acl_t)aclent);
2787 #else
2788 #ifdef HAVE_SOLARIS_ACL
2789 free(((vim_acl_solaris_T *)aclent)->acl_entry);
2790 free(aclent);
2791 #else
2792 #ifdef HAVE_AIX_ACL
2793 free(aclent);
2794 #endif /* HAVE_AIX_ACL */
2795 #endif /* HAVE_SOLARIS_ACL */
2796 #endif /* HAVE_POSIX_ACL */
2798 #endif
2801 * Set hidden flag for "name".
2803 void
2804 mch_hide(name)
2805 char_u *name UNUSED;
2807 /* can't hide a file */
2811 * return TRUE if "name" is a directory
2812 * return FALSE if "name" is not a directory
2813 * return FALSE for error
2816 mch_isdir(name)
2817 char_u *name;
2819 struct stat statb;
2821 if (*name == NUL) /* Some stat()s don't flag "" as an error. */
2822 return FALSE;
2823 if (stat((char *)name, &statb))
2824 return FALSE;
2825 #ifdef _POSIX_SOURCE
2826 return (S_ISDIR(statb.st_mode) ? TRUE : FALSE);
2827 #else
2828 return ((statb.st_mode & S_IFMT) == S_IFDIR ? TRUE : FALSE);
2829 #endif
2832 static int executable_file __ARGS((char_u *name));
2835 * Return 1 if "name" is an executable file, 0 if not or it doesn't exist.
2837 static int
2838 executable_file(name)
2839 char_u *name;
2841 struct stat st;
2843 if (stat((char *)name, &st))
2844 return 0;
2845 return S_ISREG(st.st_mode) && mch_access((char *)name, X_OK) == 0;
2849 * Return 1 if "name" can be found in $PATH and executed, 0 if not.
2850 * Return -1 if unknown.
2853 mch_can_exe(name)
2854 char_u *name;
2856 char_u *buf;
2857 char_u *p, *e;
2858 int retval;
2860 /* If it's an absolute or relative path don't need to use $PATH. */
2861 if (mch_isFullName(name) || (name[0] == '.' && (name[1] == '/'
2862 || (name[1] == '.' && name[2] == '/'))))
2863 return executable_file(name);
2865 p = (char_u *)getenv("PATH");
2866 if (p == NULL || *p == NUL)
2867 return -1;
2868 buf = alloc((unsigned)(STRLEN(name) + STRLEN(p) + 2));
2869 if (buf == NULL)
2870 return -1;
2873 * Walk through all entries in $PATH to check if "name" exists there and
2874 * is an executable file.
2876 for (;;)
2878 e = (char_u *)strchr((char *)p, ':');
2879 if (e == NULL)
2880 e = p + STRLEN(p);
2881 if (e - p <= 1) /* empty entry means current dir */
2882 STRCPY(buf, "./");
2883 else
2885 vim_strncpy(buf, p, e - p);
2886 add_pathsep(buf);
2888 STRCAT(buf, name);
2889 retval = executable_file(buf);
2890 if (retval == 1)
2891 break;
2893 if (*e != ':')
2894 break;
2895 p = e + 1;
2898 vim_free(buf);
2899 return retval;
2903 * Check what "name" is:
2904 * NODE_NORMAL: file or directory (or doesn't exist)
2905 * NODE_WRITABLE: writable device, socket, fifo, etc.
2906 * NODE_OTHER: non-writable things
2909 mch_nodetype(name)
2910 char_u *name;
2912 struct stat st;
2914 if (stat((char *)name, &st))
2915 return NODE_NORMAL;
2916 if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
2917 return NODE_NORMAL;
2918 #ifndef OS2
2919 if (S_ISBLK(st.st_mode)) /* block device isn't writable */
2920 return NODE_OTHER;
2921 #endif
2922 /* Everything else is writable? */
2923 return NODE_WRITABLE;
2926 void
2927 mch_early_init()
2929 #ifdef HAVE_CHECK_STACK_GROWTH
2930 int i;
2932 check_stack_growth((char *)&i);
2934 # ifdef HAVE_STACK_LIMIT
2935 get_stack_limit();
2936 # endif
2938 #endif
2941 * Setup an alternative stack for signals. Helps to catch signals when
2942 * running out of stack space.
2943 * Use of sigaltstack() is preferred, it's more portable.
2944 * Ignore any errors.
2946 #if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2947 signal_stack = (char *)alloc(SIGSTKSZ);
2948 init_signal_stack();
2949 #endif
2951 #ifdef FEAT_GUI_MACVIM
2952 macvim_early_init();
2953 #endif
2956 #if defined(EXITFREE) || defined(PROTO)
2957 void
2958 mch_free_mem()
2960 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
2961 if (clip_star.owned)
2962 clip_lose_selection(&clip_star);
2963 if (clip_plus.owned)
2964 clip_lose_selection(&clip_plus);
2965 # endif
2966 # if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
2967 if (xterm_Shell != (Widget)0)
2968 XtDestroyWidget(xterm_Shell);
2969 # ifndef LESSTIF_VERSION
2970 /* Lesstif crashes here, lose some memory */
2971 if (xterm_dpy != NULL)
2972 XtCloseDisplay(xterm_dpy);
2973 if (app_context != (XtAppContext)NULL)
2975 XtDestroyApplicationContext(app_context);
2976 # ifdef FEAT_X11
2977 x11_display = NULL; /* freed by XtDestroyApplicationContext() */
2978 # endif
2980 # endif
2981 # endif
2982 /* Don't close the display for GTK 1, it is done in exit(). */
2983 # if defined(FEAT_X11) && (!defined(FEAT_GUI_GTK) || defined(HAVE_GTK2))
2984 if (x11_display != NULL
2985 # ifdef FEAT_XCLIPBOARD
2986 && x11_display != xterm_dpy
2987 # endif
2989 XCloseDisplay(x11_display);
2990 # endif
2991 # if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2992 vim_free(signal_stack);
2993 signal_stack = NULL;
2994 # endif
2995 # ifdef FEAT_TITLE
2996 vim_free(oldtitle);
2997 vim_free(oldicon);
2998 # endif
3000 #endif
3002 static void exit_scroll __ARGS((void));
3005 * Output a newline when exiting.
3006 * Make sure the newline goes to the same stream as the text.
3008 static void
3009 exit_scroll()
3011 if (silent_mode)
3012 return;
3013 if (newline_on_exit || msg_didout)
3015 if (msg_use_printf())
3017 if (info_message)
3018 mch_msg("\n");
3019 else
3020 mch_errmsg("\r\n");
3022 else
3023 out_char('\n');
3025 else
3027 restore_cterm_colors(); /* get original colors back */
3028 msg_clr_eos_force(); /* clear the rest of the display */
3029 windgoto((int)Rows - 1, 0); /* may have moved the cursor */
3033 void
3034 mch_exit(r)
3035 int r;
3037 exiting = TRUE;
3039 #if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
3040 x11_export_final_selection();
3041 #endif
3043 #ifdef FEAT_GUI
3044 if (!gui.in_use)
3045 #endif
3047 settmode(TMODE_COOK);
3048 #ifdef FEAT_TITLE
3049 mch_restore_title(3); /* restore xterm title and icon name */
3050 #endif
3052 * When t_ti is not empty but it doesn't cause swapping terminal
3053 * pages, need to output a newline when msg_didout is set. But when
3054 * t_ti does swap pages it should not go to the shell page. Do this
3055 * before stoptermcap().
3057 if (swapping_screen() && !newline_on_exit)
3058 exit_scroll();
3060 /* Stop termcap: May need to check for T_CRV response, which
3061 * requires RAW mode. */
3062 stoptermcap();
3065 * A newline is only required after a message in the alternate screen.
3066 * This is set to TRUE by wait_return().
3068 if (!swapping_screen() || newline_on_exit)
3069 exit_scroll();
3071 /* Cursor may have been switched off without calling starttermcap()
3072 * when doing "vim -u vimrc" and vimrc contains ":q". */
3073 if (full_screen)
3074 cursor_on();
3076 out_flush();
3077 ml_close_all(TRUE); /* remove all memfiles */
3078 may_core_dump();
3079 #ifdef FEAT_GUI
3080 if (gui.in_use)
3081 gui_exit(r);
3082 #endif
3084 #ifdef MACOS_CONVERT
3085 mac_conv_cleanup();
3086 #endif
3088 #ifdef __QNX__
3089 /* A core dump won't be created if the signal handler
3090 * doesn't return, so we can't call exit() */
3091 if (deadly_signal != 0)
3092 return;
3093 #endif
3095 #ifdef FEAT_NETBEANS_INTG
3096 if (usingNetbeans)
3097 netbeans_send_disconnect();
3098 #endif
3100 #ifdef EXITFREE
3101 free_all_mem();
3102 #endif
3104 exit(r);
3107 static void
3108 may_core_dump()
3110 if (deadly_signal != 0)
3112 signal(deadly_signal, SIG_DFL);
3113 kill(getpid(), deadly_signal); /* Die using the signal we caught */
3117 #ifndef VMS
3119 void
3120 mch_settmode(tmode)
3121 int tmode;
3123 static int first = TRUE;
3125 /* Why is NeXT excluded here (and not in os_unixx.h)? */
3126 #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
3128 * for "new" tty systems
3130 # ifdef HAVE_TERMIOS_H
3131 static struct termios told;
3132 struct termios tnew;
3133 # else
3134 static struct termio told;
3135 struct termio tnew;
3136 # endif
3138 if (first)
3140 first = FALSE;
3141 # if defined(HAVE_TERMIOS_H)
3142 tcgetattr(read_cmd_fd, &told);
3143 # else
3144 ioctl(read_cmd_fd, TCGETA, &told);
3145 # endif
3148 tnew = told;
3149 if (tmode == TMODE_RAW)
3152 * ~ICRNL enables typing ^V^M
3154 tnew.c_iflag &= ~ICRNL;
3155 tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE
3156 # if defined(IEXTEN) && !defined(__MINT__)
3157 | IEXTEN /* IEXTEN enables typing ^V on SOLARIS */
3158 /* but it breaks function keys on MINT */
3159 # endif
3161 # ifdef ONLCR /* don't map NL -> CR NL, we do it ourselves */
3162 tnew.c_oflag &= ~ONLCR;
3163 # endif
3164 tnew.c_cc[VMIN] = 1; /* return after 1 char */
3165 tnew.c_cc[VTIME] = 0; /* don't wait */
3167 else if (tmode == TMODE_SLEEP)
3168 tnew.c_lflag &= ~(ECHO);
3170 # if defined(HAVE_TERMIOS_H)
3172 int n = 10;
3174 /* A signal may cause tcsetattr() to fail (e.g., SIGCONT). Retry a
3175 * few times. */
3176 while (tcsetattr(read_cmd_fd, TCSANOW, &tnew) == -1
3177 && errno == EINTR && n > 0)
3178 --n;
3180 # else
3181 ioctl(read_cmd_fd, TCSETA, &tnew);
3182 # endif
3184 #else
3187 * for "old" tty systems
3189 # ifndef TIOCSETN
3190 # define TIOCSETN TIOCSETP /* for hpux 9.0 */
3191 # endif
3192 static struct sgttyb ttybold;
3193 struct sgttyb ttybnew;
3195 if (first)
3197 first = FALSE;
3198 ioctl(read_cmd_fd, TIOCGETP, &ttybold);
3201 ttybnew = ttybold;
3202 if (tmode == TMODE_RAW)
3204 ttybnew.sg_flags &= ~(CRMOD | ECHO);
3205 ttybnew.sg_flags |= RAW;
3207 else if (tmode == TMODE_SLEEP)
3208 ttybnew.sg_flags &= ~(ECHO);
3209 ioctl(read_cmd_fd, TIOCSETN, &ttybnew);
3210 #endif
3211 curr_tmode = tmode;
3215 * Try to get the code for "t_kb" from the stty setting
3217 * Even if termcap claims a backspace key, the user's setting *should*
3218 * prevail. stty knows more about reality than termcap does, and if
3219 * somebody's usual erase key is DEL (which, for most BSD users, it will
3220 * be), they're going to get really annoyed if their erase key starts
3221 * doing forward deletes for no reason. (Eric Fischer)
3223 void
3224 get_stty()
3226 char_u buf[2];
3227 char_u *p;
3229 /* Why is NeXT excluded here (and not in os_unixx.h)? */
3230 #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
3231 /* for "new" tty systems */
3232 # ifdef HAVE_TERMIOS_H
3233 struct termios keys;
3234 # else
3235 struct termio keys;
3236 # endif
3238 # if defined(HAVE_TERMIOS_H)
3239 if (tcgetattr(read_cmd_fd, &keys) != -1)
3240 # else
3241 if (ioctl(read_cmd_fd, TCGETA, &keys) != -1)
3242 # endif
3244 buf[0] = keys.c_cc[VERASE];
3245 intr_char = keys.c_cc[VINTR];
3246 #else
3247 /* for "old" tty systems */
3248 struct sgttyb keys;
3250 if (ioctl(read_cmd_fd, TIOCGETP, &keys) != -1)
3252 buf[0] = keys.sg_erase;
3253 intr_char = keys.sg_kill;
3254 #endif
3255 buf[1] = NUL;
3256 add_termcode((char_u *)"kb", buf, FALSE);
3259 * If <BS> and <DEL> are now the same, redefine <DEL>.
3261 p = find_termcode((char_u *)"kD");
3262 if (p != NULL && p[0] == buf[0] && p[1] == buf[1])
3263 do_fixdel(NULL);
3265 #if 0
3266 } /* to keep cindent happy */
3267 #endif
3270 #endif /* VMS */
3272 #if defined(FEAT_MOUSE_TTY) || defined(PROTO)
3274 * Set mouse clicks on or off.
3276 void
3277 mch_setmouse(on)
3278 int on;
3280 static int ison = FALSE;
3281 int xterm_mouse_vers;
3283 if (on == ison) /* return quickly if nothing to do */
3284 return;
3286 xterm_mouse_vers = use_xterm_mouse();
3287 if (xterm_mouse_vers > 0)
3289 if (on) /* enable mouse events, use mouse tracking if available */
3290 out_str_nf((char_u *)
3291 (xterm_mouse_vers > 1
3292 ? IF_EB("\033[?1002h", ESC_STR "[?1002h")
3293 : IF_EB("\033[?1000h", ESC_STR "[?1000h")));
3294 else /* disable mouse events, could probably always send the same */
3295 out_str_nf((char_u *)
3296 (xterm_mouse_vers > 1
3297 ? IF_EB("\033[?1002l", ESC_STR "[?1002l")
3298 : IF_EB("\033[?1000l", ESC_STR "[?1000l")));
3299 ison = on;
3302 # ifdef FEAT_MOUSE_DEC
3303 else if (ttym_flags == TTYM_DEC)
3305 if (on) /* enable mouse events */
3306 out_str_nf((char_u *)"\033[1;2'z\033[1;3'{");
3307 else /* disable mouse events */
3308 out_str_nf((char_u *)"\033['z");
3309 ison = on;
3311 # endif
3313 # ifdef FEAT_MOUSE_GPM
3314 else
3316 if (on)
3318 if (gpm_open())
3319 ison = TRUE;
3321 else
3323 gpm_close();
3324 ison = FALSE;
3327 # endif
3329 # ifdef FEAT_SYSMOUSE
3330 else
3332 if (on)
3334 if (sysmouse_open() == OK)
3335 ison = TRUE;
3337 else
3339 sysmouse_close();
3340 ison = FALSE;
3343 # endif
3345 # ifdef FEAT_MOUSE_JSB
3346 else
3348 if (on)
3350 /* D - Enable Mouse up/down messages
3351 * L - Enable Left Button Reporting
3352 * M - Enable Middle Button Reporting
3353 * R - Enable Right Button Reporting
3354 * K - Enable SHIFT and CTRL key Reporting
3355 * + - Enable Advanced messaging of mouse moves and up/down messages
3356 * Q - Quiet No Ack
3357 * # - Numeric value of mouse pointer required
3358 * 0 = Multiview 2000 cursor, used as standard
3359 * 1 = Windows Arrow
3360 * 2 = Windows I Beam
3361 * 3 = Windows Hour Glass
3362 * 4 = Windows Cross Hair
3363 * 5 = Windows UP Arrow
3365 #ifdef JSBTERM_MOUSE_NONADVANCED /* Disables full feedback of pointer movements */
3366 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK1Q\033\\",
3367 ESC_STR "[0~ZwLMRK1Q" ESC_STR "\\"));
3368 #else
3369 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK+1Q\033\\",
3370 ESC_STR "[0~ZwLMRK+1Q" ESC_STR "\\"));
3371 #endif
3372 ison = TRUE;
3374 else
3376 out_str_nf((char_u *)IF_EB("\033[0~ZwQ\033\\",
3377 ESC_STR "[0~ZwQ" ESC_STR "\\"));
3378 ison = FALSE;
3381 # endif
3382 # ifdef FEAT_MOUSE_PTERM
3383 else
3385 /* 1 = button press, 6 = release, 7 = drag, 1h...9l = right button */
3386 if (on)
3387 out_str_nf("\033[>1h\033[>6h\033[>7h\033[>1h\033[>9l");
3388 else
3389 out_str_nf("\033[>1l\033[>6l\033[>7l\033[>1l\033[>9h");
3390 ison = on;
3392 # endif
3396 * Set the mouse termcode, depending on the 'term' and 'ttymouse' options.
3398 void
3399 check_mouse_termcode()
3401 # ifdef FEAT_MOUSE_XTERM
3402 if (use_xterm_mouse()
3403 # ifdef FEAT_GUI
3404 && !gui.in_use
3405 # endif
3408 set_mouse_termcode(KS_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3409 ? IF_EB("\233M", CSI_STR "M")
3410 : IF_EB("\033[M", ESC_STR "[M")));
3411 if (*p_mouse != NUL)
3413 /* force mouse off and maybe on to send possibly new mouse
3414 * activation sequence to the xterm, with(out) drag tracing. */
3415 mch_setmouse(FALSE);
3416 setmouse();
3419 else
3420 del_mouse_termcode(KS_MOUSE);
3421 # endif
3423 # ifdef FEAT_MOUSE_GPM
3424 if (!use_xterm_mouse()
3425 # ifdef FEAT_GUI
3426 && !gui.in_use
3427 # endif
3429 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MG", ESC_STR "MG"));
3430 # endif
3432 # ifdef FEAT_SYSMOUSE
3433 if (!use_xterm_mouse()
3434 # ifdef FEAT_GUI
3435 && !gui.in_use
3436 # endif
3438 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MS", ESC_STR "MS"));
3439 # endif
3441 # ifdef FEAT_MOUSE_JSB
3442 /* conflicts with xterm mouse: "\033[" and "\033[M" ??? */
3443 if (!use_xterm_mouse()
3444 # ifdef FEAT_GUI
3445 && !gui.in_use
3446 # endif
3448 set_mouse_termcode(KS_JSBTERM_MOUSE,
3449 (char_u *)IF_EB("\033[0~zw", ESC_STR "[0~zw"));
3450 else
3451 del_mouse_termcode(KS_JSBTERM_MOUSE);
3452 # endif
3454 # ifdef FEAT_MOUSE_NET
3455 /* There is no conflict, but one may type "ESC }" from Insert mode. Don't
3456 * define it in the GUI or when using an xterm. */
3457 if (!use_xterm_mouse()
3458 # ifdef FEAT_GUI
3459 && !gui.in_use
3460 # endif
3462 set_mouse_termcode(KS_NETTERM_MOUSE,
3463 (char_u *)IF_EB("\033}", ESC_STR "}"));
3464 else
3465 del_mouse_termcode(KS_NETTERM_MOUSE);
3466 # endif
3468 # ifdef FEAT_MOUSE_DEC
3469 /* conflicts with xterm mouse: "\033[" and "\033[M" */
3470 if (!use_xterm_mouse()
3471 # ifdef FEAT_GUI
3472 && !gui.in_use
3473 # endif
3475 set_mouse_termcode(KS_DEC_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3476 ? IF_EB("\233", CSI_STR) : IF_EB("\033[", ESC_STR "[")));
3477 else
3478 del_mouse_termcode(KS_DEC_MOUSE);
3479 # endif
3480 # ifdef FEAT_MOUSE_PTERM
3481 /* same as the dec mouse */
3482 if (!use_xterm_mouse()
3483 # ifdef FEAT_GUI
3484 && !gui.in_use
3485 # endif
3487 set_mouse_termcode(KS_PTERM_MOUSE,
3488 (char_u *) IF_EB("\033[", ESC_STR "["));
3489 else
3490 del_mouse_termcode(KS_PTERM_MOUSE);
3491 # endif
3493 #endif
3496 * set screen mode, always fails.
3499 mch_screenmode(arg)
3500 char_u *arg UNUSED;
3502 EMSG(_(e_screenmode));
3503 return FAIL;
3506 #ifndef VMS
3509 * Try to get the current window size:
3510 * 1. with an ioctl(), most accurate method
3511 * 2. from the environment variables LINES and COLUMNS
3512 * 3. from the termcap
3513 * 4. keep using the old values
3514 * Return OK when size could be determined, FAIL otherwise.
3517 mch_get_shellsize()
3519 long rows = 0;
3520 long columns = 0;
3521 char_u *p;
3524 * For OS/2 use _scrsize().
3526 # ifdef __EMX__
3528 int s[2];
3530 _scrsize(s);
3531 columns = s[0];
3532 rows = s[1];
3534 # endif
3537 * 1. try using an ioctl. It is the most accurate method.
3539 * Try using TIOCGWINSZ first, some systems that have it also define
3540 * TIOCGSIZE but don't have a struct ttysize.
3542 # ifdef TIOCGWINSZ
3544 struct winsize ws;
3545 int fd = 1;
3547 /* When stdout is not a tty, use stdin for the ioctl(). */
3548 if (!isatty(fd) && isatty(read_cmd_fd))
3549 fd = read_cmd_fd;
3550 if (ioctl(fd, TIOCGWINSZ, &ws) == 0)
3552 columns = ws.ws_col;
3553 rows = ws.ws_row;
3556 # else /* TIOCGWINSZ */
3557 # ifdef TIOCGSIZE
3559 struct ttysize ts;
3560 int fd = 1;
3562 /* When stdout is not a tty, use stdin for the ioctl(). */
3563 if (!isatty(fd) && isatty(read_cmd_fd))
3564 fd = read_cmd_fd;
3565 if (ioctl(fd, TIOCGSIZE, &ts) == 0)
3567 columns = ts.ts_cols;
3568 rows = ts.ts_lines;
3571 # endif /* TIOCGSIZE */
3572 # endif /* TIOCGWINSZ */
3575 * 2. get size from environment
3576 * When being POSIX compliant ('|' flag in 'cpoptions') this overrules
3577 * the ioctl() values!
3579 if (columns == 0 || rows == 0 || vim_strchr(p_cpo, CPO_TSIZE) != NULL)
3581 if ((p = (char_u *)getenv("LINES")))
3582 rows = atoi((char *)p);
3583 if ((p = (char_u *)getenv("COLUMNS")))
3584 columns = atoi((char *)p);
3587 #ifdef HAVE_TGETENT
3589 * 3. try reading "co" and "li" entries from termcap
3591 if (columns == 0 || rows == 0)
3592 getlinecol(&columns, &rows);
3593 #endif
3596 * 4. If everything fails, use the old values
3598 if (columns <= 0 || rows <= 0)
3599 return FAIL;
3601 Rows = rows;
3602 Columns = columns;
3603 return OK;
3607 * Try to set the window size to Rows and Columns.
3609 void
3610 mch_set_shellsize()
3612 if (*T_CWS)
3615 * NOTE: if you get an error here that term_set_winsize() is
3616 * undefined, check the output of configure. It could probably not
3617 * find a ncurses, termcap or termlib library.
3619 term_set_winsize((int)Rows, (int)Columns);
3620 out_flush();
3621 screen_start(); /* don't know where cursor is now */
3625 #endif /* VMS */
3628 * Rows and/or Columns has changed.
3630 void
3631 mch_new_shellsize()
3633 /* Nothing to do. */
3636 #ifndef USE_SYSTEM
3637 static void append_ga_line __ARGS((garray_T *gap));
3640 * Append the text in "gap" below the cursor line and clear "gap".
3642 static void
3643 append_ga_line(gap)
3644 garray_T *gap;
3646 /* Remove trailing CR. */
3647 if (gap->ga_len > 0
3648 && !curbuf->b_p_bin
3649 && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR)
3650 --gap->ga_len;
3651 ga_append(gap, NUL);
3652 ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE);
3653 gap->ga_len = 0;
3655 #endif
3658 mch_call_shell(cmd, options)
3659 char_u *cmd;
3660 int options; /* SHELL_*, see vim.h */
3662 #ifdef VMS
3663 char *ifn = NULL;
3664 char *ofn = NULL;
3665 #endif
3666 int tmode = cur_tmode;
3667 #ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
3668 int x;
3669 # ifndef __EMX__
3670 char_u *newcmd; /* only needed for unix */
3671 # else
3673 * Set the preferred shell in the EMXSHELL environment variable (but
3674 * only if it is different from what is already in the environment).
3675 * Emx then takes care of whether to use "/c" or "-c" in an
3676 * intelligent way. Simply pass the whole thing to emx's system() call.
3677 * Emx also starts an interactive shell if system() is passed an empty
3678 * string.
3680 char_u *p, *old;
3682 if (((old = (char_u *)getenv("EMXSHELL")) == NULL) || STRCMP(old, p_sh))
3684 /* should check HAVE_SETENV, but I know we don't have it. */
3685 p = alloc(10 + strlen(p_sh));
3686 if (p)
3688 sprintf((char *)p, "EMXSHELL=%s", p_sh);
3689 putenv((char *)p); /* don't free the pointer! */
3692 # endif
3694 out_flush();
3696 if (options & SHELL_COOKED)
3697 settmode(TMODE_COOK); /* set to normal mode */
3699 # ifdef __EMX__
3700 if (cmd == NULL)
3701 x = system(""); /* this starts an interactive shell in emx */
3702 else
3703 x = system((char *)cmd);
3704 /* system() returns -1 when error occurs in starting shell */
3705 if (x == -1 && !emsg_silent)
3707 MSG_PUTS(_("\nCannot execute shell "));
3708 msg_outtrans(p_sh);
3709 msg_putchar('\n');
3711 # else /* not __EMX__ */
3712 if (cmd == NULL)
3713 x = system((char *)p_sh);
3714 else
3716 # ifdef VMS
3717 if (ofn = strchr((char *)cmd, '>'))
3718 *ofn++ = '\0';
3719 if (ifn = strchr((char *)cmd, '<'))
3721 char *p;
3723 *ifn++ = '\0';
3724 p = strchr(ifn,' '); /* chop off any trailing spaces */
3725 if (p)
3726 *p = '\0';
3728 if (ofn)
3729 x = vms_sys((char *)cmd, ofn, ifn);
3730 else
3731 x = system((char *)cmd);
3732 # else
3733 newcmd = lalloc(STRLEN(p_sh)
3734 + (extra_shell_arg == NULL ? 0 : STRLEN(extra_shell_arg))
3735 + STRLEN(p_shcf) + STRLEN(cmd) + 4, TRUE);
3736 if (newcmd == NULL)
3737 x = 0;
3738 else
3740 sprintf((char *)newcmd, "%s %s %s %s", p_sh,
3741 extra_shell_arg == NULL ? "" : (char *)extra_shell_arg,
3742 (char *)p_shcf,
3743 (char *)cmd);
3744 x = system((char *)newcmd);
3745 vim_free(newcmd);
3747 # endif
3749 # ifdef VMS
3750 x = vms_sys_status(x);
3751 # endif
3752 if (emsg_silent)
3754 else if (x == 127)
3755 MSG_PUTS(_("\nCannot execute shell sh\n"));
3756 # endif /* __EMX__ */
3757 else if (x && !(options & SHELL_SILENT))
3759 MSG_PUTS(_("\nshell returned "));
3760 msg_outnum((long)x);
3761 msg_putchar('\n');
3764 if (tmode == TMODE_RAW)
3765 settmode(TMODE_RAW); /* set to raw mode */
3766 # ifdef FEAT_TITLE
3767 resettitle();
3768 # endif
3769 return x;
3771 #else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
3773 # define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
3774 127, some shells use that already */
3776 char_u *newcmd = NULL;
3777 pid_t pid;
3778 pid_t wpid = 0;
3779 pid_t wait_pid = 0;
3780 # ifdef HAVE_UNION_WAIT
3781 union wait status;
3782 # else
3783 int status = -1;
3784 # endif
3785 int retval = -1;
3786 char **argv = NULL;
3787 int argc;
3788 int i;
3789 char_u *p;
3790 int inquote;
3791 int pty_master_fd = -1; /* for pty's */
3792 # ifdef FEAT_GUI
3793 int pty_slave_fd = -1;
3794 char *tty_name;
3795 # endif
3796 int fd_toshell[2]; /* for pipes */
3797 int fd_fromshell[2];
3798 int pipe_error = FALSE;
3799 # ifdef HAVE_SETENV
3800 char envbuf[50];
3801 # else
3802 static char envbuf_Rows[20];
3803 static char envbuf_Columns[20];
3804 # endif
3805 int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
3807 out_flush();
3808 if (options & SHELL_COOKED)
3809 settmode(TMODE_COOK); /* set to normal mode */
3811 newcmd = vim_strsave(p_sh);
3812 if (newcmd == NULL) /* out of memory */
3813 goto error;
3816 * Do this loop twice:
3817 * 1: find number of arguments
3818 * 2: separate them and build argv[]
3820 for (i = 0; i < 2; ++i)
3822 p = newcmd;
3823 inquote = FALSE;
3824 argc = 0;
3825 for (;;)
3827 if (i == 1)
3828 argv[argc] = (char *)p;
3829 ++argc;
3830 while (*p && (inquote || (*p != ' ' && *p != TAB)))
3832 if (*p == '"')
3833 inquote = !inquote;
3834 ++p;
3836 if (*p == NUL)
3837 break;
3838 if (i == 1)
3839 *p++ = NUL;
3840 p = skipwhite(p);
3842 if (argv == NULL)
3844 argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *)));
3845 if (argv == NULL) /* out of memory */
3846 goto error;
3849 if (cmd != NULL)
3851 if (extra_shell_arg != NULL)
3852 argv[argc++] = (char *)extra_shell_arg;
3853 argv[argc++] = (char *)p_shcf;
3854 argv[argc++] = (char *)cmd;
3856 argv[argc] = NULL;
3859 * For the GUI, when writing the output into the buffer and when reading
3860 * input from the buffer: Try using a pseudo-tty to get the stdin/stdout
3861 * of the executed command into the Vim window. Or use a pipe.
3863 if ((options & (SHELL_READ|SHELL_WRITE))
3864 # ifdef FEAT_GUI
3865 || (gui.in_use && show_shell_mess)
3866 # endif
3869 # ifdef FEAT_GUI
3871 * Try to open a master pty.
3872 * If this works, open the slave pty.
3873 * If the slave can't be opened, close the master pty.
3875 if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
3877 pty_master_fd = OpenPTY(&tty_name); /* open pty */
3878 if (pty_master_fd >= 0 && ((pty_slave_fd =
3879 open(tty_name, O_RDWR | O_EXTRA, 0)) < 0))
3881 close(pty_master_fd);
3882 pty_master_fd = -1;
3886 * If not opening a pty or it didn't work, try using pipes.
3888 if (pty_master_fd < 0)
3889 # endif
3891 pipe_error = (pipe(fd_toshell) < 0);
3892 if (!pipe_error) /* pipe create OK */
3894 pipe_error = (pipe(fd_fromshell) < 0);
3895 if (pipe_error) /* pipe create failed */
3897 close(fd_toshell[0]);
3898 close(fd_toshell[1]);
3901 if (pipe_error)
3903 MSG_PUTS(_("\nCannot create pipes\n"));
3904 out_flush();
3909 if (!pipe_error) /* pty or pipe opened or not used */
3911 # ifdef __BEOS__
3912 beos_cleanup_read_thread();
3913 # endif
3915 if ((pid = fork()) == -1) /* maybe we should use vfork() */
3917 MSG_PUTS(_("\nCannot fork\n"));
3918 if ((options & (SHELL_READ|SHELL_WRITE))
3919 # ifdef FEAT_GUI
3920 || (gui.in_use && show_shell_mess)
3921 # endif
3924 # ifdef FEAT_GUI
3925 if (pty_master_fd >= 0) /* close the pseudo tty */
3927 close(pty_master_fd);
3928 close(pty_slave_fd);
3930 else /* close the pipes */
3931 # endif
3933 close(fd_toshell[0]);
3934 close(fd_toshell[1]);
3935 close(fd_fromshell[0]);
3936 close(fd_fromshell[1]);
3940 else if (pid == 0) /* child */
3942 reset_signals(); /* handle signals normally */
3944 if (!show_shell_mess || (options & SHELL_EXPAND))
3946 int fd;
3949 * Don't want to show any message from the shell. Can't just
3950 * close stdout and stderr though, because some systems will
3951 * break if you try to write to them after that, so we must
3952 * use dup() to replace them with something else -- webb
3953 * Connect stdin to /dev/null too, so ":n `cat`" doesn't hang,
3954 * waiting for input.
3956 fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
3957 fclose(stdin);
3958 fclose(stdout);
3959 fclose(stderr);
3962 * If any of these open()'s and dup()'s fail, we just continue
3963 * anyway. It's not fatal, and on most systems it will make
3964 * no difference at all. On a few it will cause the execvp()
3965 * to exit with a non-zero status even when the completion
3966 * could be done, which is nothing too serious. If the open()
3967 * or dup() failed we'd just do the same thing ourselves
3968 * anyway -- webb
3970 if (fd >= 0)
3972 ignored = dup(fd); /* To replace stdin (fd 0) */
3973 ignored = dup(fd); /* To replace stdout (fd 1) */
3974 ignored = dup(fd); /* To replace stderr (fd 2) */
3976 /* Don't need this now that we've duplicated it */
3977 close(fd);
3980 else if ((options & (SHELL_READ|SHELL_WRITE))
3981 # ifdef FEAT_GUI
3982 || gui.in_use
3983 # endif
3987 # ifdef HAVE_SETSID
3988 /* Create our own process group, so that the child and all its
3989 * children can be kill()ed. Don't do this when using pipes,
3990 * because stdin is not a tty, we would lose /dev/tty. */
3991 if (p_stmp)
3993 (void)setsid();
3994 # if defined(SIGHUP)
3995 /* When doing "!xterm&" and 'shell' is bash: the shell
3996 * will exit and send SIGHUP to all processes in its
3997 * group, killing the just started process. Ignore SIGHUP
3998 * to avoid that. (suggested by Simon Schubert)
4000 signal(SIGHUP, SIG_IGN);
4001 # endif
4003 # endif
4004 # ifdef FEAT_GUI
4005 if (pty_slave_fd >= 0)
4007 /* push stream discipline modules */
4008 if (options & SHELL_COOKED)
4009 SetupSlavePTY(pty_slave_fd);
4010 # if defined(TIOCSCTTY) && !defined(FEAT_GUI_MACVIM)
4011 /* Try to become controlling tty (probably doesn't work,
4012 * unless run by root) */
4013 ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
4014 # endif
4016 # endif
4017 /* Simulate to have a dumb terminal (for now) */
4018 # ifdef HAVE_SETENV
4019 setenv("TERM", "dumb", 1);
4020 sprintf((char *)envbuf, "%ld", Rows);
4021 setenv("ROWS", (char *)envbuf, 1);
4022 sprintf((char *)envbuf, "%ld", Rows);
4023 setenv("LINES", (char *)envbuf, 1);
4024 sprintf((char *)envbuf, "%ld", Columns);
4025 setenv("COLUMNS", (char *)envbuf, 1);
4026 # else
4028 * Putenv does not copy the string, it has to remain valid.
4029 * Use a static array to avoid losing allocated memory.
4031 putenv("TERM=dumb");
4032 sprintf(envbuf_Rows, "ROWS=%ld", Rows);
4033 putenv(envbuf_Rows);
4034 sprintf(envbuf_Rows, "LINES=%ld", Rows);
4035 putenv(envbuf_Rows);
4036 sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
4037 putenv(envbuf_Columns);
4038 # endif
4041 * stderr is only redirected when using the GUI, so that a
4042 * program like gpg can still access the terminal to get a
4043 * passphrase using stderr.
4045 # ifdef FEAT_GUI
4046 if (pty_master_fd >= 0)
4048 close(pty_master_fd); /* close master side of pty */
4050 /* set up stdin/stdout/stderr for the child */
4051 close(0);
4052 ignored = dup(pty_slave_fd);
4053 close(1);
4054 ignored = dup(pty_slave_fd);
4055 if (gui.in_use)
4057 close(2);
4058 ignored = dup(pty_slave_fd);
4061 close(pty_slave_fd); /* has been dupped, close it now */
4063 else
4064 # endif
4066 /* set up stdin for the child */
4067 close(fd_toshell[1]);
4068 close(0);
4069 ignored = dup(fd_toshell[0]);
4070 close(fd_toshell[0]);
4072 /* set up stdout for the child */
4073 close(fd_fromshell[0]);
4074 close(1);
4075 ignored = dup(fd_fromshell[1]);
4076 close(fd_fromshell[1]);
4078 # ifdef FEAT_GUI
4079 if (gui.in_use)
4081 /* set up stderr for the child */
4082 close(2);
4083 ignored = dup(1);
4085 # endif
4090 * There is no type cast for the argv, because the type may be
4091 * different on different machines. This may cause a warning
4092 * message with strict compilers, don't worry about it.
4093 * Call _exit() instead of exit() to avoid closing the connection
4094 * to the X server (esp. with GTK, which uses atexit()).
4096 execvp(argv[0], argv);
4097 _exit(EXEC_FAILED); /* exec failed, return failure code */
4099 else /* parent */
4102 * While child is running, ignore terminating signals.
4103 * Do catch CTRL-C, so that "got_int" is set.
4105 catch_signals(SIG_IGN, SIG_ERR);
4106 catch_int_signal();
4109 * For the GUI we redirect stdin, stdout and stderr to our window.
4110 * This is also used to pipe stdin/stdout to/from the external
4111 * command.
4113 if ((options & (SHELL_READ|SHELL_WRITE))
4114 # ifdef FEAT_GUI
4115 || (gui.in_use && show_shell_mess)
4116 # endif
4119 # define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
4120 char_u buffer[BUFLEN + 1];
4121 # ifdef FEAT_MBYTE
4122 int buffer_off = 0; /* valid bytes in buffer[] */
4123 # endif
4124 char_u ta_buf[BUFLEN + 1]; /* TypeAHead */
4125 int ta_len = 0; /* valid bytes in ta_buf[] */
4126 int len;
4127 int p_more_save;
4128 int old_State;
4129 int c;
4130 int toshell_fd;
4131 int fromshell_fd;
4132 garray_T ga;
4133 int noread_cnt;
4134 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4135 struct timeval start_tv;
4136 # endif
4138 # ifdef FEAT_GUI
4139 if (pty_master_fd >= 0)
4141 close(pty_slave_fd); /* close slave side of pty */
4142 fromshell_fd = pty_master_fd;
4143 toshell_fd = dup(pty_master_fd);
4145 else
4146 # endif
4148 close(fd_toshell[0]);
4149 close(fd_fromshell[1]);
4150 toshell_fd = fd_toshell[1];
4151 fromshell_fd = fd_fromshell[0];
4155 * Write to the child if there are typed characters.
4156 * Read from the child if there are characters available.
4157 * Repeat the reading a few times if more characters are
4158 * available. Need to check for typed keys now and then, but
4159 * not too often (delays when no chars are available).
4160 * This loop is quit if no characters can be read from the pty
4161 * (WaitForChar detected special condition), or there are no
4162 * characters available and the child has exited.
4163 * Only check if the child has exited when there is no more
4164 * output. The child may exit before all the output has
4165 * been printed.
4167 * Currently this busy loops!
4168 * This can probably dead-lock when the write blocks!
4170 p_more_save = p_more;
4171 p_more = FALSE;
4172 old_State = State;
4173 State = EXTERNCMD; /* don't redraw at window resize */
4175 if ((options & SHELL_WRITE) && toshell_fd >= 0)
4177 /* Fork a process that will write the lines to the
4178 * external program. */
4179 if ((wpid = fork()) == -1)
4181 MSG_PUTS(_("\nCannot fork\n"));
4183 else if (wpid == 0)
4185 linenr_T lnum = curbuf->b_op_start.lnum;
4186 int written = 0;
4187 char_u *lp = ml_get(lnum);
4188 char_u *s;
4189 size_t l;
4191 /* child */
4192 close(fromshell_fd);
4193 for (;;)
4195 l = STRLEN(lp + written);
4196 if (l == 0)
4197 len = 0;
4198 else if (lp[written] == NL)
4199 /* NL -> NUL translation */
4200 len = write(toshell_fd, "", (size_t)1);
4201 else
4203 s = vim_strchr(lp + written, NL);
4204 len = write(toshell_fd, (char *)lp + written,
4205 s == NULL ? l
4206 : (size_t)(s - (lp + written)));
4208 if (len == (int)l)
4210 /* Finished a line, add a NL, unless this line
4211 * should not have one. */
4212 if (lnum != curbuf->b_op_end.lnum
4213 || !curbuf->b_p_bin
4214 || (lnum != write_no_eol_lnum
4215 && (lnum !=
4216 curbuf->b_ml.ml_line_count
4217 || curbuf->b_p_eol)))
4218 ignored = write(toshell_fd, "\n",
4219 (size_t)1);
4220 ++lnum;
4221 if (lnum > curbuf->b_op_end.lnum)
4223 /* finished all the lines, close pipe */
4224 close(toshell_fd);
4225 toshell_fd = -1;
4226 break;
4228 lp = ml_get(lnum);
4229 written = 0;
4231 else if (len > 0)
4232 written += len;
4234 _exit(0);
4236 else
4238 close(toshell_fd);
4239 toshell_fd = -1;
4243 if (options & SHELL_READ)
4244 ga_init2(&ga, 1, BUFLEN);
4246 noread_cnt = 0;
4247 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4248 gettimeofday(&start_tv, NULL);
4249 # endif
4250 for (;;)
4253 * Check if keys have been typed, write them to the child
4254 * if there are any.
4255 * Don't do this if we are expanding wild cards (would eat
4256 * typeahead).
4257 * Don't do this when filtering and terminal is in cooked
4258 * mode, the shell command will handle the I/O. Avoids
4259 * that a typed password is echoed for ssh or gpg command.
4260 * Don't get characters when the child has already
4261 * finished (wait_pid == 0).
4262 * Don't read characters unless we didn't get output for a
4263 * while (noread_cnt > 4), avoids that ":r !ls" eats
4264 * typeahead.
4266 len = 0;
4267 if (!(options & SHELL_EXPAND)
4268 && ((options &
4269 (SHELL_READ|SHELL_WRITE|SHELL_COOKED))
4270 != (SHELL_READ|SHELL_WRITE|SHELL_COOKED)
4271 # ifdef FEAT_GUI
4272 || gui.in_use
4273 # endif
4275 && wait_pid == 0
4276 && (ta_len > 0 || noread_cnt > 4))
4278 if (ta_len == 0)
4280 /* Get extra characters when we don't have any.
4281 * Reset the counter and timer. */
4282 noread_cnt = 0;
4283 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4284 gettimeofday(&start_tv, NULL);
4285 # endif
4286 len = ui_inchar(ta_buf, BUFLEN, 10L, 0);
4288 if (ta_len > 0 || len > 0)
4291 * For pipes:
4292 * Check for CTRL-C: send interrupt signal to child.
4293 * Check for CTRL-D: EOF, close pipe to child.
4295 if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
4297 # ifdef SIGINT
4299 * Send SIGINT to the child's group or all
4300 * processes in our group.
4302 if (ta_buf[ta_len] == Ctrl_C
4303 || ta_buf[ta_len] == intr_char)
4305 # ifdef HAVE_SETSID
4306 kill(-pid, SIGINT);
4307 # else
4308 kill(0, SIGINT);
4309 # endif
4310 if (wpid > 0)
4311 kill(wpid, SIGINT);
4313 # endif
4314 if (pty_master_fd < 0 && toshell_fd >= 0
4315 && ta_buf[ta_len] == Ctrl_D)
4317 close(toshell_fd);
4318 toshell_fd = -1;
4322 /* replace K_BS by <BS> and K_DEL by <DEL> */
4323 for (i = ta_len; i < ta_len + len; ++i)
4325 if (ta_buf[i] == CSI && len - i > 2)
4327 c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]);
4328 if (c == K_DEL || c == K_KDEL || c == K_BS)
4330 mch_memmove(ta_buf + i + 1, ta_buf + i + 3,
4331 (size_t)(len - i - 2));
4332 if (c == K_DEL || c == K_KDEL)
4333 ta_buf[i] = DEL;
4334 else
4335 ta_buf[i] = Ctrl_H;
4336 len -= 2;
4339 else if (ta_buf[i] == '\r')
4340 ta_buf[i] = '\n';
4341 # ifdef FEAT_MBYTE
4342 if (has_mbyte)
4343 i += (*mb_ptr2len_len)(ta_buf + i,
4344 ta_len + len - i) - 1;
4345 # endif
4349 * For pipes: echo the typed characters.
4350 * For a pty this does not seem to work.
4352 if (pty_master_fd < 0)
4354 for (i = ta_len; i < ta_len + len; ++i)
4356 if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
4357 msg_putchar(ta_buf[i]);
4358 # ifdef FEAT_MBYTE
4359 else if (has_mbyte)
4361 int l = (*mb_ptr2len)(ta_buf + i);
4363 msg_outtrans_len(ta_buf + i, l);
4364 i += l - 1;
4366 # endif
4367 else
4368 msg_outtrans_len(ta_buf + i, 1);
4370 windgoto(msg_row, msg_col);
4371 out_flush();
4374 ta_len += len;
4377 * Write the characters to the child, unless EOF has
4378 * been typed for pipes. Write one character at a
4379 * time, to avoid losing too much typeahead.
4380 * When writing buffer lines, drop the typed
4381 * characters (only check for CTRL-C).
4383 if (options & SHELL_WRITE)
4384 ta_len = 0;
4385 else if (toshell_fd >= 0)
4387 len = write(toshell_fd, (char *)ta_buf, (size_t)1);
4388 if (len > 0)
4390 ta_len -= len;
4391 mch_memmove(ta_buf, ta_buf + len, ta_len);
4397 if (got_int)
4399 /* CTRL-C sends a signal to the child, we ignore it
4400 * ourselves */
4401 # ifdef HAVE_SETSID
4402 kill(-pid, SIGINT);
4403 # else
4404 kill(0, SIGINT);
4405 # endif
4406 if (wpid > 0)
4407 kill(wpid, SIGINT);
4408 got_int = FALSE;
4412 * Check if the child has any characters to be printed.
4413 * Read them and write them to our window. Repeat this as
4414 * long as there is something to do, avoid the 10ms wait
4415 * for mch_inchar(), or sending typeahead characters to
4416 * the external process.
4417 * TODO: This should handle escape sequences, compatible
4418 * to some terminal (vt52?).
4420 ++noread_cnt;
4421 while (RealWaitForChar(fromshell_fd, 10L, NULL))
4423 len = read(fromshell_fd, (char *)buffer
4424 # ifdef FEAT_MBYTE
4425 + buffer_off, (size_t)(BUFLEN - buffer_off)
4426 # else
4427 , (size_t)BUFLEN
4428 # endif
4430 if (len <= 0) /* end of file or error */
4431 goto finished;
4433 noread_cnt = 0;
4434 if (options & SHELL_READ)
4436 /* Do NUL -> NL translation, append NL separated
4437 * lines to the current buffer. */
4438 for (i = 0; i < len; ++i)
4440 if (buffer[i] == NL)
4441 append_ga_line(&ga);
4442 else if (buffer[i] == NUL)
4443 ga_append(&ga, NL);
4444 else
4445 ga_append(&ga, buffer[i]);
4448 # ifdef FEAT_MBYTE
4449 else if (has_mbyte)
4451 int l;
4453 len += buffer_off;
4454 buffer[len] = NUL;
4456 /* Check if the last character in buffer[] is
4457 * incomplete, keep these bytes for the next
4458 * round. */
4459 for (p = buffer; p < buffer + len; p += l)
4461 l = mb_cptr2len(p);
4462 if (l == 0)
4463 l = 1; /* NUL byte? */
4464 else if (MB_BYTE2LEN(*p) != l)
4465 break;
4467 if (p == buffer) /* no complete character */
4469 /* avoid getting stuck at an illegal byte */
4470 if (len >= 12)
4471 ++p;
4472 else
4474 buffer_off = len;
4475 continue;
4478 c = *p;
4479 *p = NUL;
4480 msg_puts(buffer);
4481 if (p < buffer + len)
4483 *p = c;
4484 buffer_off = (buffer + len) - p;
4485 mch_memmove(buffer, p, buffer_off);
4486 continue;
4488 buffer_off = 0;
4490 # endif /* FEAT_MBYTE */
4491 else
4493 buffer[len] = NUL;
4494 msg_puts(buffer);
4497 windgoto(msg_row, msg_col);
4498 cursor_on();
4499 out_flush();
4500 # if FEAT_GUI_MACVIM
4501 if (gui.in_use)
4502 gui_macvim_flush();
4503 # endif
4504 if (got_int)
4505 break;
4507 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4509 struct timeval now_tv;
4510 long msec;
4512 /* Avoid that we keep looping here without
4513 * checking for a CTRL-C for a long time. Don't
4514 * break out too often to avoid losing typeahead. */
4515 gettimeofday(&now_tv, NULL);
4516 msec = (now_tv.tv_sec - start_tv.tv_sec) * 1000L
4517 + (now_tv.tv_usec - start_tv.tv_usec) / 1000L;
4518 if (msec > 2000)
4520 noread_cnt = 5;
4521 break;
4524 # endif
4527 /* If we already detected the child has finished break the
4528 * loop now. */
4529 if (wait_pid == pid)
4530 break;
4533 * Check if the child still exists, before checking for
4534 * typed characters (otherwise we would lose typeahead).
4536 # ifdef __NeXT__
4537 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *) 0);
4538 # else
4539 wait_pid = waitpid(pid, &status, WNOHANG);
4540 # endif
4541 if ((wait_pid == (pid_t)-1 && errno == ECHILD)
4542 || (wait_pid == pid && WIFEXITED(status)))
4544 /* Don't break the loop yet, try reading more
4545 * characters from "fromshell_fd" first. When using
4546 * pipes there might still be something to read and
4547 * then we'll break the loop at the "break" above. */
4548 wait_pid = pid;
4550 else
4551 wait_pid = 0;
4553 finished:
4554 p_more = p_more_save;
4555 if (options & SHELL_READ)
4557 if (ga.ga_len > 0)
4559 append_ga_line(&ga);
4560 /* remember that the NL was missing */
4561 write_no_eol_lnum = curwin->w_cursor.lnum;
4563 else
4564 write_no_eol_lnum = 0;
4565 ga_clear(&ga);
4569 * Give all typeahead that wasn't used back to ui_inchar().
4571 if (ta_len)
4572 ui_inchar_undo(ta_buf, ta_len);
4573 State = old_State;
4574 if (toshell_fd >= 0)
4575 close(toshell_fd);
4576 close(fromshell_fd);
4580 * Wait until our child has exited.
4581 * Ignore wait() returning pids of other children and returning
4582 * because of some signal like SIGWINCH.
4583 * Don't wait if wait_pid was already set above, indicating the
4584 * child already exited.
4586 while (wait_pid != pid)
4588 # ifdef _THREAD_SAFE
4589 /* Ugly hack: when compiled with Python threads are probably
4590 * used, in which case wait() sometimes hangs for no obvious
4591 * reason. Use waitpid() instead and loop (like the GUI). */
4592 # ifdef __NeXT__
4593 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0);
4594 # else
4595 wait_pid = waitpid(pid, &status, WNOHANG);
4596 # endif
4597 if (wait_pid == 0)
4599 /* Wait for 1/100 sec before trying again. */
4600 mch_delay(10L, TRUE);
4601 continue;
4603 # else
4604 wait_pid = wait(&status);
4605 # endif
4606 if (wait_pid <= 0
4607 # ifdef ECHILD
4608 && errno == ECHILD
4609 # endif
4611 break;
4614 /* Make sure the child that writes to the external program is
4615 * dead. */
4616 if (wpid > 0)
4617 kill(wpid, SIGKILL);
4620 * Set to raw mode right now, otherwise a CTRL-C after
4621 * catch_signals() will kill Vim.
4623 if (tmode == TMODE_RAW)
4624 settmode(TMODE_RAW);
4625 did_settmode = TRUE;
4626 set_signals();
4628 if (WIFEXITED(status))
4630 /* LINTED avoid "bitwise operation on signed value" */
4631 retval = WEXITSTATUS(status);
4632 if (retval && !emsg_silent)
4634 if (retval == EXEC_FAILED)
4636 MSG_PUTS(_("\nCannot execute shell "));
4637 msg_outtrans(p_sh);
4638 msg_putchar('\n');
4640 else if (!(options & SHELL_SILENT))
4642 MSG_PUTS(_("\nshell returned "));
4643 msg_outnum((long)retval);
4644 msg_putchar('\n');
4648 else
4649 MSG_PUTS(_("\nCommand terminated\n"));
4652 vim_free(argv);
4654 error:
4655 if (!did_settmode)
4656 if (tmode == TMODE_RAW)
4657 settmode(TMODE_RAW); /* set to raw mode */
4658 # ifdef FEAT_TITLE
4659 resettitle();
4660 # endif
4661 vim_free(newcmd);
4663 return retval;
4665 #endif /* USE_SYSTEM */
4669 * Check for CTRL-C typed by reading all available characters.
4670 * In cooked mode we should get SIGINT, no need to check.
4672 void
4673 mch_breakcheck()
4675 if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL))
4676 fill_input_buf(FALSE);
4680 * Wait "msec" msec until a character is available from the keyboard or from
4681 * inbuf[]. msec == -1 will block forever.
4682 * When a GUI is being used, this will never get called -- webb
4684 static int
4685 WaitForChar(msec)
4686 long msec;
4688 #ifdef FEAT_MOUSE_GPM
4689 int gpm_process_wanted;
4690 #endif
4691 #ifdef FEAT_XCLIPBOARD
4692 int rest;
4693 #endif
4694 int avail;
4696 if (input_available()) /* something in inbuf[] */
4697 return 1;
4699 #if defined(FEAT_MOUSE_DEC)
4700 /* May need to query the mouse position. */
4701 if (WantQueryMouse)
4703 WantQueryMouse = FALSE;
4704 mch_write((char_u *)IF_EB("\033[1'|", ESC_STR "[1'|"), 5);
4706 #endif
4709 * For FEAT_MOUSE_GPM and FEAT_XCLIPBOARD we loop here to process mouse
4710 * events. This is a bit complicated, because they might both be defined.
4712 #if defined(FEAT_MOUSE_GPM) || defined(FEAT_XCLIPBOARD)
4713 # ifdef FEAT_XCLIPBOARD
4714 rest = 0;
4715 if (do_xterm_trace())
4716 rest = msec;
4717 # endif
4720 # ifdef FEAT_XCLIPBOARD
4721 if (rest != 0)
4723 msec = XT_TRACE_DELAY;
4724 if (rest >= 0 && rest < XT_TRACE_DELAY)
4725 msec = rest;
4726 if (rest >= 0)
4727 rest -= msec;
4729 # endif
4730 # ifdef FEAT_MOUSE_GPM
4731 gpm_process_wanted = 0;
4732 avail = RealWaitForChar(read_cmd_fd, msec, &gpm_process_wanted);
4733 # else
4734 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4735 # endif
4736 if (!avail)
4738 if (input_available())
4739 return 1;
4740 # ifdef FEAT_XCLIPBOARD
4741 if (rest == 0 || !do_xterm_trace())
4742 # endif
4743 break;
4746 while (FALSE
4747 # ifdef FEAT_MOUSE_GPM
4748 || (gpm_process_wanted && mch_gpm_process() == 0)
4749 # endif
4750 # ifdef FEAT_XCLIPBOARD
4751 || (!avail && rest != 0)
4752 # endif
4755 #else
4756 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4757 #endif
4758 return avail;
4762 * Wait "msec" msec until a character is available from file descriptor "fd".
4763 * Time == -1 will block forever.
4764 * When a GUI is being used, this will not be used for input -- webb
4765 * Returns also, when a request from Sniff is waiting -- toni.
4766 * Or when a Linux GPM mouse event is waiting.
4768 #if defined(__BEOS__)
4770 #else
4771 static int
4772 #endif
4773 RealWaitForChar(fd, msec, check_for_gpm)
4774 int fd;
4775 long msec;
4776 int *check_for_gpm UNUSED;
4778 int ret;
4779 #if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4780 static int busy = FALSE;
4782 /* May retry getting characters after an event was handled. */
4783 # define MAY_LOOP
4785 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4786 /* Remember at what time we started, so that we know how much longer we
4787 * should wait after being interrupted. */
4788 # define USE_START_TV
4789 struct timeval start_tv;
4791 if (msec > 0 && (
4792 # ifdef FEAT_XCLIPBOARD
4793 xterm_Shell != (Widget)0
4794 # if defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4796 # endif
4797 # endif
4798 # ifdef USE_XSMP
4799 xsmp_icefd != -1
4800 # ifdef FEAT_MZSCHEME
4802 # endif
4803 # endif
4804 # ifdef FEAT_MZSCHEME
4805 (mzthreads_allowed() && p_mzq > 0)
4806 # endif
4808 gettimeofday(&start_tv, NULL);
4809 # endif
4811 /* Handle being called recursively. This may happen for the session
4812 * manager stuff, it may save the file, which does a breakcheck. */
4813 if (busy)
4814 return 0;
4815 #endif
4817 #ifdef MAY_LOOP
4818 for (;;)
4819 #endif
4821 #ifdef MAY_LOOP
4822 int finished = TRUE; /* default is to 'loop' just once */
4823 # ifdef FEAT_MZSCHEME
4824 int mzquantum_used = FALSE;
4825 # endif
4826 #endif
4827 #ifndef HAVE_SELECT
4828 struct pollfd fds[5];
4829 int nfd;
4830 # ifdef FEAT_XCLIPBOARD
4831 int xterm_idx = -1;
4832 # endif
4833 # ifdef FEAT_MOUSE_GPM
4834 int gpm_idx = -1;
4835 # endif
4836 # ifdef USE_XSMP
4837 int xsmp_idx = -1;
4838 # endif
4839 int towait = (int)msec;
4841 # ifdef FEAT_MZSCHEME
4842 mzvim_check_threads();
4843 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4845 towait = (int)p_mzq; /* don't wait longer than 'mzquantum' */
4846 mzquantum_used = TRUE;
4848 # endif
4849 fds[0].fd = fd;
4850 fds[0].events = POLLIN;
4851 nfd = 1;
4853 # ifdef FEAT_SNIFF
4854 # define SNIFF_IDX 1
4855 if (want_sniff_request)
4857 fds[SNIFF_IDX].fd = fd_from_sniff;
4858 fds[SNIFF_IDX].events = POLLIN;
4859 nfd++;
4861 # endif
4862 # ifdef FEAT_XCLIPBOARD
4863 if (xterm_Shell != (Widget)0)
4865 xterm_idx = nfd;
4866 fds[nfd].fd = ConnectionNumber(xterm_dpy);
4867 fds[nfd].events = POLLIN;
4868 nfd++;
4870 # endif
4871 # ifdef FEAT_MOUSE_GPM
4872 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4874 gpm_idx = nfd;
4875 fds[nfd].fd = gpm_fd;
4876 fds[nfd].events = POLLIN;
4877 nfd++;
4879 # endif
4880 # ifdef USE_XSMP
4881 if (xsmp_icefd != -1)
4883 xsmp_idx = nfd;
4884 fds[nfd].fd = xsmp_icefd;
4885 fds[nfd].events = POLLIN;
4886 nfd++;
4888 # endif
4890 ret = poll(fds, nfd, towait);
4891 # ifdef FEAT_MZSCHEME
4892 if (ret == 0 && mzquantum_used)
4893 /* MzThreads scheduling is required and timeout occurred */
4894 finished = FALSE;
4895 # endif
4897 # ifdef FEAT_SNIFF
4898 if (ret < 0)
4899 sniff_disconnect(1);
4900 else if (want_sniff_request)
4902 if (fds[SNIFF_IDX].revents & POLLHUP)
4903 sniff_disconnect(1);
4904 if (fds[SNIFF_IDX].revents & POLLIN)
4905 sniff_request_waiting = 1;
4907 # endif
4908 # ifdef FEAT_XCLIPBOARD
4909 if (xterm_Shell != (Widget)0 && (fds[xterm_idx].revents & POLLIN))
4911 xterm_update(); /* Maybe we should hand out clipboard */
4912 if (--ret == 0 && !input_available())
4913 /* Try again */
4914 finished = FALSE;
4916 # endif
4917 # ifdef FEAT_MOUSE_GPM
4918 if (gpm_idx >= 0 && (fds[gpm_idx].revents & POLLIN))
4920 *check_for_gpm = 1;
4922 # endif
4923 # ifdef USE_XSMP
4924 if (xsmp_idx >= 0 && (fds[xsmp_idx].revents & (POLLIN | POLLHUP)))
4926 if (fds[xsmp_idx].revents & POLLIN)
4928 busy = TRUE;
4929 xsmp_handle_requests();
4930 busy = FALSE;
4932 else if (fds[xsmp_idx].revents & POLLHUP)
4934 if (p_verbose > 0)
4935 verb_msg((char_u *)_("XSMP lost ICE connection"));
4936 xsmp_close();
4938 if (--ret == 0)
4939 finished = FALSE; /* Try again */
4941 # endif
4944 #else /* HAVE_SELECT */
4946 struct timeval tv;
4947 struct timeval *tvp;
4948 fd_set rfds, efds;
4949 int maxfd;
4950 long towait = msec;
4952 # ifdef FEAT_MZSCHEME
4953 mzvim_check_threads();
4954 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4956 towait = p_mzq; /* don't wait longer than 'mzquantum' */
4957 mzquantum_used = TRUE;
4959 # endif
4960 # ifdef __EMX__
4961 /* don't check for incoming chars if not in raw mode, because select()
4962 * always returns TRUE then (in some version of emx.dll) */
4963 if (curr_tmode != TMODE_RAW)
4964 return 0;
4965 # endif
4967 if (towait >= 0)
4969 tv.tv_sec = towait / 1000;
4970 tv.tv_usec = (towait % 1000) * (1000000/1000);
4971 tvp = &tv;
4973 else
4974 tvp = NULL;
4977 * Select on ready for reading and exceptional condition (end of file).
4979 FD_ZERO(&rfds); /* calls bzero() on a sun */
4980 FD_ZERO(&efds);
4981 FD_SET(fd, &rfds);
4982 # if !defined(__QNX__) && !defined(__CYGWIN32__)
4983 /* For QNX select() always returns 1 if this is set. Why? */
4984 FD_SET(fd, &efds);
4985 # endif
4986 maxfd = fd;
4988 # ifdef FEAT_SNIFF
4989 if (want_sniff_request)
4991 FD_SET(fd_from_sniff, &rfds);
4992 FD_SET(fd_from_sniff, &efds);
4993 if (maxfd < fd_from_sniff)
4994 maxfd = fd_from_sniff;
4996 # endif
4997 # ifdef FEAT_XCLIPBOARD
4998 if (xterm_Shell != (Widget)0)
5000 FD_SET(ConnectionNumber(xterm_dpy), &rfds);
5001 if (maxfd < ConnectionNumber(xterm_dpy))
5002 maxfd = ConnectionNumber(xterm_dpy);
5004 # endif
5005 # ifdef FEAT_MOUSE_GPM
5006 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
5008 FD_SET(gpm_fd, &rfds);
5009 FD_SET(gpm_fd, &efds);
5010 if (maxfd < gpm_fd)
5011 maxfd = gpm_fd;
5013 # endif
5014 # ifdef USE_XSMP
5015 if (xsmp_icefd != -1)
5017 FD_SET(xsmp_icefd, &rfds);
5018 FD_SET(xsmp_icefd, &efds);
5019 if (maxfd < xsmp_icefd)
5020 maxfd = xsmp_icefd;
5022 # endif
5024 # ifdef OLD_VMS
5025 /* Old VMS as v6.2 and older have broken select(). It waits more than
5026 * required. Should not be used */
5027 ret = 0;
5028 # else
5029 ret = select(maxfd + 1, &rfds, NULL, &efds, tvp);
5030 # endif
5031 # ifdef __TANDEM
5032 if (ret == -1 && errno == ENOTSUP)
5034 FD_ZERO(&rfds);
5035 FD_ZERO(&efds);
5036 ret = 0;
5038 #endif
5039 # ifdef FEAT_MZSCHEME
5040 if (ret == 0 && mzquantum_used)
5041 /* loop if MzThreads must be scheduled and timeout occurred */
5042 finished = FALSE;
5043 # endif
5045 # ifdef FEAT_SNIFF
5046 if (ret < 0 )
5047 sniff_disconnect(1);
5048 else if (ret > 0 && want_sniff_request)
5050 if (FD_ISSET(fd_from_sniff, &efds))
5051 sniff_disconnect(1);
5052 if (FD_ISSET(fd_from_sniff, &rfds))
5053 sniff_request_waiting = 1;
5055 # endif
5056 # ifdef FEAT_XCLIPBOARD
5057 if (ret > 0 && xterm_Shell != (Widget)0
5058 && FD_ISSET(ConnectionNumber(xterm_dpy), &rfds))
5060 xterm_update(); /* Maybe we should hand out clipboard */
5061 /* continue looping when we only got the X event and the input
5062 * buffer is empty */
5063 if (--ret == 0 && !input_available())
5065 /* Try again */
5066 finished = FALSE;
5069 # endif
5070 # ifdef FEAT_MOUSE_GPM
5071 if (ret > 0 && gpm_flag && check_for_gpm != NULL && gpm_fd >= 0)
5073 if (FD_ISSET(gpm_fd, &efds))
5074 gpm_close();
5075 else if (FD_ISSET(gpm_fd, &rfds))
5076 *check_for_gpm = 1;
5078 # endif
5079 # ifdef USE_XSMP
5080 if (ret > 0 && xsmp_icefd != -1)
5082 if (FD_ISSET(xsmp_icefd, &efds))
5084 if (p_verbose > 0)
5085 verb_msg((char_u *)_("XSMP lost ICE connection"));
5086 xsmp_close();
5087 if (--ret == 0)
5088 finished = FALSE; /* keep going if event was only one */
5090 else if (FD_ISSET(xsmp_icefd, &rfds))
5092 busy = TRUE;
5093 xsmp_handle_requests();
5094 busy = FALSE;
5095 if (--ret == 0)
5096 finished = FALSE; /* keep going if event was only one */
5099 # endif
5101 #endif /* HAVE_SELECT */
5103 #ifdef MAY_LOOP
5104 if (finished || msec == 0)
5105 break;
5107 /* We're going to loop around again, find out for how long */
5108 if (msec > 0)
5110 # ifdef USE_START_TV
5111 struct timeval mtv;
5113 /* Compute remaining wait time. */
5114 gettimeofday(&mtv, NULL);
5115 msec -= (mtv.tv_sec - start_tv.tv_sec) * 1000L
5116 + (mtv.tv_usec - start_tv.tv_usec) / 1000L;
5117 # else
5118 /* Guess we got interrupted halfway. */
5119 msec = msec / 2;
5120 # endif
5121 if (msec <= 0)
5122 break; /* waited long enough */
5124 #endif
5127 return (ret > 0);
5130 #ifndef VMS
5132 #ifndef NO_EXPANDPATH
5134 * Expand a path into all matching files and/or directories. Handles "*",
5135 * "?", "[a-z]", "**", etc.
5136 * "path" has backslashes before chars that are not to be expanded.
5137 * Returns the number of matches found.
5140 mch_expandpath(gap, path, flags)
5141 garray_T *gap;
5142 char_u *path;
5143 int flags; /* EW_* flags */
5145 return unix_expandpath(gap, path, 0, flags, FALSE);
5147 #endif
5150 * mch_expand_wildcards() - this code does wild-card pattern matching using
5151 * the shell
5153 * return OK for success, FAIL for error (you may lose some memory) and put
5154 * an error message in *file.
5156 * num_pat is number of input patterns
5157 * pat is array of pointers to input patterns
5158 * num_file is pointer to number of matched file names
5159 * file is pointer to array of pointers to matched file names
5162 #ifndef SEEK_SET
5163 # define SEEK_SET 0
5164 #endif
5165 #ifndef SEEK_END
5166 # define SEEK_END 2
5167 #endif
5169 #define SHELL_SPECIAL (char_u *)"\t \"&'$;<>()\\|"
5172 mch_expand_wildcards(num_pat, pat, num_file, file, flags)
5173 int num_pat;
5174 char_u **pat;
5175 int *num_file;
5176 char_u ***file;
5177 int flags; /* EW_* flags */
5179 int i;
5180 size_t len;
5181 char_u *p;
5182 int dir;
5183 #ifdef __EMX__
5185 * This is the OS/2 implementation.
5187 # define EXPL_ALLOC_INC 16
5188 char_u **expl_files;
5189 size_t files_alloced, files_free;
5190 char_u *buf;
5191 int has_wildcard;
5193 *num_file = 0; /* default: no files found */
5194 files_alloced = EXPL_ALLOC_INC; /* how much space is allocated */
5195 files_free = EXPL_ALLOC_INC; /* how much space is not used */
5196 *file = (char_u **)alloc(sizeof(char_u **) * files_alloced);
5197 if (*file == NULL)
5198 return FAIL;
5200 for (; num_pat > 0; num_pat--, pat++)
5202 expl_files = NULL;
5203 if (vim_strchr(*pat, '$') || vim_strchr(*pat, '~'))
5204 /* expand environment var or home dir */
5205 buf = expand_env_save(*pat);
5206 else
5207 buf = vim_strsave(*pat);
5208 expl_files = NULL;
5209 has_wildcard = mch_has_exp_wildcard(buf); /* (still) wildcards? */
5210 if (has_wildcard) /* yes, so expand them */
5211 expl_files = (char_u **)_fnexplode(buf);
5214 * return value of buf if no wildcards left,
5215 * OR if no match AND EW_NOTFOUND is set.
5217 if ((!has_wildcard && ((flags & EW_NOTFOUND) || mch_getperm(buf) >= 0))
5218 || (expl_files == NULL && (flags & EW_NOTFOUND)))
5219 { /* simply save the current contents of *buf */
5220 expl_files = (char_u **)alloc(sizeof(char_u **) * 2);
5221 if (expl_files != NULL)
5223 expl_files[0] = vim_strsave(buf);
5224 expl_files[1] = NULL;
5227 vim_free(buf);
5230 * Count number of names resulting from expansion,
5231 * At the same time add a backslash to the end of names that happen to
5232 * be directories, and replace slashes with backslashes.
5234 if (expl_files)
5236 for (i = 0; (p = expl_files[i]) != NULL; i++)
5238 dir = mch_isdir(p);
5239 /* If we don't want dirs and this is one, skip it */
5240 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5241 continue;
5243 /* Skip files that are not executable if we check for that. */
5244 if (!dir && (flags & EW_EXEC) && !mch_can_exe(p))
5245 continue;
5247 if (--files_free == 0)
5249 /* need more room in table of pointers */
5250 files_alloced += EXPL_ALLOC_INC;
5251 *file = (char_u **)vim_realloc(*file,
5252 sizeof(char_u **) * files_alloced);
5253 if (*file == NULL)
5255 EMSG(_(e_outofmem));
5256 *num_file = 0;
5257 return FAIL;
5259 files_free = EXPL_ALLOC_INC;
5261 slash_adjust(p);
5262 if (dir)
5264 /* For a directory we add a '/', unless it's already
5265 * there. */
5266 len = STRLEN(p);
5267 if (((*file)[*num_file] = alloc(len + 2)) != NULL)
5269 STRCPY((*file)[*num_file], p);
5270 if (!after_pathsep((*file)[*num_file],
5271 (*file)[*num_file] + len))
5273 (*file)[*num_file][len] = psepc;
5274 (*file)[*num_file][len + 1] = NUL;
5278 else
5280 (*file)[*num_file] = vim_strsave(p);
5284 * Error message already given by either alloc or vim_strsave.
5285 * Should return FAIL, but returning OK works also.
5287 if ((*file)[*num_file] == NULL)
5288 break;
5289 (*num_file)++;
5291 _fnexplodefree((char **)expl_files);
5294 return OK;
5296 #else /* __EMX__ */
5298 * This is the non-OS/2 implementation (really Unix).
5300 int j;
5301 char_u *tempname;
5302 char_u *command;
5303 FILE *fd;
5304 char_u *buffer;
5305 #define STYLE_ECHO 0 /* use "echo", the default */
5306 #define STYLE_GLOB 1 /* use "glob", for csh */
5307 #define STYLE_VIMGLOB 2 /* use "vimglob", for Posix sh */
5308 #define STYLE_PRINT 3 /* use "print -N", for zsh */
5309 #define STYLE_BT 4 /* `cmd` expansion, execute the pattern
5310 * directly */
5311 int shell_style = STYLE_ECHO;
5312 int check_spaces;
5313 static int did_find_nul = FALSE;
5314 int ampersent = FALSE;
5315 /* vimglob() function to define for Posix shell */
5316 static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >";
5318 *num_file = 0; /* default: no files found */
5319 *file = NULL;
5322 * If there are no wildcards, just copy the names to allocated memory.
5323 * Saves a lot of time, because we don't have to start a new shell.
5325 if (!have_wildcard(num_pat, pat))
5326 return save_patterns(num_pat, pat, num_file, file);
5328 # ifdef HAVE_SANDBOX
5329 /* Don't allow any shell command in the sandbox. */
5330 if (sandbox != 0 && check_secure())
5331 return FAIL;
5332 # endif
5335 * Don't allow the use of backticks in secure and restricted mode.
5337 if (secure || restricted)
5338 for (i = 0; i < num_pat; ++i)
5339 if (vim_strchr(pat[i], '`') != NULL
5340 && (check_restricted() || check_secure()))
5341 return FAIL;
5344 * get a name for the temp file
5346 if ((tempname = vim_tempname('o')) == NULL)
5348 EMSG(_(e_notmp));
5349 return FAIL;
5353 * Let the shell expand the patterns and write the result into the temp
5354 * file.
5355 * STYLE_BT: NL separated
5356 * If expanding `cmd` execute it directly.
5357 * STYLE_GLOB: NUL separated
5358 * If we use *csh, "glob" will work better than "echo".
5359 * STYLE_PRINT: NL or NUL separated
5360 * If we use *zsh, "print -N" will work better than "glob".
5361 * STYLE_VIMGLOB: NL separated
5362 * If we use *sh*, we define "vimglob()".
5363 * STYLE_ECHO: space separated.
5364 * A shell we don't know, stay safe and use "echo".
5366 if (num_pat == 1 && *pat[0] == '`'
5367 && (len = STRLEN(pat[0])) > 2
5368 && *(pat[0] + len - 1) == '`')
5369 shell_style = STYLE_BT;
5370 else if ((len = STRLEN(p_sh)) >= 3)
5372 if (STRCMP(p_sh + len - 3, "csh") == 0)
5373 shell_style = STYLE_GLOB;
5374 else if (STRCMP(p_sh + len - 3, "zsh") == 0)
5375 shell_style = STYLE_PRINT;
5377 if (shell_style == STYLE_ECHO && strstr((char *)gettail(p_sh),
5378 "sh") != NULL)
5379 shell_style = STYLE_VIMGLOB;
5381 /* Compute the length of the command. We need 2 extra bytes: for the
5382 * optional '&' and for the NUL.
5383 * Worst case: "unset nonomatch; print -N >" plus two is 29 */
5384 len = STRLEN(tempname) + 29;
5385 if (shell_style == STYLE_VIMGLOB)
5386 len += STRLEN(sh_vimglob_func);
5388 for (i = 0; i < num_pat; ++i)
5390 /* Count the length of the patterns in the same way as they are put in
5391 * "command" below. */
5392 #ifdef USE_SYSTEM
5393 len += STRLEN(pat[i]) + 3; /* add space and two quotes */
5394 #else
5395 ++len; /* add space */
5396 for (j = 0; pat[i][j] != NUL; ++j)
5398 if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL)
5399 ++len; /* may add a backslash */
5400 ++len;
5402 #endif
5404 command = alloc(len);
5405 if (command == NULL)
5407 /* out of memory */
5408 vim_free(tempname);
5409 return FAIL;
5413 * Build the shell command:
5414 * - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell
5415 * recognizes this).
5416 * - Add the shell command to print the expanded names.
5417 * - Add the temp file name.
5418 * - Add the file name patterns.
5420 if (shell_style == STYLE_BT)
5422 /* change `command; command& ` to (command; command ) */
5423 STRCPY(command, "(");
5424 STRCAT(command, pat[0] + 1); /* exclude first backtick */
5425 p = command + STRLEN(command) - 1;
5426 *p-- = ')'; /* remove last backtick */
5427 while (p > command && vim_iswhite(*p))
5428 --p;
5429 if (*p == '&') /* remove trailing '&' */
5431 ampersent = TRUE;
5432 *p = ' ';
5434 STRCAT(command, ">");
5436 else
5438 if (flags & EW_NOTFOUND)
5439 STRCPY(command, "set nonomatch; ");
5440 else
5441 STRCPY(command, "unset nonomatch; ");
5442 if (shell_style == STYLE_GLOB)
5443 STRCAT(command, "glob >");
5444 else if (shell_style == STYLE_PRINT)
5445 STRCAT(command, "print -N >");
5446 else if (shell_style == STYLE_VIMGLOB)
5447 STRCAT(command, sh_vimglob_func);
5448 else
5449 STRCAT(command, "echo >");
5452 STRCAT(command, tempname);
5454 if (shell_style != STYLE_BT)
5455 for (i = 0; i < num_pat; ++i)
5457 /* When using system() always add extra quotes, because the shell
5458 * is started twice. Otherwise put a backslash before special
5459 * characters, except inside ``. */
5460 #ifdef USE_SYSTEM
5461 STRCAT(command, " \"");
5462 STRCAT(command, pat[i]);
5463 STRCAT(command, "\"");
5464 #else
5465 int intick = FALSE;
5467 p = command + STRLEN(command);
5468 *p++ = ' ';
5469 for (j = 0; pat[i][j] != NUL; ++j)
5471 if (pat[i][j] == '`')
5472 intick = !intick;
5473 else if (pat[i][j] == '\\' && pat[i][j + 1] != NUL)
5475 /* Remove a backslash, take char literally. But keep
5476 * backslash inside backticks, before a special character
5477 * and before a backtick. */
5478 if (intick
5479 || vim_strchr(SHELL_SPECIAL, pat[i][j + 1]) != NULL
5480 || pat[i][j + 1] == '`')
5481 *p++ = '\\';
5482 ++j;
5484 else if (!intick && vim_strchr(SHELL_SPECIAL,
5485 pat[i][j]) != NULL)
5486 /* Put a backslash before a special character, but not
5487 * when inside ``. */
5488 *p++ = '\\';
5490 /* Copy one character. */
5491 *p++ = pat[i][j];
5493 *p = NUL;
5494 #endif
5496 if (flags & EW_SILENT)
5497 show_shell_mess = FALSE;
5498 if (ampersent)
5499 STRCAT(command, "&"); /* put the '&' after the redirection */
5502 * Using zsh -G: If a pattern has no matches, it is just deleted from
5503 * the argument list, otherwise zsh gives an error message and doesn't
5504 * expand any other pattern.
5506 if (shell_style == STYLE_PRINT)
5507 extra_shell_arg = (char_u *)"-G"; /* Use zsh NULL_GLOB option */
5510 * If we use -f then shell variables set in .cshrc won't get expanded.
5511 * vi can do it, so we will too, but it is only necessary if there is a "$"
5512 * in one of the patterns, otherwise we can still use the fast option.
5514 else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat))
5515 extra_shell_arg = (char_u *)"-f"; /* Use csh fast option */
5518 * execute the shell command
5520 i = call_shell(command, SHELL_EXPAND | SHELL_SILENT);
5522 /* When running in the background, give it some time to create the temp
5523 * file, but don't wait for it to finish. */
5524 if (ampersent)
5525 mch_delay(10L, TRUE);
5527 extra_shell_arg = NULL; /* cleanup */
5528 show_shell_mess = TRUE;
5529 vim_free(command);
5531 if (i != 0) /* mch_call_shell() failed */
5533 mch_remove(tempname);
5534 vim_free(tempname);
5536 * With interactive completion, the error message is not printed.
5537 * However with USE_SYSTEM, I don't know how to turn off error messages
5538 * from the shell, so screen may still get messed up -- webb.
5540 #ifndef USE_SYSTEM
5541 if (!(flags & EW_SILENT))
5542 #endif
5544 redraw_later_clear(); /* probably messed up screen */
5545 msg_putchar('\n'); /* clear bottom line quickly */
5546 cmdline_row = Rows - 1; /* continue on last line */
5547 #ifdef USE_SYSTEM
5548 if (!(flags & EW_SILENT))
5549 #endif
5551 MSG(_(e_wildexpand));
5552 msg_start(); /* don't overwrite this message */
5555 /* If a `cmd` expansion failed, don't list `cmd` as a match, even when
5556 * EW_NOTFOUND is given */
5557 if (shell_style == STYLE_BT)
5558 return FAIL;
5559 goto notfound;
5563 * read the names from the file into memory
5565 fd = fopen((char *)tempname, READBIN);
5566 if (fd == NULL)
5568 /* Something went wrong, perhaps a file name with a special char. */
5569 if (!(flags & EW_SILENT))
5571 MSG(_(e_wildexpand));
5572 msg_start(); /* don't overwrite this message */
5574 vim_free(tempname);
5575 goto notfound;
5577 fseek(fd, 0L, SEEK_END);
5578 len = ftell(fd); /* get size of temp file */
5579 fseek(fd, 0L, SEEK_SET);
5580 buffer = alloc(len + 1);
5581 if (buffer == NULL)
5583 /* out of memory */
5584 mch_remove(tempname);
5585 vim_free(tempname);
5586 fclose(fd);
5587 return FAIL;
5589 i = fread((char *)buffer, 1, len, fd);
5590 fclose(fd);
5591 mch_remove(tempname);
5592 if (i != (int)len)
5594 /* unexpected read error */
5595 EMSG2(_(e_notread), tempname);
5596 vim_free(tempname);
5597 vim_free(buffer);
5598 return FAIL;
5600 vim_free(tempname);
5602 # if defined(__CYGWIN__) || defined(__CYGWIN32__)
5603 /* Translate <CR><NL> into <NL>. Caution, buffer may contain NUL. */
5604 p = buffer;
5605 for (i = 0; i < len; ++i)
5606 if (!(buffer[i] == CAR && buffer[i + 1] == NL))
5607 *p++ = buffer[i];
5608 len = p - buffer;
5609 # endif
5612 /* file names are separated with Space */
5613 if (shell_style == STYLE_ECHO)
5615 buffer[len] = '\n'; /* make sure the buffer ends in NL */
5616 p = buffer;
5617 for (i = 0; *p != '\n'; ++i) /* count number of entries */
5619 while (*p != ' ' && *p != '\n')
5620 ++p;
5621 p = skipwhite(p); /* skip to next entry */
5624 /* file names are separated with NL */
5625 else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB)
5627 buffer[len] = NUL; /* make sure the buffer ends in NUL */
5628 p = buffer;
5629 for (i = 0; *p != NUL; ++i) /* count number of entries */
5631 while (*p != '\n' && *p != NUL)
5632 ++p;
5633 if (*p != NUL)
5634 ++p;
5635 p = skipwhite(p); /* skip leading white space */
5638 /* file names are separated with NUL */
5639 else
5642 * Some versions of zsh use spaces instead of NULs to separate
5643 * results. Only do this when there is no NUL before the end of the
5644 * buffer, otherwise we would never be able to use file names with
5645 * embedded spaces when zsh does use NULs.
5646 * When we found a NUL once, we know zsh is OK, set did_find_nul and
5647 * don't check for spaces again.
5649 check_spaces = FALSE;
5650 if (shell_style == STYLE_PRINT && !did_find_nul)
5652 /* If there is a NUL, set did_find_nul, else set check_spaces */
5653 if (len && (int)STRLEN(buffer) < (int)len - 1)
5654 did_find_nul = TRUE;
5655 else
5656 check_spaces = TRUE;
5660 * Make sure the buffer ends with a NUL. For STYLE_PRINT there
5661 * already is one, for STYLE_GLOB it needs to be added.
5663 if (len && buffer[len - 1] == NUL)
5664 --len;
5665 else
5666 buffer[len] = NUL;
5667 i = 0;
5668 for (p = buffer; p < buffer + len; ++p)
5669 if (*p == NUL || (*p == ' ' && check_spaces)) /* count entry */
5671 ++i;
5672 *p = NUL;
5674 if (len)
5675 ++i; /* count last entry */
5677 if (i == 0)
5680 * Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I".
5681 * /bin/sh will happily expand it to nothing rather than returning an
5682 * error; and hey, it's good to check anyway -- webb.
5684 vim_free(buffer);
5685 goto notfound;
5687 *num_file = i;
5688 *file = (char_u **)alloc(sizeof(char_u *) * i);
5689 if (*file == NULL)
5691 /* out of memory */
5692 vim_free(buffer);
5693 return FAIL;
5697 * Isolate the individual file names.
5699 p = buffer;
5700 for (i = 0; i < *num_file; ++i)
5702 (*file)[i] = p;
5703 /* Space or NL separates */
5704 if (shell_style == STYLE_ECHO || shell_style == STYLE_BT
5705 || shell_style == STYLE_VIMGLOB)
5707 while (!(shell_style == STYLE_ECHO && *p == ' ')
5708 && *p != '\n' && *p != NUL)
5709 ++p;
5710 if (p == buffer + len) /* last entry */
5711 *p = NUL;
5712 else
5714 *p++ = NUL;
5715 p = skipwhite(p); /* skip to next entry */
5718 else /* NUL separates */
5720 while (*p && p < buffer + len) /* skip entry */
5721 ++p;
5722 ++p; /* skip NUL */
5727 * Move the file names to allocated memory.
5729 for (j = 0, i = 0; i < *num_file; ++i)
5731 /* Require the files to exist. Helps when using /bin/sh */
5732 if (!(flags & EW_NOTFOUND) && mch_getperm((*file)[i]) < 0)
5733 continue;
5735 /* check if this entry should be included */
5736 dir = (mch_isdir((*file)[i]));
5737 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5738 continue;
5740 /* Skip files that are not executable if we check for that. */
5741 if (!dir && (flags & EW_EXEC) && !mch_can_exe((*file)[i]))
5742 continue;
5744 p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir));
5745 if (p)
5747 STRCPY(p, (*file)[i]);
5748 if (dir)
5749 add_pathsep(p); /* add '/' to a directory name */
5750 (*file)[j++] = p;
5753 vim_free(buffer);
5754 *num_file = j;
5756 if (*num_file == 0) /* rejected all entries */
5758 vim_free(*file);
5759 *file = NULL;
5760 goto notfound;
5763 return OK;
5765 notfound:
5766 if (flags & EW_NOTFOUND)
5767 return save_patterns(num_pat, pat, num_file, file);
5768 return FAIL;
5770 #endif /* __EMX__ */
5773 #endif /* VMS */
5775 #ifndef __EMX__
5776 static int
5777 save_patterns(num_pat, pat, num_file, file)
5778 int num_pat;
5779 char_u **pat;
5780 int *num_file;
5781 char_u ***file;
5783 int i;
5784 char_u *s;
5786 *file = (char_u **)alloc(num_pat * sizeof(char_u *));
5787 if (*file == NULL)
5788 return FAIL;
5789 for (i = 0; i < num_pat; i++)
5791 s = vim_strsave(pat[i]);
5792 if (s != NULL)
5793 /* Be compatible with expand_filename(): halve the number of
5794 * backslashes. */
5795 backslash_halve(s);
5796 (*file)[i] = s;
5798 *num_file = num_pat;
5799 return OK;
5801 #endif
5805 * Return TRUE if the string "p" contains a wildcard that mch_expandpath() can
5806 * expand.
5809 mch_has_exp_wildcard(p)
5810 char_u *p;
5812 for ( ; *p; mb_ptr_adv(p))
5814 #ifndef OS2
5815 if (*p == '\\' && p[1] != NUL)
5816 ++p;
5817 else
5818 #endif
5819 if (vim_strchr((char_u *)
5820 #ifdef VMS
5821 "*?%"
5822 #else
5823 # ifdef OS2
5824 "*?"
5825 # else
5826 "*?[{'"
5827 # endif
5828 #endif
5829 , *p) != NULL)
5830 return TRUE;
5832 return FALSE;
5836 * Return TRUE if the string "p" contains a wildcard.
5837 * Don't recognize '~' at the end as a wildcard.
5840 mch_has_wildcard(p)
5841 char_u *p;
5843 for ( ; *p; mb_ptr_adv(p))
5845 #ifndef OS2
5846 if (*p == '\\' && p[1] != NUL)
5847 ++p;
5848 else
5849 #endif
5850 if (vim_strchr((char_u *)
5851 #ifdef VMS
5852 "*?%$"
5853 #else
5854 # ifdef OS2
5855 # ifdef VIM_BACKTICK
5856 "*?$`"
5857 # else
5858 "*?$"
5859 # endif
5860 # else
5861 "*?[{`'$"
5862 # endif
5863 #endif
5864 , *p) != NULL
5865 || (*p == '~' && p[1] != NUL))
5866 return TRUE;
5868 return FALSE;
5871 #ifndef __EMX__
5872 static int
5873 have_wildcard(num, file)
5874 int num;
5875 char_u **file;
5877 int i;
5879 for (i = 0; i < num; i++)
5880 if (mch_has_wildcard(file[i]))
5881 return 1;
5882 return 0;
5885 static int
5886 have_dollars(num, file)
5887 int num;
5888 char_u **file;
5890 int i;
5892 for (i = 0; i < num; i++)
5893 if (vim_strchr(file[i], '$') != NULL)
5894 return TRUE;
5895 return FALSE;
5897 #endif /* ifndef __EMX__ */
5899 #ifndef HAVE_RENAME
5901 * Scaled-down version of rename(), which is missing in Xenix.
5902 * This version can only move regular files and will fail if the
5903 * destination exists.
5906 mch_rename(src, dest)
5907 const char *src, *dest;
5909 struct stat st;
5911 if (stat(dest, &st) >= 0) /* fail if destination exists */
5912 return -1;
5913 if (link(src, dest) != 0) /* link file to new name */
5914 return -1;
5915 if (mch_remove(src) == 0) /* delete link to old name */
5916 return 0;
5917 return -1;
5919 #endif /* !HAVE_RENAME */
5921 #ifdef FEAT_MOUSE_GPM
5923 * Initializes connection with gpm (if it isn't already opened)
5924 * Return 1 if succeeded (or connection already opened), 0 if failed
5926 static int
5927 gpm_open()
5929 static Gpm_Connect gpm_connect; /* Must it be kept till closing ? */
5931 if (!gpm_flag)
5933 gpm_connect.eventMask = (GPM_UP | GPM_DRAG | GPM_DOWN);
5934 gpm_connect.defaultMask = ~GPM_HARD;
5935 /* Default handling for mouse move*/
5936 gpm_connect.minMod = 0; /* Handle any modifier keys */
5937 gpm_connect.maxMod = 0xffff;
5938 if (Gpm_Open(&gpm_connect, 0) > 0)
5940 /* gpm library tries to handling TSTP causes
5941 * problems. Anyways, we close connection to Gpm whenever
5942 * we are going to suspend or starting an external process
5943 * so we shouldn't have problem with this
5945 # ifdef SIGTSTP
5946 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
5947 # endif
5948 return 1; /* succeed */
5950 if (gpm_fd == -2)
5951 Gpm_Close(); /* We don't want to talk to xterm via gpm */
5952 return 0;
5954 return 1; /* already open */
5958 * Closes connection to gpm
5960 static void
5961 gpm_close()
5963 if (gpm_flag && gpm_fd >= 0) /* if Open */
5964 Gpm_Close();
5967 /* Reads gpm event and adds special keys to input buf. Returns length of
5968 * generated key sequence.
5969 * This function is made after gui_send_mouse_event
5971 static int
5972 mch_gpm_process()
5974 int button;
5975 static Gpm_Event gpm_event;
5976 char_u string[6];
5977 int_u vim_modifiers;
5978 int row,col;
5979 unsigned char buttons_mask;
5980 unsigned char gpm_modifiers;
5981 static unsigned char old_buttons = 0;
5983 Gpm_GetEvent(&gpm_event);
5985 #ifdef FEAT_GUI
5986 /* Don't put events in the input queue now. */
5987 if (hold_gui_events)
5988 return 0;
5989 #endif
5991 row = gpm_event.y - 1;
5992 col = gpm_event.x - 1;
5994 string[0] = ESC; /* Our termcode */
5995 string[1] = 'M';
5996 string[2] = 'G';
5997 switch (GPM_BARE_EVENTS(gpm_event.type))
5999 case GPM_DRAG:
6000 string[3] = MOUSE_DRAG;
6001 break;
6002 case GPM_DOWN:
6003 buttons_mask = gpm_event.buttons & ~old_buttons;
6004 old_buttons = gpm_event.buttons;
6005 switch (buttons_mask)
6007 case GPM_B_LEFT:
6008 button = MOUSE_LEFT;
6009 break;
6010 case GPM_B_MIDDLE:
6011 button = MOUSE_MIDDLE;
6012 break;
6013 case GPM_B_RIGHT:
6014 button = MOUSE_RIGHT;
6015 break;
6016 default:
6017 return 0;
6018 /*Don't know what to do. Can more than one button be
6019 * reported in one event? */
6021 string[3] = (char_u)(button | 0x20);
6022 SET_NUM_MOUSE_CLICKS(string[3], gpm_event.clicks + 1);
6023 break;
6024 case GPM_UP:
6025 string[3] = MOUSE_RELEASE;
6026 old_buttons &= ~gpm_event.buttons;
6027 break;
6028 default:
6029 return 0;
6031 /*This code is based on gui_x11_mouse_cb in gui_x11.c */
6032 gpm_modifiers = gpm_event.modifiers;
6033 vim_modifiers = 0x0;
6034 /* I ignore capslock stats. Aren't we all just hate capslock mixing with
6035 * Vim commands ? Besides, gpm_event.modifiers is unsigned char, and
6036 * K_CAPSSHIFT is defined 8, so it probably isn't even reported
6038 if (gpm_modifiers & ((1 << KG_SHIFT) | (1 << KG_SHIFTR) | (1 << KG_SHIFTL)))
6039 vim_modifiers |= MOUSE_SHIFT;
6041 if (gpm_modifiers & ((1 << KG_CTRL) | (1 << KG_CTRLR) | (1 << KG_CTRLL)))
6042 vim_modifiers |= MOUSE_CTRL;
6043 if (gpm_modifiers & ((1 << KG_ALT) | (1 << KG_ALTGR)))
6044 vim_modifiers |= MOUSE_ALT;
6045 string[3] |= vim_modifiers;
6046 string[4] = (char_u)(col + ' ' + 1);
6047 string[5] = (char_u)(row + ' ' + 1);
6048 add_to_input_buf(string, 6);
6049 return 6;
6051 #endif /* FEAT_MOUSE_GPM */
6053 #ifdef FEAT_SYSMOUSE
6055 * Initialize connection with sysmouse.
6056 * Let virtual console inform us with SIGUSR2 for pending sysmouse
6057 * output, any sysmouse output than will be processed via sig_sysmouse().
6058 * Return OK if succeeded, FAIL if failed.
6060 static int
6061 sysmouse_open()
6063 struct mouse_info mouse;
6065 mouse.operation = MOUSE_MODE;
6066 mouse.u.mode.mode = 0;
6067 mouse.u.mode.signal = SIGUSR2;
6068 if (ioctl(1, CONS_MOUSECTL, &mouse) != -1)
6070 signal(SIGUSR2, (RETSIGTYPE (*)())sig_sysmouse);
6071 mouse.operation = MOUSE_SHOW;
6072 ioctl(1, CONS_MOUSECTL, &mouse);
6073 return OK;
6075 return FAIL;
6079 * Stop processing SIGUSR2 signals, and also make sure that
6080 * virtual console do not send us any sysmouse related signal.
6082 static void
6083 sysmouse_close()
6085 struct mouse_info mouse;
6087 signal(SIGUSR2, restricted ? SIG_IGN : SIG_DFL);
6088 mouse.operation = MOUSE_MODE;
6089 mouse.u.mode.mode = 0;
6090 mouse.u.mode.signal = 0;
6091 ioctl(1, CONS_MOUSECTL, &mouse);
6095 * Gets info from sysmouse and adds special keys to input buf.
6097 static RETSIGTYPE
6098 sig_sysmouse SIGDEFARG(sigarg)
6100 struct mouse_info mouse;
6101 struct video_info video;
6102 char_u string[6];
6103 int row, col;
6104 int button;
6105 int buttons;
6106 static int oldbuttons = 0;
6108 #ifdef FEAT_GUI
6109 /* Don't put events in the input queue now. */
6110 if (hold_gui_events)
6111 return;
6112 #endif
6114 mouse.operation = MOUSE_GETINFO;
6115 if (ioctl(1, FBIO_GETMODE, &video.vi_mode) != -1
6116 && ioctl(1, FBIO_MODEINFO, &video) != -1
6117 && ioctl(1, CONS_MOUSECTL, &mouse) != -1
6118 && video.vi_cheight > 0 && video.vi_cwidth > 0)
6120 row = mouse.u.data.y / video.vi_cheight;
6121 col = mouse.u.data.x / video.vi_cwidth;
6122 buttons = mouse.u.data.buttons;
6123 string[0] = ESC; /* Our termcode */
6124 string[1] = 'M';
6125 string[2] = 'S';
6126 if (oldbuttons == buttons && buttons != 0)
6128 button = MOUSE_DRAG;
6130 else
6132 switch (buttons)
6134 case 0:
6135 button = MOUSE_RELEASE;
6136 break;
6137 case 1:
6138 button = MOUSE_LEFT;
6139 break;
6140 case 2:
6141 button = MOUSE_MIDDLE;
6142 break;
6143 case 4:
6144 button = MOUSE_RIGHT;
6145 break;
6146 default:
6147 return;
6149 oldbuttons = buttons;
6151 string[3] = (char_u)(button);
6152 string[4] = (char_u)(col + ' ' + 1);
6153 string[5] = (char_u)(row + ' ' + 1);
6154 add_to_input_buf(string, 6);
6156 return;
6158 #endif /* FEAT_SYSMOUSE */
6160 #if defined(FEAT_LIBCALL) || defined(PROTO)
6161 typedef char_u * (*STRPROCSTR)__ARGS((char_u *));
6162 typedef char_u * (*INTPROCSTR)__ARGS((int));
6163 typedef int (*STRPROCINT)__ARGS((char_u *));
6164 typedef int (*INTPROCINT)__ARGS((int));
6167 * Call a DLL routine which takes either a string or int param
6168 * and returns an allocated string.
6171 mch_libcall(libname, funcname, argstring, argint, string_result, number_result)
6172 char_u *libname;
6173 char_u *funcname;
6174 char_u *argstring; /* NULL when using a argint */
6175 int argint;
6176 char_u **string_result;/* NULL when using number_result */
6177 int *number_result;
6179 # if defined(USE_DLOPEN)
6180 void *hinstLib;
6181 char *dlerr = NULL;
6182 # else
6183 shl_t hinstLib;
6184 # endif
6185 STRPROCSTR ProcAdd;
6186 INTPROCSTR ProcAddI;
6187 char_u *retval_str = NULL;
6188 int retval_int = 0;
6189 int success = FALSE;
6192 * Get a handle to the DLL module.
6194 # if defined(USE_DLOPEN)
6195 /* First clear any error, it's not cleared by the dlopen() call. */
6196 (void)dlerror();
6198 hinstLib = dlopen((char *)libname, RTLD_LAZY
6199 # ifdef RTLD_LOCAL
6200 | RTLD_LOCAL
6201 # endif
6203 if (hinstLib == NULL)
6205 /* "dlerr" must be used before dlclose() */
6206 dlerr = (char *)dlerror();
6207 if (dlerr != NULL)
6208 EMSG2(_("dlerror = \"%s\""), dlerr);
6210 # else
6211 hinstLib = shl_load((const char*)libname, BIND_IMMEDIATE|BIND_VERBOSE, 0L);
6212 # endif
6214 /* If the handle is valid, try to get the function address. */
6215 if (hinstLib != NULL)
6217 # ifdef HAVE_SETJMP_H
6219 * Catch a crash when calling the library function. For example when
6220 * using a number where a string pointer is expected.
6222 mch_startjmp();
6223 if (SETJMP(lc_jump_env) != 0)
6225 success = FALSE;
6226 # if defined(USE_DLOPEN)
6227 dlerr = NULL;
6228 # endif
6229 mch_didjmp();
6231 else
6232 # endif
6234 retval_str = NULL;
6235 retval_int = 0;
6237 if (argstring != NULL)
6239 # if defined(USE_DLOPEN)
6240 ProcAdd = (STRPROCSTR)dlsym(hinstLib, (const char *)funcname);
6241 dlerr = (char *)dlerror();
6242 # else
6243 if (shl_findsym(&hinstLib, (const char *)funcname,
6244 TYPE_PROCEDURE, (void *)&ProcAdd) < 0)
6245 ProcAdd = NULL;
6246 # endif
6247 if ((success = (ProcAdd != NULL
6248 # if defined(USE_DLOPEN)
6249 && dlerr == NULL
6250 # endif
6253 if (string_result == NULL)
6254 retval_int = ((STRPROCINT)ProcAdd)(argstring);
6255 else
6256 retval_str = (ProcAdd)(argstring);
6259 else
6261 # if defined(USE_DLOPEN)
6262 ProcAddI = (INTPROCSTR)dlsym(hinstLib, (const char *)funcname);
6263 dlerr = (char *)dlerror();
6264 # else
6265 if (shl_findsym(&hinstLib, (const char *)funcname,
6266 TYPE_PROCEDURE, (void *)&ProcAddI) < 0)
6267 ProcAddI = NULL;
6268 # endif
6269 if ((success = (ProcAddI != NULL
6270 # if defined(USE_DLOPEN)
6271 && dlerr == NULL
6272 # endif
6275 if (string_result == NULL)
6276 retval_int = ((INTPROCINT)ProcAddI)(argint);
6277 else
6278 retval_str = (ProcAddI)(argint);
6282 /* Save the string before we free the library. */
6283 /* Assume that a "1" or "-1" result is an illegal pointer. */
6284 if (string_result == NULL)
6285 *number_result = retval_int;
6286 else if (retval_str != NULL
6287 && retval_str != (char_u *)1
6288 && retval_str != (char_u *)-1)
6289 *string_result = vim_strsave(retval_str);
6292 # ifdef HAVE_SETJMP_H
6293 mch_endjmp();
6294 # ifdef SIGHASARG
6295 if (lc_signal != 0)
6297 int i;
6299 /* try to find the name of this signal */
6300 for (i = 0; signal_info[i].sig != -1; i++)
6301 if (lc_signal == signal_info[i].sig)
6302 break;
6303 EMSG2("E368: got SIG%s in libcall()", signal_info[i].name);
6305 # endif
6306 # endif
6308 # if defined(USE_DLOPEN)
6309 /* "dlerr" must be used before dlclose() */
6310 if (dlerr != NULL)
6311 EMSG2(_("dlerror = \"%s\""), dlerr);
6313 /* Free the DLL module. */
6314 (void)dlclose(hinstLib);
6315 # else
6316 (void)shl_unload(hinstLib);
6317 # endif
6320 if (!success)
6322 EMSG2(_(e_libcall), funcname);
6323 return FAIL;
6326 return OK;
6328 #endif
6330 #if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
6331 static int xterm_trace = -1; /* default: disabled */
6332 static int xterm_button;
6335 * Setup a dummy window for X selections in a terminal.
6337 void
6338 setup_term_clip()
6340 int z = 0;
6341 char *strp = "";
6342 Widget AppShell;
6344 if (!x_connect_to_server())
6345 return;
6347 open_app_context();
6348 if (app_context != NULL && xterm_Shell == (Widget)0)
6350 int (*oldhandler)();
6351 #if defined(HAVE_SETJMP_H)
6352 int (*oldIOhandler)();
6353 #endif
6354 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
6355 struct timeval start_tv;
6357 if (p_verbose > 0)
6358 gettimeofday(&start_tv, NULL);
6359 # endif
6361 /* Ignore X errors while opening the display */
6362 oldhandler = XSetErrorHandler(x_error_check);
6364 #if defined(HAVE_SETJMP_H)
6365 /* Ignore X IO errors while opening the display */
6366 oldIOhandler = XSetIOErrorHandler(x_IOerror_check);
6367 mch_startjmp();
6368 if (SETJMP(lc_jump_env) != 0)
6370 mch_didjmp();
6371 xterm_dpy = NULL;
6373 else
6374 #endif
6376 xterm_dpy = XtOpenDisplay(app_context, xterm_display,
6377 "vim_xterm", "Vim_xterm", NULL, 0, &z, &strp);
6378 #if defined(HAVE_SETJMP_H)
6379 mch_endjmp();
6380 #endif
6383 #if defined(HAVE_SETJMP_H)
6384 /* Now handle X IO errors normally. */
6385 (void)XSetIOErrorHandler(oldIOhandler);
6386 #endif
6387 /* Now handle X errors normally. */
6388 (void)XSetErrorHandler(oldhandler);
6390 if (xterm_dpy == NULL)
6392 if (p_verbose > 0)
6393 verb_msg((char_u *)_("Opening the X display failed"));
6394 return;
6397 /* Catch terminating error of the X server connection. */
6398 (void)XSetIOErrorHandler(x_IOerror_handler);
6400 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
6401 if (p_verbose > 0)
6403 verbose_enter();
6404 xopen_message(&start_tv);
6405 verbose_leave();
6407 # endif
6409 /* Create a Shell to make converters work. */
6410 AppShell = XtVaAppCreateShell("vim_xterm", "Vim_xterm",
6411 applicationShellWidgetClass, xterm_dpy,
6412 NULL);
6413 if (AppShell == (Widget)0)
6414 return;
6415 xterm_Shell = XtVaCreatePopupShell("VIM",
6416 topLevelShellWidgetClass, AppShell,
6417 XtNmappedWhenManaged, 0,
6418 XtNwidth, 1,
6419 XtNheight, 1,
6420 NULL);
6421 if (xterm_Shell == (Widget)0)
6422 return;
6424 x11_setup_atoms(xterm_dpy);
6425 if (x11_display == NULL)
6426 x11_display = xterm_dpy;
6428 XtRealizeWidget(xterm_Shell);
6429 XSync(xterm_dpy, False);
6430 xterm_update();
6432 if (xterm_Shell != (Widget)0)
6434 clip_init(TRUE);
6435 if (x11_window == 0 && (strp = getenv("WINDOWID")) != NULL)
6436 x11_window = (Window)atol(strp);
6437 /* Check if $WINDOWID is valid. */
6438 if (test_x11_window(xterm_dpy) == FAIL)
6439 x11_window = 0;
6440 if (x11_window != 0)
6441 xterm_trace = 0;
6445 void
6446 start_xterm_trace(button)
6447 int button;
6449 if (x11_window == 0 || xterm_trace < 0 || xterm_Shell == (Widget)0)
6450 return;
6451 xterm_trace = 1;
6452 xterm_button = button;
6453 do_xterm_trace();
6457 void
6458 stop_xterm_trace()
6460 if (xterm_trace < 0)
6461 return;
6462 xterm_trace = 0;
6466 * Query the xterm pointer and generate mouse termcodes if necessary
6467 * return TRUE if dragging is active, else FALSE
6469 static int
6470 do_xterm_trace()
6472 Window root, child;
6473 int root_x, root_y;
6474 int win_x, win_y;
6475 int row, col;
6476 int_u mask_return;
6477 char_u buf[50];
6478 char_u *strp;
6479 long got_hints;
6480 static char_u *mouse_code;
6481 static char_u mouse_name[2] = {KS_MOUSE, KE_FILLER};
6482 static int prev_row = 0, prev_col = 0;
6483 static XSizeHints xterm_hints;
6485 if (xterm_trace <= 0)
6486 return FALSE;
6488 if (xterm_trace == 1)
6490 /* Get the hints just before tracking starts. The font size might
6491 * have changed recently. */
6492 if (!XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints)
6493 || !(got_hints & PResizeInc)
6494 || xterm_hints.width_inc <= 1
6495 || xterm_hints.height_inc <= 1)
6497 xterm_trace = -1; /* Not enough data -- disable tracing */
6498 return FALSE;
6501 /* Rely on the same mouse code for the duration of this */
6502 mouse_code = find_termcode(mouse_name);
6503 prev_row = mouse_row;
6504 prev_row = mouse_col;
6505 xterm_trace = 2;
6507 /* Find the offset of the chars, there might be a scrollbar on the
6508 * left of the window and/or a menu on the top (eterm etc.) */
6509 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
6510 &win_x, &win_y, &mask_return);
6511 xterm_hints.y = win_y - (xterm_hints.height_inc * mouse_row)
6512 - (xterm_hints.height_inc / 2);
6513 if (xterm_hints.y <= xterm_hints.height_inc / 2)
6514 xterm_hints.y = 2;
6515 xterm_hints.x = win_x - (xterm_hints.width_inc * mouse_col)
6516 - (xterm_hints.width_inc / 2);
6517 if (xterm_hints.x <= xterm_hints.width_inc / 2)
6518 xterm_hints.x = 2;
6519 return TRUE;
6521 if (mouse_code == NULL)
6523 xterm_trace = 0;
6524 return FALSE;
6527 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
6528 &win_x, &win_y, &mask_return);
6530 row = check_row((win_y - xterm_hints.y) / xterm_hints.height_inc);
6531 col = check_col((win_x - xterm_hints.x) / xterm_hints.width_inc);
6532 if (row == prev_row && col == prev_col)
6533 return TRUE;
6535 STRCPY(buf, mouse_code);
6536 strp = buf + STRLEN(buf);
6537 *strp++ = (xterm_button | MOUSE_DRAG) & ~0x20;
6538 *strp++ = (char_u)(col + ' ' + 1);
6539 *strp++ = (char_u)(row + ' ' + 1);
6540 *strp = 0;
6541 add_to_input_buf(buf, STRLEN(buf));
6543 prev_row = row;
6544 prev_col = col;
6545 return TRUE;
6548 # if defined(FEAT_GUI) || defined(PROTO)
6550 * Destroy the display, window and app_context. Required for GTK.
6552 void
6553 clear_xterm_clip()
6555 if (xterm_Shell != (Widget)0)
6557 XtDestroyWidget(xterm_Shell);
6558 xterm_Shell = (Widget)0;
6560 if (xterm_dpy != NULL)
6562 # if 0
6563 /* Lesstif and Solaris crash here, lose some memory */
6564 XtCloseDisplay(xterm_dpy);
6565 # endif
6566 if (x11_display == xterm_dpy)
6567 x11_display = NULL;
6568 xterm_dpy = NULL;
6570 # if 0
6571 if (app_context != (XtAppContext)NULL)
6573 /* Lesstif and Solaris crash here, lose some memory */
6574 XtDestroyApplicationContext(app_context);
6575 app_context = (XtAppContext)NULL;
6577 # endif
6579 # endif
6582 * Catch up with any queued X events. This may put keyboard input into the
6583 * input buffer, call resize call-backs, trigger timers etc. If there is
6584 * nothing in the X event queue (& no timers pending), then we return
6585 * immediately.
6587 static void
6588 xterm_update()
6590 XEvent event;
6592 while (XtAppPending(app_context) && !vim_is_input_buf_full())
6594 XtAppNextEvent(app_context, &event);
6595 #ifdef FEAT_CLIENTSERVER
6597 XPropertyEvent *e = (XPropertyEvent *)&event;
6599 if (e->type == PropertyNotify && e->window == commWindow
6600 && e->atom == commProperty && e->state == PropertyNewValue)
6601 serverEventProc(xterm_dpy, &event);
6603 #endif
6604 XtDispatchEvent(&event);
6609 clip_xterm_own_selection(cbd)
6610 VimClipboard *cbd;
6612 if (xterm_Shell != (Widget)0)
6613 return clip_x11_own_selection(xterm_Shell, cbd);
6614 return FAIL;
6617 void
6618 clip_xterm_lose_selection(cbd)
6619 VimClipboard *cbd;
6621 if (xterm_Shell != (Widget)0)
6622 clip_x11_lose_selection(xterm_Shell, cbd);
6625 void
6626 clip_xterm_request_selection(cbd)
6627 VimClipboard *cbd;
6629 if (xterm_Shell != (Widget)0)
6630 clip_x11_request_selection(xterm_Shell, xterm_dpy, cbd);
6633 void
6634 clip_xterm_set_selection(cbd)
6635 VimClipboard *cbd;
6637 clip_x11_set_selection(cbd);
6639 #endif
6642 #if defined(USE_XSMP) || defined(PROTO)
6644 * Code for X Session Management Protocol.
6646 static void xsmp_handle_save_yourself __ARGS((SmcConn smc_conn, SmPointer client_data, int save_type, Bool shutdown, int interact_style, Bool fast));
6647 static void xsmp_die __ARGS((SmcConn smc_conn, SmPointer client_data));
6648 static void xsmp_save_complete __ARGS((SmcConn smc_conn, SmPointer client_data));
6649 static void xsmp_shutdown_cancelled __ARGS((SmcConn smc_conn, SmPointer client_data));
6650 static void xsmp_ice_connection __ARGS((IceConn iceConn, IcePointer clientData, Bool opening, IcePointer *watchData));
6653 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6654 static void xsmp_handle_interaction __ARGS((SmcConn smc_conn, SmPointer client_data));
6657 * This is our chance to ask the user if they want to save,
6658 * or abort the logout
6660 static void
6661 xsmp_handle_interaction(smc_conn, client_data)
6662 SmcConn smc_conn;
6663 SmPointer client_data UNUSED;
6665 cmdmod_T save_cmdmod;
6666 int cancel_shutdown = False;
6668 save_cmdmod = cmdmod;
6669 cmdmod.confirm = TRUE;
6670 if (check_changed_any(FALSE))
6671 /* Mustn't logout */
6672 cancel_shutdown = True;
6673 cmdmod = save_cmdmod;
6674 setcursor(); /* position cursor */
6675 out_flush();
6677 /* Done interaction */
6678 SmcInteractDone(smc_conn, cancel_shutdown);
6680 /* Finish off
6681 * Only end save-yourself here if we're not cancelling shutdown;
6682 * we'll get a cancelled callback later in which we'll end it.
6683 * Hopefully get around glitchy SMs (like GNOME-1)
6685 if (!cancel_shutdown)
6687 xsmp.save_yourself = False;
6688 SmcSaveYourselfDone(smc_conn, True);
6691 # endif
6694 * Callback that starts save-yourself.
6696 static void
6697 xsmp_handle_save_yourself(smc_conn, client_data, save_type,
6698 shutdown, interact_style, fast)
6699 SmcConn smc_conn;
6700 SmPointer client_data UNUSED;
6701 int save_type UNUSED;
6702 Bool shutdown;
6703 int interact_style UNUSED;
6704 Bool fast UNUSED;
6706 /* Handle already being in saveyourself */
6707 if (xsmp.save_yourself)
6708 SmcSaveYourselfDone(smc_conn, True);
6709 xsmp.save_yourself = True;
6710 xsmp.shutdown = shutdown;
6712 /* First up, preserve all files */
6713 out_flush();
6714 ml_sync_all(FALSE, FALSE); /* preserve all swap files */
6716 if (p_verbose > 0)
6717 verb_msg((char_u *)_("XSMP handling save-yourself request"));
6719 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6720 /* Now see if we can ask about unsaved files */
6721 if (shutdown && !fast && gui.in_use)
6722 /* Need to interact with user, but need SM's permission */
6723 SmcInteractRequest(smc_conn, SmDialogError,
6724 xsmp_handle_interaction, client_data);
6725 else
6726 # endif
6728 /* Can stop the cycle here */
6729 SmcSaveYourselfDone(smc_conn, True);
6730 xsmp.save_yourself = False;
6736 * Callback to warn us of imminent death.
6738 static void
6739 xsmp_die(smc_conn, client_data)
6740 SmcConn smc_conn UNUSED;
6741 SmPointer client_data UNUSED;
6743 xsmp_close();
6745 /* quit quickly leaving swapfiles for modified buffers behind */
6746 getout_preserve_modified(0);
6751 * Callback to tell us that save-yourself has completed.
6753 static void
6754 xsmp_save_complete(smc_conn, client_data)
6755 SmcConn smc_conn UNUSED;
6756 SmPointer client_data UNUSED;
6758 xsmp.save_yourself = False;
6763 * Callback to tell us that an instigated shutdown was cancelled
6764 * (maybe even by us)
6766 static void
6767 xsmp_shutdown_cancelled(smc_conn, client_data)
6768 SmcConn smc_conn;
6769 SmPointer client_data UNUSED;
6771 if (xsmp.save_yourself)
6772 SmcSaveYourselfDone(smc_conn, True);
6773 xsmp.save_yourself = False;
6774 xsmp.shutdown = False;
6779 * Callback to tell us that a new ICE connection has been established.
6781 static void
6782 xsmp_ice_connection(iceConn, clientData, opening, watchData)
6783 IceConn iceConn;
6784 IcePointer clientData UNUSED;
6785 Bool opening;
6786 IcePointer *watchData UNUSED;
6788 /* Intercept creation of ICE connection fd */
6789 if (opening)
6791 xsmp_icefd = IceConnectionNumber(iceConn);
6792 IceRemoveConnectionWatch(xsmp_ice_connection, NULL);
6797 /* Handle any ICE processing that's required; return FAIL if SM lost */
6799 xsmp_handle_requests()
6801 Bool rep;
6803 if (IceProcessMessages(xsmp.iceconn, NULL, &rep)
6804 == IceProcessMessagesIOError)
6806 /* Lost ICE */
6807 if (p_verbose > 0)
6808 verb_msg((char_u *)_("XSMP lost ICE connection"));
6809 xsmp_close();
6810 return FAIL;
6812 else
6813 return OK;
6816 static int dummy;
6818 /* Set up X Session Management Protocol */
6819 void
6820 xsmp_init(void)
6822 char errorstring[80];
6823 SmcCallbacks smcallbacks;
6824 #if 0
6825 SmPropValue smname;
6826 SmProp smnameprop;
6827 SmProp *smprops[1];
6828 #endif
6830 if (p_verbose > 0)
6831 verb_msg((char_u *)_("XSMP opening connection"));
6833 xsmp.save_yourself = xsmp.shutdown = False;
6835 /* Set up SM callbacks - must have all, even if they're not used */
6836 smcallbacks.save_yourself.callback = xsmp_handle_save_yourself;
6837 smcallbacks.save_yourself.client_data = NULL;
6838 smcallbacks.die.callback = xsmp_die;
6839 smcallbacks.die.client_data = NULL;
6840 smcallbacks.save_complete.callback = xsmp_save_complete;
6841 smcallbacks.save_complete.client_data = NULL;
6842 smcallbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
6843 smcallbacks.shutdown_cancelled.client_data = NULL;
6845 /* Set up a watch on ICE connection creations. The "dummy" argument is
6846 * apparently required for FreeBSD (we get a BUS error when using NULL). */
6847 if (IceAddConnectionWatch(xsmp_ice_connection, &dummy) == 0)
6849 if (p_verbose > 0)
6850 verb_msg((char_u *)_("XSMP ICE connection watch failed"));
6851 return;
6854 /* Create an SM connection */
6855 xsmp.smcconn = SmcOpenConnection(
6856 NULL,
6857 NULL,
6858 SmProtoMajor,
6859 SmProtoMinor,
6860 SmcSaveYourselfProcMask | SmcDieProcMask
6861 | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
6862 &smcallbacks,
6863 NULL,
6864 &xsmp.clientid,
6865 sizeof(errorstring),
6866 errorstring);
6867 if (xsmp.smcconn == NULL)
6869 char errorreport[132];
6871 if (p_verbose > 0)
6873 vim_snprintf(errorreport, sizeof(errorreport),
6874 _("XSMP SmcOpenConnection failed: %s"), errorstring);
6875 verb_msg((char_u *)errorreport);
6877 return;
6879 xsmp.iceconn = SmcGetIceConnection(xsmp.smcconn);
6881 #if 0
6882 /* ID ourselves */
6883 smname.value = "vim";
6884 smname.length = 3;
6885 smnameprop.name = "SmProgram";
6886 smnameprop.type = "SmARRAY8";
6887 smnameprop.num_vals = 1;
6888 smnameprop.vals = &smname;
6890 smprops[0] = &smnameprop;
6891 SmcSetProperties(xsmp.smcconn, 1, smprops);
6892 #endif
6896 /* Shut down XSMP comms. */
6897 void
6898 xsmp_close()
6900 if (xsmp_icefd != -1)
6902 SmcCloseConnection(xsmp.smcconn, 0, NULL);
6903 if (xsmp.clientid != NULL)
6904 free(xsmp.clientid);
6905 xsmp.clientid = NULL;
6906 xsmp_icefd = -1;
6909 #endif /* USE_XSMP */
6912 #ifdef EBCDIC
6913 /* Translate character to its CTRL- value */
6914 char CtrlTable[] =
6916 /* 00 - 5E */
6917 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6918 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6919 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6920 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6921 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6922 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6923 /* ^ */ 0x1E,
6924 /* - */ 0x1F,
6925 /* 61 - 6C */
6926 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6927 /* _ */ 0x1F,
6928 /* 6E - 80 */
6929 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6930 /* a */ 0x01,
6931 /* b */ 0x02,
6932 /* c */ 0x03,
6933 /* d */ 0x37,
6934 /* e */ 0x2D,
6935 /* f */ 0x2E,
6936 /* g */ 0x2F,
6937 /* h */ 0x16,
6938 /* i */ 0x05,
6939 /* 8A - 90 */
6940 0, 0, 0, 0, 0, 0, 0,
6941 /* j */ 0x15,
6942 /* k */ 0x0B,
6943 /* l */ 0x0C,
6944 /* m */ 0x0D,
6945 /* n */ 0x0E,
6946 /* o */ 0x0F,
6947 /* p */ 0x10,
6948 /* q */ 0x11,
6949 /* r */ 0x12,
6950 /* 9A - A1 */
6951 0, 0, 0, 0, 0, 0, 0, 0,
6952 /* s */ 0x13,
6953 /* t */ 0x3C,
6954 /* u */ 0x3D,
6955 /* v */ 0x32,
6956 /* w */ 0x26,
6957 /* x */ 0x18,
6958 /* y */ 0x19,
6959 /* z */ 0x3F,
6960 /* AA - AC */
6961 0, 0, 0,
6962 /* [ */ 0x27,
6963 /* AE - BC */
6964 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6965 /* ] */ 0x1D,
6966 /* BE - C0 */ 0, 0, 0,
6967 /* A */ 0x01,
6968 /* B */ 0x02,
6969 /* C */ 0x03,
6970 /* D */ 0x37,
6971 /* E */ 0x2D,
6972 /* F */ 0x2E,
6973 /* G */ 0x2F,
6974 /* H */ 0x16,
6975 /* I */ 0x05,
6976 /* CA - D0 */ 0, 0, 0, 0, 0, 0, 0,
6977 /* J */ 0x15,
6978 /* K */ 0x0B,
6979 /* L */ 0x0C,
6980 /* M */ 0x0D,
6981 /* N */ 0x0E,
6982 /* O */ 0x0F,
6983 /* P */ 0x10,
6984 /* Q */ 0x11,
6985 /* R */ 0x12,
6986 /* DA - DF */ 0, 0, 0, 0, 0, 0,
6987 /* \ */ 0x1C,
6988 /* E1 */ 0,
6989 /* S */ 0x13,
6990 /* T */ 0x3C,
6991 /* U */ 0x3D,
6992 /* V */ 0x32,
6993 /* W */ 0x26,
6994 /* X */ 0x18,
6995 /* Y */ 0x19,
6996 /* Z */ 0x3F,
6997 /* EA - FF*/ 0, 0, 0, 0, 0, 0,
6998 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7001 char MetaCharTable[]=
7002 {/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
7003 0, 0, 0, 0,'\\', 0,'F', 0,'W','M','N', 0, 0, 0, 0, 0,
7004 0, 0, 0, 0,']', 0, 0,'G', 0, 0,'R','O', 0, 0, 0, 0,
7005 '@','A','B','C','D','E', 0, 0,'H','I','J','K','L', 0, 0, 0,
7006 'P','Q', 0,'S','T','U','V', 0,'X','Y','Z','[', 0, 0,'^', 0
7010 /* TODO: Use characters NOT numbers!!! */
7011 char CtrlCharTable[]=
7012 {/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
7013 124,193,194,195, 0,201, 0, 0, 0, 0, 0,210,211,212,213,214,
7014 215,216,217,226, 0,209,200, 0,231,232, 0, 0,224,189, 95,109,
7015 0, 0, 0, 0, 0, 0,230,173, 0, 0, 0, 0, 0,197,198,199,
7016 0, 0,229, 0, 0, 0, 0,196, 0, 0, 0, 0,227,228, 0,233,
7020 #endif