Missing toolbar icon fallback code fix
[MacVim.git] / src / os_unix.c
blob712761fa688abfcf841c596cf82039cd99175d5b
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 static int sig_alarm_called;
185 #endif
186 static RETSIGTYPE deathtrap __ARGS(SIGPROTOARG);
188 static void catch_int_signal __ARGS((void));
189 static void set_signals __ARGS((void));
190 static void catch_signals __ARGS((RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)()));
191 #ifndef __EMX__
192 static int have_wildcard __ARGS((int, char_u **));
193 static int have_dollars __ARGS((int, char_u **));
194 #endif
196 #ifndef __EMX__
197 static int save_patterns __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file));
198 #endif
200 #ifndef SIG_ERR
201 # define SIG_ERR ((RETSIGTYPE (*)())-1)
202 #endif
204 static int do_resize = FALSE;
205 #ifndef __EMX__
206 static char_u *extra_shell_arg = NULL;
207 static int show_shell_mess = TRUE;
208 #endif
209 static int deadly_signal = 0; /* The signal we caught */
210 static int in_mch_delay = FALSE; /* sleeping in mch_delay() */
212 static int curr_tmode = TMODE_COOK; /* contains current terminal mode */
214 #ifdef USE_XSMP
215 typedef struct
217 SmcConn smcconn; /* The SM connection ID */
218 IceConn iceconn; /* The ICE connection ID */
219 char *clientid; /* The client ID for the current smc session */
220 Bool save_yourself; /* If we're in the middle of a save_yourself */
221 Bool shutdown; /* If we're in shutdown mode */
222 } xsmp_config_T;
224 static xsmp_config_T xsmp;
225 #endif
227 #ifdef SYS_SIGLIST_DECLARED
229 * I have seen
230 * extern char *_sys_siglist[NSIG];
231 * on Irix, Linux, NetBSD and Solaris. It contains a nice list of strings
232 * that describe the signals. That is nearly what we want here. But
233 * autoconf does only check for sys_siglist (without the underscore), I
234 * do not want to change everything today.... jw.
235 * This is why AC_DECL_SYS_SIGLIST is commented out in configure.in
237 #endif
239 static struct signalinfo
241 int sig; /* Signal number, eg. SIGSEGV etc */
242 char *name; /* Signal name (not char_u!). */
243 char deadly; /* Catch as a deadly signal? */
244 } signal_info[] =
246 #ifdef SIGHUP
247 {SIGHUP, "HUP", TRUE},
248 #endif
249 #ifdef SIGQUIT
250 {SIGQUIT, "QUIT", TRUE},
251 #endif
252 #ifdef SIGILL
253 {SIGILL, "ILL", TRUE},
254 #endif
255 #ifdef SIGTRAP
256 {SIGTRAP, "TRAP", TRUE},
257 #endif
258 #ifdef SIGABRT
259 {SIGABRT, "ABRT", TRUE},
260 #endif
261 #ifdef SIGEMT
262 {SIGEMT, "EMT", TRUE},
263 #endif
264 #ifdef SIGFPE
265 {SIGFPE, "FPE", TRUE},
266 #endif
267 #ifdef SIGBUS
268 {SIGBUS, "BUS", TRUE},
269 #endif
270 #ifdef SIGSEGV
271 {SIGSEGV, "SEGV", TRUE},
272 #endif
273 #ifdef SIGSYS
274 {SIGSYS, "SYS", TRUE},
275 #endif
276 #ifdef SIGALRM
277 {SIGALRM, "ALRM", FALSE}, /* Perl's alarm() can trigger it */
278 #endif
279 #ifdef SIGTERM
280 {SIGTERM, "TERM", TRUE},
281 #endif
282 #ifdef SIGVTALRM
283 {SIGVTALRM, "VTALRM", TRUE},
284 #endif
285 #if defined(SIGPROF) && !defined(FEAT_MZSCHEME) && !defined(WE_ARE_PROFILING)
286 /* MzScheme uses SIGPROF for its own needs; On Linux with profiling
287 * this makes Vim exit. WE_ARE_PROFILING is defined in Makefile. */
288 {SIGPROF, "PROF", TRUE},
289 #endif
290 #ifdef SIGXCPU
291 {SIGXCPU, "XCPU", TRUE},
292 #endif
293 #ifdef SIGXFSZ
294 {SIGXFSZ, "XFSZ", TRUE},
295 #endif
296 #ifdef SIGUSR1
297 {SIGUSR1, "USR1", TRUE},
298 #endif
299 #if defined(SIGUSR2) && !defined(FEAT_SYSMOUSE)
300 /* Used for sysmouse handling */
301 {SIGUSR2, "USR2", TRUE},
302 #endif
303 #ifdef SIGINT
304 {SIGINT, "INT", FALSE},
305 #endif
306 #ifdef SIGWINCH
307 {SIGWINCH, "WINCH", FALSE},
308 #endif
309 #ifdef SIGTSTP
310 {SIGTSTP, "TSTP", FALSE},
311 #endif
312 #ifdef SIGPIPE
313 {SIGPIPE, "PIPE", FALSE},
314 #endif
315 {-1, "Unknown!", FALSE}
318 void
319 mch_write(s, len)
320 char_u *s;
321 int len;
323 write(1, (char *)s, len);
324 if (p_wd) /* Unix is too fast, slow down a bit more */
325 RealWaitForChar(read_cmd_fd, p_wd, NULL);
329 * mch_inchar(): low level input function.
330 * Get a characters from the keyboard.
331 * Return the number of characters that are available.
332 * If wtime == 0 do not wait for characters.
333 * If wtime == n wait a short time for characters.
334 * If wtime == -1 wait forever for characters.
337 mch_inchar(buf, maxlen, wtime, tb_change_cnt)
338 char_u *buf;
339 int maxlen;
340 long wtime; /* don't use "time", MIPS cannot handle it */
341 int tb_change_cnt;
343 int len;
345 /* Check if window changed size while we were busy, perhaps the ":set
346 * columns=99" command was used. */
347 while (do_resize)
348 handle_resize();
350 if (wtime >= 0)
352 while (WaitForChar(wtime) == 0) /* no character available */
354 if (!do_resize) /* return if not interrupted by resize */
355 return 0;
356 handle_resize();
359 else /* wtime == -1 */
362 * If there is no character available within 'updatetime' seconds
363 * flush all the swap files to disk.
364 * Also done when interrupted by SIGWINCH.
366 if (WaitForChar(p_ut) == 0)
368 #ifdef FEAT_AUTOCMD
369 if (trigger_cursorhold() && maxlen >= 3
370 && !typebuf_changed(tb_change_cnt))
372 buf[0] = K_SPECIAL;
373 buf[1] = KS_EXTRA;
374 buf[2] = (int)KE_CURSORHOLD;
375 return 3;
377 #endif
378 before_blocking();
382 for (;;) /* repeat until we got a character */
384 while (do_resize) /* window changed size */
385 handle_resize();
387 * we want to be interrupted by the winch signal
389 WaitForChar(-1L);
390 if (do_resize) /* interrupted by SIGWINCH signal */
391 continue;
393 /* If input was put directly in typeahead buffer bail out here. */
394 if (typebuf_changed(tb_change_cnt))
395 return 0;
398 * For some terminals we only get one character at a time.
399 * We want the get all available characters, so we could keep on
400 * trying until none is available
401 * For some other terminals this is quite slow, that's why we don't do
402 * it.
404 len = read_from_input_buf(buf, (long)maxlen);
405 if (len > 0)
407 #ifdef OS2
408 int i;
410 for (i = 0; i < len; i++)
411 if (buf[i] == 0)
412 buf[i] = K_NUL;
413 #endif
414 return len;
419 static void
420 handle_resize()
422 do_resize = FALSE;
423 shell_resized();
427 * return non-zero if a character is available
430 mch_char_avail()
432 return WaitForChar(0L);
435 #if defined(HAVE_TOTAL_MEM) || defined(PROTO)
436 # ifdef HAVE_SYS_RESOURCE_H
437 # include <sys/resource.h>
438 # endif
439 # if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTL)
440 # include <sys/sysctl.h>
441 # endif
442 # if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
443 # include <sys/sysinfo.h>
444 # endif
447 * Return total amount of memory available in Kbyte.
448 * Doesn't change when memory has been allocated.
450 /* ARGSUSED */
451 long_u
452 mch_total_mem(special)
453 int special;
455 # ifdef __EMX__
456 return ulimit(3, 0L) >> 10; /* always 32MB? */
457 # else
458 long_u mem = 0;
459 long_u shiftright = 10; /* how much to shift "mem" right for Kbyte */
461 # ifdef HAVE_SYSCTL
462 int mib[2], physmem;
463 size_t len;
465 /* BSD way of getting the amount of RAM available. */
466 mib[0] = CTL_HW;
467 mib[1] = HW_USERMEM;
468 len = sizeof(physmem);
469 if (sysctl(mib, 2, &physmem, &len, NULL, 0) == 0)
470 mem = (long_u)physmem;
471 # endif
473 # if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
474 if (mem == 0)
476 struct sysinfo sinfo;
478 /* Linux way of getting amount of RAM available */
479 if (sysinfo(&sinfo) == 0)
481 # ifdef HAVE_SYSINFO_MEM_UNIT
482 /* avoid overflow as much as possible */
483 while (shiftright > 0 && (sinfo.mem_unit & 1) == 0)
485 sinfo.mem_unit = sinfo.mem_unit >> 1;
486 --shiftright;
488 mem = sinfo.totalram * sinfo.mem_unit;
489 # else
490 mem = sinfo.totalram;
491 # endif
494 # endif
496 # ifdef HAVE_SYSCONF
497 if (mem == 0)
499 long pagesize, pagecount;
501 /* Solaris way of getting amount of RAM available */
502 pagesize = sysconf(_SC_PAGESIZE);
503 pagecount = sysconf(_SC_PHYS_PAGES);
504 if (pagesize > 0 && pagecount > 0)
506 /* avoid overflow as much as possible */
507 while (shiftright > 0 && (pagesize & 1) == 0)
509 pagesize = (long_u)pagesize >> 1;
510 --shiftright;
512 mem = (long_u)pagesize * pagecount;
515 # endif
517 /* Return the minimum of the physical memory and the user limit, because
518 * using more than the user limit may cause Vim to be terminated. */
519 # if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT)
521 struct rlimit rlp;
523 if (getrlimit(RLIMIT_DATA, &rlp) == 0
524 && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
525 # ifdef RLIM_INFINITY
526 && rlp.rlim_cur != RLIM_INFINITY
527 # endif
528 && ((long_u)rlp.rlim_cur >> 10) < (mem >> shiftright)
531 mem = (long_u)rlp.rlim_cur;
532 shiftright = 10;
535 # endif
537 if (mem > 0)
538 return mem >> shiftright;
539 return (long_u)0x1fffff;
540 # endif
542 #endif
544 void
545 mch_delay(msec, ignoreinput)
546 long msec;
547 int ignoreinput;
549 int old_tmode;
550 #ifdef FEAT_MZSCHEME
551 long total = msec; /* remember original value */
552 #endif
554 if (ignoreinput)
556 /* Go to cooked mode without echo, to allow SIGINT interrupting us
557 * here. But we don't want QUIT to kill us (CTRL-\ used in a
558 * shell may produce SIGQUIT). */
559 in_mch_delay = TRUE;
560 old_tmode = curr_tmode;
561 if (curr_tmode == TMODE_RAW)
562 settmode(TMODE_SLEEP);
565 * Everybody sleeps in a different way...
566 * Prefer nanosleep(), some versions of usleep() can only sleep up to
567 * one second.
569 #ifdef FEAT_MZSCHEME
572 /* if total is large enough, wait by portions in p_mzq */
573 if (total > p_mzq)
574 msec = p_mzq;
575 else
576 msec = total;
577 total -= msec;
578 #endif
579 #ifdef HAVE_NANOSLEEP
581 struct timespec ts;
583 ts.tv_sec = msec / 1000;
584 ts.tv_nsec = (msec % 1000) * 1000000;
585 (void)nanosleep(&ts, NULL);
587 #else
588 # ifdef HAVE_USLEEP
589 while (msec >= 1000)
591 usleep((unsigned int)(999 * 1000));
592 msec -= 999;
594 usleep((unsigned int)(msec * 1000));
595 # else
596 # ifndef HAVE_SELECT
597 poll(NULL, 0, (int)msec);
598 # else
599 # ifdef __EMX__
600 _sleep2(msec);
601 # else
603 struct timeval tv;
605 tv.tv_sec = msec / 1000;
606 tv.tv_usec = (msec % 1000) * 1000;
608 * NOTE: Solaris 2.6 has a bug that makes select() hang here. Get
609 * a patch from Sun to fix this. Reported by Gunnar Pedersen.
611 select(0, NULL, NULL, NULL, &tv);
613 # endif /* __EMX__ */
614 # endif /* HAVE_SELECT */
615 # endif /* HAVE_NANOSLEEP */
616 #endif /* HAVE_USLEEP */
617 #ifdef FEAT_MZSCHEME
619 while (total > 0);
620 #endif
622 settmode(old_tmode);
623 in_mch_delay = FALSE;
625 else
626 WaitForChar(msec);
629 #if 0 /* disabled, no longer needed now that regmatch() is not recursive */
630 # if defined(HAVE_GETRLIMIT)
631 # define HAVE_STACK_LIMIT
632 # endif
633 #endif
635 #if defined(HAVE_STACK_LIMIT) \
636 || (!defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGSTACK))
637 # define HAVE_CHECK_STACK_GROWTH
639 * Support for checking for an almost-out-of-stack-space situation.
643 * Return a pointer to an item on the stack. Used to find out if the stack
644 * grows up or down.
646 static void check_stack_growth __ARGS((char *p));
647 static int stack_grows_downwards;
650 * Find out if the stack grows upwards or downwards.
651 * "p" points to a variable on the stack of the caller.
653 static void
654 check_stack_growth(p)
655 char *p;
657 int i;
659 stack_grows_downwards = (p > (char *)&i);
661 #endif
663 #if defined(HAVE_STACK_LIMIT) || defined(PROTO)
664 static char *stack_limit = NULL;
666 #if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
667 # include <pthread.h>
668 # include <pthread_np.h>
669 #endif
672 * Find out until how var the stack can grow without getting into trouble.
673 * Called when starting up and when switching to the signal stack in
674 * deathtrap().
676 static void
677 get_stack_limit()
679 struct rlimit rlp;
680 int i;
681 long lim;
683 /* Set the stack limit to 15/16 of the allowable size. Skip this when the
684 * limit doesn't fit in a long (rlim_cur might be "long long"). */
685 if (getrlimit(RLIMIT_STACK, &rlp) == 0
686 && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
687 # ifdef RLIM_INFINITY
688 && rlp.rlim_cur != RLIM_INFINITY
689 # endif
692 lim = (long)rlp.rlim_cur;
693 #if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
695 pthread_attr_t attr;
696 size_t size;
698 /* On FreeBSD the initial thread always has a fixed stack size, no
699 * matter what the limits are set to. Normally it's 1 Mbyte. */
700 pthread_attr_init(&attr);
701 if (pthread_attr_get_np(pthread_self(), &attr) == 0)
703 pthread_attr_getstacksize(&attr, &size);
704 if (lim > (long)size)
705 lim = (long)size;
707 pthread_attr_destroy(&attr);
709 #endif
710 if (stack_grows_downwards)
712 stack_limit = (char *)((long)&i - (lim / 16L * 15L));
713 if (stack_limit >= (char *)&i)
714 /* overflow, set to 1/16 of current stack position */
715 stack_limit = (char *)((long)&i / 16L);
717 else
719 stack_limit = (char *)((long)&i + (lim / 16L * 15L));
720 if (stack_limit <= (char *)&i)
721 stack_limit = NULL; /* overflow */
727 * Return FAIL when running out of stack space.
728 * "p" must point to any variable local to the caller that's on the stack.
731 mch_stackcheck(p)
732 char *p;
734 if (stack_limit != NULL)
736 if (stack_grows_downwards)
738 if (p < stack_limit)
739 return FAIL;
741 else if (p > stack_limit)
742 return FAIL;
744 return OK;
746 #endif
748 #if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
750 * Support for using the signal stack.
751 * This helps when we run out of stack space, which causes a SIGSEGV. The
752 * signal handler then must run on another stack, since the normal stack is
753 * completely full.
756 #ifndef SIGSTKSZ
757 # define SIGSTKSZ 8000 /* just a guess of how much stack is needed... */
758 #endif
760 # ifdef HAVE_SIGALTSTACK
761 static stack_t sigstk; /* for sigaltstack() */
762 # else
763 static struct sigstack sigstk; /* for sigstack() */
764 # endif
766 static void init_signal_stack __ARGS((void));
767 static char *signal_stack;
769 static void
770 init_signal_stack()
772 if (signal_stack != NULL)
774 # ifdef HAVE_SIGALTSTACK
775 # if defined(__APPLE__) && (!defined(MAC_OS_X_VERSION_MAX_ALLOWED) \
776 || MAC_OS_X_VERSION_MAX_ALLOWED <= 1040)
777 /* missing prototype. Adding it to osdef?.h.in doesn't work, because
778 * "struct sigaltstack" needs to be declared. */
779 extern int sigaltstack __ARGS((const struct sigaltstack *ss, struct sigaltstack *oss));
780 # endif
782 # ifdef HAVE_SS_BASE
783 sigstk.ss_base = signal_stack;
784 # else
785 sigstk.ss_sp = signal_stack;
786 # endif
787 sigstk.ss_size = SIGSTKSZ;
788 sigstk.ss_flags = 0;
789 (void)sigaltstack(&sigstk, NULL);
790 # else
791 sigstk.ss_sp = signal_stack;
792 if (stack_grows_downwards)
793 sigstk.ss_sp += SIGSTKSZ - 1;
794 sigstk.ss_onstack = 0;
795 (void)sigstack(&sigstk, NULL);
796 # endif
799 #endif
802 * We need correct potatotypes for a signal function, otherwise mean compilers
803 * will barf when the second argument to signal() is ``wrong''.
804 * Let me try it with a few tricky defines from my own osdef.h (jw).
806 #if defined(SIGWINCH)
807 /* ARGSUSED */
808 static RETSIGTYPE
809 sig_winch SIGDEFARG(sigarg)
811 /* this is not required on all systems, but it doesn't hurt anybody */
812 signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
813 do_resize = TRUE;
814 SIGRETURN;
816 #endif
818 #if defined(SIGINT)
819 /* ARGSUSED */
820 static RETSIGTYPE
821 catch_sigint SIGDEFARG(sigarg)
823 /* this is not required on all systems, but it doesn't hurt anybody */
824 signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
825 got_int = TRUE;
826 SIGRETURN;
828 #endif
830 #if defined(SIGPWR)
831 /* ARGSUSED */
832 static RETSIGTYPE
833 catch_sigpwr SIGDEFARG(sigarg)
835 /* this is not required on all systems, but it doesn't hurt anybody */
836 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
838 * I'm not sure we get the SIGPWR signal when the system is really going
839 * down or when the batteries are almost empty. Just preserve the swap
840 * files and don't exit, that can't do any harm.
842 ml_sync_all(FALSE, FALSE);
843 SIGRETURN;
845 #endif
847 #ifdef SET_SIG_ALARM
849 * signal function for alarm().
851 /* ARGSUSED */
852 static RETSIGTYPE
853 sig_alarm SIGDEFARG(sigarg)
855 /* doesn't do anything, just to break a system call */
856 sig_alarm_called = TRUE;
857 SIGRETURN;
859 #endif
861 #if (defined(HAVE_SETJMP_H) \
862 && ((defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) \
863 || defined(FEAT_LIBCALL))) \
864 || defined(PROTO)
866 * A simplistic version of setjmp() that only allows one level of using.
867 * Don't call twice before calling mch_endjmp()!.
868 * Usage:
869 * mch_startjmp();
870 * if (SETJMP(lc_jump_env) != 0)
872 * mch_didjmp();
873 * EMSG("crash!");
875 * else
877 * do_the_work;
878 * mch_endjmp();
880 * Note: Can't move SETJMP() here, because a function calling setjmp() must
881 * not return before the saved environment is used.
882 * Returns OK for normal return, FAIL when the protected code caused a
883 * problem and LONGJMP() was used.
885 void
886 mch_startjmp()
888 #ifdef SIGHASARG
889 lc_signal = 0;
890 #endif
891 lc_active = TRUE;
894 void
895 mch_endjmp()
897 lc_active = FALSE;
900 void
901 mch_didjmp()
903 # if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
904 /* On FreeBSD the signal stack has to be reset after using siglongjmp(),
905 * otherwise catching the signal only works once. */
906 init_signal_stack();
907 # endif
909 #endif
912 * This function handles deadly signals.
913 * It tries to preserve any swap file and exit properly.
914 * (partly from Elvis).
916 static RETSIGTYPE
917 deathtrap SIGDEFARG(sigarg)
919 static int entered = 0; /* count the number of times we got here.
920 Note: when memory has been corrupted
921 this may get an arbitrary value! */
922 #ifdef SIGHASARG
923 int i;
924 #endif
926 #if defined(HAVE_SETJMP_H)
928 * Catch a crash in protected code.
929 * Restores the environment saved in lc_jump_env, which looks like
930 * SETJMP() returns 1.
932 if (lc_active)
934 # if defined(SIGHASARG)
935 lc_signal = sigarg;
936 # endif
937 lc_active = FALSE; /* don't jump again */
938 LONGJMP(lc_jump_env, 1);
939 /* NOTREACHED */
941 #endif
943 #ifdef SIGHASARG
944 # ifdef SIGQUIT
945 /* While in mch_delay() we go to cooked mode to allow a CTRL-C to
946 * interrupt us. But in cooked mode we may also get SIGQUIT, e.g., when
947 * pressing CTRL-\, but we don't want Vim to exit then. */
948 if (in_mch_delay && sigarg == SIGQUIT)
949 SIGRETURN;
950 # endif
952 /* When SIGHUP, SIGQUIT, etc. are blocked: postpone the effect and return
953 * here. This avoids that a non-reentrant function is interrupted, e.g.,
954 * free(). Calling free() again may then cause a crash. */
955 if (entered == 0
956 && (0
957 # ifdef SIGHUP
958 || sigarg == SIGHUP
959 # endif
960 # ifdef SIGQUIT
961 || sigarg == SIGQUIT
962 # endif
963 # ifdef SIGTERM
964 || sigarg == SIGTERM
965 # endif
966 # ifdef SIGPWR
967 || sigarg == SIGPWR
968 # endif
969 # ifdef SIGUSR1
970 || sigarg == SIGUSR1
971 # endif
972 # ifdef SIGUSR2
973 || sigarg == SIGUSR2
974 # endif
976 && !vim_handle_signal(sigarg))
977 SIGRETURN;
978 #endif
980 /* Remember how often we have been called. */
981 ++entered;
983 #ifdef FEAT_EVAL
984 /* Set the v:dying variable. */
985 set_vim_var_nr(VV_DYING, (long)entered);
986 #endif
988 #ifdef HAVE_STACK_LIMIT
989 /* Since we are now using the signal stack, need to reset the stack
990 * limit. Otherwise using a regexp will fail. */
991 get_stack_limit();
992 #endif
994 #if 0
995 /* This is for opening gdb the moment Vim crashes.
996 * You need to manually adjust the file name and Vim executable name.
997 * Suggested by SungHyun Nam. */
999 # define VI_GDB_FILE "/tmp/vimgdb"
1000 # define VIM_NAME "/usr/bin/vim"
1001 FILE *fp = fopen(VI_GDB_FILE, "w");
1002 if (fp)
1004 fprintf(fp,
1005 "file %s\n"
1006 "attach %d\n"
1007 "set height 1000\n"
1008 "bt full\n"
1009 , VIM_NAME, getpid());
1010 fclose(fp);
1011 system("xterm -e gdb -x "VI_GDB_FILE);
1012 unlink(VI_GDB_FILE);
1015 #endif
1017 #ifdef SIGHASARG
1018 /* try to find the name of this signal */
1019 for (i = 0; signal_info[i].sig != -1; i++)
1020 if (sigarg == signal_info[i].sig)
1021 break;
1022 deadly_signal = sigarg;
1023 #endif
1025 full_screen = FALSE; /* don't write message to the GUI, it might be
1026 * part of the problem... */
1028 * If something goes wrong after entering here, we may get here again.
1029 * When this happens, give a message and try to exit nicely (resetting the
1030 * terminal mode, etc.)
1031 * When this happens twice, just exit, don't even try to give a message,
1032 * stack may be corrupt or something weird.
1033 * When this still happens again (or memory was corrupted in such a way
1034 * that "entered" was clobbered) use _exit(), don't try freeing resources.
1036 if (entered >= 3)
1038 reset_signals(); /* don't catch any signals anymore */
1039 may_core_dump();
1040 if (entered >= 4)
1041 _exit(8);
1042 exit(7);
1044 if (entered == 2)
1046 OUT_STR(_("Vim: Double signal, exiting\n"));
1047 out_flush();
1048 getout(1);
1051 #ifdef SIGHASARG
1052 sprintf((char *)IObuff, _("Vim: Caught deadly signal %s\n"),
1053 signal_info[i].name);
1054 #else
1055 sprintf((char *)IObuff, _("Vim: Caught deadly signal\n"));
1056 #endif
1057 preserve_exit(); /* preserve files and exit */
1059 #ifdef NBDEBUG
1060 reset_signals();
1061 may_core_dump();
1062 abort();
1063 #endif
1065 SIGRETURN;
1068 #ifdef _REENTRANT
1070 * On Solaris with multi-threading, suspending might not work immediately.
1071 * Catch the SIGCONT signal, which will be used as an indication whether the
1072 * suspending has been done or not.
1074 static int sigcont_received;
1075 static RETSIGTYPE sigcont_handler __ARGS(SIGPROTOARG);
1078 * signal handler for SIGCONT
1080 /* ARGSUSED */
1081 static RETSIGTYPE
1082 sigcont_handler SIGDEFARG(sigarg)
1084 sigcont_received = TRUE;
1085 SIGRETURN;
1087 #endif
1090 * If the machine has job control, use it to suspend the program,
1091 * otherwise fake it by starting a new shell.
1093 void
1094 mch_suspend()
1096 /* BeOS does have SIGTSTP, but it doesn't work. */
1097 #if defined(SIGTSTP) && !defined(__BEOS__)
1098 out_flush(); /* needed to make cursor visible on some systems */
1099 settmode(TMODE_COOK);
1100 out_flush(); /* needed to disable mouse on some systems */
1102 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
1103 /* Since we are going to sleep, we can't respond to requests for the X
1104 * selections. Lose them, otherwise other applications will hang. But
1105 * first copy the text to cut buffer 0. */
1106 if (clip_star.owned || clip_plus.owned)
1108 x11_export_final_selection();
1109 if (clip_star.owned)
1110 clip_lose_selection(&clip_star);
1111 if (clip_plus.owned)
1112 clip_lose_selection(&clip_plus);
1113 if (x11_display != NULL)
1114 XFlush(x11_display);
1116 # endif
1118 # ifdef _REENTRANT
1119 sigcont_received = FALSE;
1120 # endif
1121 kill(0, SIGTSTP); /* send ourselves a STOP signal */
1122 # ifdef _REENTRANT
1123 /* When we didn't suspend immediately in the kill(), do it now. Happens
1124 * on multi-threaded Solaris. */
1125 if (!sigcont_received)
1126 pause();
1127 # endif
1129 # ifdef FEAT_TITLE
1131 * Set oldtitle to NULL, so the current title is obtained again.
1133 vim_free(oldtitle);
1134 oldtitle = NULL;
1135 # endif
1136 settmode(TMODE_RAW);
1137 need_check_timestamps = TRUE;
1138 did_check_timestamps = FALSE;
1139 #else
1140 suspend_shell();
1141 #endif
1144 void
1145 mch_init()
1147 Columns = 80;
1148 Rows = 24;
1150 out_flush();
1151 set_signals();
1153 #ifdef MACOS_CONVERT
1154 mac_conv_init();
1155 #endif
1158 static void
1159 set_signals()
1161 #if defined(SIGWINCH)
1163 * WINDOW CHANGE signal is handled with sig_winch().
1165 signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
1166 #endif
1169 * We want the STOP signal to work, to make mch_suspend() work.
1170 * For "rvim" the STOP signal is ignored.
1172 #ifdef SIGTSTP
1173 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
1174 #endif
1175 #ifdef _REENTRANT
1176 signal(SIGCONT, sigcont_handler);
1177 #endif
1180 * We want to ignore breaking of PIPEs.
1182 #ifdef SIGPIPE
1183 signal(SIGPIPE, SIG_IGN);
1184 #endif
1186 #ifdef SIGINT
1187 catch_int_signal();
1188 #endif
1191 * Ignore alarm signals (Perl's alarm() generates it).
1193 #ifdef SIGALRM
1194 signal(SIGALRM, SIG_IGN);
1195 #endif
1198 * Catch SIGPWR (power failure?) to preserve the swap files, so that no
1199 * work will be lost.
1201 #ifdef SIGPWR
1202 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
1203 #endif
1206 * Arrange for other signals to gracefully shutdown Vim.
1208 catch_signals(deathtrap, SIG_ERR);
1210 #if defined(FEAT_GUI) && defined(SIGHUP)
1212 * When the GUI is running, ignore the hangup signal.
1214 if (gui.in_use)
1215 signal(SIGHUP, SIG_IGN);
1216 #endif
1219 #if defined(SIGINT) || defined(PROTO)
1221 * Catch CTRL-C (only works while in Cooked mode).
1223 static void
1224 catch_int_signal()
1226 signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
1228 #endif
1230 void
1231 reset_signals()
1233 catch_signals(SIG_DFL, SIG_DFL);
1234 #ifdef _REENTRANT
1235 /* SIGCONT isn't in the list, because its default action is ignore */
1236 signal(SIGCONT, SIG_DFL);
1237 #endif
1240 static void
1241 catch_signals(func_deadly, func_other)
1242 RETSIGTYPE (*func_deadly)();
1243 RETSIGTYPE (*func_other)();
1245 int i;
1247 for (i = 0; signal_info[i].sig != -1; i++)
1248 if (signal_info[i].deadly)
1250 #if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
1251 struct sigaction sa;
1253 /* Setup to use the alternate stack for the signal function. */
1254 sa.sa_handler = func_deadly;
1255 sigemptyset(&sa.sa_mask);
1256 # if defined(__linux__) && defined(_REENTRANT)
1257 /* On Linux, with glibc compiled for kernel 2.2, there is a bug in
1258 * thread handling in combination with using the alternate stack:
1259 * pthread library functions try to use the stack pointer to
1260 * identify the current thread, causing a SEGV signal, which
1261 * recursively calls deathtrap() and hangs. */
1262 sa.sa_flags = 0;
1263 # else
1264 sa.sa_flags = SA_ONSTACK;
1265 # endif
1266 sigaction(signal_info[i].sig, &sa, NULL);
1267 #else
1268 # if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGVEC)
1269 struct sigvec sv;
1271 /* Setup to use the alternate stack for the signal function. */
1272 sv.sv_handler = func_deadly;
1273 sv.sv_mask = 0;
1274 sv.sv_flags = SV_ONSTACK;
1275 sigvec(signal_info[i].sig, &sv, NULL);
1276 # else
1277 signal(signal_info[i].sig, func_deadly);
1278 # endif
1279 #endif
1281 else if (func_other != SIG_ERR)
1282 signal(signal_info[i].sig, func_other);
1286 * Handling of SIGHUP, SIGQUIT and SIGTERM:
1287 * "when" == a signal: when busy, postpone and return FALSE, otherwise
1288 * return TRUE
1289 * "when" == SIGNAL_BLOCK: Going to be busy, block signals
1290 * "when" == SIGNAL_UNBLOCK: Going to wait, unblock signals, use postponed
1291 * signal
1292 * Returns TRUE when Vim should exit.
1295 vim_handle_signal(sig)
1296 int sig;
1298 static int got_signal = 0;
1299 static int blocked = TRUE;
1301 switch (sig)
1303 case SIGNAL_BLOCK: blocked = TRUE;
1304 break;
1306 case SIGNAL_UNBLOCK: blocked = FALSE;
1307 if (got_signal != 0)
1309 kill(getpid(), got_signal);
1310 got_signal = 0;
1312 break;
1314 default: if (!blocked)
1315 return TRUE; /* exit! */
1316 got_signal = sig;
1317 #ifdef SIGPWR
1318 if (sig != SIGPWR)
1319 #endif
1320 got_int = TRUE; /* break any loops */
1321 break;
1323 return FALSE;
1327 * Check_win checks whether we have an interactive stdout.
1329 /* ARGSUSED */
1331 mch_check_win(argc, argv)
1332 int argc;
1333 char **argv;
1335 #ifdef OS2
1337 * Store argv[0], may be used for $VIM. Only use it if it is an absolute
1338 * name, mostly it's just "vim" and found in the path, which is unusable.
1340 if (mch_isFullName(argv[0]))
1341 exe_name = vim_strsave((char_u *)argv[0]);
1342 #endif
1343 if (isatty(1))
1344 return OK;
1345 return FAIL;
1349 * Return TRUE if the input comes from a terminal, FALSE otherwise.
1352 mch_input_isatty()
1354 if (isatty(read_cmd_fd))
1355 return TRUE;
1356 return FALSE;
1359 #ifdef FEAT_X11
1361 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) \
1362 && (defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE))
1364 static void xopen_message __ARGS((struct timeval *tvp));
1367 * Give a message about the elapsed time for opening the X window.
1369 static void
1370 xopen_message(tvp)
1371 struct timeval *tvp; /* must contain start time */
1373 struct timeval end_tv;
1375 /* Compute elapsed time. */
1376 gettimeofday(&end_tv, NULL);
1377 smsg((char_u *)_("Opening the X display took %ld msec"),
1378 (end_tv.tv_sec - tvp->tv_sec) * 1000L
1379 + (end_tv.tv_usec - tvp->tv_usec) / 1000L);
1381 # endif
1382 #endif
1384 #if defined(FEAT_X11) && (defined(FEAT_TITLE) || defined(FEAT_XCLIPBOARD))
1386 * A few functions shared by X11 title and clipboard code.
1388 static int x_error_handler __ARGS((Display *dpy, XErrorEvent *error_event));
1389 static int x_error_check __ARGS((Display *dpy, XErrorEvent *error_event));
1390 static int x_connect_to_server __ARGS((void));
1391 static int test_x11_window __ARGS((Display *dpy));
1393 static int got_x_error = FALSE;
1396 * X Error handler, otherwise X just exits! (very rude) -- webb
1398 static int
1399 x_error_handler(dpy, error_event)
1400 Display *dpy;
1401 XErrorEvent *error_event;
1403 XGetErrorText(dpy, error_event->error_code, (char *)IObuff, IOSIZE);
1404 STRCAT(IObuff, _("\nVim: Got X error\n"));
1406 /* We cannot print a message and continue, because no X calls are allowed
1407 * here (causes my system to hang). Silently continuing might be an
1408 * alternative... */
1409 preserve_exit(); /* preserve files and exit */
1411 return 0; /* NOTREACHED */
1415 * Another X Error handler, just used to check for errors.
1417 /* ARGSUSED */
1418 static int
1419 x_error_check(dpy, error_event)
1420 Display *dpy;
1421 XErrorEvent *error_event;
1423 got_x_error = TRUE;
1424 return 0;
1427 #if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
1428 # if defined(HAVE_SETJMP_H)
1430 * An X IO Error handler, used to catch error while opening the display.
1432 static int x_IOerror_check __ARGS((Display *dpy));
1434 /* ARGSUSED */
1435 static int
1436 x_IOerror_check(dpy)
1437 Display *dpy;
1439 /* This function should not return, it causes exit(). Longjump instead. */
1440 LONGJMP(lc_jump_env, 1);
1441 /*NOTREACHED*/
1442 return 0;
1444 # endif
1447 * An X IO Error handler, used to catch terminal errors.
1449 static int x_IOerror_handler __ARGS((Display *dpy));
1451 /* ARGSUSED */
1452 static int
1453 x_IOerror_handler(dpy)
1454 Display *dpy;
1456 xterm_dpy = NULL;
1457 x11_window = 0;
1458 x11_display = NULL;
1459 xterm_Shell = (Widget)0;
1461 /* This function should not return, it causes exit(). Longjump instead. */
1462 LONGJMP(x_jump_env, 1);
1463 /*NOTREACHED*/
1464 return 0;
1466 #endif
1469 * Return TRUE when connection to the X server is desired.
1471 static int
1472 x_connect_to_server()
1474 regmatch_T regmatch;
1476 #if defined(FEAT_CLIENTSERVER)
1477 if (x_force_connect)
1478 return TRUE;
1479 #endif
1480 if (x_no_connect)
1481 return FALSE;
1483 /* Check for a match with "exclude:" from 'clipboard'. */
1484 if (clip_exclude_prog != NULL)
1486 regmatch.rm_ic = FALSE; /* Don't ignore case */
1487 regmatch.regprog = clip_exclude_prog;
1488 if (vim_regexec(&regmatch, T_NAME, (colnr_T)0))
1489 return FALSE;
1491 return TRUE;
1495 * Test if "dpy" and x11_window are valid by getting the window title.
1496 * I don't actually want it yet, so there may be a simpler call to use, but
1497 * this will cause the error handler x_error_check() to be called if anything
1498 * is wrong, such as the window pointer being invalid (as can happen when the
1499 * user changes his DISPLAY, but not his WINDOWID) -- webb
1501 static int
1502 test_x11_window(dpy)
1503 Display *dpy;
1505 int (*old_handler)();
1506 XTextProperty text_prop;
1508 old_handler = XSetErrorHandler(x_error_check);
1509 got_x_error = FALSE;
1510 if (XGetWMName(dpy, x11_window, &text_prop))
1511 XFree((void *)text_prop.value);
1512 XSync(dpy, False);
1513 (void)XSetErrorHandler(old_handler);
1515 if (p_verbose > 0 && got_x_error)
1516 verb_msg((char_u *)_("Testing the X display failed"));
1518 return (got_x_error ? FAIL : OK);
1520 #endif
1522 #ifdef FEAT_TITLE
1524 #ifdef FEAT_X11
1526 static int get_x11_thing __ARGS((int get_title, int test_only));
1529 * try to get x11 window and display
1531 * return FAIL for failure, OK otherwise
1533 static int
1534 get_x11_windis()
1536 char *winid;
1537 static int result = -1;
1538 #define XD_NONE 0 /* x11_display not set here */
1539 #define XD_HERE 1 /* x11_display opened here */
1540 #define XD_GUI 2 /* x11_display used from gui.dpy */
1541 #define XD_XTERM 3 /* x11_display used from xterm_dpy */
1542 static int x11_display_from = XD_NONE;
1543 static int did_set_error_handler = FALSE;
1545 if (!did_set_error_handler)
1547 /* X just exits if it finds an error otherwise! */
1548 (void)XSetErrorHandler(x_error_handler);
1549 did_set_error_handler = TRUE;
1552 #if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
1553 if (gui.in_use)
1556 * If the X11 display was opened here before, for the window where Vim
1557 * was started, close that one now to avoid a memory leak.
1559 if (x11_display_from == XD_HERE && x11_display != NULL)
1561 XCloseDisplay(x11_display);
1562 x11_display_from = XD_NONE;
1564 if (gui_get_x11_windis(&x11_window, &x11_display) == OK)
1566 x11_display_from = XD_GUI;
1567 return OK;
1569 x11_display = NULL;
1570 return FAIL;
1572 else if (x11_display_from == XD_GUI)
1574 /* GUI must have stopped somehow, clear x11_display */
1575 x11_window = 0;
1576 x11_display = NULL;
1577 x11_display_from = XD_NONE;
1579 #endif
1581 /* When started with the "-X" argument, don't try connecting. */
1582 if (!x_connect_to_server())
1583 return FAIL;
1586 * If WINDOWID not set, should try another method to find out
1587 * what the current window number is. The only code I know for
1588 * this is very complicated.
1589 * We assume that zero is invalid for WINDOWID.
1591 if (x11_window == 0 && (winid = getenv("WINDOWID")) != NULL)
1592 x11_window = (Window)atol(winid);
1594 #ifdef FEAT_XCLIPBOARD
1595 if (xterm_dpy != NULL && x11_window != 0)
1597 /* We may have checked it already, but Gnome terminal can move us to
1598 * another window, so we need to check every time. */
1599 if (x11_display_from != XD_XTERM)
1602 * If the X11 display was opened here before, for the window where
1603 * Vim was started, close that one now to avoid a memory leak.
1605 if (x11_display_from == XD_HERE && x11_display != NULL)
1606 XCloseDisplay(x11_display);
1607 x11_display = xterm_dpy;
1608 x11_display_from = XD_XTERM;
1610 if (test_x11_window(x11_display) == FAIL)
1612 /* probably bad $WINDOWID */
1613 x11_window = 0;
1614 x11_display = NULL;
1615 x11_display_from = XD_NONE;
1616 return FAIL;
1618 return OK;
1620 #endif
1622 if (x11_window == 0 || x11_display == NULL)
1623 result = -1;
1625 if (result != -1) /* Have already been here and set this */
1626 return result; /* Don't do all these X calls again */
1628 if (x11_window != 0 && x11_display == NULL)
1630 #ifdef SET_SIG_ALARM
1631 RETSIGTYPE (*sig_save)();
1632 #endif
1633 #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1634 struct timeval start_tv;
1636 if (p_verbose > 0)
1637 gettimeofday(&start_tv, NULL);
1638 #endif
1640 #ifdef SET_SIG_ALARM
1642 * Opening the Display may hang if the DISPLAY setting is wrong, or
1643 * the network connection is bad. Set an alarm timer to get out.
1645 sig_alarm_called = FALSE;
1646 sig_save = (RETSIGTYPE (*)())signal(SIGALRM,
1647 (RETSIGTYPE (*)())sig_alarm);
1648 alarm(2);
1649 #endif
1650 x11_display = XOpenDisplay(NULL);
1652 #ifdef SET_SIG_ALARM
1653 alarm(0);
1654 signal(SIGALRM, (RETSIGTYPE (*)())sig_save);
1655 if (p_verbose > 0 && sig_alarm_called)
1656 verb_msg((char_u *)_("Opening the X display timed out"));
1657 #endif
1658 if (x11_display != NULL)
1660 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1661 if (p_verbose > 0)
1663 verbose_enter();
1664 xopen_message(&start_tv);
1665 verbose_leave();
1667 # endif
1668 if (test_x11_window(x11_display) == FAIL)
1670 /* Maybe window id is bad */
1671 x11_window = 0;
1672 XCloseDisplay(x11_display);
1673 x11_display = NULL;
1675 else
1676 x11_display_from = XD_HERE;
1679 if (x11_window == 0 || x11_display == NULL)
1680 return (result = FAIL);
1681 return (result = OK);
1685 * Determine original x11 Window Title
1687 static int
1688 get_x11_title(test_only)
1689 int test_only;
1691 return get_x11_thing(TRUE, test_only);
1695 * Determine original x11 Window icon
1697 static int
1698 get_x11_icon(test_only)
1699 int test_only;
1701 int retval = FALSE;
1703 retval = get_x11_thing(FALSE, test_only);
1705 /* could not get old icon, use terminal name */
1706 if (oldicon == NULL && !test_only)
1708 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1709 oldicon = T_NAME + 8;
1710 else
1711 oldicon = T_NAME;
1714 return retval;
1717 static int
1718 get_x11_thing(get_title, test_only)
1719 int get_title; /* get title string */
1720 int test_only;
1722 XTextProperty text_prop;
1723 int retval = FALSE;
1724 Status status;
1726 if (get_x11_windis() == OK)
1728 /* Get window/icon name if any */
1729 if (get_title)
1730 status = XGetWMName(x11_display, x11_window, &text_prop);
1731 else
1732 status = XGetWMIconName(x11_display, x11_window, &text_prop);
1735 * If terminal is xterm, then x11_window may be a child window of the
1736 * outer xterm window that actually contains the window/icon name, so
1737 * keep traversing up the tree until a window with a title/icon is
1738 * found.
1740 /* Previously this was only done for xterm and alikes. I don't see a
1741 * reason why it would fail for other terminal emulators.
1742 * if (term_is_xterm) */
1744 Window root;
1745 Window parent;
1746 Window win = x11_window;
1747 Window *children;
1748 unsigned int num_children;
1750 while (!status || text_prop.value == NULL)
1752 if (!XQueryTree(x11_display, win, &root, &parent, &children,
1753 &num_children))
1754 break;
1755 if (children)
1756 XFree((void *)children);
1757 if (parent == root || parent == 0)
1758 break;
1760 win = parent;
1761 if (get_title)
1762 status = XGetWMName(x11_display, win, &text_prop);
1763 else
1764 status = XGetWMIconName(x11_display, win, &text_prop);
1767 if (status && text_prop.value != NULL)
1769 retval = TRUE;
1770 if (!test_only)
1772 #ifdef FEAT_XFONTSET
1773 if (text_prop.encoding == XA_STRING)
1775 #endif
1776 if (get_title)
1777 oldtitle = vim_strsave((char_u *)text_prop.value);
1778 else
1779 oldicon = vim_strsave((char_u *)text_prop.value);
1780 #ifdef FEAT_XFONTSET
1782 else
1784 char **cl;
1785 Status transform_status;
1786 int n = 0;
1788 transform_status = XmbTextPropertyToTextList(x11_display,
1789 &text_prop,
1790 &cl, &n);
1791 if (transform_status >= Success && n > 0 && cl[0])
1793 if (get_title)
1794 oldtitle = vim_strsave((char_u *) cl[0]);
1795 else
1796 oldicon = vim_strsave((char_u *) cl[0]);
1797 XFreeStringList(cl);
1799 else
1801 if (get_title)
1802 oldtitle = vim_strsave((char_u *)text_prop.value);
1803 else
1804 oldicon = vim_strsave((char_u *)text_prop.value);
1807 #endif
1809 XFree((void *)text_prop.value);
1812 return retval;
1815 /* Are Xutf8 functions available? Avoid error from old compilers. */
1816 #if defined(X_HAVE_UTF8_STRING) && defined(FEAT_MBYTE)
1817 # if X_HAVE_UTF8_STRING
1818 # define USE_UTF8_STRING
1819 # endif
1820 #endif
1823 * Set x11 Window Title
1825 * get_x11_windis() must be called before this and have returned OK
1827 static void
1828 set_x11_title(title)
1829 char_u *title;
1831 /* XmbSetWMProperties() and Xutf8SetWMProperties() should use a STRING
1832 * when possible, COMPOUND_TEXT otherwise. COMPOUND_TEXT isn't
1833 * supported everywhere and STRING doesn't work for multi-byte titles.
1835 #ifdef USE_UTF8_STRING
1836 if (enc_utf8)
1837 Xutf8SetWMProperties(x11_display, x11_window, (const char *)title,
1838 NULL, NULL, 0, NULL, NULL, NULL);
1839 else
1840 #endif
1842 #if XtSpecificationRelease >= 4
1843 # ifdef FEAT_XFONTSET
1844 XmbSetWMProperties(x11_display, x11_window, (const char *)title,
1845 NULL, NULL, 0, NULL, NULL, NULL);
1846 # else
1847 XTextProperty text_prop;
1848 char *c_title = (char *)title;
1850 /* directly from example 3-18 "basicwin" of Xlib Programming Manual */
1851 (void)XStringListToTextProperty(&c_title, 1, &text_prop);
1852 XSetWMProperties(x11_display, x11_window, &text_prop,
1853 NULL, NULL, 0, NULL, NULL, NULL);
1854 # endif
1855 #else
1856 XStoreName(x11_display, x11_window, (char *)title);
1857 #endif
1859 XFlush(x11_display);
1863 * Set x11 Window icon
1865 * get_x11_windis() must be called before this and have returned OK
1867 static void
1868 set_x11_icon(icon)
1869 char_u *icon;
1871 /* See above for comments about using X*SetWMProperties(). */
1872 #ifdef USE_UTF8_STRING
1873 if (enc_utf8)
1874 Xutf8SetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
1875 NULL, 0, NULL, NULL, NULL);
1876 else
1877 #endif
1879 #if XtSpecificationRelease >= 4
1880 # ifdef FEAT_XFONTSET
1881 XmbSetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
1882 NULL, 0, NULL, NULL, NULL);
1883 # else
1884 XTextProperty text_prop;
1885 char *c_icon = (char *)icon;
1887 (void)XStringListToTextProperty(&c_icon, 1, &text_prop);
1888 XSetWMProperties(x11_display, x11_window, NULL, &text_prop,
1889 NULL, 0, NULL, NULL, NULL);
1890 # endif
1891 #else
1892 XSetIconName(x11_display, x11_window, (char *)icon);
1893 #endif
1895 XFlush(x11_display);
1898 #else /* FEAT_X11 */
1900 /*ARGSUSED*/
1901 static int
1902 get_x11_title(test_only)
1903 int test_only;
1905 return FALSE;
1908 static int
1909 get_x11_icon(test_only)
1910 int test_only;
1912 if (!test_only)
1914 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1915 oldicon = T_NAME + 8;
1916 else
1917 oldicon = T_NAME;
1919 return FALSE;
1922 #endif /* FEAT_X11 */
1925 mch_can_restore_title()
1927 return get_x11_title(TRUE);
1931 mch_can_restore_icon()
1933 return get_x11_icon(TRUE);
1937 * Set the window title and icon.
1939 void
1940 mch_settitle(title, icon)
1941 char_u *title;
1942 char_u *icon;
1944 int type = 0;
1945 static int recursive = 0;
1947 if (T_NAME == NULL) /* no terminal name (yet) */
1948 return;
1949 if (title == NULL && icon == NULL) /* nothing to do */
1950 return;
1952 /* When one of the X11 functions causes a deadly signal, we get here again
1953 * recursively. Avoid hanging then (something is probably locked). */
1954 if (recursive)
1955 return;
1956 ++recursive;
1959 * if the window ID and the display is known, we may use X11 calls
1961 #ifdef FEAT_X11
1962 if (get_x11_windis() == OK)
1963 type = 1;
1964 #else
1965 # if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) \
1966 || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MACVIM)
1967 if (gui.in_use)
1968 type = 1;
1969 # endif
1970 #endif
1973 * Note: if "t_TS" is set, title is set with escape sequence rather
1974 * than x11 calls, because the x11 calls don't always work
1976 if ((type || *T_TS != NUL) && title != NULL)
1978 if (oldtitle == NULL
1979 #ifdef FEAT_GUI
1980 && !gui.in_use
1981 #endif
1982 ) /* first call but not in GUI, save title */
1983 (void)get_x11_title(FALSE);
1985 if (*T_TS != NUL) /* it's OK if t_fs is empty */
1986 term_settitle(title);
1987 #ifdef FEAT_X11
1988 else
1989 # ifdef FEAT_GUI_GTK
1990 if (!gui.in_use) /* don't do this if GTK+ is running */
1991 # endif
1992 set_x11_title(title); /* x11 */
1993 #endif
1994 #if defined(FEAT_GUI_GTK) \
1995 || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) \
1996 || defined(FEAT_GUI_MACVIM)
1997 else
1998 gui_mch_settitle(title, icon);
1999 #endif
2000 did_set_title = TRUE;
2003 if ((type || *T_CIS != NUL) && icon != NULL)
2005 if (oldicon == NULL
2006 #ifdef FEAT_GUI
2007 && !gui.in_use
2008 #endif
2009 ) /* first call, save icon */
2010 get_x11_icon(FALSE);
2012 if (*T_CIS != NUL)
2014 out_str(T_CIS); /* set icon start */
2015 out_str_nf(icon);
2016 out_str(T_CIE); /* set icon end */
2017 out_flush();
2019 #ifdef FEAT_X11
2020 else
2021 # ifdef FEAT_GUI_GTK
2022 if (!gui.in_use) /* don't do this if GTK+ is running */
2023 # endif
2024 set_x11_icon(icon); /* x11 */
2025 #endif
2026 did_set_icon = TRUE;
2028 --recursive;
2032 * Restore the window/icon title.
2033 * "which" is one of:
2034 * 1 only restore title
2035 * 2 only restore icon
2036 * 3 restore title and icon
2038 void
2039 mch_restore_title(which)
2040 int which;
2042 /* only restore the title or icon when it has been set */
2043 mch_settitle(((which & 1) && did_set_title) ?
2044 (oldtitle ? oldtitle : p_titleold) : NULL,
2045 ((which & 2) && did_set_icon) ? oldicon : NULL);
2048 #endif /* FEAT_TITLE */
2051 * Return TRUE if "name" looks like some xterm name.
2052 * Seiichi Sato mentioned that "mlterm" works like xterm.
2055 vim_is_xterm(name)
2056 char_u *name;
2058 if (name == NULL)
2059 return FALSE;
2060 return (STRNICMP(name, "xterm", 5) == 0
2061 || STRNICMP(name, "nxterm", 6) == 0
2062 || STRNICMP(name, "kterm", 5) == 0
2063 || STRNICMP(name, "mlterm", 6) == 0
2064 || STRNICMP(name, "rxvt", 4) == 0
2065 || STRCMP(name, "builtin_xterm") == 0);
2068 #if defined(FEAT_MOUSE_XTERM) || defined(PROTO)
2070 * Return TRUE if "name" appears to be that of a terminal
2071 * known to support the xterm-style mouse protocol.
2072 * Relies on term_is_xterm having been set to its correct value.
2075 use_xterm_like_mouse(name)
2076 char_u *name;
2078 return (name != NULL
2079 && (term_is_xterm || STRNICMP(name, "screen", 6) == 0));
2081 #endif
2083 #if defined(FEAT_MOUSE_TTY) || defined(PROTO)
2085 * Return non-zero when using an xterm mouse, according to 'ttymouse'.
2086 * Return 1 for "xterm".
2087 * Return 2 for "xterm2".
2090 use_xterm_mouse()
2092 if (ttym_flags == TTYM_XTERM2)
2093 return 2;
2094 if (ttym_flags == TTYM_XTERM)
2095 return 1;
2096 return 0;
2098 #endif
2101 vim_is_iris(name)
2102 char_u *name;
2104 if (name == NULL)
2105 return FALSE;
2106 return (STRNICMP(name, "iris-ansi", 9) == 0
2107 || STRCMP(name, "builtin_iris-ansi") == 0);
2111 vim_is_vt300(name)
2112 char_u *name;
2114 if (name == NULL)
2115 return FALSE; /* actually all ANSI comp. terminals should be here */
2116 /* catch VT100 - VT5xx */
2117 return ((STRNICMP(name, "vt", 2) == 0
2118 && vim_strchr((char_u *)"12345", name[2]) != NULL)
2119 || STRCMP(name, "builtin_vt320") == 0);
2123 * Return TRUE if "name" is a terminal for which 'ttyfast' should be set.
2124 * This should include all windowed terminal emulators.
2127 vim_is_fastterm(name)
2128 char_u *name;
2130 if (name == NULL)
2131 return FALSE;
2132 if (vim_is_xterm(name) || vim_is_vt300(name) || vim_is_iris(name))
2133 return TRUE;
2134 return ( STRNICMP(name, "hpterm", 6) == 0
2135 || STRNICMP(name, "sun-cmd", 7) == 0
2136 || STRNICMP(name, "screen", 6) == 0
2137 || STRNICMP(name, "dtterm", 6) == 0);
2141 * Insert user name in s[len].
2142 * Return OK if a name found.
2145 mch_get_user_name(s, len)
2146 char_u *s;
2147 int len;
2149 #ifdef VMS
2150 vim_strncpy(s, (char_u *)cuserid(NULL), len - 1);
2151 return OK;
2152 #else
2153 return mch_get_uname(getuid(), s, len);
2154 #endif
2158 * Insert user name for "uid" in s[len].
2159 * Return OK if a name found.
2162 mch_get_uname(uid, s, len)
2163 uid_t uid;
2164 char_u *s;
2165 int len;
2167 #if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
2168 struct passwd *pw;
2170 if ((pw = getpwuid(uid)) != NULL
2171 && pw->pw_name != NULL && *(pw->pw_name) != NUL)
2173 vim_strncpy(s, (char_u *)pw->pw_name, len - 1);
2174 return OK;
2176 #endif
2177 sprintf((char *)s, "%d", (int)uid); /* assumes s is long enough */
2178 return FAIL; /* a number is not a name */
2182 * Insert host name is s[len].
2185 #ifdef HAVE_SYS_UTSNAME_H
2186 void
2187 mch_get_host_name(s, len)
2188 char_u *s;
2189 int len;
2191 struct utsname vutsname;
2193 if (uname(&vutsname) < 0)
2194 *s = NUL;
2195 else
2196 vim_strncpy(s, (char_u *)vutsname.nodename, len - 1);
2198 #else /* HAVE_SYS_UTSNAME_H */
2200 # ifdef HAVE_SYS_SYSTEMINFO_H
2201 # define gethostname(nam, len) sysinfo(SI_HOSTNAME, nam, len)
2202 # endif
2204 void
2205 mch_get_host_name(s, len)
2206 char_u *s;
2207 int len;
2209 # ifdef VAXC
2210 vaxc$gethostname((char *)s, len);
2211 # else
2212 gethostname((char *)s, len);
2213 # endif
2214 s[len - 1] = NUL; /* make sure it's terminated */
2216 #endif /* HAVE_SYS_UTSNAME_H */
2219 * return process ID
2221 long
2222 mch_get_pid()
2224 return (long)getpid();
2227 #if !defined(HAVE_STRERROR) && defined(USE_GETCWD)
2228 static char *strerror __ARGS((int));
2230 static char *
2231 strerror(err)
2232 int err;
2234 extern int sys_nerr;
2235 extern char *sys_errlist[];
2236 static char er[20];
2238 if (err > 0 && err < sys_nerr)
2239 return (sys_errlist[err]);
2240 sprintf(er, "Error %d", err);
2241 return er;
2243 #endif
2246 * Get name of current directory into buffer 'buf' of length 'len' bytes.
2247 * Return OK for success, FAIL for failure.
2250 mch_dirname(buf, len)
2251 char_u *buf;
2252 int len;
2254 #if defined(USE_GETCWD)
2255 if (getcwd((char *)buf, len) == NULL)
2257 STRCPY(buf, strerror(errno));
2258 return FAIL;
2260 return OK;
2261 #else
2262 return (getwd((char *)buf) != NULL ? OK : FAIL);
2263 #endif
2266 #if defined(OS2) || defined(PROTO)
2268 * Replace all slashes by backslashes.
2269 * When 'shellslash' set do it the other way around.
2271 void
2272 slash_adjust(p)
2273 char_u *p;
2275 while (*p)
2277 if (*p == psepcN)
2278 *p = psepc;
2279 mb_ptr_adv(p);
2282 #endif
2285 * Get absolute file name into "buf[len]".
2287 * return FAIL for failure, OK for success
2290 mch_FullName(fname, buf, len, force)
2291 char_u *fname, *buf;
2292 int len;
2293 int force; /* also expand when already absolute path */
2295 int l;
2296 #ifdef OS2
2297 int only_drive; /* file name is only a drive letter */
2298 #endif
2299 #ifdef HAVE_FCHDIR
2300 int fd = -1;
2301 static int dont_fchdir = FALSE; /* TRUE when fchdir() doesn't work */
2302 #endif
2303 char_u olddir[MAXPATHL];
2304 char_u *p;
2305 int retval = OK;
2306 #ifdef __CYGWIN__
2307 char_u posix_fname[MAXPATHL]; /* Cygwin docs mention MAX_PATH, but
2308 it's not always defined */
2309 #endif
2311 #ifdef VMS
2312 fname = vms_fixfilename(fname);
2313 #endif
2315 #ifdef __CYGWIN__
2317 * This helps for when "/etc/hosts" is a symlink to "c:/something/hosts".
2319 # if CYGWIN_VERSION_DLL_MAJOR >= 1007
2320 cygwin_conv_path(CCP_WIN_A_TO_POSIX, fname, posix_fname, MAXPATHL);
2321 # else
2322 cygwin_conv_to_posix_path(fname, posix_fname);
2323 # endif
2324 fname = posix_fname;
2325 #endif
2327 /* expand it if forced or not an absolute path */
2328 if (force || !mch_isFullName(fname))
2331 * If the file name has a path, change to that directory for a moment,
2332 * and then do the getwd() (and get back to where we were).
2333 * This will get the correct path name with "../" things.
2335 #ifdef OS2
2336 only_drive = 0;
2337 if (((p = vim_strrchr(fname, '/')) != NULL)
2338 || ((p = vim_strrchr(fname, '\\')) != NULL)
2339 || (((p = vim_strchr(fname, ':')) != NULL) && ++only_drive))
2340 #else
2341 if ((p = vim_strrchr(fname, '/')) != NULL)
2342 #endif
2344 #ifdef HAVE_FCHDIR
2346 * Use fchdir() if possible, it's said to be faster and more
2347 * reliable. But on SunOS 4 it might not work. Check this by
2348 * doing a fchdir() right now.
2350 if (!dont_fchdir)
2352 fd = open(".", O_RDONLY | O_EXTRA, 0);
2353 if (fd >= 0 && fchdir(fd) < 0)
2355 close(fd);
2356 fd = -1;
2357 dont_fchdir = TRUE; /* don't try again */
2360 #endif
2362 /* Only change directory when we are sure we can return to where
2363 * we are now. After doing "su" chdir(".") might not work. */
2364 if (
2365 #ifdef HAVE_FCHDIR
2366 fd < 0 &&
2367 #endif
2368 (mch_dirname(olddir, MAXPATHL) == FAIL
2369 || mch_chdir((char *)olddir) != 0))
2371 p = NULL; /* can't get current dir: don't chdir */
2372 retval = FAIL;
2374 else
2376 #ifdef OS2
2378 * compensate for case where ':' from "D:" was the only
2379 * path separator detected in the file name; the _next_
2380 * character has to be removed, and then restored later.
2382 if (only_drive)
2383 p++;
2384 #endif
2385 /* The directory is copied into buf[], to be able to remove
2386 * the file name without changing it (could be a string in
2387 * read-only memory) */
2388 if (p - fname >= len)
2389 retval = FAIL;
2390 else
2392 vim_strncpy(buf, fname, p - fname);
2393 if (mch_chdir((char *)buf))
2394 retval = FAIL;
2395 else
2396 fname = p + 1;
2397 *buf = NUL;
2399 #ifdef OS2
2400 if (only_drive)
2402 p--;
2403 if (retval != FAIL)
2404 fname--;
2406 #endif
2409 if (mch_dirname(buf, len) == FAIL)
2411 retval = FAIL;
2412 *buf = NUL;
2414 if (p != NULL)
2416 #ifdef HAVE_FCHDIR
2417 if (fd >= 0)
2419 l = fchdir(fd);
2420 close(fd);
2422 else
2423 #endif
2424 l = mch_chdir((char *)olddir);
2425 if (l != 0)
2426 EMSG(_(e_prev_dir));
2429 l = STRLEN(buf);
2430 if (l >= len)
2431 retval = FAIL;
2432 #ifndef VMS
2433 else
2435 if (l > 0 && buf[l - 1] != '/' && *fname != NUL
2436 && STRCMP(fname, ".") != 0)
2437 STRCAT(buf, "/");
2439 #endif
2442 /* Catch file names which are too long. */
2443 if (retval == FAIL || STRLEN(buf) + STRLEN(fname) >= len)
2444 return FAIL;
2446 /* Do not append ".", "/dir/." is equal to "/dir". */
2447 if (STRCMP(fname, ".") != 0)
2448 STRCAT(buf, fname);
2450 return OK;
2454 * Return TRUE if "fname" does not depend on the current directory.
2457 mch_isFullName(fname)
2458 char_u *fname;
2460 #ifdef __EMX__
2461 return _fnisabs(fname);
2462 #else
2463 # ifdef VMS
2464 return ( fname[0] == '/' || fname[0] == '.' ||
2465 strchr((char *)fname,':') || strchr((char *)fname,'"') ||
2466 (strchr((char *)fname,'[') && strchr((char *)fname,']'))||
2467 (strchr((char *)fname,'<') && strchr((char *)fname,'>')) );
2468 # else
2469 return (*fname == '/' || *fname == '~');
2470 # endif
2471 #endif
2474 #if defined(USE_FNAME_CASE) || defined(PROTO)
2476 * Set the case of the file name, if it already exists. This will cause the
2477 * file name to remain exactly the same.
2478 * Only required for file systems where case is ignored and preserved.
2480 /*ARGSUSED*/
2481 void
2482 fname_case(name, len)
2483 char_u *name;
2484 int len; /* buffer size, only used when name gets longer */
2486 struct stat st;
2487 char_u *slash, *tail;
2488 DIR *dirp;
2489 struct dirent *dp;
2491 if (lstat((char *)name, &st) >= 0)
2493 /* Open the directory where the file is located. */
2494 slash = vim_strrchr(name, '/');
2495 if (slash == NULL)
2497 dirp = opendir(".");
2498 tail = name;
2500 else
2502 *slash = NUL;
2503 dirp = opendir((char *)name);
2504 *slash = '/';
2505 tail = slash + 1;
2508 if (dirp != NULL)
2510 while ((dp = readdir(dirp)) != NULL)
2512 /* Only accept names that differ in case and are the same byte
2513 * length. TODO: accept different length name. */
2514 if (STRICMP(tail, dp->d_name) == 0
2515 && STRLEN(tail) == STRLEN(dp->d_name))
2517 char_u newname[MAXPATHL + 1];
2518 struct stat st2;
2520 /* Verify the inode is equal. */
2521 vim_strncpy(newname, name, MAXPATHL);
2522 vim_strncpy(newname + (tail - name), (char_u *)dp->d_name,
2523 MAXPATHL - (tail - name));
2524 if (lstat((char *)newname, &st2) >= 0
2525 && st.st_ino == st2.st_ino
2526 && st.st_dev == st2.st_dev)
2528 STRCPY(tail, dp->d_name);
2529 break;
2534 closedir(dirp);
2538 #endif
2541 * Get file permissions for 'name'.
2542 * Returns -1 when it doesn't exist.
2544 long
2545 mch_getperm(name)
2546 char_u *name;
2548 struct stat statb;
2550 /* Keep the #ifdef outside of stat(), it may be a macro. */
2551 #ifdef VMS
2552 if (stat((char *)vms_fixfilename(name), &statb))
2553 #else
2554 if (stat((char *)name, &statb))
2555 #endif
2556 return -1;
2557 #ifdef __INTERIX
2558 /* The top bit makes the value negative, which means the file doesn't
2559 * exist. Remove the bit, we don't use it. */
2560 return statb.st_mode & ~S_ADDACE;
2561 #else
2562 return statb.st_mode;
2563 #endif
2567 * set file permission for 'name' to 'perm'
2569 * return FAIL for failure, OK otherwise
2572 mch_setperm(name, perm)
2573 char_u *name;
2574 long perm;
2576 return (chmod((char *)
2577 #ifdef VMS
2578 vms_fixfilename(name),
2579 #else
2580 name,
2581 #endif
2582 (mode_t)perm) == 0 ? OK : FAIL);
2585 #if defined(HAVE_ACL) || defined(PROTO)
2586 # ifdef HAVE_SYS_ACL_H
2587 # include <sys/acl.h>
2588 # endif
2589 # ifdef HAVE_SYS_ACCESS_H
2590 # include <sys/access.h>
2591 # endif
2593 # ifdef HAVE_SOLARIS_ACL
2594 typedef struct vim_acl_solaris_T {
2595 int acl_cnt;
2596 aclent_t *acl_entry;
2597 } vim_acl_solaris_T;
2598 # endif
2600 #if defined(HAVE_SELINUX) || defined(PROTO)
2602 * Copy security info from "from_file" to "to_file".
2604 void
2605 mch_copy_sec(from_file, to_file)
2606 char_u *from_file;
2607 char_u *to_file;
2609 if (from_file == NULL)
2610 return;
2612 if (selinux_enabled == -1)
2613 selinux_enabled = is_selinux_enabled();
2615 if (selinux_enabled > 0)
2617 security_context_t from_context = NULL;
2618 security_context_t to_context = NULL;
2620 if (getfilecon((char *)from_file, &from_context) < 0)
2622 /* If the filesystem doesn't support extended attributes,
2623 the original had no special security context and the
2624 target cannot have one either. */
2625 if (errno == EOPNOTSUPP)
2626 return;
2628 MSG_PUTS(_("\nCould not get security context for "));
2629 msg_outtrans(from_file);
2630 msg_putchar('\n');
2631 return;
2633 if (getfilecon((char *)to_file, &to_context) < 0)
2635 MSG_PUTS(_("\nCould not get security context for "));
2636 msg_outtrans(to_file);
2637 msg_putchar('\n');
2638 freecon (from_context);
2639 return ;
2641 if (strcmp(from_context, to_context) != 0)
2643 if (setfilecon((char *)to_file, from_context) < 0)
2645 MSG_PUTS(_("\nCould not set security context for "));
2646 msg_outtrans(to_file);
2647 msg_putchar('\n');
2650 freecon(to_context);
2651 freecon(from_context);
2654 #endif /* HAVE_SELINUX */
2657 * Return a pointer to the ACL of file "fname" in allocated memory.
2658 * Return NULL if the ACL is not available for whatever reason.
2660 vim_acl_T
2661 mch_get_acl(fname)
2662 char_u *fname;
2664 vim_acl_T ret = NULL;
2665 #ifdef HAVE_POSIX_ACL
2666 ret = (vim_acl_T)acl_get_file((char *)fname, ACL_TYPE_ACCESS);
2667 #else
2668 #ifdef HAVE_SOLARIS_ACL
2669 vim_acl_solaris_T *aclent;
2671 aclent = malloc(sizeof(vim_acl_solaris_T));
2672 if ((aclent->acl_cnt = acl((char *)fname, GETACLCNT, 0, NULL)) < 0)
2674 free(aclent);
2675 return NULL;
2677 aclent->acl_entry = malloc(aclent->acl_cnt * sizeof(aclent_t));
2678 if (acl((char *)fname, GETACL, aclent->acl_cnt, aclent->acl_entry) < 0)
2680 free(aclent->acl_entry);
2681 free(aclent);
2682 return NULL;
2684 ret = (vim_acl_T)aclent;
2685 #else
2686 #if defined(HAVE_AIX_ACL)
2687 int aclsize;
2688 struct acl *aclent;
2690 aclsize = sizeof(struct acl);
2691 aclent = malloc(aclsize);
2692 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2694 if (errno == ENOSPC)
2696 aclsize = aclent->acl_len;
2697 aclent = realloc(aclent, aclsize);
2698 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2700 free(aclent);
2701 return NULL;
2704 else
2706 free(aclent);
2707 return NULL;
2710 ret = (vim_acl_T)aclent;
2711 #endif /* HAVE_AIX_ACL */
2712 #endif /* HAVE_SOLARIS_ACL */
2713 #endif /* HAVE_POSIX_ACL */
2714 return ret;
2718 * Set the ACL of file "fname" to "acl" (unless it's NULL).
2720 void
2721 mch_set_acl(fname, aclent)
2722 char_u *fname;
2723 vim_acl_T aclent;
2725 if (aclent == NULL)
2726 return;
2727 #ifdef HAVE_POSIX_ACL
2728 acl_set_file((char *)fname, ACL_TYPE_ACCESS, (acl_t)aclent);
2729 #else
2730 #ifdef HAVE_SOLARIS_ACL
2731 acl((char *)fname, SETACL, ((vim_acl_solaris_T *)aclent)->acl_cnt,
2732 ((vim_acl_solaris_T *)aclent)->acl_entry);
2733 #else
2734 #ifdef HAVE_AIX_ACL
2735 chacl((char *)fname, aclent, ((struct acl *)aclent)->acl_len);
2736 #endif /* HAVE_AIX_ACL */
2737 #endif /* HAVE_SOLARIS_ACL */
2738 #endif /* HAVE_POSIX_ACL */
2741 void
2742 mch_free_acl(aclent)
2743 vim_acl_T aclent;
2745 if (aclent == NULL)
2746 return;
2747 #ifdef HAVE_POSIX_ACL
2748 acl_free((acl_t)aclent);
2749 #else
2750 #ifdef HAVE_SOLARIS_ACL
2751 free(((vim_acl_solaris_T *)aclent)->acl_entry);
2752 free(aclent);
2753 #else
2754 #ifdef HAVE_AIX_ACL
2755 free(aclent);
2756 #endif /* HAVE_AIX_ACL */
2757 #endif /* HAVE_SOLARIS_ACL */
2758 #endif /* HAVE_POSIX_ACL */
2760 #endif
2763 * Set hidden flag for "name".
2765 /* ARGSUSED */
2766 void
2767 mch_hide(name)
2768 char_u *name;
2770 /* can't hide a file */
2774 * return TRUE if "name" is a directory
2775 * return FALSE if "name" is not a directory
2776 * return FALSE for error
2779 mch_isdir(name)
2780 char_u *name;
2782 struct stat statb;
2784 if (*name == NUL) /* Some stat()s don't flag "" as an error. */
2785 return FALSE;
2786 if (stat((char *)name, &statb))
2787 return FALSE;
2788 #ifdef _POSIX_SOURCE
2789 return (S_ISDIR(statb.st_mode) ? TRUE : FALSE);
2790 #else
2791 return ((statb.st_mode & S_IFMT) == S_IFDIR ? TRUE : FALSE);
2792 #endif
2795 static int executable_file __ARGS((char_u *name));
2798 * Return 1 if "name" is an executable file, 0 if not or it doesn't exist.
2800 static int
2801 executable_file(name)
2802 char_u *name;
2804 struct stat st;
2806 if (stat((char *)name, &st))
2807 return 0;
2808 return S_ISREG(st.st_mode) && mch_access((char *)name, X_OK) == 0;
2812 * Return 1 if "name" can be found in $PATH and executed, 0 if not.
2813 * Return -1 if unknown.
2816 mch_can_exe(name)
2817 char_u *name;
2819 char_u *buf;
2820 char_u *p, *e;
2821 int retval;
2823 /* If it's an absolute or relative path don't need to use $PATH. */
2824 if (mch_isFullName(name) || (name[0] == '.' && (name[1] == '/'
2825 || (name[1] == '.' && name[2] == '/'))))
2826 return executable_file(name);
2828 p = (char_u *)getenv("PATH");
2829 if (p == NULL || *p == NUL)
2830 return -1;
2831 buf = alloc((unsigned)(STRLEN(name) + STRLEN(p) + 2));
2832 if (buf == NULL)
2833 return -1;
2836 * Walk through all entries in $PATH to check if "name" exists there and
2837 * is an executable file.
2839 for (;;)
2841 e = (char_u *)strchr((char *)p, ':');
2842 if (e == NULL)
2843 e = p + STRLEN(p);
2844 if (e - p <= 1) /* empty entry means current dir */
2845 STRCPY(buf, "./");
2846 else
2848 vim_strncpy(buf, p, e - p);
2849 add_pathsep(buf);
2851 STRCAT(buf, name);
2852 retval = executable_file(buf);
2853 if (retval == 1)
2854 break;
2856 if (*e != ':')
2857 break;
2858 p = e + 1;
2861 vim_free(buf);
2862 return retval;
2866 * Check what "name" is:
2867 * NODE_NORMAL: file or directory (or doesn't exist)
2868 * NODE_WRITABLE: writable device, socket, fifo, etc.
2869 * NODE_OTHER: non-writable things
2872 mch_nodetype(name)
2873 char_u *name;
2875 struct stat st;
2877 if (stat((char *)name, &st))
2878 return NODE_NORMAL;
2879 if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
2880 return NODE_NORMAL;
2881 #ifndef OS2
2882 if (S_ISBLK(st.st_mode)) /* block device isn't writable */
2883 return NODE_OTHER;
2884 #endif
2885 /* Everything else is writable? */
2886 return NODE_WRITABLE;
2889 void
2890 mch_early_init()
2892 #ifdef HAVE_CHECK_STACK_GROWTH
2893 int i;
2895 check_stack_growth((char *)&i);
2897 # ifdef HAVE_STACK_LIMIT
2898 get_stack_limit();
2899 # endif
2901 #endif
2904 * Setup an alternative stack for signals. Helps to catch signals when
2905 * running out of stack space.
2906 * Use of sigaltstack() is preferred, it's more portable.
2907 * Ignore any errors.
2909 #if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2910 signal_stack = malloc(SIGSTKSZ);
2911 init_signal_stack();
2912 #endif
2915 #if defined(EXITFREE) || defined(PROTO)
2916 void
2917 mch_free_mem()
2919 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
2920 if (clip_star.owned)
2921 clip_lose_selection(&clip_star);
2922 if (clip_plus.owned)
2923 clip_lose_selection(&clip_plus);
2924 # endif
2925 # if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
2926 if (xterm_Shell != (Widget)0)
2927 XtDestroyWidget(xterm_Shell);
2928 # ifndef LESSTIF_VERSION
2929 /* Lesstif crashes here, lose some memory */
2930 if (xterm_dpy != NULL)
2931 XtCloseDisplay(xterm_dpy);
2932 if (app_context != (XtAppContext)NULL)
2934 XtDestroyApplicationContext(app_context);
2935 # ifdef FEAT_X11
2936 x11_display = NULL; /* freed by XtDestroyApplicationContext() */
2937 # endif
2939 # endif
2940 # endif
2941 # ifdef FEAT_X11
2942 if (x11_display != NULL
2943 # ifdef FEAT_XCLIPBOARD
2944 && x11_display != xterm_dpy
2945 # endif
2947 XCloseDisplay(x11_display);
2948 # endif
2949 # if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2950 vim_free(signal_stack);
2951 signal_stack = NULL;
2952 # endif
2953 # ifdef FEAT_TITLE
2954 vim_free(oldtitle);
2955 vim_free(oldicon);
2956 # endif
2958 #endif
2960 static void exit_scroll __ARGS((void));
2963 * Output a newline when exiting.
2964 * Make sure the newline goes to the same stream as the text.
2966 static void
2967 exit_scroll()
2969 if (silent_mode)
2970 return;
2971 if (newline_on_exit || msg_didout)
2973 if (msg_use_printf())
2975 if (info_message)
2976 mch_msg("\n");
2977 else
2978 mch_errmsg("\r\n");
2980 else
2981 out_char('\n');
2983 else
2985 restore_cterm_colors(); /* get original colors back */
2986 msg_clr_eos_force(); /* clear the rest of the display */
2987 windgoto((int)Rows - 1, 0); /* may have moved the cursor */
2991 void
2992 mch_exit(r)
2993 int r;
2995 exiting = TRUE;
2997 #if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
2998 x11_export_final_selection();
2999 #endif
3001 #ifdef FEAT_GUI
3002 if (!gui.in_use)
3003 #endif
3005 settmode(TMODE_COOK);
3006 #ifdef FEAT_TITLE
3007 mch_restore_title(3); /* restore xterm title and icon name */
3008 #endif
3010 * When t_ti is not empty but it doesn't cause swapping terminal
3011 * pages, need to output a newline when msg_didout is set. But when
3012 * t_ti does swap pages it should not go to the shell page. Do this
3013 * before stoptermcap().
3015 if (swapping_screen() && !newline_on_exit)
3016 exit_scroll();
3018 /* Stop termcap: May need to check for T_CRV response, which
3019 * requires RAW mode. */
3020 stoptermcap();
3023 * A newline is only required after a message in the alternate screen.
3024 * This is set to TRUE by wait_return().
3026 if (!swapping_screen() || newline_on_exit)
3027 exit_scroll();
3029 /* Cursor may have been switched off without calling starttermcap()
3030 * when doing "vim -u vimrc" and vimrc contains ":q". */
3031 if (full_screen)
3032 cursor_on();
3034 out_flush();
3035 ml_close_all(TRUE); /* remove all memfiles */
3036 may_core_dump();
3037 #ifdef FEAT_GUI
3038 if (gui.in_use)
3039 gui_exit(r);
3040 #endif
3042 #ifdef MACOS_CONVERT
3043 mac_conv_cleanup();
3044 #endif
3046 #ifdef __QNX__
3047 /* A core dump won't be created if the signal handler
3048 * doesn't return, so we can't call exit() */
3049 if (deadly_signal != 0)
3050 return;
3051 #endif
3053 #ifdef FEAT_NETBEANS_INTG
3054 if (usingNetbeans)
3055 netbeans_send_disconnect();
3056 #endif
3058 #ifdef EXITFREE
3059 free_all_mem();
3060 #endif
3062 exit(r);
3065 static void
3066 may_core_dump()
3068 if (deadly_signal != 0)
3070 signal(deadly_signal, SIG_DFL);
3071 kill(getpid(), deadly_signal); /* Die using the signal we caught */
3075 #ifndef VMS
3077 void
3078 mch_settmode(tmode)
3079 int tmode;
3081 static int first = TRUE;
3083 /* Why is NeXT excluded here (and not in os_unixx.h)? */
3084 #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
3086 * for "new" tty systems
3088 # ifdef HAVE_TERMIOS_H
3089 static struct termios told;
3090 struct termios tnew;
3091 # else
3092 static struct termio told;
3093 struct termio tnew;
3094 # endif
3096 if (first)
3098 first = FALSE;
3099 # if defined(HAVE_TERMIOS_H)
3100 tcgetattr(read_cmd_fd, &told);
3101 # else
3102 ioctl(read_cmd_fd, TCGETA, &told);
3103 # endif
3106 tnew = told;
3107 if (tmode == TMODE_RAW)
3110 * ~ICRNL enables typing ^V^M
3112 tnew.c_iflag &= ~ICRNL;
3113 tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE
3114 # if defined(IEXTEN) && !defined(__MINT__)
3115 | IEXTEN /* IEXTEN enables typing ^V on SOLARIS */
3116 /* but it breaks function keys on MINT */
3117 # endif
3119 # ifdef ONLCR /* don't map NL -> CR NL, we do it ourselves */
3120 tnew.c_oflag &= ~ONLCR;
3121 # endif
3122 tnew.c_cc[VMIN] = 1; /* return after 1 char */
3123 tnew.c_cc[VTIME] = 0; /* don't wait */
3125 else if (tmode == TMODE_SLEEP)
3126 tnew.c_lflag &= ~(ECHO);
3128 # if defined(HAVE_TERMIOS_H)
3130 int n = 10;
3132 /* A signal may cause tcsetattr() to fail (e.g., SIGCONT). Retry a
3133 * few times. */
3134 while (tcsetattr(read_cmd_fd, TCSANOW, &tnew) == -1
3135 && errno == EINTR && n > 0)
3136 --n;
3138 # else
3139 ioctl(read_cmd_fd, TCSETA, &tnew);
3140 # endif
3142 #else
3145 * for "old" tty systems
3147 # ifndef TIOCSETN
3148 # define TIOCSETN TIOCSETP /* for hpux 9.0 */
3149 # endif
3150 static struct sgttyb ttybold;
3151 struct sgttyb ttybnew;
3153 if (first)
3155 first = FALSE;
3156 ioctl(read_cmd_fd, TIOCGETP, &ttybold);
3159 ttybnew = ttybold;
3160 if (tmode == TMODE_RAW)
3162 ttybnew.sg_flags &= ~(CRMOD | ECHO);
3163 ttybnew.sg_flags |= RAW;
3165 else if (tmode == TMODE_SLEEP)
3166 ttybnew.sg_flags &= ~(ECHO);
3167 ioctl(read_cmd_fd, TIOCSETN, &ttybnew);
3168 #endif
3169 curr_tmode = tmode;
3173 * Try to get the code for "t_kb" from the stty setting
3175 * Even if termcap claims a backspace key, the user's setting *should*
3176 * prevail. stty knows more about reality than termcap does, and if
3177 * somebody's usual erase key is DEL (which, for most BSD users, it will
3178 * be), they're going to get really annoyed if their erase key starts
3179 * doing forward deletes for no reason. (Eric Fischer)
3181 void
3182 get_stty()
3184 char_u buf[2];
3185 char_u *p;
3187 /* Why is NeXT excluded here (and not in os_unixx.h)? */
3188 #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
3189 /* for "new" tty systems */
3190 # ifdef HAVE_TERMIOS_H
3191 struct termios keys;
3192 # else
3193 struct termio keys;
3194 # endif
3196 # if defined(HAVE_TERMIOS_H)
3197 if (tcgetattr(read_cmd_fd, &keys) != -1)
3198 # else
3199 if (ioctl(read_cmd_fd, TCGETA, &keys) != -1)
3200 # endif
3202 buf[0] = keys.c_cc[VERASE];
3203 intr_char = keys.c_cc[VINTR];
3204 #else
3205 /* for "old" tty systems */
3206 struct sgttyb keys;
3208 if (ioctl(read_cmd_fd, TIOCGETP, &keys) != -1)
3210 buf[0] = keys.sg_erase;
3211 intr_char = keys.sg_kill;
3212 #endif
3213 buf[1] = NUL;
3214 add_termcode((char_u *)"kb", buf, FALSE);
3217 * If <BS> and <DEL> are now the same, redefine <DEL>.
3219 p = find_termcode((char_u *)"kD");
3220 if (p != NULL && p[0] == buf[0] && p[1] == buf[1])
3221 do_fixdel(NULL);
3223 #if 0
3224 } /* to keep cindent happy */
3225 #endif
3228 #endif /* VMS */
3230 #if defined(FEAT_MOUSE_TTY) || defined(PROTO)
3232 * Set mouse clicks on or off.
3234 void
3235 mch_setmouse(on)
3236 int on;
3238 static int ison = FALSE;
3239 int xterm_mouse_vers;
3241 if (on == ison) /* return quickly if nothing to do */
3242 return;
3244 xterm_mouse_vers = use_xterm_mouse();
3245 if (xterm_mouse_vers > 0)
3247 if (on) /* enable mouse events, use mouse tracking if available */
3248 out_str_nf((char_u *)
3249 (xterm_mouse_vers > 1
3250 ? IF_EB("\033[?1002h", ESC_STR "[?1002h")
3251 : IF_EB("\033[?1000h", ESC_STR "[?1000h")));
3252 else /* disable mouse events, could probably always send the same */
3253 out_str_nf((char_u *)
3254 (xterm_mouse_vers > 1
3255 ? IF_EB("\033[?1002l", ESC_STR "[?1002l")
3256 : IF_EB("\033[?1000l", ESC_STR "[?1000l")));
3257 ison = on;
3260 # ifdef FEAT_MOUSE_DEC
3261 else if (ttym_flags == TTYM_DEC)
3263 if (on) /* enable mouse events */
3264 out_str_nf((char_u *)"\033[1;2'z\033[1;3'{");
3265 else /* disable mouse events */
3266 out_str_nf((char_u *)"\033['z");
3267 ison = on;
3269 # endif
3271 # ifdef FEAT_MOUSE_GPM
3272 else
3274 if (on)
3276 if (gpm_open())
3277 ison = TRUE;
3279 else
3281 gpm_close();
3282 ison = FALSE;
3285 # endif
3287 # ifdef FEAT_SYSMOUSE
3288 else
3290 if (on)
3292 if (sysmouse_open() == OK)
3293 ison = TRUE;
3295 else
3297 sysmouse_close();
3298 ison = FALSE;
3301 # endif
3303 # ifdef FEAT_MOUSE_JSB
3304 else
3306 if (on)
3308 /* D - Enable Mouse up/down messages
3309 * L - Enable Left Button Reporting
3310 * M - Enable Middle Button Reporting
3311 * R - Enable Right Button Reporting
3312 * K - Enable SHIFT and CTRL key Reporting
3313 * + - Enable Advanced messaging of mouse moves and up/down messages
3314 * Q - Quiet No Ack
3315 * # - Numeric value of mouse pointer required
3316 * 0 = Multiview 2000 cursor, used as standard
3317 * 1 = Windows Arrow
3318 * 2 = Windows I Beam
3319 * 3 = Windows Hour Glass
3320 * 4 = Windows Cross Hair
3321 * 5 = Windows UP Arrow
3323 #ifdef JSBTERM_MOUSE_NONADVANCED /* Disables full feedback of pointer movements */
3324 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK1Q\033\\",
3325 ESC_STR "[0~ZwLMRK1Q" ESC_STR "\\"));
3326 #else
3327 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK+1Q\033\\",
3328 ESC_STR "[0~ZwLMRK+1Q" ESC_STR "\\"));
3329 #endif
3330 ison = TRUE;
3332 else
3334 out_str_nf((char_u *)IF_EB("\033[0~ZwQ\033\\",
3335 ESC_STR "[0~ZwQ" ESC_STR "\\"));
3336 ison = FALSE;
3339 # endif
3340 # ifdef FEAT_MOUSE_PTERM
3341 else
3343 /* 1 = button press, 6 = release, 7 = drag, 1h...9l = right button */
3344 if (on)
3345 out_str_nf("\033[>1h\033[>6h\033[>7h\033[>1h\033[>9l");
3346 else
3347 out_str_nf("\033[>1l\033[>6l\033[>7l\033[>1l\033[>9h");
3348 ison = on;
3350 # endif
3354 * Set the mouse termcode, depending on the 'term' and 'ttymouse' options.
3356 void
3357 check_mouse_termcode()
3359 # ifdef FEAT_MOUSE_XTERM
3360 if (use_xterm_mouse()
3361 # ifdef FEAT_GUI
3362 && !gui.in_use
3363 # endif
3366 set_mouse_termcode(KS_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3367 ? IF_EB("\233M", CSI_STR "M")
3368 : IF_EB("\033[M", ESC_STR "[M")));
3369 if (*p_mouse != NUL)
3371 /* force mouse off and maybe on to send possibly new mouse
3372 * activation sequence to the xterm, with(out) drag tracing. */
3373 mch_setmouse(FALSE);
3374 setmouse();
3377 else
3378 del_mouse_termcode(KS_MOUSE);
3379 # endif
3381 # ifdef FEAT_MOUSE_GPM
3382 if (!use_xterm_mouse()
3383 # ifdef FEAT_GUI
3384 && !gui.in_use
3385 # endif
3387 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MG", ESC_STR "MG"));
3388 # endif
3390 # ifdef FEAT_SYSMOUSE
3391 if (!use_xterm_mouse()
3392 # ifdef FEAT_GUI
3393 && !gui.in_use
3394 # endif
3396 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MS", ESC_STR "MS"));
3397 # endif
3399 # ifdef FEAT_MOUSE_JSB
3400 /* conflicts with xterm mouse: "\033[" and "\033[M" ??? */
3401 if (!use_xterm_mouse()
3402 # ifdef FEAT_GUI
3403 && !gui.in_use
3404 # endif
3406 set_mouse_termcode(KS_JSBTERM_MOUSE,
3407 (char_u *)IF_EB("\033[0~zw", ESC_STR "[0~zw"));
3408 else
3409 del_mouse_termcode(KS_JSBTERM_MOUSE);
3410 # endif
3412 # ifdef FEAT_MOUSE_NET
3413 /* There is no conflict, but one may type "ESC }" from Insert mode. Don't
3414 * define it in the GUI or when using an xterm. */
3415 if (!use_xterm_mouse()
3416 # ifdef FEAT_GUI
3417 && !gui.in_use
3418 # endif
3420 set_mouse_termcode(KS_NETTERM_MOUSE,
3421 (char_u *)IF_EB("\033}", ESC_STR "}"));
3422 else
3423 del_mouse_termcode(KS_NETTERM_MOUSE);
3424 # endif
3426 # ifdef FEAT_MOUSE_DEC
3427 /* conflicts with xterm mouse: "\033[" and "\033[M" */
3428 if (!use_xterm_mouse()
3429 # ifdef FEAT_GUI
3430 && !gui.in_use
3431 # endif
3433 set_mouse_termcode(KS_DEC_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3434 ? IF_EB("\233", CSI_STR) : IF_EB("\033[", ESC_STR "[")));
3435 else
3436 del_mouse_termcode(KS_DEC_MOUSE);
3437 # endif
3438 # ifdef FEAT_MOUSE_PTERM
3439 /* same as the dec mouse */
3440 if (!use_xterm_mouse()
3441 # ifdef FEAT_GUI
3442 && !gui.in_use
3443 # endif
3445 set_mouse_termcode(KS_PTERM_MOUSE,
3446 (char_u *) IF_EB("\033[", ESC_STR "["));
3447 else
3448 del_mouse_termcode(KS_PTERM_MOUSE);
3449 # endif
3451 #endif
3454 * set screen mode, always fails.
3456 /* ARGSUSED */
3458 mch_screenmode(arg)
3459 char_u *arg;
3461 EMSG(_(e_screenmode));
3462 return FAIL;
3465 #ifndef VMS
3468 * Try to get the current window size:
3469 * 1. with an ioctl(), most accurate method
3470 * 2. from the environment variables LINES and COLUMNS
3471 * 3. from the termcap
3472 * 4. keep using the old values
3473 * Return OK when size could be determined, FAIL otherwise.
3476 mch_get_shellsize()
3478 long rows = 0;
3479 long columns = 0;
3480 char_u *p;
3483 * For OS/2 use _scrsize().
3485 # ifdef __EMX__
3487 int s[2];
3489 _scrsize(s);
3490 columns = s[0];
3491 rows = s[1];
3493 # endif
3496 * 1. try using an ioctl. It is the most accurate method.
3498 * Try using TIOCGWINSZ first, some systems that have it also define
3499 * TIOCGSIZE but don't have a struct ttysize.
3501 # ifdef TIOCGWINSZ
3503 struct winsize ws;
3504 int fd = 1;
3506 /* When stdout is not a tty, use stdin for the ioctl(). */
3507 if (!isatty(fd) && isatty(read_cmd_fd))
3508 fd = read_cmd_fd;
3509 if (ioctl(fd, TIOCGWINSZ, &ws) == 0)
3511 columns = ws.ws_col;
3512 rows = ws.ws_row;
3515 # else /* TIOCGWINSZ */
3516 # ifdef TIOCGSIZE
3518 struct ttysize ts;
3519 int fd = 1;
3521 /* When stdout is not a tty, use stdin for the ioctl(). */
3522 if (!isatty(fd) && isatty(read_cmd_fd))
3523 fd = read_cmd_fd;
3524 if (ioctl(fd, TIOCGSIZE, &ts) == 0)
3526 columns = ts.ts_cols;
3527 rows = ts.ts_lines;
3530 # endif /* TIOCGSIZE */
3531 # endif /* TIOCGWINSZ */
3534 * 2. get size from environment
3535 * When being POSIX compliant ('|' flag in 'cpoptions') this overrules
3536 * the ioctl() values!
3538 if (columns == 0 || rows == 0 || vim_strchr(p_cpo, CPO_TSIZE) != NULL)
3540 if ((p = (char_u *)getenv("LINES")))
3541 rows = atoi((char *)p);
3542 if ((p = (char_u *)getenv("COLUMNS")))
3543 columns = atoi((char *)p);
3546 #ifdef HAVE_TGETENT
3548 * 3. try reading "co" and "li" entries from termcap
3550 if (columns == 0 || rows == 0)
3551 getlinecol(&columns, &rows);
3552 #endif
3555 * 4. If everything fails, use the old values
3557 if (columns <= 0 || rows <= 0)
3558 return FAIL;
3560 Rows = rows;
3561 Columns = columns;
3562 return OK;
3566 * Try to set the window size to Rows and Columns.
3568 void
3569 mch_set_shellsize()
3571 if (*T_CWS)
3574 * NOTE: if you get an error here that term_set_winsize() is
3575 * undefined, check the output of configure. It could probably not
3576 * find a ncurses, termcap or termlib library.
3578 term_set_winsize((int)Rows, (int)Columns);
3579 out_flush();
3580 screen_start(); /* don't know where cursor is now */
3584 #endif /* VMS */
3587 * Rows and/or Columns has changed.
3589 void
3590 mch_new_shellsize()
3592 /* Nothing to do. */
3595 #ifndef USE_SYSTEM
3596 static void append_ga_line __ARGS((garray_T *gap));
3599 * Append the text in "gap" below the cursor line and clear "gap".
3601 static void
3602 append_ga_line(gap)
3603 garray_T *gap;
3605 /* Remove trailing CR. */
3606 if (gap->ga_len > 0
3607 && !curbuf->b_p_bin
3608 && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR)
3609 --gap->ga_len;
3610 ga_append(gap, NUL);
3611 ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE);
3612 gap->ga_len = 0;
3614 #endif
3617 mch_call_shell(cmd, options)
3618 char_u *cmd;
3619 int options; /* SHELL_*, see vim.h */
3621 #ifdef VMS
3622 char *ifn = NULL;
3623 char *ofn = NULL;
3624 #endif
3625 int tmode = cur_tmode;
3626 #ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
3627 int x;
3628 # ifndef __EMX__
3629 char_u *newcmd; /* only needed for unix */
3630 # else
3632 * Set the preferred shell in the EMXSHELL environment variable (but
3633 * only if it is different from what is already in the environment).
3634 * Emx then takes care of whether to use "/c" or "-c" in an
3635 * intelligent way. Simply pass the whole thing to emx's system() call.
3636 * Emx also starts an interactive shell if system() is passed an empty
3637 * string.
3639 char_u *p, *old;
3641 if (((old = (char_u *)getenv("EMXSHELL")) == NULL) || STRCMP(old, p_sh))
3643 /* should check HAVE_SETENV, but I know we don't have it. */
3644 p = alloc(10 + strlen(p_sh));
3645 if (p)
3647 sprintf((char *)p, "EMXSHELL=%s", p_sh);
3648 putenv((char *)p); /* don't free the pointer! */
3651 # endif
3653 out_flush();
3655 if (options & SHELL_COOKED)
3656 settmode(TMODE_COOK); /* set to normal mode */
3658 # ifdef __EMX__
3659 if (cmd == NULL)
3660 x = system(""); /* this starts an interactive shell in emx */
3661 else
3662 x = system((char *)cmd);
3663 /* system() returns -1 when error occurs in starting shell */
3664 if (x == -1 && !emsg_silent)
3666 MSG_PUTS(_("\nCannot execute shell "));
3667 msg_outtrans(p_sh);
3668 msg_putchar('\n');
3670 # else /* not __EMX__ */
3671 if (cmd == NULL)
3672 x = system((char *)p_sh);
3673 else
3675 # ifdef VMS
3676 if (ofn = strchr((char *)cmd, '>'))
3677 *ofn++ = '\0';
3678 if (ifn = strchr((char *)cmd, '<'))
3680 char *p;
3682 *ifn++ = '\0';
3683 p = strchr(ifn,' '); /* chop off any trailing spaces */
3684 if (p)
3685 *p = '\0';
3687 if (ofn)
3688 x = vms_sys((char *)cmd, ofn, ifn);
3689 else
3690 x = system((char *)cmd);
3691 # else
3692 newcmd = lalloc(STRLEN(p_sh)
3693 + (extra_shell_arg == NULL ? 0 : STRLEN(extra_shell_arg))
3694 + STRLEN(p_shcf) + STRLEN(cmd) + 4, TRUE);
3695 if (newcmd == NULL)
3696 x = 0;
3697 else
3699 sprintf((char *)newcmd, "%s %s %s %s", p_sh,
3700 extra_shell_arg == NULL ? "" : (char *)extra_shell_arg,
3701 (char *)p_shcf,
3702 (char *)cmd);
3703 x = system((char *)newcmd);
3704 vim_free(newcmd);
3706 # endif
3708 # ifdef VMS
3709 x = vms_sys_status(x);
3710 # endif
3711 if (emsg_silent)
3713 else if (x == 127)
3714 MSG_PUTS(_("\nCannot execute shell sh\n"));
3715 # endif /* __EMX__ */
3716 else if (x && !(options & SHELL_SILENT))
3718 MSG_PUTS(_("\nshell returned "));
3719 msg_outnum((long)x);
3720 msg_putchar('\n');
3723 if (tmode == TMODE_RAW)
3724 settmode(TMODE_RAW); /* set to raw mode */
3725 # ifdef FEAT_TITLE
3726 resettitle();
3727 # endif
3728 return x;
3730 #else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
3732 # define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
3733 127, some shells use that already */
3735 char_u *newcmd = NULL;
3736 pid_t pid;
3737 pid_t wpid = 0;
3738 pid_t wait_pid = 0;
3739 # ifdef HAVE_UNION_WAIT
3740 union wait status;
3741 # else
3742 int status = -1;
3743 # endif
3744 int retval = -1;
3745 char **argv = NULL;
3746 int argc;
3747 int i;
3748 char_u *p;
3749 int inquote;
3750 int pty_master_fd = -1; /* for pty's */
3751 # ifdef FEAT_GUI
3752 int pty_slave_fd = -1;
3753 char *tty_name;
3754 # endif
3755 int fd_toshell[2]; /* for pipes */
3756 int fd_fromshell[2];
3757 int pipe_error = FALSE;
3758 # ifdef HAVE_SETENV
3759 char envbuf[50];
3760 # else
3761 static char envbuf_Rows[20];
3762 static char envbuf_Columns[20];
3763 # endif
3764 int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
3766 out_flush();
3767 if (options & SHELL_COOKED)
3768 settmode(TMODE_COOK); /* set to normal mode */
3770 newcmd = vim_strsave(p_sh);
3771 if (newcmd == NULL) /* out of memory */
3772 goto error;
3775 * Do this loop twice:
3776 * 1: find number of arguments
3777 * 2: separate them and build argv[]
3779 for (i = 0; i < 2; ++i)
3781 p = newcmd;
3782 inquote = FALSE;
3783 argc = 0;
3784 for (;;)
3786 if (i == 1)
3787 argv[argc] = (char *)p;
3788 ++argc;
3789 while (*p && (inquote || (*p != ' ' && *p != TAB)))
3791 if (*p == '"')
3792 inquote = !inquote;
3793 ++p;
3795 if (*p == NUL)
3796 break;
3797 if (i == 1)
3798 *p++ = NUL;
3799 p = skipwhite(p);
3801 if (argv == NULL)
3803 argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *)));
3804 if (argv == NULL) /* out of memory */
3805 goto error;
3808 if (cmd != NULL)
3810 if (extra_shell_arg != NULL)
3811 argv[argc++] = (char *)extra_shell_arg;
3812 argv[argc++] = (char *)p_shcf;
3813 argv[argc++] = (char *)cmd;
3815 argv[argc] = NULL;
3818 * For the GUI, when writing the output into the buffer and when reading
3819 * input from the buffer: Try using a pseudo-tty to get the stdin/stdout
3820 * of the executed command into the Vim window. Or use a pipe.
3822 if ((options & (SHELL_READ|SHELL_WRITE))
3823 # ifdef FEAT_GUI
3824 || (gui.in_use && show_shell_mess)
3825 # endif
3828 # ifdef FEAT_GUI
3830 * Try to open a master pty.
3831 * If this works, open the slave pty.
3832 * If the slave can't be opened, close the master pty.
3834 if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
3836 pty_master_fd = OpenPTY(&tty_name); /* open pty */
3837 if (pty_master_fd >= 0 && ((pty_slave_fd =
3838 open(tty_name, O_RDWR | O_EXTRA, 0)) < 0))
3840 close(pty_master_fd);
3841 pty_master_fd = -1;
3845 * If not opening a pty or it didn't work, try using pipes.
3847 if (pty_master_fd < 0)
3848 # endif
3850 pipe_error = (pipe(fd_toshell) < 0);
3851 if (!pipe_error) /* pipe create OK */
3853 pipe_error = (pipe(fd_fromshell) < 0);
3854 if (pipe_error) /* pipe create failed */
3856 close(fd_toshell[0]);
3857 close(fd_toshell[1]);
3860 if (pipe_error)
3862 MSG_PUTS(_("\nCannot create pipes\n"));
3863 out_flush();
3868 if (!pipe_error) /* pty or pipe opened or not used */
3870 # ifdef __BEOS__
3871 beos_cleanup_read_thread();
3872 # endif
3874 if ((pid = fork()) == -1) /* maybe we should use vfork() */
3876 MSG_PUTS(_("\nCannot fork\n"));
3877 if ((options & (SHELL_READ|SHELL_WRITE))
3878 # ifdef FEAT_GUI
3879 || (gui.in_use && show_shell_mess)
3880 # endif
3883 # ifdef FEAT_GUI
3884 if (pty_master_fd >= 0) /* close the pseudo tty */
3886 close(pty_master_fd);
3887 close(pty_slave_fd);
3889 else /* close the pipes */
3890 # endif
3892 close(fd_toshell[0]);
3893 close(fd_toshell[1]);
3894 close(fd_fromshell[0]);
3895 close(fd_fromshell[1]);
3899 else if (pid == 0) /* child */
3901 reset_signals(); /* handle signals normally */
3903 if (!show_shell_mess || (options & SHELL_EXPAND))
3905 int fd;
3908 * Don't want to show any message from the shell. Can't just
3909 * close stdout and stderr though, because some systems will
3910 * break if you try to write to them after that, so we must
3911 * use dup() to replace them with something else -- webb
3912 * Connect stdin to /dev/null too, so ":n `cat`" doesn't hang,
3913 * waiting for input.
3915 fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
3916 fclose(stdin);
3917 fclose(stdout);
3918 fclose(stderr);
3921 * If any of these open()'s and dup()'s fail, we just continue
3922 * anyway. It's not fatal, and on most systems it will make
3923 * no difference at all. On a few it will cause the execvp()
3924 * to exit with a non-zero status even when the completion
3925 * could be done, which is nothing too serious. If the open()
3926 * or dup() failed we'd just do the same thing ourselves
3927 * anyway -- webb
3929 if (fd >= 0)
3931 dup(fd); /* To replace stdin (file descriptor 0) */
3932 dup(fd); /* To replace stdout (file descriptor 1) */
3933 dup(fd); /* To replace stderr (file descriptor 2) */
3935 /* Don't need this now that we've duplicated it */
3936 close(fd);
3939 else if ((options & (SHELL_READ|SHELL_WRITE))
3940 # ifdef FEAT_GUI
3941 || gui.in_use
3942 # endif
3946 # ifdef HAVE_SETSID
3947 /* Create our own process group, so that the child and all its
3948 * children can be kill()ed. Don't do this when using pipes,
3949 * because stdin is not a tty, we would lose /dev/tty. */
3950 if (p_stmp)
3951 (void)setsid();
3952 # endif
3953 # ifdef FEAT_GUI
3954 if (pty_slave_fd >= 0)
3956 /* push stream discipline modules */
3957 if (options & SHELL_COOKED)
3958 SetupSlavePTY(pty_slave_fd);
3959 # if defined(TIOCSCTTY) && !defined(FEAT_GUI_MACVIM)
3960 /* Try to become controlling tty (probably doesn't work,
3961 * unless run by root) */
3962 ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
3963 # endif
3965 # endif
3966 /* Simulate to have a dumb terminal (for now) */
3967 # ifdef HAVE_SETENV
3968 setenv("TERM", "dumb", 1);
3969 sprintf((char *)envbuf, "%ld", Rows);
3970 setenv("ROWS", (char *)envbuf, 1);
3971 sprintf((char *)envbuf, "%ld", Rows);
3972 setenv("LINES", (char *)envbuf, 1);
3973 sprintf((char *)envbuf, "%ld", Columns);
3974 setenv("COLUMNS", (char *)envbuf, 1);
3975 # else
3977 * Putenv does not copy the string, it has to remain valid.
3978 * Use a static array to avoid losing allocated memory.
3980 putenv("TERM=dumb");
3981 sprintf(envbuf_Rows, "ROWS=%ld", Rows);
3982 putenv(envbuf_Rows);
3983 sprintf(envbuf_Rows, "LINES=%ld", Rows);
3984 putenv(envbuf_Rows);
3985 sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
3986 putenv(envbuf_Columns);
3987 # endif
3990 * stderr is only redirected when using the GUI, so that a
3991 * program like gpg can still access the terminal to get a
3992 * passphrase using stderr.
3994 # ifdef FEAT_GUI
3995 if (pty_master_fd >= 0)
3997 close(pty_master_fd); /* close master side of pty */
3999 /* set up stdin/stdout/stderr for the child */
4000 close(0);
4001 dup(pty_slave_fd);
4002 close(1);
4003 dup(pty_slave_fd);
4004 if (gui.in_use)
4006 close(2);
4007 dup(pty_slave_fd);
4010 close(pty_slave_fd); /* has been dupped, close it now */
4012 else
4013 # endif
4015 /* set up stdin for the child */
4016 close(fd_toshell[1]);
4017 close(0);
4018 dup(fd_toshell[0]);
4019 close(fd_toshell[0]);
4021 /* set up stdout for the child */
4022 close(fd_fromshell[0]);
4023 close(1);
4024 dup(fd_fromshell[1]);
4025 close(fd_fromshell[1]);
4027 # ifdef FEAT_GUI
4028 if (gui.in_use)
4030 /* set up stderr for the child */
4031 close(2);
4032 dup(1);
4034 # endif
4039 * There is no type cast for the argv, because the type may be
4040 * different on different machines. This may cause a warning
4041 * message with strict compilers, don't worry about it.
4042 * Call _exit() instead of exit() to avoid closing the connection
4043 * to the X server (esp. with GTK, which uses atexit()).
4045 execvp(argv[0], argv);
4046 _exit(EXEC_FAILED); /* exec failed, return failure code */
4048 else /* parent */
4051 * While child is running, ignore terminating signals.
4052 * Do catch CTRL-C, so that "got_int" is set.
4054 catch_signals(SIG_IGN, SIG_ERR);
4055 catch_int_signal();
4058 * For the GUI we redirect stdin, stdout and stderr to our window.
4059 * This is also used to pipe stdin/stdout to/from the external
4060 * command.
4062 if ((options & (SHELL_READ|SHELL_WRITE))
4063 # ifdef FEAT_GUI
4064 || (gui.in_use && show_shell_mess)
4065 # endif
4068 # define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
4069 char_u buffer[BUFLEN + 1];
4070 # ifdef FEAT_MBYTE
4071 int buffer_off = 0; /* valid bytes in buffer[] */
4072 # endif
4073 char_u ta_buf[BUFLEN + 1]; /* TypeAHead */
4074 int ta_len = 0; /* valid bytes in ta_buf[] */
4075 int len;
4076 int p_more_save;
4077 int old_State;
4078 int c;
4079 int toshell_fd;
4080 int fromshell_fd;
4081 garray_T ga;
4082 int noread_cnt;
4084 # ifdef FEAT_GUI
4085 if (pty_master_fd >= 0)
4087 close(pty_slave_fd); /* close slave side of pty */
4088 fromshell_fd = pty_master_fd;
4089 toshell_fd = dup(pty_master_fd);
4091 else
4092 # endif
4094 close(fd_toshell[0]);
4095 close(fd_fromshell[1]);
4096 toshell_fd = fd_toshell[1];
4097 fromshell_fd = fd_fromshell[0];
4101 * Write to the child if there are typed characters.
4102 * Read from the child if there are characters available.
4103 * Repeat the reading a few times if more characters are
4104 * available. Need to check for typed keys now and then, but
4105 * not too often (delays when no chars are available).
4106 * This loop is quit if no characters can be read from the pty
4107 * (WaitForChar detected special condition), or there are no
4108 * characters available and the child has exited.
4109 * Only check if the child has exited when there is no more
4110 * output. The child may exit before all the output has
4111 * been printed.
4113 * Currently this busy loops!
4114 * This can probably dead-lock when the write blocks!
4116 p_more_save = p_more;
4117 p_more = FALSE;
4118 old_State = State;
4119 State = EXTERNCMD; /* don't redraw at window resize */
4121 if ((options & SHELL_WRITE) && toshell_fd >= 0)
4123 /* Fork a process that will write the lines to the
4124 * external program. */
4125 if ((wpid = fork()) == -1)
4127 MSG_PUTS(_("\nCannot fork\n"));
4129 else if (wpid == 0)
4131 linenr_T lnum = curbuf->b_op_start.lnum;
4132 int written = 0;
4133 char_u *lp = ml_get(lnum);
4134 char_u *s;
4135 size_t l;
4137 /* child */
4138 close(fromshell_fd);
4139 for (;;)
4141 l = STRLEN(lp + written);
4142 if (l == 0)
4143 len = 0;
4144 else if (lp[written] == NL)
4145 /* NL -> NUL translation */
4146 len = write(toshell_fd, "", (size_t)1);
4147 else
4149 s = vim_strchr(lp + written, NL);
4150 len = write(toshell_fd, (char *)lp + written,
4151 s == NULL ? l : s - (lp + written));
4153 if (len == l)
4155 /* Finished a line, add a NL, unless this line
4156 * should not have one. */
4157 if (lnum != curbuf->b_op_end.lnum
4158 || !curbuf->b_p_bin
4159 || (lnum != write_no_eol_lnum
4160 && (lnum !=
4161 curbuf->b_ml.ml_line_count
4162 || curbuf->b_p_eol)))
4163 write(toshell_fd, "\n", (size_t)1);
4164 ++lnum;
4165 if (lnum > curbuf->b_op_end.lnum)
4167 /* finished all the lines, close pipe */
4168 close(toshell_fd);
4169 toshell_fd = -1;
4170 break;
4172 lp = ml_get(lnum);
4173 written = 0;
4175 else if (len > 0)
4176 written += len;
4178 _exit(0);
4180 else
4182 close(toshell_fd);
4183 toshell_fd = -1;
4187 if (options & SHELL_READ)
4188 ga_init2(&ga, 1, BUFLEN);
4190 noread_cnt = 0;
4192 for (;;)
4195 * Check if keys have been typed, write them to the child
4196 * if there are any.
4197 * Don't do this if we are expanding wild cards (would eat
4198 * typeahead).
4199 * Don't do this when filtering and terminal is in cooked
4200 * mode, the shell command will handle the I/O. Avoids
4201 * that a typed password is echoed for ssh or gpg command.
4202 * Don't get characters when the child has already
4203 * finished (wait_pid == 0).
4204 * Don't get extra characters when we already have one.
4205 * Don't read characters unless we didn't get output for a
4206 * while, avoids that ":r !ls" eats typeahead.
4208 len = 0;
4209 if (!(options & SHELL_EXPAND)
4210 && ((options &
4211 (SHELL_READ|SHELL_WRITE|SHELL_COOKED))
4212 != (SHELL_READ|SHELL_WRITE|SHELL_COOKED)
4213 #ifdef FEAT_GUI
4214 || gui.in_use
4215 #endif
4217 && wait_pid == 0
4218 && (ta_len > 0
4219 || (noread_cnt > 4
4220 && (len = ui_inchar(ta_buf,
4221 BUFLEN, 10L, 0)) > 0)))
4224 * For pipes:
4225 * Check for CTRL-C: send interrupt signal to child.
4226 * Check for CTRL-D: EOF, close pipe to child.
4228 if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
4230 # ifdef SIGINT
4232 * Send SIGINT to the child's group or all
4233 * processes in our group.
4235 if (ta_buf[ta_len] == Ctrl_C
4236 || ta_buf[ta_len] == intr_char)
4238 # ifdef HAVE_SETSID
4239 kill(-pid, SIGINT);
4240 # else
4241 kill(0, SIGINT);
4242 # endif
4243 if (wpid > 0)
4244 kill(wpid, SIGINT);
4246 # endif
4247 if (pty_master_fd < 0 && toshell_fd >= 0
4248 && ta_buf[ta_len] == Ctrl_D)
4250 close(toshell_fd);
4251 toshell_fd = -1;
4255 /* replace K_BS by <BS> and K_DEL by <DEL> */
4256 for (i = ta_len; i < ta_len + len; ++i)
4258 if (ta_buf[i] == CSI && len - i > 2)
4260 c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]);
4261 if (c == K_DEL || c == K_KDEL || c == K_BS)
4263 mch_memmove(ta_buf + i + 1, ta_buf + i + 3,
4264 (size_t)(len - i - 2));
4265 if (c == K_DEL || c == K_KDEL)
4266 ta_buf[i] = DEL;
4267 else
4268 ta_buf[i] = Ctrl_H;
4269 len -= 2;
4272 else if (ta_buf[i] == '\r')
4273 ta_buf[i] = '\n';
4274 # ifdef FEAT_MBYTE
4275 if (has_mbyte)
4276 i += (*mb_ptr2len)(ta_buf + i) - 1;
4277 # endif
4281 * For pipes: echo the typed characters.
4282 * For a pty this does not seem to work.
4284 if (pty_master_fd < 0)
4286 for (i = ta_len; i < ta_len + len; ++i)
4288 if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
4289 msg_putchar(ta_buf[i]);
4290 # ifdef FEAT_MBYTE
4291 else if (has_mbyte)
4293 int l = (*mb_ptr2len)(ta_buf + i);
4295 msg_outtrans_len(ta_buf + i, l);
4296 i += l - 1;
4298 # endif
4299 else
4300 msg_outtrans_len(ta_buf + i, 1);
4302 windgoto(msg_row, msg_col);
4303 out_flush();
4306 ta_len += len;
4309 * Write the characters to the child, unless EOF has
4310 * been typed for pipes. Write one character at a
4311 * time, to avoid losing too much typeahead.
4312 * When writing buffer lines, drop the typed
4313 * characters (only check for CTRL-C).
4315 if (options & SHELL_WRITE)
4316 ta_len = 0;
4317 else if (toshell_fd >= 0)
4319 len = write(toshell_fd, (char *)ta_buf, (size_t)1);
4320 if (len > 0)
4322 ta_len -= len;
4323 mch_memmove(ta_buf, ta_buf + len, ta_len);
4324 noread_cnt = 0;
4329 if (got_int)
4331 /* CTRL-C sends a signal to the child, we ignore it
4332 * ourselves */
4333 # ifdef HAVE_SETSID
4334 kill(-pid, SIGINT);
4335 # else
4336 kill(0, SIGINT);
4337 # endif
4338 if (wpid > 0)
4339 kill(wpid, SIGINT);
4340 got_int = FALSE;
4344 * Check if the child has any characters to be printed.
4345 * Read them and write them to our window. Repeat this as
4346 * long as there is something to do, avoid the 10ms wait
4347 * for mch_inchar(), or sending typeahead characters to
4348 * the external process.
4349 * TODO: This should handle escape sequences, compatible
4350 * to some terminal (vt52?).
4352 ++noread_cnt;
4353 while (RealWaitForChar(fromshell_fd, 10L, NULL))
4355 len = read(fromshell_fd, (char *)buffer
4356 # ifdef FEAT_MBYTE
4357 + buffer_off, (size_t)(BUFLEN - buffer_off)
4358 # else
4359 , (size_t)BUFLEN
4360 # endif
4362 if (len <= 0) /* end of file or error */
4363 goto finished;
4365 noread_cnt = 0;
4366 if (options & SHELL_READ)
4368 /* Do NUL -> NL translation, append NL separated
4369 * lines to the current buffer. */
4370 for (i = 0; i < len; ++i)
4372 if (buffer[i] == NL)
4373 append_ga_line(&ga);
4374 else if (buffer[i] == NUL)
4375 ga_append(&ga, NL);
4376 else
4377 ga_append(&ga, buffer[i]);
4380 # ifdef FEAT_MBYTE
4381 else if (has_mbyte)
4383 int l;
4385 len += buffer_off;
4386 buffer[len] = NUL;
4388 /* Check if the last character in buffer[] is
4389 * incomplete, keep these bytes for the next
4390 * round. */
4391 for (p = buffer; p < buffer + len; p += l)
4393 l = mb_cptr2len(p);
4394 if (l == 0)
4395 l = 1; /* NUL byte? */
4396 else if (MB_BYTE2LEN(*p) != l)
4397 break;
4399 if (p == buffer) /* no complete character */
4401 /* avoid getting stuck at an illegal byte */
4402 if (len >= 12)
4403 ++p;
4404 else
4406 buffer_off = len;
4407 continue;
4410 c = *p;
4411 *p = NUL;
4412 msg_puts(buffer);
4413 if (p < buffer + len)
4415 *p = c;
4416 buffer_off = (buffer + len) - p;
4417 mch_memmove(buffer, p, buffer_off);
4418 continue;
4420 buffer_off = 0;
4422 # endif /* FEAT_MBYTE */
4423 else
4425 buffer[len] = NUL;
4426 msg_puts(buffer);
4429 windgoto(msg_row, msg_col);
4430 cursor_on();
4431 out_flush();
4432 if (got_int)
4433 break;
4436 /* If we already detected the child has finished break the
4437 * loop now. */
4438 if (wait_pid == pid)
4439 break;
4442 * Check if the child still exists, before checking for
4443 * typed characters (otherwise we would lose typeahead).
4445 # ifdef __NeXT__
4446 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *) 0);
4447 # else
4448 wait_pid = waitpid(pid, &status, WNOHANG);
4449 # endif
4450 if ((wait_pid == (pid_t)-1 && errno == ECHILD)
4451 || (wait_pid == pid && WIFEXITED(status)))
4453 /* Don't break the loop yet, try reading more
4454 * characters from "fromshell_fd" first. When using
4455 * pipes there might still be something to read and
4456 * then we'll break the loop at the "break" above. */
4457 wait_pid = pid;
4459 else
4460 wait_pid = 0;
4462 finished:
4463 p_more = p_more_save;
4464 if (options & SHELL_READ)
4466 if (ga.ga_len > 0)
4468 append_ga_line(&ga);
4469 /* remember that the NL was missing */
4470 write_no_eol_lnum = curwin->w_cursor.lnum;
4472 else
4473 write_no_eol_lnum = 0;
4474 ga_clear(&ga);
4478 * Give all typeahead that wasn't used back to ui_inchar().
4480 if (ta_len)
4481 ui_inchar_undo(ta_buf, ta_len);
4482 State = old_State;
4483 if (toshell_fd >= 0)
4484 close(toshell_fd);
4485 close(fromshell_fd);
4489 * Wait until our child has exited.
4490 * Ignore wait() returning pids of other children and returning
4491 * because of some signal like SIGWINCH.
4492 * Don't wait if wait_pid was already set above, indicating the
4493 * child already exited.
4495 while (wait_pid != pid)
4497 # ifdef _THREAD_SAFE
4498 /* Ugly hack: when compiled with Python threads are probably
4499 * used, in which case wait() sometimes hangs for no obvious
4500 * reason. Use waitpid() instead and loop (like the GUI). */
4501 # ifdef __NeXT__
4502 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0);
4503 # else
4504 wait_pid = waitpid(pid, &status, WNOHANG);
4505 # endif
4506 if (wait_pid == 0)
4508 /* Wait for 1/100 sec before trying again. */
4509 mch_delay(10L, TRUE);
4510 continue;
4512 # else
4513 wait_pid = wait(&status);
4514 # endif
4515 if (wait_pid <= 0
4516 # ifdef ECHILD
4517 && errno == ECHILD
4518 # endif
4520 break;
4523 /* Make sure the child that writes to the external program is
4524 * dead. */
4525 if (wpid > 0)
4526 kill(wpid, SIGKILL);
4529 * Set to raw mode right now, otherwise a CTRL-C after
4530 * catch_signals() will kill Vim.
4532 if (tmode == TMODE_RAW)
4533 settmode(TMODE_RAW);
4534 did_settmode = TRUE;
4535 set_signals();
4537 if (WIFEXITED(status))
4539 /* LINTED avoid "bitwise operation on signed value" */
4540 retval = WEXITSTATUS(status);
4541 if (retval && !emsg_silent)
4543 if (retval == EXEC_FAILED)
4545 MSG_PUTS(_("\nCannot execute shell "));
4546 msg_outtrans(p_sh);
4547 msg_putchar('\n');
4549 else if (!(options & SHELL_SILENT))
4551 MSG_PUTS(_("\nshell returned "));
4552 msg_outnum((long)retval);
4553 msg_putchar('\n');
4557 else
4558 MSG_PUTS(_("\nCommand terminated\n"));
4561 vim_free(argv);
4563 error:
4564 if (!did_settmode)
4565 if (tmode == TMODE_RAW)
4566 settmode(TMODE_RAW); /* set to raw mode */
4567 # ifdef FEAT_TITLE
4568 resettitle();
4569 # endif
4570 vim_free(newcmd);
4572 return retval;
4574 #endif /* USE_SYSTEM */
4578 * Check for CTRL-C typed by reading all available characters.
4579 * In cooked mode we should get SIGINT, no need to check.
4581 void
4582 mch_breakcheck()
4584 if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL))
4585 fill_input_buf(FALSE);
4589 * Wait "msec" msec until a character is available from the keyboard or from
4590 * inbuf[]. msec == -1 will block forever.
4591 * When a GUI is being used, this will never get called -- webb
4593 static int
4594 WaitForChar(msec)
4595 long msec;
4597 #ifdef FEAT_MOUSE_GPM
4598 int gpm_process_wanted;
4599 #endif
4600 #ifdef FEAT_XCLIPBOARD
4601 int rest;
4602 #endif
4603 int avail;
4605 if (input_available()) /* something in inbuf[] */
4606 return 1;
4608 #if defined(FEAT_MOUSE_DEC)
4609 /* May need to query the mouse position. */
4610 if (WantQueryMouse)
4612 WantQueryMouse = FALSE;
4613 mch_write((char_u *)IF_EB("\033[1'|", ESC_STR "[1'|"), 5);
4615 #endif
4618 * For FEAT_MOUSE_GPM and FEAT_XCLIPBOARD we loop here to process mouse
4619 * events. This is a bit complicated, because they might both be defined.
4621 #if defined(FEAT_MOUSE_GPM) || defined(FEAT_XCLIPBOARD)
4622 # ifdef FEAT_XCLIPBOARD
4623 rest = 0;
4624 if (do_xterm_trace())
4625 rest = msec;
4626 # endif
4629 # ifdef FEAT_XCLIPBOARD
4630 if (rest != 0)
4632 msec = XT_TRACE_DELAY;
4633 if (rest >= 0 && rest < XT_TRACE_DELAY)
4634 msec = rest;
4635 if (rest >= 0)
4636 rest -= msec;
4638 # endif
4639 # ifdef FEAT_MOUSE_GPM
4640 gpm_process_wanted = 0;
4641 avail = RealWaitForChar(read_cmd_fd, msec, &gpm_process_wanted);
4642 # else
4643 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4644 # endif
4645 if (!avail)
4647 if (input_available())
4648 return 1;
4649 # ifdef FEAT_XCLIPBOARD
4650 if (rest == 0 || !do_xterm_trace())
4651 # endif
4652 break;
4655 while (FALSE
4656 # ifdef FEAT_MOUSE_GPM
4657 || (gpm_process_wanted && mch_gpm_process() == 0)
4658 # endif
4659 # ifdef FEAT_XCLIPBOARD
4660 || (!avail && rest != 0)
4661 # endif
4664 #else
4665 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4666 #endif
4667 return avail;
4671 * Wait "msec" msec until a character is available from file descriptor "fd".
4672 * Time == -1 will block forever.
4673 * When a GUI is being used, this will not be used for input -- webb
4674 * Returns also, when a request from Sniff is waiting -- toni.
4675 * Or when a Linux GPM mouse event is waiting.
4677 /* ARGSUSED */
4678 #if defined(__BEOS__)
4680 #else
4681 static int
4682 #endif
4683 RealWaitForChar(fd, msec, check_for_gpm)
4684 int fd;
4685 long msec;
4686 int *check_for_gpm;
4688 int ret;
4689 #if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4690 static int busy = FALSE;
4692 /* May retry getting characters after an event was handled. */
4693 # define MAY_LOOP
4695 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4696 /* Remember at what time we started, so that we know how much longer we
4697 * should wait after being interrupted. */
4698 # define USE_START_TV
4699 struct timeval start_tv;
4701 if (msec > 0 && (
4702 # ifdef FEAT_XCLIPBOARD
4703 xterm_Shell != (Widget)0
4704 # if defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4706 # endif
4707 # endif
4708 # ifdef USE_XSMP
4709 xsmp_icefd != -1
4710 # ifdef FEAT_MZSCHEME
4712 # endif
4713 # endif
4714 # ifdef FEAT_MZSCHEME
4715 (mzthreads_allowed() && p_mzq > 0)
4716 # endif
4718 gettimeofday(&start_tv, NULL);
4719 # endif
4721 /* Handle being called recursively. This may happen for the session
4722 * manager stuff, it may save the file, which does a breakcheck. */
4723 if (busy)
4724 return 0;
4725 #endif
4727 #ifdef MAY_LOOP
4728 for (;;)
4729 #endif
4731 #ifdef MAY_LOOP
4732 int finished = TRUE; /* default is to 'loop' just once */
4733 # ifdef FEAT_MZSCHEME
4734 int mzquantum_used = FALSE;
4735 # endif
4736 #endif
4737 #ifndef HAVE_SELECT
4738 struct pollfd fds[5];
4739 int nfd;
4740 # ifdef FEAT_XCLIPBOARD
4741 int xterm_idx = -1;
4742 # endif
4743 # ifdef FEAT_MOUSE_GPM
4744 int gpm_idx = -1;
4745 # endif
4746 # ifdef USE_XSMP
4747 int xsmp_idx = -1;
4748 # endif
4749 int towait = (int)msec;
4751 # ifdef FEAT_MZSCHEME
4752 mzvim_check_threads();
4753 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4755 towait = (int)p_mzq; /* don't wait longer than 'mzquantum' */
4756 mzquantum_used = TRUE;
4758 # endif
4759 fds[0].fd = fd;
4760 fds[0].events = POLLIN;
4761 nfd = 1;
4763 # ifdef FEAT_SNIFF
4764 # define SNIFF_IDX 1
4765 if (want_sniff_request)
4767 fds[SNIFF_IDX].fd = fd_from_sniff;
4768 fds[SNIFF_IDX].events = POLLIN;
4769 nfd++;
4771 # endif
4772 # ifdef FEAT_XCLIPBOARD
4773 if (xterm_Shell != (Widget)0)
4775 xterm_idx = nfd;
4776 fds[nfd].fd = ConnectionNumber(xterm_dpy);
4777 fds[nfd].events = POLLIN;
4778 nfd++;
4780 # endif
4781 # ifdef FEAT_MOUSE_GPM
4782 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4784 gpm_idx = nfd;
4785 fds[nfd].fd = gpm_fd;
4786 fds[nfd].events = POLLIN;
4787 nfd++;
4789 # endif
4790 # ifdef USE_XSMP
4791 if (xsmp_icefd != -1)
4793 xsmp_idx = nfd;
4794 fds[nfd].fd = xsmp_icefd;
4795 fds[nfd].events = POLLIN;
4796 nfd++;
4798 # endif
4800 ret = poll(fds, nfd, towait);
4801 # ifdef FEAT_MZSCHEME
4802 if (ret == 0 && mzquantum_used)
4803 /* MzThreads scheduling is required and timeout occurred */
4804 finished = FALSE;
4805 # endif
4807 # ifdef FEAT_SNIFF
4808 if (ret < 0)
4809 sniff_disconnect(1);
4810 else if (want_sniff_request)
4812 if (fds[SNIFF_IDX].revents & POLLHUP)
4813 sniff_disconnect(1);
4814 if (fds[SNIFF_IDX].revents & POLLIN)
4815 sniff_request_waiting = 1;
4817 # endif
4818 # ifdef FEAT_XCLIPBOARD
4819 if (xterm_Shell != (Widget)0 && (fds[xterm_idx].revents & POLLIN))
4821 xterm_update(); /* Maybe we should hand out clipboard */
4822 if (--ret == 0 && !input_available())
4823 /* Try again */
4824 finished = FALSE;
4826 # endif
4827 # ifdef FEAT_MOUSE_GPM
4828 if (gpm_idx >= 0 && (fds[gpm_idx].revents & POLLIN))
4830 *check_for_gpm = 1;
4832 # endif
4833 # ifdef USE_XSMP
4834 if (xsmp_idx >= 0 && (fds[xsmp_idx].revents & (POLLIN | POLLHUP)))
4836 if (fds[xsmp_idx].revents & POLLIN)
4838 busy = TRUE;
4839 xsmp_handle_requests();
4840 busy = FALSE;
4842 else if (fds[xsmp_idx].revents & POLLHUP)
4844 if (p_verbose > 0)
4845 verb_msg((char_u *)_("XSMP lost ICE connection"));
4846 xsmp_close();
4848 if (--ret == 0)
4849 finished = FALSE; /* Try again */
4851 # endif
4854 #else /* HAVE_SELECT */
4856 struct timeval tv;
4857 struct timeval *tvp;
4858 fd_set rfds, efds;
4859 int maxfd;
4860 long towait = msec;
4862 # ifdef FEAT_MZSCHEME
4863 mzvim_check_threads();
4864 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4866 towait = p_mzq; /* don't wait longer than 'mzquantum' */
4867 mzquantum_used = TRUE;
4869 # endif
4870 # ifdef __EMX__
4871 /* don't check for incoming chars if not in raw mode, because select()
4872 * always returns TRUE then (in some version of emx.dll) */
4873 if (curr_tmode != TMODE_RAW)
4874 return 0;
4875 # endif
4877 if (towait >= 0)
4879 tv.tv_sec = towait / 1000;
4880 tv.tv_usec = (towait % 1000) * (1000000/1000);
4881 tvp = &tv;
4883 else
4884 tvp = NULL;
4887 * Select on ready for reading and exceptional condition (end of file).
4889 FD_ZERO(&rfds); /* calls bzero() on a sun */
4890 FD_ZERO(&efds);
4891 FD_SET(fd, &rfds);
4892 # if !defined(__QNX__) && !defined(__CYGWIN32__)
4893 /* For QNX select() always returns 1 if this is set. Why? */
4894 FD_SET(fd, &efds);
4895 # endif
4896 maxfd = fd;
4898 # ifdef FEAT_SNIFF
4899 if (want_sniff_request)
4901 FD_SET(fd_from_sniff, &rfds);
4902 FD_SET(fd_from_sniff, &efds);
4903 if (maxfd < fd_from_sniff)
4904 maxfd = fd_from_sniff;
4906 # endif
4907 # ifdef FEAT_XCLIPBOARD
4908 if (xterm_Shell != (Widget)0)
4910 FD_SET(ConnectionNumber(xterm_dpy), &rfds);
4911 if (maxfd < ConnectionNumber(xterm_dpy))
4912 maxfd = ConnectionNumber(xterm_dpy);
4914 # endif
4915 # ifdef FEAT_MOUSE_GPM
4916 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4918 FD_SET(gpm_fd, &rfds);
4919 FD_SET(gpm_fd, &efds);
4920 if (maxfd < gpm_fd)
4921 maxfd = gpm_fd;
4923 # endif
4924 # ifdef USE_XSMP
4925 if (xsmp_icefd != -1)
4927 FD_SET(xsmp_icefd, &rfds);
4928 FD_SET(xsmp_icefd, &efds);
4929 if (maxfd < xsmp_icefd)
4930 maxfd = xsmp_icefd;
4932 # endif
4934 # ifdef OLD_VMS
4935 /* Old VMS as v6.2 and older have broken select(). It waits more than
4936 * required. Should not be used */
4937 ret = 0;
4938 # else
4939 ret = select(maxfd + 1, &rfds, NULL, &efds, tvp);
4940 # endif
4941 # ifdef __TANDEM
4942 if (ret == -1 && errno == ENOTSUP)
4944 FD_ZERO(&rfds);
4945 FD_ZERO(&efds);
4946 ret = 0;
4948 #endif
4949 # ifdef FEAT_MZSCHEME
4950 if (ret == 0 && mzquantum_used)
4951 /* loop if MzThreads must be scheduled and timeout occurred */
4952 finished = FALSE;
4953 # endif
4955 # ifdef FEAT_SNIFF
4956 if (ret < 0 )
4957 sniff_disconnect(1);
4958 else if (ret > 0 && want_sniff_request)
4960 if (FD_ISSET(fd_from_sniff, &efds))
4961 sniff_disconnect(1);
4962 if (FD_ISSET(fd_from_sniff, &rfds))
4963 sniff_request_waiting = 1;
4965 # endif
4966 # ifdef FEAT_XCLIPBOARD
4967 if (ret > 0 && xterm_Shell != (Widget)0
4968 && FD_ISSET(ConnectionNumber(xterm_dpy), &rfds))
4970 xterm_update(); /* Maybe we should hand out clipboard */
4971 /* continue looping when we only got the X event and the input
4972 * buffer is empty */
4973 if (--ret == 0 && !input_available())
4975 /* Try again */
4976 finished = FALSE;
4979 # endif
4980 # ifdef FEAT_MOUSE_GPM
4981 if (ret > 0 && gpm_flag && check_for_gpm != NULL && gpm_fd >= 0)
4983 if (FD_ISSET(gpm_fd, &efds))
4984 gpm_close();
4985 else if (FD_ISSET(gpm_fd, &rfds))
4986 *check_for_gpm = 1;
4988 # endif
4989 # ifdef USE_XSMP
4990 if (ret > 0 && xsmp_icefd != -1)
4992 if (FD_ISSET(xsmp_icefd, &efds))
4994 if (p_verbose > 0)
4995 verb_msg((char_u *)_("XSMP lost ICE connection"));
4996 xsmp_close();
4997 if (--ret == 0)
4998 finished = FALSE; /* keep going if event was only one */
5000 else if (FD_ISSET(xsmp_icefd, &rfds))
5002 busy = TRUE;
5003 xsmp_handle_requests();
5004 busy = FALSE;
5005 if (--ret == 0)
5006 finished = FALSE; /* keep going if event was only one */
5009 # endif
5011 #endif /* HAVE_SELECT */
5013 #ifdef MAY_LOOP
5014 if (finished || msec == 0)
5015 break;
5017 /* We're going to loop around again, find out for how long */
5018 if (msec > 0)
5020 # ifdef USE_START_TV
5021 struct timeval mtv;
5023 /* Compute remaining wait time. */
5024 gettimeofday(&mtv, NULL);
5025 msec -= (mtv.tv_sec - start_tv.tv_sec) * 1000L
5026 + (mtv.tv_usec - start_tv.tv_usec) / 1000L;
5027 # else
5028 /* Guess we got interrupted halfway. */
5029 msec = msec / 2;
5030 # endif
5031 if (msec <= 0)
5032 break; /* waited long enough */
5034 #endif
5037 return (ret > 0);
5040 #ifndef VMS
5042 #ifndef NO_EXPANDPATH
5044 * Expand a path into all matching files and/or directories. Handles "*",
5045 * "?", "[a-z]", "**", etc.
5046 * "path" has backslashes before chars that are not to be expanded.
5047 * Returns the number of matches found.
5050 mch_expandpath(gap, path, flags)
5051 garray_T *gap;
5052 char_u *path;
5053 int flags; /* EW_* flags */
5055 return unix_expandpath(gap, path, 0, flags, FALSE);
5057 #endif
5060 * mch_expand_wildcards() - this code does wild-card pattern matching using
5061 * the shell
5063 * return OK for success, FAIL for error (you may lose some memory) and put
5064 * an error message in *file.
5066 * num_pat is number of input patterns
5067 * pat is array of pointers to input patterns
5068 * num_file is pointer to number of matched file names
5069 * file is pointer to array of pointers to matched file names
5072 #ifndef SEEK_SET
5073 # define SEEK_SET 0
5074 #endif
5075 #ifndef SEEK_END
5076 # define SEEK_END 2
5077 #endif
5079 #define SHELL_SPECIAL (char_u *)"\t \"&'$;<>()\\|"
5081 /* ARGSUSED */
5083 mch_expand_wildcards(num_pat, pat, num_file, file, flags)
5084 int num_pat;
5085 char_u **pat;
5086 int *num_file;
5087 char_u ***file;
5088 int flags; /* EW_* flags */
5090 int i;
5091 size_t len;
5092 char_u *p;
5093 int dir;
5094 #ifdef __EMX__
5096 * This is the OS/2 implementation.
5098 # define EXPL_ALLOC_INC 16
5099 char_u **expl_files;
5100 size_t files_alloced, files_free;
5101 char_u *buf;
5102 int has_wildcard;
5104 *num_file = 0; /* default: no files found */
5105 files_alloced = EXPL_ALLOC_INC; /* how much space is allocated */
5106 files_free = EXPL_ALLOC_INC; /* how much space is not used */
5107 *file = (char_u **)alloc(sizeof(char_u **) * files_alloced);
5108 if (*file == NULL)
5109 return FAIL;
5111 for (; num_pat > 0; num_pat--, pat++)
5113 expl_files = NULL;
5114 if (vim_strchr(*pat, '$') || vim_strchr(*pat, '~'))
5115 /* expand environment var or home dir */
5116 buf = expand_env_save(*pat);
5117 else
5118 buf = vim_strsave(*pat);
5119 expl_files = NULL;
5120 has_wildcard = mch_has_exp_wildcard(buf); /* (still) wildcards? */
5121 if (has_wildcard) /* yes, so expand them */
5122 expl_files = (char_u **)_fnexplode(buf);
5125 * return value of buf if no wildcards left,
5126 * OR if no match AND EW_NOTFOUND is set.
5128 if ((!has_wildcard && ((flags & EW_NOTFOUND) || mch_getperm(buf) >= 0))
5129 || (expl_files == NULL && (flags & EW_NOTFOUND)))
5130 { /* simply save the current contents of *buf */
5131 expl_files = (char_u **)alloc(sizeof(char_u **) * 2);
5132 if (expl_files != NULL)
5134 expl_files[0] = vim_strsave(buf);
5135 expl_files[1] = NULL;
5138 vim_free(buf);
5141 * Count number of names resulting from expansion,
5142 * At the same time add a backslash to the end of names that happen to
5143 * be directories, and replace slashes with backslashes.
5145 if (expl_files)
5147 for (i = 0; (p = expl_files[i]) != NULL; i++)
5149 dir = mch_isdir(p);
5150 /* If we don't want dirs and this is one, skip it */
5151 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5152 continue;
5154 /* Skip files that are not executable if we check for that. */
5155 if (!dir && (flags & EW_EXEC) && !mch_can_exe(p))
5156 continue;
5158 if (--files_free == 0)
5160 /* need more room in table of pointers */
5161 files_alloced += EXPL_ALLOC_INC;
5162 *file = (char_u **)vim_realloc(*file,
5163 sizeof(char_u **) * files_alloced);
5164 if (*file == NULL)
5166 EMSG(_(e_outofmem));
5167 *num_file = 0;
5168 return FAIL;
5170 files_free = EXPL_ALLOC_INC;
5172 slash_adjust(p);
5173 if (dir)
5175 /* For a directory we add a '/', unless it's already
5176 * there. */
5177 len = STRLEN(p);
5178 if (((*file)[*num_file] = alloc(len + 2)) != NULL)
5180 STRCPY((*file)[*num_file], p);
5181 if (!after_pathsep((*file)[*num_file],
5182 (*file)[*num_file] + len))
5184 (*file)[*num_file][len] = psepc;
5185 (*file)[*num_file][len + 1] = NUL;
5189 else
5191 (*file)[*num_file] = vim_strsave(p);
5195 * Error message already given by either alloc or vim_strsave.
5196 * Should return FAIL, but returning OK works also.
5198 if ((*file)[*num_file] == NULL)
5199 break;
5200 (*num_file)++;
5202 _fnexplodefree((char **)expl_files);
5205 return OK;
5207 #else /* __EMX__ */
5209 * This is the non-OS/2 implementation (really Unix).
5211 int j;
5212 char_u *tempname;
5213 char_u *command;
5214 FILE *fd;
5215 char_u *buffer;
5216 #define STYLE_ECHO 0 /* use "echo", the default */
5217 #define STYLE_GLOB 1 /* use "glob", for csh */
5218 #define STYLE_VIMGLOB 2 /* use "vimglob", for Posix sh */
5219 #define STYLE_PRINT 3 /* use "print -N", for zsh */
5220 #define STYLE_BT 4 /* `cmd` expansion, execute the pattern
5221 * directly */
5222 int shell_style = STYLE_ECHO;
5223 int check_spaces;
5224 static int did_find_nul = FALSE;
5225 int ampersent = FALSE;
5226 /* vimglob() function to define for Posix shell */
5227 static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >";
5229 *num_file = 0; /* default: no files found */
5230 *file = NULL;
5233 * If there are no wildcards, just copy the names to allocated memory.
5234 * Saves a lot of time, because we don't have to start a new shell.
5236 if (!have_wildcard(num_pat, pat))
5237 return save_patterns(num_pat, pat, num_file, file);
5239 # ifdef HAVE_SANDBOX
5240 /* Don't allow any shell command in the sandbox. */
5241 if (sandbox != 0 && check_secure())
5242 return FAIL;
5243 # endif
5246 * Don't allow the use of backticks in secure and restricted mode.
5248 if (secure || restricted)
5249 for (i = 0; i < num_pat; ++i)
5250 if (vim_strchr(pat[i], '`') != NULL
5251 && (check_restricted() || check_secure()))
5252 return FAIL;
5255 * get a name for the temp file
5257 if ((tempname = vim_tempname('o')) == NULL)
5259 EMSG(_(e_notmp));
5260 return FAIL;
5264 * Let the shell expand the patterns and write the result into the temp
5265 * file.
5266 * STYLE_BT: NL separated
5267 * If expanding `cmd` execute it directly.
5268 * STYLE_GLOB: NUL separated
5269 * If we use *csh, "glob" will work better than "echo".
5270 * STYLE_PRINT: NL or NUL separated
5271 * If we use *zsh, "print -N" will work better than "glob".
5272 * STYLE_VIMGLOB: NL separated
5273 * If we use *sh*, we define "vimglob()".
5274 * STYLE_ECHO: space separated.
5275 * A shell we don't know, stay safe and use "echo".
5277 if (num_pat == 1 && *pat[0] == '`'
5278 && (len = STRLEN(pat[0])) > 2
5279 && *(pat[0] + len - 1) == '`')
5280 shell_style = STYLE_BT;
5281 else if ((len = STRLEN(p_sh)) >= 3)
5283 if (STRCMP(p_sh + len - 3, "csh") == 0)
5284 shell_style = STYLE_GLOB;
5285 else if (STRCMP(p_sh + len - 3, "zsh") == 0)
5286 shell_style = STYLE_PRINT;
5288 if (shell_style == STYLE_ECHO && strstr((char *)gettail(p_sh),
5289 "sh") != NULL)
5290 shell_style = STYLE_VIMGLOB;
5292 /* Compute the length of the command. We need 2 extra bytes: for the
5293 * optional '&' and for the NUL.
5294 * Worst case: "unset nonomatch; print -N >" plus two is 29 */
5295 len = STRLEN(tempname) + 29;
5296 if (shell_style == STYLE_VIMGLOB)
5297 len += STRLEN(sh_vimglob_func);
5299 for (i = 0; i < num_pat; ++i)
5301 /* Count the length of the patterns in the same way as they are put in
5302 * "command" below. */
5303 #ifdef USE_SYSTEM
5304 len += STRLEN(pat[i]) + 3; /* add space and two quotes */
5305 #else
5306 ++len; /* add space */
5307 for (j = 0; pat[i][j] != NUL; ++j)
5309 if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL)
5310 ++len; /* may add a backslash */
5311 ++len;
5313 #endif
5315 command = alloc(len);
5316 if (command == NULL)
5318 /* out of memory */
5319 vim_free(tempname);
5320 return FAIL;
5324 * Build the shell command:
5325 * - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell
5326 * recognizes this).
5327 * - Add the shell command to print the expanded names.
5328 * - Add the temp file name.
5329 * - Add the file name patterns.
5331 if (shell_style == STYLE_BT)
5333 /* change `command; command& ` to (command; command ) */
5334 STRCPY(command, "(");
5335 STRCAT(command, pat[0] + 1); /* exclude first backtick */
5336 p = command + STRLEN(command) - 1;
5337 *p-- = ')'; /* remove last backtick */
5338 while (p > command && vim_iswhite(*p))
5339 --p;
5340 if (*p == '&') /* remove trailing '&' */
5342 ampersent = TRUE;
5343 *p = ' ';
5345 STRCAT(command, ">");
5347 else
5349 if (flags & EW_NOTFOUND)
5350 STRCPY(command, "set nonomatch; ");
5351 else
5352 STRCPY(command, "unset nonomatch; ");
5353 if (shell_style == STYLE_GLOB)
5354 STRCAT(command, "glob >");
5355 else if (shell_style == STYLE_PRINT)
5356 STRCAT(command, "print -N >");
5357 else if (shell_style == STYLE_VIMGLOB)
5358 STRCAT(command, sh_vimglob_func);
5359 else
5360 STRCAT(command, "echo >");
5363 STRCAT(command, tempname);
5365 if (shell_style != STYLE_BT)
5366 for (i = 0; i < num_pat; ++i)
5368 /* When using system() always add extra quotes, because the shell
5369 * is started twice. Otherwise put a backslash before special
5370 * characters, except inside ``. */
5371 #ifdef USE_SYSTEM
5372 STRCAT(command, " \"");
5373 STRCAT(command, pat[i]);
5374 STRCAT(command, "\"");
5375 #else
5376 int intick = FALSE;
5378 p = command + STRLEN(command);
5379 *p++ = ' ';
5380 for (j = 0; pat[i][j] != NUL; ++j)
5382 if (pat[i][j] == '`')
5383 intick = !intick;
5384 else if (pat[i][j] == '\\' && pat[i][j + 1] != NUL)
5386 /* Remove a backslash, take char literally. But keep
5387 * backslash inside backticks, before a special character
5388 * and before a backtick. */
5389 if (intick
5390 || vim_strchr(SHELL_SPECIAL, pat[i][j + 1]) != NULL
5391 || pat[i][j + 1] == '`')
5392 *p++ = '\\';
5393 ++j;
5395 else if (!intick && vim_strchr(SHELL_SPECIAL,
5396 pat[i][j]) != NULL)
5397 /* Put a backslash before a special character, but not
5398 * when inside ``. */
5399 *p++ = '\\';
5401 /* Copy one character. */
5402 *p++ = pat[i][j];
5404 *p = NUL;
5405 #endif
5407 if (flags & EW_SILENT)
5408 show_shell_mess = FALSE;
5409 if (ampersent)
5410 STRCAT(command, "&"); /* put the '&' after the redirection */
5413 * Using zsh -G: If a pattern has no matches, it is just deleted from
5414 * the argument list, otherwise zsh gives an error message and doesn't
5415 * expand any other pattern.
5417 if (shell_style == STYLE_PRINT)
5418 extra_shell_arg = (char_u *)"-G"; /* Use zsh NULL_GLOB option */
5421 * If we use -f then shell variables set in .cshrc won't get expanded.
5422 * vi can do it, so we will too, but it is only necessary if there is a "$"
5423 * in one of the patterns, otherwise we can still use the fast option.
5425 else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat))
5426 extra_shell_arg = (char_u *)"-f"; /* Use csh fast option */
5429 * execute the shell command
5431 i = call_shell(command, SHELL_EXPAND | SHELL_SILENT);
5433 /* When running in the background, give it some time to create the temp
5434 * file, but don't wait for it to finish. */
5435 if (ampersent)
5436 mch_delay(10L, TRUE);
5438 extra_shell_arg = NULL; /* cleanup */
5439 show_shell_mess = TRUE;
5440 vim_free(command);
5442 if (i != 0) /* mch_call_shell() failed */
5444 mch_remove(tempname);
5445 vim_free(tempname);
5447 * With interactive completion, the error message is not printed.
5448 * However with USE_SYSTEM, I don't know how to turn off error messages
5449 * from the shell, so screen may still get messed up -- webb.
5451 #ifndef USE_SYSTEM
5452 if (!(flags & EW_SILENT))
5453 #endif
5455 redraw_later_clear(); /* probably messed up screen */
5456 msg_putchar('\n'); /* clear bottom line quickly */
5457 cmdline_row = Rows - 1; /* continue on last line */
5458 #ifdef USE_SYSTEM
5459 if (!(flags & EW_SILENT))
5460 #endif
5462 MSG(_(e_wildexpand));
5463 msg_start(); /* don't overwrite this message */
5466 /* If a `cmd` expansion failed, don't list `cmd` as a match, even when
5467 * EW_NOTFOUND is given */
5468 if (shell_style == STYLE_BT)
5469 return FAIL;
5470 goto notfound;
5474 * read the names from the file into memory
5476 fd = fopen((char *)tempname, READBIN);
5477 if (fd == NULL)
5479 /* Something went wrong, perhaps a file name with a special char. */
5480 if (!(flags & EW_SILENT))
5482 MSG(_(e_wildexpand));
5483 msg_start(); /* don't overwrite this message */
5485 vim_free(tempname);
5486 goto notfound;
5488 fseek(fd, 0L, SEEK_END);
5489 len = ftell(fd); /* get size of temp file */
5490 fseek(fd, 0L, SEEK_SET);
5491 buffer = alloc(len + 1);
5492 if (buffer == NULL)
5494 /* out of memory */
5495 mch_remove(tempname);
5496 vim_free(tempname);
5497 fclose(fd);
5498 return FAIL;
5500 i = fread((char *)buffer, 1, len, fd);
5501 fclose(fd);
5502 mch_remove(tempname);
5503 if (i != len)
5505 /* unexpected read error */
5506 EMSG2(_(e_notread), tempname);
5507 vim_free(tempname);
5508 vim_free(buffer);
5509 return FAIL;
5511 vim_free(tempname);
5513 # if defined(__CYGWIN__) || defined(__CYGWIN32__)
5514 /* Translate <CR><NL> into <NL>. Caution, buffer may contain NUL. */
5515 p = buffer;
5516 for (i = 0; i < len; ++i)
5517 if (!(buffer[i] == CAR && buffer[i + 1] == NL))
5518 *p++ = buffer[i];
5519 len = p - buffer;
5520 # endif
5523 /* file names are separated with Space */
5524 if (shell_style == STYLE_ECHO)
5526 buffer[len] = '\n'; /* make sure the buffer ends in NL */
5527 p = buffer;
5528 for (i = 0; *p != '\n'; ++i) /* count number of entries */
5530 while (*p != ' ' && *p != '\n')
5531 ++p;
5532 p = skipwhite(p); /* skip to next entry */
5535 /* file names are separated with NL */
5536 else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB)
5538 buffer[len] = NUL; /* make sure the buffer ends in NUL */
5539 p = buffer;
5540 for (i = 0; *p != NUL; ++i) /* count number of entries */
5542 while (*p != '\n' && *p != NUL)
5543 ++p;
5544 if (*p != NUL)
5545 ++p;
5546 p = skipwhite(p); /* skip leading white space */
5549 /* file names are separated with NUL */
5550 else
5553 * Some versions of zsh use spaces instead of NULs to separate
5554 * results. Only do this when there is no NUL before the end of the
5555 * buffer, otherwise we would never be able to use file names with
5556 * embedded spaces when zsh does use NULs.
5557 * When we found a NUL once, we know zsh is OK, set did_find_nul and
5558 * don't check for spaces again.
5560 check_spaces = FALSE;
5561 if (shell_style == STYLE_PRINT && !did_find_nul)
5563 /* If there is a NUL, set did_find_nul, else set check_spaces */
5564 if (len && (int)STRLEN(buffer) < len - 1)
5565 did_find_nul = TRUE;
5566 else
5567 check_spaces = TRUE;
5571 * Make sure the buffer ends with a NUL. For STYLE_PRINT there
5572 * already is one, for STYLE_GLOB it needs to be added.
5574 if (len && buffer[len - 1] == NUL)
5575 --len;
5576 else
5577 buffer[len] = NUL;
5578 i = 0;
5579 for (p = buffer; p < buffer + len; ++p)
5580 if (*p == NUL || (*p == ' ' && check_spaces)) /* count entry */
5582 ++i;
5583 *p = NUL;
5585 if (len)
5586 ++i; /* count last entry */
5588 if (i == 0)
5591 * Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I".
5592 * /bin/sh will happily expand it to nothing rather than returning an
5593 * error; and hey, it's good to check anyway -- webb.
5595 vim_free(buffer);
5596 goto notfound;
5598 *num_file = i;
5599 *file = (char_u **)alloc(sizeof(char_u *) * i);
5600 if (*file == NULL)
5602 /* out of memory */
5603 vim_free(buffer);
5604 return FAIL;
5608 * Isolate the individual file names.
5610 p = buffer;
5611 for (i = 0; i < *num_file; ++i)
5613 (*file)[i] = p;
5614 /* Space or NL separates */
5615 if (shell_style == STYLE_ECHO || shell_style == STYLE_BT
5616 || shell_style == STYLE_VIMGLOB)
5618 while (!(shell_style == STYLE_ECHO && *p == ' ')
5619 && *p != '\n' && *p != NUL)
5620 ++p;
5621 if (p == buffer + len) /* last entry */
5622 *p = NUL;
5623 else
5625 *p++ = NUL;
5626 p = skipwhite(p); /* skip to next entry */
5629 else /* NUL separates */
5631 while (*p && p < buffer + len) /* skip entry */
5632 ++p;
5633 ++p; /* skip NUL */
5638 * Move the file names to allocated memory.
5640 for (j = 0, i = 0; i < *num_file; ++i)
5642 /* Require the files to exist. Helps when using /bin/sh */
5643 if (!(flags & EW_NOTFOUND) && mch_getperm((*file)[i]) < 0)
5644 continue;
5646 /* check if this entry should be included */
5647 dir = (mch_isdir((*file)[i]));
5648 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5649 continue;
5651 /* Skip files that are not executable if we check for that. */
5652 if (!dir && (flags & EW_EXEC) && !mch_can_exe((*file)[i]))
5653 continue;
5655 p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir));
5656 if (p)
5658 STRCPY(p, (*file)[i]);
5659 if (dir)
5660 add_pathsep(p); /* add '/' to a directory name */
5661 (*file)[j++] = p;
5664 vim_free(buffer);
5665 *num_file = j;
5667 if (*num_file == 0) /* rejected all entries */
5669 vim_free(*file);
5670 *file = NULL;
5671 goto notfound;
5674 return OK;
5676 notfound:
5677 if (flags & EW_NOTFOUND)
5678 return save_patterns(num_pat, pat, num_file, file);
5679 return FAIL;
5681 #endif /* __EMX__ */
5684 #endif /* VMS */
5686 #ifndef __EMX__
5687 static int
5688 save_patterns(num_pat, pat, num_file, file)
5689 int num_pat;
5690 char_u **pat;
5691 int *num_file;
5692 char_u ***file;
5694 int i;
5695 char_u *s;
5697 *file = (char_u **)alloc(num_pat * sizeof(char_u *));
5698 if (*file == NULL)
5699 return FAIL;
5700 for (i = 0; i < num_pat; i++)
5702 s = vim_strsave(pat[i]);
5703 if (s != NULL)
5704 /* Be compatible with expand_filename(): halve the number of
5705 * backslashes. */
5706 backslash_halve(s);
5707 (*file)[i] = s;
5709 *num_file = num_pat;
5710 return OK;
5712 #endif
5716 * Return TRUE if the string "p" contains a wildcard that mch_expandpath() can
5717 * expand.
5720 mch_has_exp_wildcard(p)
5721 char_u *p;
5723 for ( ; *p; mb_ptr_adv(p))
5725 #ifndef OS2
5726 if (*p == '\\' && p[1] != NUL)
5727 ++p;
5728 else
5729 #endif
5730 if (vim_strchr((char_u *)
5731 #ifdef VMS
5732 "*?%"
5733 #else
5734 # ifdef OS2
5735 "*?"
5736 # else
5737 "*?[{'"
5738 # endif
5739 #endif
5740 , *p) != NULL)
5741 return TRUE;
5743 return FALSE;
5747 * Return TRUE if the string "p" contains a wildcard.
5748 * Don't recognize '~' at the end as a wildcard.
5751 mch_has_wildcard(p)
5752 char_u *p;
5754 for ( ; *p; mb_ptr_adv(p))
5756 #ifndef OS2
5757 if (*p == '\\' && p[1] != NUL)
5758 ++p;
5759 else
5760 #endif
5761 if (vim_strchr((char_u *)
5762 #ifdef VMS
5763 "*?%$"
5764 #else
5765 # ifdef OS2
5766 # ifdef VIM_BACKTICK
5767 "*?$`"
5768 # else
5769 "*?$"
5770 # endif
5771 # else
5772 "*?[{`'$"
5773 # endif
5774 #endif
5775 , *p) != NULL
5776 || (*p == '~' && p[1] != NUL))
5777 return TRUE;
5779 return FALSE;
5782 #ifndef __EMX__
5783 static int
5784 have_wildcard(num, file)
5785 int num;
5786 char_u **file;
5788 int i;
5790 for (i = 0; i < num; i++)
5791 if (mch_has_wildcard(file[i]))
5792 return 1;
5793 return 0;
5796 static int
5797 have_dollars(num, file)
5798 int num;
5799 char_u **file;
5801 int i;
5803 for (i = 0; i < num; i++)
5804 if (vim_strchr(file[i], '$') != NULL)
5805 return TRUE;
5806 return FALSE;
5808 #endif /* ifndef __EMX__ */
5810 #ifndef HAVE_RENAME
5812 * Scaled-down version of rename(), which is missing in Xenix.
5813 * This version can only move regular files and will fail if the
5814 * destination exists.
5817 mch_rename(src, dest)
5818 const char *src, *dest;
5820 struct stat st;
5822 if (stat(dest, &st) >= 0) /* fail if destination exists */
5823 return -1;
5824 if (link(src, dest) != 0) /* link file to new name */
5825 return -1;
5826 if (mch_remove(src) == 0) /* delete link to old name */
5827 return 0;
5828 return -1;
5830 #endif /* !HAVE_RENAME */
5832 #ifdef FEAT_MOUSE_GPM
5834 * Initializes connection with gpm (if it isn't already opened)
5835 * Return 1 if succeeded (or connection already opened), 0 if failed
5837 static int
5838 gpm_open()
5840 static Gpm_Connect gpm_connect; /* Must it be kept till closing ? */
5842 if (!gpm_flag)
5844 gpm_connect.eventMask = (GPM_UP | GPM_DRAG | GPM_DOWN);
5845 gpm_connect.defaultMask = ~GPM_HARD;
5846 /* Default handling for mouse move*/
5847 gpm_connect.minMod = 0; /* Handle any modifier keys */
5848 gpm_connect.maxMod = 0xffff;
5849 if (Gpm_Open(&gpm_connect, 0) > 0)
5851 /* gpm library tries to handling TSTP causes
5852 * problems. Anyways, we close connection to Gpm whenever
5853 * we are going to suspend or starting an external process
5854 * so we shouldn't have problem with this
5856 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
5857 return 1; /* succeed */
5859 if (gpm_fd == -2)
5860 Gpm_Close(); /* We don't want to talk to xterm via gpm */
5861 return 0;
5863 return 1; /* already open */
5867 * Closes connection to gpm
5869 static void
5870 gpm_close()
5872 if (gpm_flag && gpm_fd >= 0) /* if Open */
5873 Gpm_Close();
5876 /* Reads gpm event and adds special keys to input buf. Returns length of
5877 * generated key sequence.
5878 * This function is made after gui_send_mouse_event
5880 static int
5881 mch_gpm_process()
5883 int button;
5884 static Gpm_Event gpm_event;
5885 char_u string[6];
5886 int_u vim_modifiers;
5887 int row,col;
5888 unsigned char buttons_mask;
5889 unsigned char gpm_modifiers;
5890 static unsigned char old_buttons = 0;
5892 Gpm_GetEvent(&gpm_event);
5894 #ifdef FEAT_GUI
5895 /* Don't put events in the input queue now. */
5896 if (hold_gui_events)
5897 return 0;
5898 #endif
5900 row = gpm_event.y - 1;
5901 col = gpm_event.x - 1;
5903 string[0] = ESC; /* Our termcode */
5904 string[1] = 'M';
5905 string[2] = 'G';
5906 switch (GPM_BARE_EVENTS(gpm_event.type))
5908 case GPM_DRAG:
5909 string[3] = MOUSE_DRAG;
5910 break;
5911 case GPM_DOWN:
5912 buttons_mask = gpm_event.buttons & ~old_buttons;
5913 old_buttons = gpm_event.buttons;
5914 switch (buttons_mask)
5916 case GPM_B_LEFT:
5917 button = MOUSE_LEFT;
5918 break;
5919 case GPM_B_MIDDLE:
5920 button = MOUSE_MIDDLE;
5921 break;
5922 case GPM_B_RIGHT:
5923 button = MOUSE_RIGHT;
5924 break;
5925 default:
5926 return 0;
5927 /*Don't know what to do. Can more than one button be
5928 * reported in one event? */
5930 string[3] = (char_u)(button | 0x20);
5931 SET_NUM_MOUSE_CLICKS(string[3], gpm_event.clicks + 1);
5932 break;
5933 case GPM_UP:
5934 string[3] = MOUSE_RELEASE;
5935 old_buttons &= ~gpm_event.buttons;
5936 break;
5937 default:
5938 return 0;
5940 /*This code is based on gui_x11_mouse_cb in gui_x11.c */
5941 gpm_modifiers = gpm_event.modifiers;
5942 vim_modifiers = 0x0;
5943 /* I ignore capslock stats. Aren't we all just hate capslock mixing with
5944 * Vim commands ? Besides, gpm_event.modifiers is unsigned char, and
5945 * K_CAPSSHIFT is defined 8, so it probably isn't even reported
5947 if (gpm_modifiers & ((1 << KG_SHIFT) | (1 << KG_SHIFTR) | (1 << KG_SHIFTL)))
5948 vim_modifiers |= MOUSE_SHIFT;
5950 if (gpm_modifiers & ((1 << KG_CTRL) | (1 << KG_CTRLR) | (1 << KG_CTRLL)))
5951 vim_modifiers |= MOUSE_CTRL;
5952 if (gpm_modifiers & ((1 << KG_ALT) | (1 << KG_ALTGR)))
5953 vim_modifiers |= MOUSE_ALT;
5954 string[3] |= vim_modifiers;
5955 string[4] = (char_u)(col + ' ' + 1);
5956 string[5] = (char_u)(row + ' ' + 1);
5957 add_to_input_buf(string, 6);
5958 return 6;
5960 #endif /* FEAT_MOUSE_GPM */
5962 #ifdef FEAT_SYSMOUSE
5964 * Initialize connection with sysmouse.
5965 * Let virtual console inform us with SIGUSR2 for pending sysmouse
5966 * output, any sysmouse output than will be processed via sig_sysmouse().
5967 * Return OK if succeeded, FAIL if failed.
5969 static int
5970 sysmouse_open()
5972 struct mouse_info mouse;
5974 mouse.operation = MOUSE_MODE;
5975 mouse.u.mode.mode = 0;
5976 mouse.u.mode.signal = SIGUSR2;
5977 if (ioctl(1, CONS_MOUSECTL, &mouse) != -1)
5979 signal(SIGUSR2, (RETSIGTYPE (*)())sig_sysmouse);
5980 mouse.operation = MOUSE_SHOW;
5981 ioctl(1, CONS_MOUSECTL, &mouse);
5982 return OK;
5984 return FAIL;
5988 * Stop processing SIGUSR2 signals, and also make sure that
5989 * virtual console do not send us any sysmouse related signal.
5991 static void
5992 sysmouse_close()
5994 struct mouse_info mouse;
5996 signal(SIGUSR2, restricted ? SIG_IGN : SIG_DFL);
5997 mouse.operation = MOUSE_MODE;
5998 mouse.u.mode.mode = 0;
5999 mouse.u.mode.signal = 0;
6000 ioctl(1, CONS_MOUSECTL, &mouse);
6004 * Gets info from sysmouse and adds special keys to input buf.
6006 /* ARGSUSED */
6007 static RETSIGTYPE
6008 sig_sysmouse SIGDEFARG(sigarg)
6010 struct mouse_info mouse;
6011 struct video_info video;
6012 char_u string[6];
6013 int row, col;
6014 int button;
6015 int buttons;
6016 static int oldbuttons = 0;
6018 #ifdef FEAT_GUI
6019 /* Don't put events in the input queue now. */
6020 if (hold_gui_events)
6021 return;
6022 #endif
6024 mouse.operation = MOUSE_GETINFO;
6025 if (ioctl(1, FBIO_GETMODE, &video.vi_mode) != -1
6026 && ioctl(1, FBIO_MODEINFO, &video) != -1
6027 && ioctl(1, CONS_MOUSECTL, &mouse) != -1
6028 && video.vi_cheight > 0 && video.vi_cwidth > 0)
6030 row = mouse.u.data.y / video.vi_cheight;
6031 col = mouse.u.data.x / video.vi_cwidth;
6032 buttons = mouse.u.data.buttons;
6033 string[0] = ESC; /* Our termcode */
6034 string[1] = 'M';
6035 string[2] = 'S';
6036 if (oldbuttons == buttons && buttons != 0)
6038 button = MOUSE_DRAG;
6040 else
6042 switch (buttons)
6044 case 0:
6045 button = MOUSE_RELEASE;
6046 break;
6047 case 1:
6048 button = MOUSE_LEFT;
6049 break;
6050 case 2:
6051 button = MOUSE_MIDDLE;
6052 break;
6053 case 4:
6054 button = MOUSE_RIGHT;
6055 break;
6056 default:
6057 return;
6059 oldbuttons = buttons;
6061 string[3] = (char_u)(button);
6062 string[4] = (char_u)(col + ' ' + 1);
6063 string[5] = (char_u)(row + ' ' + 1);
6064 add_to_input_buf(string, 6);
6066 return;
6068 #endif /* FEAT_SYSMOUSE */
6070 #if defined(FEAT_LIBCALL) || defined(PROTO)
6071 typedef char_u * (*STRPROCSTR)__ARGS((char_u *));
6072 typedef char_u * (*INTPROCSTR)__ARGS((int));
6073 typedef int (*STRPROCINT)__ARGS((char_u *));
6074 typedef int (*INTPROCINT)__ARGS((int));
6077 * Call a DLL routine which takes either a string or int param
6078 * and returns an allocated string.
6081 mch_libcall(libname, funcname, argstring, argint, string_result, number_result)
6082 char_u *libname;
6083 char_u *funcname;
6084 char_u *argstring; /* NULL when using a argint */
6085 int argint;
6086 char_u **string_result;/* NULL when using number_result */
6087 int *number_result;
6089 # if defined(USE_DLOPEN)
6090 void *hinstLib;
6091 char *dlerr = NULL;
6092 # else
6093 shl_t hinstLib;
6094 # endif
6095 STRPROCSTR ProcAdd;
6096 INTPROCSTR ProcAddI;
6097 char_u *retval_str = NULL;
6098 int retval_int = 0;
6099 int success = FALSE;
6102 * Get a handle to the DLL module.
6104 # if defined(USE_DLOPEN)
6105 /* First clear any error, it's not cleared by the dlopen() call. */
6106 (void)dlerror();
6108 hinstLib = dlopen((char *)libname, RTLD_LAZY
6109 # ifdef RTLD_LOCAL
6110 | RTLD_LOCAL
6111 # endif
6113 if (hinstLib == NULL)
6115 /* "dlerr" must be used before dlclose() */
6116 dlerr = (char *)dlerror();
6117 if (dlerr != NULL)
6118 EMSG2(_("dlerror = \"%s\""), dlerr);
6120 # else
6121 hinstLib = shl_load((const char*)libname, BIND_IMMEDIATE|BIND_VERBOSE, 0L);
6122 # endif
6124 /* If the handle is valid, try to get the function address. */
6125 if (hinstLib != NULL)
6127 # ifdef HAVE_SETJMP_H
6129 * Catch a crash when calling the library function. For example when
6130 * using a number where a string pointer is expected.
6132 mch_startjmp();
6133 if (SETJMP(lc_jump_env) != 0)
6135 success = FALSE;
6136 # if defined(USE_DLOPEN)
6137 dlerr = NULL;
6138 # endif
6139 mch_didjmp();
6141 else
6142 # endif
6144 retval_str = NULL;
6145 retval_int = 0;
6147 if (argstring != NULL)
6149 # if defined(USE_DLOPEN)
6150 ProcAdd = (STRPROCSTR)dlsym(hinstLib, (const char *)funcname);
6151 dlerr = (char *)dlerror();
6152 # else
6153 if (shl_findsym(&hinstLib, (const char *)funcname,
6154 TYPE_PROCEDURE, (void *)&ProcAdd) < 0)
6155 ProcAdd = NULL;
6156 # endif
6157 if ((success = (ProcAdd != NULL
6158 # if defined(USE_DLOPEN)
6159 && dlerr == NULL
6160 # endif
6163 if (string_result == NULL)
6164 retval_int = ((STRPROCINT)ProcAdd)(argstring);
6165 else
6166 retval_str = (ProcAdd)(argstring);
6169 else
6171 # if defined(USE_DLOPEN)
6172 ProcAddI = (INTPROCSTR)dlsym(hinstLib, (const char *)funcname);
6173 dlerr = (char *)dlerror();
6174 # else
6175 if (shl_findsym(&hinstLib, (const char *)funcname,
6176 TYPE_PROCEDURE, (void *)&ProcAddI) < 0)
6177 ProcAddI = NULL;
6178 # endif
6179 if ((success = (ProcAddI != NULL
6180 # if defined(USE_DLOPEN)
6181 && dlerr == NULL
6182 # endif
6185 if (string_result == NULL)
6186 retval_int = ((INTPROCINT)ProcAddI)(argint);
6187 else
6188 retval_str = (ProcAddI)(argint);
6192 /* Save the string before we free the library. */
6193 /* Assume that a "1" or "-1" result is an illegal pointer. */
6194 if (string_result == NULL)
6195 *number_result = retval_int;
6196 else if (retval_str != NULL
6197 && retval_str != (char_u *)1
6198 && retval_str != (char_u *)-1)
6199 *string_result = vim_strsave(retval_str);
6202 # ifdef HAVE_SETJMP_H
6203 mch_endjmp();
6204 # ifdef SIGHASARG
6205 if (lc_signal != 0)
6207 int i;
6209 /* try to find the name of this signal */
6210 for (i = 0; signal_info[i].sig != -1; i++)
6211 if (lc_signal == signal_info[i].sig)
6212 break;
6213 EMSG2("E368: got SIG%s in libcall()", signal_info[i].name);
6215 # endif
6216 # endif
6218 # if defined(USE_DLOPEN)
6219 /* "dlerr" must be used before dlclose() */
6220 if (dlerr != NULL)
6221 EMSG2(_("dlerror = \"%s\""), dlerr);
6223 /* Free the DLL module. */
6224 (void)dlclose(hinstLib);
6225 # else
6226 (void)shl_unload(hinstLib);
6227 # endif
6230 if (!success)
6232 EMSG2(_(e_libcall), funcname);
6233 return FAIL;
6236 return OK;
6238 #endif
6240 #if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
6241 static int xterm_trace = -1; /* default: disabled */
6242 static int xterm_button;
6245 * Setup a dummy window for X selections in a terminal.
6247 void
6248 setup_term_clip()
6250 int z = 0;
6251 char *strp = "";
6252 Widget AppShell;
6254 if (!x_connect_to_server())
6255 return;
6257 open_app_context();
6258 if (app_context != NULL && xterm_Shell == (Widget)0)
6260 int (*oldhandler)();
6261 #if defined(HAVE_SETJMP_H)
6262 int (*oldIOhandler)();
6263 #endif
6264 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
6265 struct timeval start_tv;
6267 if (p_verbose > 0)
6268 gettimeofday(&start_tv, NULL);
6269 # endif
6271 /* Ignore X errors while opening the display */
6272 oldhandler = XSetErrorHandler(x_error_check);
6274 #if defined(HAVE_SETJMP_H)
6275 /* Ignore X IO errors while opening the display */
6276 oldIOhandler = XSetIOErrorHandler(x_IOerror_check);
6277 mch_startjmp();
6278 if (SETJMP(lc_jump_env) != 0)
6280 mch_didjmp();
6281 xterm_dpy = NULL;
6283 else
6284 #endif
6286 xterm_dpy = XtOpenDisplay(app_context, xterm_display,
6287 "vim_xterm", "Vim_xterm", NULL, 0, &z, &strp);
6288 #if defined(HAVE_SETJMP_H)
6289 mch_endjmp();
6290 #endif
6293 #if defined(HAVE_SETJMP_H)
6294 /* Now handle X IO errors normally. */
6295 (void)XSetIOErrorHandler(oldIOhandler);
6296 #endif
6297 /* Now handle X errors normally. */
6298 (void)XSetErrorHandler(oldhandler);
6300 if (xterm_dpy == NULL)
6302 if (p_verbose > 0)
6303 verb_msg((char_u *)_("Opening the X display failed"));
6304 return;
6307 /* Catch terminating error of the X server connection. */
6308 (void)XSetIOErrorHandler(x_IOerror_handler);
6310 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
6311 if (p_verbose > 0)
6313 verbose_enter();
6314 xopen_message(&start_tv);
6315 verbose_leave();
6317 # endif
6319 /* Create a Shell to make converters work. */
6320 AppShell = XtVaAppCreateShell("vim_xterm", "Vim_xterm",
6321 applicationShellWidgetClass, xterm_dpy,
6322 NULL);
6323 if (AppShell == (Widget)0)
6324 return;
6325 xterm_Shell = XtVaCreatePopupShell("VIM",
6326 topLevelShellWidgetClass, AppShell,
6327 XtNmappedWhenManaged, 0,
6328 XtNwidth, 1,
6329 XtNheight, 1,
6330 NULL);
6331 if (xterm_Shell == (Widget)0)
6332 return;
6334 x11_setup_atoms(xterm_dpy);
6335 if (x11_display == NULL)
6336 x11_display = xterm_dpy;
6338 XtRealizeWidget(xterm_Shell);
6339 XSync(xterm_dpy, False);
6340 xterm_update();
6342 if (xterm_Shell != (Widget)0)
6344 clip_init(TRUE);
6345 if (x11_window == 0 && (strp = getenv("WINDOWID")) != NULL)
6346 x11_window = (Window)atol(strp);
6347 /* Check if $WINDOWID is valid. */
6348 if (test_x11_window(xterm_dpy) == FAIL)
6349 x11_window = 0;
6350 if (x11_window != 0)
6351 xterm_trace = 0;
6355 void
6356 start_xterm_trace(button)
6357 int button;
6359 if (x11_window == 0 || xterm_trace < 0 || xterm_Shell == (Widget)0)
6360 return;
6361 xterm_trace = 1;
6362 xterm_button = button;
6363 do_xterm_trace();
6367 void
6368 stop_xterm_trace()
6370 if (xterm_trace < 0)
6371 return;
6372 xterm_trace = 0;
6376 * Query the xterm pointer and generate mouse termcodes if necessary
6377 * return TRUE if dragging is active, else FALSE
6379 static int
6380 do_xterm_trace()
6382 Window root, child;
6383 int root_x, root_y;
6384 int win_x, win_y;
6385 int row, col;
6386 int_u mask_return;
6387 char_u buf[50];
6388 char_u *strp;
6389 long got_hints;
6390 static char_u *mouse_code;
6391 static char_u mouse_name[2] = {KS_MOUSE, KE_FILLER};
6392 static int prev_row = 0, prev_col = 0;
6393 static XSizeHints xterm_hints;
6395 if (xterm_trace <= 0)
6396 return FALSE;
6398 if (xterm_trace == 1)
6400 /* Get the hints just before tracking starts. The font size might
6401 * have changed recently. */
6402 if (!XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints)
6403 || !(got_hints & PResizeInc)
6404 || xterm_hints.width_inc <= 1
6405 || xterm_hints.height_inc <= 1)
6407 xterm_trace = -1; /* Not enough data -- disable tracing */
6408 return FALSE;
6411 /* Rely on the same mouse code for the duration of this */
6412 mouse_code = find_termcode(mouse_name);
6413 prev_row = mouse_row;
6414 prev_row = mouse_col;
6415 xterm_trace = 2;
6417 /* Find the offset of the chars, there might be a scrollbar on the
6418 * left of the window and/or a menu on the top (eterm etc.) */
6419 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
6420 &win_x, &win_y, &mask_return);
6421 xterm_hints.y = win_y - (xterm_hints.height_inc * mouse_row)
6422 - (xterm_hints.height_inc / 2);
6423 if (xterm_hints.y <= xterm_hints.height_inc / 2)
6424 xterm_hints.y = 2;
6425 xterm_hints.x = win_x - (xterm_hints.width_inc * mouse_col)
6426 - (xterm_hints.width_inc / 2);
6427 if (xterm_hints.x <= xterm_hints.width_inc / 2)
6428 xterm_hints.x = 2;
6429 return TRUE;
6431 if (mouse_code == NULL)
6433 xterm_trace = 0;
6434 return FALSE;
6437 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
6438 &win_x, &win_y, &mask_return);
6440 row = check_row((win_y - xterm_hints.y) / xterm_hints.height_inc);
6441 col = check_col((win_x - xterm_hints.x) / xterm_hints.width_inc);
6442 if (row == prev_row && col == prev_col)
6443 return TRUE;
6445 STRCPY(buf, mouse_code);
6446 strp = buf + STRLEN(buf);
6447 *strp++ = (xterm_button | MOUSE_DRAG) & ~0x20;
6448 *strp++ = (char_u)(col + ' ' + 1);
6449 *strp++ = (char_u)(row + ' ' + 1);
6450 *strp = 0;
6451 add_to_input_buf(buf, STRLEN(buf));
6453 prev_row = row;
6454 prev_col = col;
6455 return TRUE;
6458 # if defined(FEAT_GUI) || defined(PROTO)
6460 * Destroy the display, window and app_context. Required for GTK.
6462 void
6463 clear_xterm_clip()
6465 if (xterm_Shell != (Widget)0)
6467 XtDestroyWidget(xterm_Shell);
6468 xterm_Shell = (Widget)0;
6470 if (xterm_dpy != NULL)
6472 # if 0
6473 /* Lesstif and Solaris crash here, lose some memory */
6474 XtCloseDisplay(xterm_dpy);
6475 # endif
6476 if (x11_display == xterm_dpy)
6477 x11_display = NULL;
6478 xterm_dpy = NULL;
6480 # if 0
6481 if (app_context != (XtAppContext)NULL)
6483 /* Lesstif and Solaris crash here, lose some memory */
6484 XtDestroyApplicationContext(app_context);
6485 app_context = (XtAppContext)NULL;
6487 # endif
6489 # endif
6492 * Catch up with any queued X events. This may put keyboard input into the
6493 * input buffer, call resize call-backs, trigger timers etc. If there is
6494 * nothing in the X event queue (& no timers pending), then we return
6495 * immediately.
6497 static void
6498 xterm_update()
6500 XEvent event;
6502 while (XtAppPending(app_context) && !vim_is_input_buf_full())
6504 XtAppNextEvent(app_context, &event);
6505 #ifdef FEAT_CLIENTSERVER
6507 XPropertyEvent *e = (XPropertyEvent *)&event;
6509 if (e->type == PropertyNotify && e->window == commWindow
6510 && e->atom == commProperty && e->state == PropertyNewValue)
6511 serverEventProc(xterm_dpy, &event);
6513 #endif
6514 XtDispatchEvent(&event);
6519 clip_xterm_own_selection(cbd)
6520 VimClipboard *cbd;
6522 if (xterm_Shell != (Widget)0)
6523 return clip_x11_own_selection(xterm_Shell, cbd);
6524 return FAIL;
6527 void
6528 clip_xterm_lose_selection(cbd)
6529 VimClipboard *cbd;
6531 if (xterm_Shell != (Widget)0)
6532 clip_x11_lose_selection(xterm_Shell, cbd);
6535 void
6536 clip_xterm_request_selection(cbd)
6537 VimClipboard *cbd;
6539 if (xterm_Shell != (Widget)0)
6540 clip_x11_request_selection(xterm_Shell, xterm_dpy, cbd);
6543 void
6544 clip_xterm_set_selection(cbd)
6545 VimClipboard *cbd;
6547 clip_x11_set_selection(cbd);
6549 #endif
6552 #if defined(USE_XSMP) || defined(PROTO)
6554 * Code for X Session Management Protocol.
6556 static void xsmp_handle_save_yourself __ARGS((SmcConn smc_conn, SmPointer client_data, int save_type, Bool shutdown, int interact_style, Bool fast));
6557 static void xsmp_die __ARGS((SmcConn smc_conn, SmPointer client_data));
6558 static void xsmp_save_complete __ARGS((SmcConn smc_conn, SmPointer client_data));
6559 static void xsmp_shutdown_cancelled __ARGS((SmcConn smc_conn, SmPointer client_data));
6560 static void xsmp_ice_connection __ARGS((IceConn iceConn, IcePointer clientData, Bool opening, IcePointer *watchData));
6563 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6564 static void xsmp_handle_interaction __ARGS((SmcConn smc_conn, SmPointer client_data));
6567 * This is our chance to ask the user if they want to save,
6568 * or abort the logout
6570 /*ARGSUSED*/
6571 static void
6572 xsmp_handle_interaction(smc_conn, client_data)
6573 SmcConn smc_conn;
6574 SmPointer client_data;
6576 cmdmod_T save_cmdmod;
6577 int cancel_shutdown = False;
6579 save_cmdmod = cmdmod;
6580 cmdmod.confirm = TRUE;
6581 if (check_changed_any(FALSE))
6582 /* Mustn't logout */
6583 cancel_shutdown = True;
6584 cmdmod = save_cmdmod;
6585 setcursor(); /* position cursor */
6586 out_flush();
6588 /* Done interaction */
6589 SmcInteractDone(smc_conn, cancel_shutdown);
6591 /* Finish off
6592 * Only end save-yourself here if we're not cancelling shutdown;
6593 * we'll get a cancelled callback later in which we'll end it.
6594 * Hopefully get around glitchy SMs (like GNOME-1)
6596 if (!cancel_shutdown)
6598 xsmp.save_yourself = False;
6599 SmcSaveYourselfDone(smc_conn, True);
6602 # endif
6605 * Callback that starts save-yourself.
6607 /*ARGSUSED*/
6608 static void
6609 xsmp_handle_save_yourself(smc_conn, client_data, save_type,
6610 shutdown, interact_style, fast)
6611 SmcConn smc_conn;
6612 SmPointer client_data;
6613 int save_type;
6614 Bool shutdown;
6615 int interact_style;
6616 Bool fast;
6618 /* Handle already being in saveyourself */
6619 if (xsmp.save_yourself)
6620 SmcSaveYourselfDone(smc_conn, True);
6621 xsmp.save_yourself = True;
6622 xsmp.shutdown = shutdown;
6624 /* First up, preserve all files */
6625 out_flush();
6626 ml_sync_all(FALSE, FALSE); /* preserve all swap files */
6628 if (p_verbose > 0)
6629 verb_msg((char_u *)_("XSMP handling save-yourself request"));
6631 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6632 /* Now see if we can ask about unsaved files */
6633 if (shutdown && !fast && gui.in_use)
6634 /* Need to interact with user, but need SM's permission */
6635 SmcInteractRequest(smc_conn, SmDialogError,
6636 xsmp_handle_interaction, client_data);
6637 else
6638 # endif
6640 /* Can stop the cycle here */
6641 SmcSaveYourselfDone(smc_conn, True);
6642 xsmp.save_yourself = False;
6648 * Callback to warn us of imminent death.
6650 /*ARGSUSED*/
6651 static void
6652 xsmp_die(smc_conn, client_data)
6653 SmcConn smc_conn;
6654 SmPointer client_data;
6656 xsmp_close();
6658 /* quit quickly leaving swapfiles for modified buffers behind */
6659 getout_preserve_modified(0);
6664 * Callback to tell us that save-yourself has completed.
6666 /*ARGSUSED*/
6667 static void
6668 xsmp_save_complete(smc_conn, client_data)
6669 SmcConn smc_conn;
6670 SmPointer client_data;
6672 xsmp.save_yourself = False;
6677 * Callback to tell us that an instigated shutdown was cancelled
6678 * (maybe even by us)
6680 /*ARGSUSED*/
6681 static void
6682 xsmp_shutdown_cancelled(smc_conn, client_data)
6683 SmcConn smc_conn;
6684 SmPointer client_data;
6686 if (xsmp.save_yourself)
6687 SmcSaveYourselfDone(smc_conn, True);
6688 xsmp.save_yourself = False;
6689 xsmp.shutdown = False;
6694 * Callback to tell us that a new ICE connection has been established.
6696 /*ARGSUSED*/
6697 static void
6698 xsmp_ice_connection(iceConn, clientData, opening, watchData)
6699 IceConn iceConn;
6700 IcePointer clientData;
6701 Bool opening;
6702 IcePointer *watchData;
6704 /* Intercept creation of ICE connection fd */
6705 if (opening)
6707 xsmp_icefd = IceConnectionNumber(iceConn);
6708 IceRemoveConnectionWatch(xsmp_ice_connection, NULL);
6713 /* Handle any ICE processing that's required; return FAIL if SM lost */
6715 xsmp_handle_requests()
6717 Bool rep;
6719 if (IceProcessMessages(xsmp.iceconn, NULL, &rep)
6720 == IceProcessMessagesIOError)
6722 /* Lost ICE */
6723 if (p_verbose > 0)
6724 verb_msg((char_u *)_("XSMP lost ICE connection"));
6725 xsmp_close();
6726 return FAIL;
6728 else
6729 return OK;
6732 static int dummy;
6734 /* Set up X Session Management Protocol */
6735 void
6736 xsmp_init(void)
6738 char errorstring[80];
6739 SmcCallbacks smcallbacks;
6740 #if 0
6741 SmPropValue smname;
6742 SmProp smnameprop;
6743 SmProp *smprops[1];
6744 #endif
6746 if (p_verbose > 0)
6747 verb_msg((char_u *)_("XSMP opening connection"));
6749 xsmp.save_yourself = xsmp.shutdown = False;
6751 /* Set up SM callbacks - must have all, even if they're not used */
6752 smcallbacks.save_yourself.callback = xsmp_handle_save_yourself;
6753 smcallbacks.save_yourself.client_data = NULL;
6754 smcallbacks.die.callback = xsmp_die;
6755 smcallbacks.die.client_data = NULL;
6756 smcallbacks.save_complete.callback = xsmp_save_complete;
6757 smcallbacks.save_complete.client_data = NULL;
6758 smcallbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
6759 smcallbacks.shutdown_cancelled.client_data = NULL;
6761 /* Set up a watch on ICE connection creations. The "dummy" argument is
6762 * apparently required for FreeBSD (we get a BUS error when using NULL). */
6763 if (IceAddConnectionWatch(xsmp_ice_connection, &dummy) == 0)
6765 if (p_verbose > 0)
6766 verb_msg((char_u *)_("XSMP ICE connection watch failed"));
6767 return;
6770 /* Create an SM connection */
6771 xsmp.smcconn = SmcOpenConnection(
6772 NULL,
6773 NULL,
6774 SmProtoMajor,
6775 SmProtoMinor,
6776 SmcSaveYourselfProcMask | SmcDieProcMask
6777 | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
6778 &smcallbacks,
6779 NULL,
6780 &xsmp.clientid,
6781 sizeof(errorstring),
6782 errorstring);
6783 if (xsmp.smcconn == NULL)
6785 char errorreport[132];
6787 if (p_verbose > 0)
6789 vim_snprintf(errorreport, sizeof(errorreport),
6790 _("XSMP SmcOpenConnection failed: %s"), errorstring);
6791 verb_msg((char_u *)errorreport);
6793 return;
6795 xsmp.iceconn = SmcGetIceConnection(xsmp.smcconn);
6797 #if 0
6798 /* ID ourselves */
6799 smname.value = "vim";
6800 smname.length = 3;
6801 smnameprop.name = "SmProgram";
6802 smnameprop.type = "SmARRAY8";
6803 smnameprop.num_vals = 1;
6804 smnameprop.vals = &smname;
6806 smprops[0] = &smnameprop;
6807 SmcSetProperties(xsmp.smcconn, 1, smprops);
6808 #endif
6812 /* Shut down XSMP comms. */
6813 void
6814 xsmp_close()
6816 if (xsmp_icefd != -1)
6818 SmcCloseConnection(xsmp.smcconn, 0, NULL);
6819 vim_free(xsmp.clientid);
6820 xsmp.clientid = NULL;
6821 xsmp_icefd = -1;
6824 #endif /* USE_XSMP */
6827 #ifdef EBCDIC
6828 /* Translate character to its CTRL- value */
6829 char CtrlTable[] =
6831 /* 00 - 5E */
6832 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6833 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6834 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6835 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6836 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6837 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6838 /* ^ */ 0x1E,
6839 /* - */ 0x1F,
6840 /* 61 - 6C */
6841 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6842 /* _ */ 0x1F,
6843 /* 6E - 80 */
6844 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6845 /* a */ 0x01,
6846 /* b */ 0x02,
6847 /* c */ 0x03,
6848 /* d */ 0x37,
6849 /* e */ 0x2D,
6850 /* f */ 0x2E,
6851 /* g */ 0x2F,
6852 /* h */ 0x16,
6853 /* i */ 0x05,
6854 /* 8A - 90 */
6855 0, 0, 0, 0, 0, 0, 0,
6856 /* j */ 0x15,
6857 /* k */ 0x0B,
6858 /* l */ 0x0C,
6859 /* m */ 0x0D,
6860 /* n */ 0x0E,
6861 /* o */ 0x0F,
6862 /* p */ 0x10,
6863 /* q */ 0x11,
6864 /* r */ 0x12,
6865 /* 9A - A1 */
6866 0, 0, 0, 0, 0, 0, 0, 0,
6867 /* s */ 0x13,
6868 /* t */ 0x3C,
6869 /* u */ 0x3D,
6870 /* v */ 0x32,
6871 /* w */ 0x26,
6872 /* x */ 0x18,
6873 /* y */ 0x19,
6874 /* z */ 0x3F,
6875 /* AA - AC */
6876 0, 0, 0,
6877 /* [ */ 0x27,
6878 /* AE - BC */
6879 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6880 /* ] */ 0x1D,
6881 /* BE - C0 */ 0, 0, 0,
6882 /* A */ 0x01,
6883 /* B */ 0x02,
6884 /* C */ 0x03,
6885 /* D */ 0x37,
6886 /* E */ 0x2D,
6887 /* F */ 0x2E,
6888 /* G */ 0x2F,
6889 /* H */ 0x16,
6890 /* I */ 0x05,
6891 /* CA - D0 */ 0, 0, 0, 0, 0, 0, 0,
6892 /* J */ 0x15,
6893 /* K */ 0x0B,
6894 /* L */ 0x0C,
6895 /* M */ 0x0D,
6896 /* N */ 0x0E,
6897 /* O */ 0x0F,
6898 /* P */ 0x10,
6899 /* Q */ 0x11,
6900 /* R */ 0x12,
6901 /* DA - DF */ 0, 0, 0, 0, 0, 0,
6902 /* \ */ 0x1C,
6903 /* E1 */ 0,
6904 /* S */ 0x13,
6905 /* T */ 0x3C,
6906 /* U */ 0x3D,
6907 /* V */ 0x32,
6908 /* W */ 0x26,
6909 /* X */ 0x18,
6910 /* Y */ 0x19,
6911 /* Z */ 0x3F,
6912 /* EA - FF*/ 0, 0, 0, 0, 0, 0,
6913 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6916 char MetaCharTable[]=
6917 {/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6918 0, 0, 0, 0,'\\', 0,'F', 0,'W','M','N', 0, 0, 0, 0, 0,
6919 0, 0, 0, 0,']', 0, 0,'G', 0, 0,'R','O', 0, 0, 0, 0,
6920 '@','A','B','C','D','E', 0, 0,'H','I','J','K','L', 0, 0, 0,
6921 'P','Q', 0,'S','T','U','V', 0,'X','Y','Z','[', 0, 0,'^', 0
6925 /* TODO: Use characters NOT numbers!!! */
6926 char CtrlCharTable[]=
6927 {/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6928 124,193,194,195, 0,201, 0, 0, 0, 0, 0,210,211,212,213,214,
6929 215,216,217,226, 0,209,200, 0,231,232, 0, 0,224,189, 95,109,
6930 0, 0, 0, 0, 0, 0,230,173, 0, 0, 0, 0, 0,197,198,199,
6931 0, 0,229, 0, 0, 0, 0,196, 0, 0, 0, 0,227,228, 0,233,
6935 #endif