Automatically generate document icons
[MacVim.git] / src / os_unix.c
blobc9dcbd9c7f473f223efe52cc097af0407225643d
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 = (char *)alloc(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 /* Don't close the display for GTK 1, it is done in exit(). */
2942 # if defined(FEAT_X11) && (!defined(FEAT_GUI_GTK) || defined(HAVE_GTK2))
2943 if (x11_display != NULL
2944 # ifdef FEAT_XCLIPBOARD
2945 && x11_display != xterm_dpy
2946 # endif
2948 XCloseDisplay(x11_display);
2949 # endif
2950 # if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2951 vim_free(signal_stack);
2952 signal_stack = NULL;
2953 # endif
2954 # ifdef FEAT_TITLE
2955 vim_free(oldtitle);
2956 vim_free(oldicon);
2957 # endif
2959 #endif
2961 static void exit_scroll __ARGS((void));
2964 * Output a newline when exiting.
2965 * Make sure the newline goes to the same stream as the text.
2967 static void
2968 exit_scroll()
2970 if (silent_mode)
2971 return;
2972 if (newline_on_exit || msg_didout)
2974 if (msg_use_printf())
2976 if (info_message)
2977 mch_msg("\n");
2978 else
2979 mch_errmsg("\r\n");
2981 else
2982 out_char('\n');
2984 else
2986 restore_cterm_colors(); /* get original colors back */
2987 msg_clr_eos_force(); /* clear the rest of the display */
2988 windgoto((int)Rows - 1, 0); /* may have moved the cursor */
2992 void
2993 mch_exit(r)
2994 int r;
2996 exiting = TRUE;
2998 #if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
2999 x11_export_final_selection();
3000 #endif
3002 #ifdef FEAT_GUI
3003 if (!gui.in_use)
3004 #endif
3006 settmode(TMODE_COOK);
3007 #ifdef FEAT_TITLE
3008 mch_restore_title(3); /* restore xterm title and icon name */
3009 #endif
3011 * When t_ti is not empty but it doesn't cause swapping terminal
3012 * pages, need to output a newline when msg_didout is set. But when
3013 * t_ti does swap pages it should not go to the shell page. Do this
3014 * before stoptermcap().
3016 if (swapping_screen() && !newline_on_exit)
3017 exit_scroll();
3019 /* Stop termcap: May need to check for T_CRV response, which
3020 * requires RAW mode. */
3021 stoptermcap();
3024 * A newline is only required after a message in the alternate screen.
3025 * This is set to TRUE by wait_return().
3027 if (!swapping_screen() || newline_on_exit)
3028 exit_scroll();
3030 /* Cursor may have been switched off without calling starttermcap()
3031 * when doing "vim -u vimrc" and vimrc contains ":q". */
3032 if (full_screen)
3033 cursor_on();
3035 out_flush();
3036 ml_close_all(TRUE); /* remove all memfiles */
3037 may_core_dump();
3038 #ifdef FEAT_GUI
3039 if (gui.in_use)
3040 gui_exit(r);
3041 #endif
3043 #ifdef MACOS_CONVERT
3044 mac_conv_cleanup();
3045 #endif
3047 #ifdef __QNX__
3048 /* A core dump won't be created if the signal handler
3049 * doesn't return, so we can't call exit() */
3050 if (deadly_signal != 0)
3051 return;
3052 #endif
3054 #ifdef FEAT_NETBEANS_INTG
3055 if (usingNetbeans)
3056 netbeans_send_disconnect();
3057 #endif
3059 #ifdef EXITFREE
3060 free_all_mem();
3061 #endif
3063 exit(r);
3066 static void
3067 may_core_dump()
3069 if (deadly_signal != 0)
3071 signal(deadly_signal, SIG_DFL);
3072 kill(getpid(), deadly_signal); /* Die using the signal we caught */
3076 #ifndef VMS
3078 void
3079 mch_settmode(tmode)
3080 int tmode;
3082 static int first = TRUE;
3084 /* Why is NeXT excluded here (and not in os_unixx.h)? */
3085 #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
3087 * for "new" tty systems
3089 # ifdef HAVE_TERMIOS_H
3090 static struct termios told;
3091 struct termios tnew;
3092 # else
3093 static struct termio told;
3094 struct termio tnew;
3095 # endif
3097 if (first)
3099 first = FALSE;
3100 # if defined(HAVE_TERMIOS_H)
3101 tcgetattr(read_cmd_fd, &told);
3102 # else
3103 ioctl(read_cmd_fd, TCGETA, &told);
3104 # endif
3107 tnew = told;
3108 if (tmode == TMODE_RAW)
3111 * ~ICRNL enables typing ^V^M
3113 tnew.c_iflag &= ~ICRNL;
3114 tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE
3115 # if defined(IEXTEN) && !defined(__MINT__)
3116 | IEXTEN /* IEXTEN enables typing ^V on SOLARIS */
3117 /* but it breaks function keys on MINT */
3118 # endif
3120 # ifdef ONLCR /* don't map NL -> CR NL, we do it ourselves */
3121 tnew.c_oflag &= ~ONLCR;
3122 # endif
3123 tnew.c_cc[VMIN] = 1; /* return after 1 char */
3124 tnew.c_cc[VTIME] = 0; /* don't wait */
3126 else if (tmode == TMODE_SLEEP)
3127 tnew.c_lflag &= ~(ECHO);
3129 # if defined(HAVE_TERMIOS_H)
3131 int n = 10;
3133 /* A signal may cause tcsetattr() to fail (e.g., SIGCONT). Retry a
3134 * few times. */
3135 while (tcsetattr(read_cmd_fd, TCSANOW, &tnew) == -1
3136 && errno == EINTR && n > 0)
3137 --n;
3139 # else
3140 ioctl(read_cmd_fd, TCSETA, &tnew);
3141 # endif
3143 #else
3146 * for "old" tty systems
3148 # ifndef TIOCSETN
3149 # define TIOCSETN TIOCSETP /* for hpux 9.0 */
3150 # endif
3151 static struct sgttyb ttybold;
3152 struct sgttyb ttybnew;
3154 if (first)
3156 first = FALSE;
3157 ioctl(read_cmd_fd, TIOCGETP, &ttybold);
3160 ttybnew = ttybold;
3161 if (tmode == TMODE_RAW)
3163 ttybnew.sg_flags &= ~(CRMOD | ECHO);
3164 ttybnew.sg_flags |= RAW;
3166 else if (tmode == TMODE_SLEEP)
3167 ttybnew.sg_flags &= ~(ECHO);
3168 ioctl(read_cmd_fd, TIOCSETN, &ttybnew);
3169 #endif
3170 curr_tmode = tmode;
3174 * Try to get the code for "t_kb" from the stty setting
3176 * Even if termcap claims a backspace key, the user's setting *should*
3177 * prevail. stty knows more about reality than termcap does, and if
3178 * somebody's usual erase key is DEL (which, for most BSD users, it will
3179 * be), they're going to get really annoyed if their erase key starts
3180 * doing forward deletes for no reason. (Eric Fischer)
3182 void
3183 get_stty()
3185 char_u buf[2];
3186 char_u *p;
3188 /* Why is NeXT excluded here (and not in os_unixx.h)? */
3189 #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
3190 /* for "new" tty systems */
3191 # ifdef HAVE_TERMIOS_H
3192 struct termios keys;
3193 # else
3194 struct termio keys;
3195 # endif
3197 # if defined(HAVE_TERMIOS_H)
3198 if (tcgetattr(read_cmd_fd, &keys) != -1)
3199 # else
3200 if (ioctl(read_cmd_fd, TCGETA, &keys) != -1)
3201 # endif
3203 buf[0] = keys.c_cc[VERASE];
3204 intr_char = keys.c_cc[VINTR];
3205 #else
3206 /* for "old" tty systems */
3207 struct sgttyb keys;
3209 if (ioctl(read_cmd_fd, TIOCGETP, &keys) != -1)
3211 buf[0] = keys.sg_erase;
3212 intr_char = keys.sg_kill;
3213 #endif
3214 buf[1] = NUL;
3215 add_termcode((char_u *)"kb", buf, FALSE);
3218 * If <BS> and <DEL> are now the same, redefine <DEL>.
3220 p = find_termcode((char_u *)"kD");
3221 if (p != NULL && p[0] == buf[0] && p[1] == buf[1])
3222 do_fixdel(NULL);
3224 #if 0
3225 } /* to keep cindent happy */
3226 #endif
3229 #endif /* VMS */
3231 #if defined(FEAT_MOUSE_TTY) || defined(PROTO)
3233 * Set mouse clicks on or off.
3235 void
3236 mch_setmouse(on)
3237 int on;
3239 static int ison = FALSE;
3240 int xterm_mouse_vers;
3242 if (on == ison) /* return quickly if nothing to do */
3243 return;
3245 xterm_mouse_vers = use_xterm_mouse();
3246 if (xterm_mouse_vers > 0)
3248 if (on) /* enable mouse events, use mouse tracking if available */
3249 out_str_nf((char_u *)
3250 (xterm_mouse_vers > 1
3251 ? IF_EB("\033[?1002h", ESC_STR "[?1002h")
3252 : IF_EB("\033[?1000h", ESC_STR "[?1000h")));
3253 else /* disable mouse events, could probably always send the same */
3254 out_str_nf((char_u *)
3255 (xterm_mouse_vers > 1
3256 ? IF_EB("\033[?1002l", ESC_STR "[?1002l")
3257 : IF_EB("\033[?1000l", ESC_STR "[?1000l")));
3258 ison = on;
3261 # ifdef FEAT_MOUSE_DEC
3262 else if (ttym_flags == TTYM_DEC)
3264 if (on) /* enable mouse events */
3265 out_str_nf((char_u *)"\033[1;2'z\033[1;3'{");
3266 else /* disable mouse events */
3267 out_str_nf((char_u *)"\033['z");
3268 ison = on;
3270 # endif
3272 # ifdef FEAT_MOUSE_GPM
3273 else
3275 if (on)
3277 if (gpm_open())
3278 ison = TRUE;
3280 else
3282 gpm_close();
3283 ison = FALSE;
3286 # endif
3288 # ifdef FEAT_SYSMOUSE
3289 else
3291 if (on)
3293 if (sysmouse_open() == OK)
3294 ison = TRUE;
3296 else
3298 sysmouse_close();
3299 ison = FALSE;
3302 # endif
3304 # ifdef FEAT_MOUSE_JSB
3305 else
3307 if (on)
3309 /* D - Enable Mouse up/down messages
3310 * L - Enable Left Button Reporting
3311 * M - Enable Middle Button Reporting
3312 * R - Enable Right Button Reporting
3313 * K - Enable SHIFT and CTRL key Reporting
3314 * + - Enable Advanced messaging of mouse moves and up/down messages
3315 * Q - Quiet No Ack
3316 * # - Numeric value of mouse pointer required
3317 * 0 = Multiview 2000 cursor, used as standard
3318 * 1 = Windows Arrow
3319 * 2 = Windows I Beam
3320 * 3 = Windows Hour Glass
3321 * 4 = Windows Cross Hair
3322 * 5 = Windows UP Arrow
3324 #ifdef JSBTERM_MOUSE_NONADVANCED /* Disables full feedback of pointer movements */
3325 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK1Q\033\\",
3326 ESC_STR "[0~ZwLMRK1Q" ESC_STR "\\"));
3327 #else
3328 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK+1Q\033\\",
3329 ESC_STR "[0~ZwLMRK+1Q" ESC_STR "\\"));
3330 #endif
3331 ison = TRUE;
3333 else
3335 out_str_nf((char_u *)IF_EB("\033[0~ZwQ\033\\",
3336 ESC_STR "[0~ZwQ" ESC_STR "\\"));
3337 ison = FALSE;
3340 # endif
3341 # ifdef FEAT_MOUSE_PTERM
3342 else
3344 /* 1 = button press, 6 = release, 7 = drag, 1h...9l = right button */
3345 if (on)
3346 out_str_nf("\033[>1h\033[>6h\033[>7h\033[>1h\033[>9l");
3347 else
3348 out_str_nf("\033[>1l\033[>6l\033[>7l\033[>1l\033[>9h");
3349 ison = on;
3351 # endif
3355 * Set the mouse termcode, depending on the 'term' and 'ttymouse' options.
3357 void
3358 check_mouse_termcode()
3360 # ifdef FEAT_MOUSE_XTERM
3361 if (use_xterm_mouse()
3362 # ifdef FEAT_GUI
3363 && !gui.in_use
3364 # endif
3367 set_mouse_termcode(KS_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3368 ? IF_EB("\233M", CSI_STR "M")
3369 : IF_EB("\033[M", ESC_STR "[M")));
3370 if (*p_mouse != NUL)
3372 /* force mouse off and maybe on to send possibly new mouse
3373 * activation sequence to the xterm, with(out) drag tracing. */
3374 mch_setmouse(FALSE);
3375 setmouse();
3378 else
3379 del_mouse_termcode(KS_MOUSE);
3380 # endif
3382 # ifdef FEAT_MOUSE_GPM
3383 if (!use_xterm_mouse()
3384 # ifdef FEAT_GUI
3385 && !gui.in_use
3386 # endif
3388 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MG", ESC_STR "MG"));
3389 # endif
3391 # ifdef FEAT_SYSMOUSE
3392 if (!use_xterm_mouse()
3393 # ifdef FEAT_GUI
3394 && !gui.in_use
3395 # endif
3397 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MS", ESC_STR "MS"));
3398 # endif
3400 # ifdef FEAT_MOUSE_JSB
3401 /* conflicts with xterm mouse: "\033[" and "\033[M" ??? */
3402 if (!use_xterm_mouse()
3403 # ifdef FEAT_GUI
3404 && !gui.in_use
3405 # endif
3407 set_mouse_termcode(KS_JSBTERM_MOUSE,
3408 (char_u *)IF_EB("\033[0~zw", ESC_STR "[0~zw"));
3409 else
3410 del_mouse_termcode(KS_JSBTERM_MOUSE);
3411 # endif
3413 # ifdef FEAT_MOUSE_NET
3414 /* There is no conflict, but one may type "ESC }" from Insert mode. Don't
3415 * define it in the GUI or when using an xterm. */
3416 if (!use_xterm_mouse()
3417 # ifdef FEAT_GUI
3418 && !gui.in_use
3419 # endif
3421 set_mouse_termcode(KS_NETTERM_MOUSE,
3422 (char_u *)IF_EB("\033}", ESC_STR "}"));
3423 else
3424 del_mouse_termcode(KS_NETTERM_MOUSE);
3425 # endif
3427 # ifdef FEAT_MOUSE_DEC
3428 /* conflicts with xterm mouse: "\033[" and "\033[M" */
3429 if (!use_xterm_mouse()
3430 # ifdef FEAT_GUI
3431 && !gui.in_use
3432 # endif
3434 set_mouse_termcode(KS_DEC_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3435 ? IF_EB("\233", CSI_STR) : IF_EB("\033[", ESC_STR "[")));
3436 else
3437 del_mouse_termcode(KS_DEC_MOUSE);
3438 # endif
3439 # ifdef FEAT_MOUSE_PTERM
3440 /* same as the dec mouse */
3441 if (!use_xterm_mouse()
3442 # ifdef FEAT_GUI
3443 && !gui.in_use
3444 # endif
3446 set_mouse_termcode(KS_PTERM_MOUSE,
3447 (char_u *) IF_EB("\033[", ESC_STR "["));
3448 else
3449 del_mouse_termcode(KS_PTERM_MOUSE);
3450 # endif
3452 #endif
3455 * set screen mode, always fails.
3457 /* ARGSUSED */
3459 mch_screenmode(arg)
3460 char_u *arg;
3462 EMSG(_(e_screenmode));
3463 return FAIL;
3466 #ifndef VMS
3469 * Try to get the current window size:
3470 * 1. with an ioctl(), most accurate method
3471 * 2. from the environment variables LINES and COLUMNS
3472 * 3. from the termcap
3473 * 4. keep using the old values
3474 * Return OK when size could be determined, FAIL otherwise.
3477 mch_get_shellsize()
3479 long rows = 0;
3480 long columns = 0;
3481 char_u *p;
3484 * For OS/2 use _scrsize().
3486 # ifdef __EMX__
3488 int s[2];
3490 _scrsize(s);
3491 columns = s[0];
3492 rows = s[1];
3494 # endif
3497 * 1. try using an ioctl. It is the most accurate method.
3499 * Try using TIOCGWINSZ first, some systems that have it also define
3500 * TIOCGSIZE but don't have a struct ttysize.
3502 # ifdef TIOCGWINSZ
3504 struct winsize ws;
3505 int fd = 1;
3507 /* When stdout is not a tty, use stdin for the ioctl(). */
3508 if (!isatty(fd) && isatty(read_cmd_fd))
3509 fd = read_cmd_fd;
3510 if (ioctl(fd, TIOCGWINSZ, &ws) == 0)
3512 columns = ws.ws_col;
3513 rows = ws.ws_row;
3516 # else /* TIOCGWINSZ */
3517 # ifdef TIOCGSIZE
3519 struct ttysize ts;
3520 int fd = 1;
3522 /* When stdout is not a tty, use stdin for the ioctl(). */
3523 if (!isatty(fd) && isatty(read_cmd_fd))
3524 fd = read_cmd_fd;
3525 if (ioctl(fd, TIOCGSIZE, &ts) == 0)
3527 columns = ts.ts_cols;
3528 rows = ts.ts_lines;
3531 # endif /* TIOCGSIZE */
3532 # endif /* TIOCGWINSZ */
3535 * 2. get size from environment
3536 * When being POSIX compliant ('|' flag in 'cpoptions') this overrules
3537 * the ioctl() values!
3539 if (columns == 0 || rows == 0 || vim_strchr(p_cpo, CPO_TSIZE) != NULL)
3541 if ((p = (char_u *)getenv("LINES")))
3542 rows = atoi((char *)p);
3543 if ((p = (char_u *)getenv("COLUMNS")))
3544 columns = atoi((char *)p);
3547 #ifdef HAVE_TGETENT
3549 * 3. try reading "co" and "li" entries from termcap
3551 if (columns == 0 || rows == 0)
3552 getlinecol(&columns, &rows);
3553 #endif
3556 * 4. If everything fails, use the old values
3558 if (columns <= 0 || rows <= 0)
3559 return FAIL;
3561 Rows = rows;
3562 Columns = columns;
3563 return OK;
3567 * Try to set the window size to Rows and Columns.
3569 void
3570 mch_set_shellsize()
3572 if (*T_CWS)
3575 * NOTE: if you get an error here that term_set_winsize() is
3576 * undefined, check the output of configure. It could probably not
3577 * find a ncurses, termcap or termlib library.
3579 term_set_winsize((int)Rows, (int)Columns);
3580 out_flush();
3581 screen_start(); /* don't know where cursor is now */
3585 #endif /* VMS */
3588 * Rows and/or Columns has changed.
3590 void
3591 mch_new_shellsize()
3593 /* Nothing to do. */
3596 #ifndef USE_SYSTEM
3597 static void append_ga_line __ARGS((garray_T *gap));
3600 * Append the text in "gap" below the cursor line and clear "gap".
3602 static void
3603 append_ga_line(gap)
3604 garray_T *gap;
3606 /* Remove trailing CR. */
3607 if (gap->ga_len > 0
3608 && !curbuf->b_p_bin
3609 && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR)
3610 --gap->ga_len;
3611 ga_append(gap, NUL);
3612 ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE);
3613 gap->ga_len = 0;
3615 #endif
3618 mch_call_shell(cmd, options)
3619 char_u *cmd;
3620 int options; /* SHELL_*, see vim.h */
3622 #ifdef VMS
3623 char *ifn = NULL;
3624 char *ofn = NULL;
3625 #endif
3626 int tmode = cur_tmode;
3627 #ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
3628 int x;
3629 # ifndef __EMX__
3630 char_u *newcmd; /* only needed for unix */
3631 # else
3633 * Set the preferred shell in the EMXSHELL environment variable (but
3634 * only if it is different from what is already in the environment).
3635 * Emx then takes care of whether to use "/c" or "-c" in an
3636 * intelligent way. Simply pass the whole thing to emx's system() call.
3637 * Emx also starts an interactive shell if system() is passed an empty
3638 * string.
3640 char_u *p, *old;
3642 if (((old = (char_u *)getenv("EMXSHELL")) == NULL) || STRCMP(old, p_sh))
3644 /* should check HAVE_SETENV, but I know we don't have it. */
3645 p = alloc(10 + strlen(p_sh));
3646 if (p)
3648 sprintf((char *)p, "EMXSHELL=%s", p_sh);
3649 putenv((char *)p); /* don't free the pointer! */
3652 # endif
3654 out_flush();
3656 if (options & SHELL_COOKED)
3657 settmode(TMODE_COOK); /* set to normal mode */
3659 # ifdef __EMX__
3660 if (cmd == NULL)
3661 x = system(""); /* this starts an interactive shell in emx */
3662 else
3663 x = system((char *)cmd);
3664 /* system() returns -1 when error occurs in starting shell */
3665 if (x == -1 && !emsg_silent)
3667 MSG_PUTS(_("\nCannot execute shell "));
3668 msg_outtrans(p_sh);
3669 msg_putchar('\n');
3671 # else /* not __EMX__ */
3672 if (cmd == NULL)
3673 x = system((char *)p_sh);
3674 else
3676 # ifdef VMS
3677 if (ofn = strchr((char *)cmd, '>'))
3678 *ofn++ = '\0';
3679 if (ifn = strchr((char *)cmd, '<'))
3681 char *p;
3683 *ifn++ = '\0';
3684 p = strchr(ifn,' '); /* chop off any trailing spaces */
3685 if (p)
3686 *p = '\0';
3688 if (ofn)
3689 x = vms_sys((char *)cmd, ofn, ifn);
3690 else
3691 x = system((char *)cmd);
3692 # else
3693 newcmd = lalloc(STRLEN(p_sh)
3694 + (extra_shell_arg == NULL ? 0 : STRLEN(extra_shell_arg))
3695 + STRLEN(p_shcf) + STRLEN(cmd) + 4, TRUE);
3696 if (newcmd == NULL)
3697 x = 0;
3698 else
3700 sprintf((char *)newcmd, "%s %s %s %s", p_sh,
3701 extra_shell_arg == NULL ? "" : (char *)extra_shell_arg,
3702 (char *)p_shcf,
3703 (char *)cmd);
3704 x = system((char *)newcmd);
3705 vim_free(newcmd);
3707 # endif
3709 # ifdef VMS
3710 x = vms_sys_status(x);
3711 # endif
3712 if (emsg_silent)
3714 else if (x == 127)
3715 MSG_PUTS(_("\nCannot execute shell sh\n"));
3716 # endif /* __EMX__ */
3717 else if (x && !(options & SHELL_SILENT))
3719 MSG_PUTS(_("\nshell returned "));
3720 msg_outnum((long)x);
3721 msg_putchar('\n');
3724 if (tmode == TMODE_RAW)
3725 settmode(TMODE_RAW); /* set to raw mode */
3726 # ifdef FEAT_TITLE
3727 resettitle();
3728 # endif
3729 return x;
3731 #else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
3733 # define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
3734 127, some shells use that already */
3736 char_u *newcmd = NULL;
3737 pid_t pid;
3738 pid_t wpid = 0;
3739 pid_t wait_pid = 0;
3740 # ifdef HAVE_UNION_WAIT
3741 union wait status;
3742 # else
3743 int status = -1;
3744 # endif
3745 int retval = -1;
3746 char **argv = NULL;
3747 int argc;
3748 int i;
3749 char_u *p;
3750 int inquote;
3751 int pty_master_fd = -1; /* for pty's */
3752 # ifdef FEAT_GUI
3753 int pty_slave_fd = -1;
3754 char *tty_name;
3755 # endif
3756 int fd_toshell[2]; /* for pipes */
3757 int fd_fromshell[2];
3758 int pipe_error = FALSE;
3759 # ifdef HAVE_SETENV
3760 char envbuf[50];
3761 # else
3762 static char envbuf_Rows[20];
3763 static char envbuf_Columns[20];
3764 # endif
3765 int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
3767 out_flush();
3768 if (options & SHELL_COOKED)
3769 settmode(TMODE_COOK); /* set to normal mode */
3771 newcmd = vim_strsave(p_sh);
3772 if (newcmd == NULL) /* out of memory */
3773 goto error;
3776 * Do this loop twice:
3777 * 1: find number of arguments
3778 * 2: separate them and build argv[]
3780 for (i = 0; i < 2; ++i)
3782 p = newcmd;
3783 inquote = FALSE;
3784 argc = 0;
3785 for (;;)
3787 if (i == 1)
3788 argv[argc] = (char *)p;
3789 ++argc;
3790 while (*p && (inquote || (*p != ' ' && *p != TAB)))
3792 if (*p == '"')
3793 inquote = !inquote;
3794 ++p;
3796 if (*p == NUL)
3797 break;
3798 if (i == 1)
3799 *p++ = NUL;
3800 p = skipwhite(p);
3802 if (argv == NULL)
3804 argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *)));
3805 if (argv == NULL) /* out of memory */
3806 goto error;
3809 if (cmd != NULL)
3811 if (extra_shell_arg != NULL)
3812 argv[argc++] = (char *)extra_shell_arg;
3813 argv[argc++] = (char *)p_shcf;
3814 argv[argc++] = (char *)cmd;
3816 argv[argc] = NULL;
3819 * For the GUI, when writing the output into the buffer and when reading
3820 * input from the buffer: Try using a pseudo-tty to get the stdin/stdout
3821 * of the executed command into the Vim window. Or use a pipe.
3823 if ((options & (SHELL_READ|SHELL_WRITE))
3824 # ifdef FEAT_GUI
3825 || (gui.in_use && show_shell_mess)
3826 # endif
3829 # ifdef FEAT_GUI
3831 * Try to open a master pty.
3832 * If this works, open the slave pty.
3833 * If the slave can't be opened, close the master pty.
3835 if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
3837 pty_master_fd = OpenPTY(&tty_name); /* open pty */
3838 if (pty_master_fd >= 0 && ((pty_slave_fd =
3839 open(tty_name, O_RDWR | O_EXTRA, 0)) < 0))
3841 close(pty_master_fd);
3842 pty_master_fd = -1;
3846 * If not opening a pty or it didn't work, try using pipes.
3848 if (pty_master_fd < 0)
3849 # endif
3851 pipe_error = (pipe(fd_toshell) < 0);
3852 if (!pipe_error) /* pipe create OK */
3854 pipe_error = (pipe(fd_fromshell) < 0);
3855 if (pipe_error) /* pipe create failed */
3857 close(fd_toshell[0]);
3858 close(fd_toshell[1]);
3861 if (pipe_error)
3863 MSG_PUTS(_("\nCannot create pipes\n"));
3864 out_flush();
3869 if (!pipe_error) /* pty or pipe opened or not used */
3871 # ifdef __BEOS__
3872 beos_cleanup_read_thread();
3873 # endif
3875 if ((pid = fork()) == -1) /* maybe we should use vfork() */
3877 MSG_PUTS(_("\nCannot fork\n"));
3878 if ((options & (SHELL_READ|SHELL_WRITE))
3879 # ifdef FEAT_GUI
3880 || (gui.in_use && show_shell_mess)
3881 # endif
3884 # ifdef FEAT_GUI
3885 if (pty_master_fd >= 0) /* close the pseudo tty */
3887 close(pty_master_fd);
3888 close(pty_slave_fd);
3890 else /* close the pipes */
3891 # endif
3893 close(fd_toshell[0]);
3894 close(fd_toshell[1]);
3895 close(fd_fromshell[0]);
3896 close(fd_fromshell[1]);
3900 else if (pid == 0) /* child */
3902 reset_signals(); /* handle signals normally */
3904 if (!show_shell_mess || (options & SHELL_EXPAND))
3906 int fd;
3909 * Don't want to show any message from the shell. Can't just
3910 * close stdout and stderr though, because some systems will
3911 * break if you try to write to them after that, so we must
3912 * use dup() to replace them with something else -- webb
3913 * Connect stdin to /dev/null too, so ":n `cat`" doesn't hang,
3914 * waiting for input.
3916 fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
3917 fclose(stdin);
3918 fclose(stdout);
3919 fclose(stderr);
3922 * If any of these open()'s and dup()'s fail, we just continue
3923 * anyway. It's not fatal, and on most systems it will make
3924 * no difference at all. On a few it will cause the execvp()
3925 * to exit with a non-zero status even when the completion
3926 * could be done, which is nothing too serious. If the open()
3927 * or dup() failed we'd just do the same thing ourselves
3928 * anyway -- webb
3930 if (fd >= 0)
3932 dup(fd); /* To replace stdin (file descriptor 0) */
3933 dup(fd); /* To replace stdout (file descriptor 1) */
3934 dup(fd); /* To replace stderr (file descriptor 2) */
3936 /* Don't need this now that we've duplicated it */
3937 close(fd);
3940 else if ((options & (SHELL_READ|SHELL_WRITE))
3941 # ifdef FEAT_GUI
3942 || gui.in_use
3943 # endif
3947 # ifdef HAVE_SETSID
3948 /* Create our own process group, so that the child and all its
3949 * children can be kill()ed. Don't do this when using pipes,
3950 * because stdin is not a tty, we would lose /dev/tty. */
3951 if (p_stmp)
3952 (void)setsid();
3953 # endif
3954 # ifdef FEAT_GUI
3955 if (pty_slave_fd >= 0)
3957 /* push stream discipline modules */
3958 if (options & SHELL_COOKED)
3959 SetupSlavePTY(pty_slave_fd);
3960 # if defined(TIOCSCTTY) && !defined(FEAT_GUI_MACVIM)
3961 /* Try to become controlling tty (probably doesn't work,
3962 * unless run by root) */
3963 ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
3964 # endif
3966 # endif
3967 /* Simulate to have a dumb terminal (for now) */
3968 # ifdef HAVE_SETENV
3969 setenv("TERM", "dumb", 1);
3970 sprintf((char *)envbuf, "%ld", Rows);
3971 setenv("ROWS", (char *)envbuf, 1);
3972 sprintf((char *)envbuf, "%ld", Rows);
3973 setenv("LINES", (char *)envbuf, 1);
3974 sprintf((char *)envbuf, "%ld", Columns);
3975 setenv("COLUMNS", (char *)envbuf, 1);
3976 # else
3978 * Putenv does not copy the string, it has to remain valid.
3979 * Use a static array to avoid losing allocated memory.
3981 putenv("TERM=dumb");
3982 sprintf(envbuf_Rows, "ROWS=%ld", Rows);
3983 putenv(envbuf_Rows);
3984 sprintf(envbuf_Rows, "LINES=%ld", Rows);
3985 putenv(envbuf_Rows);
3986 sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
3987 putenv(envbuf_Columns);
3988 # endif
3991 * stderr is only redirected when using the GUI, so that a
3992 * program like gpg can still access the terminal to get a
3993 * passphrase using stderr.
3995 # ifdef FEAT_GUI
3996 if (pty_master_fd >= 0)
3998 close(pty_master_fd); /* close master side of pty */
4000 /* set up stdin/stdout/stderr for the child */
4001 close(0);
4002 dup(pty_slave_fd);
4003 close(1);
4004 dup(pty_slave_fd);
4005 if (gui.in_use)
4007 close(2);
4008 dup(pty_slave_fd);
4011 close(pty_slave_fd); /* has been dupped, close it now */
4013 else
4014 # endif
4016 /* set up stdin for the child */
4017 close(fd_toshell[1]);
4018 close(0);
4019 dup(fd_toshell[0]);
4020 close(fd_toshell[0]);
4022 /* set up stdout for the child */
4023 close(fd_fromshell[0]);
4024 close(1);
4025 dup(fd_fromshell[1]);
4026 close(fd_fromshell[1]);
4028 # ifdef FEAT_GUI
4029 if (gui.in_use)
4031 /* set up stderr for the child */
4032 close(2);
4033 dup(1);
4035 # endif
4040 * There is no type cast for the argv, because the type may be
4041 * different on different machines. This may cause a warning
4042 * message with strict compilers, don't worry about it.
4043 * Call _exit() instead of exit() to avoid closing the connection
4044 * to the X server (esp. with GTK, which uses atexit()).
4046 execvp(argv[0], argv);
4047 _exit(EXEC_FAILED); /* exec failed, return failure code */
4049 else /* parent */
4052 * While child is running, ignore terminating signals.
4053 * Do catch CTRL-C, so that "got_int" is set.
4055 catch_signals(SIG_IGN, SIG_ERR);
4056 catch_int_signal();
4059 * For the GUI we redirect stdin, stdout and stderr to our window.
4060 * This is also used to pipe stdin/stdout to/from the external
4061 * command.
4063 if ((options & (SHELL_READ|SHELL_WRITE))
4064 # ifdef FEAT_GUI
4065 || (gui.in_use && show_shell_mess)
4066 # endif
4069 # define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
4070 char_u buffer[BUFLEN + 1];
4071 # ifdef FEAT_MBYTE
4072 int buffer_off = 0; /* valid bytes in buffer[] */
4073 # endif
4074 char_u ta_buf[BUFLEN + 1]; /* TypeAHead */
4075 int ta_len = 0; /* valid bytes in ta_buf[] */
4076 int len;
4077 int p_more_save;
4078 int old_State;
4079 int c;
4080 int toshell_fd;
4081 int fromshell_fd;
4082 garray_T ga;
4083 int noread_cnt;
4085 # ifdef FEAT_GUI
4086 if (pty_master_fd >= 0)
4088 close(pty_slave_fd); /* close slave side of pty */
4089 fromshell_fd = pty_master_fd;
4090 toshell_fd = dup(pty_master_fd);
4092 else
4093 # endif
4095 close(fd_toshell[0]);
4096 close(fd_fromshell[1]);
4097 toshell_fd = fd_toshell[1];
4098 fromshell_fd = fd_fromshell[0];
4102 * Write to the child if there are typed characters.
4103 * Read from the child if there are characters available.
4104 * Repeat the reading a few times if more characters are
4105 * available. Need to check for typed keys now and then, but
4106 * not too often (delays when no chars are available).
4107 * This loop is quit if no characters can be read from the pty
4108 * (WaitForChar detected special condition), or there are no
4109 * characters available and the child has exited.
4110 * Only check if the child has exited when there is no more
4111 * output. The child may exit before all the output has
4112 * been printed.
4114 * Currently this busy loops!
4115 * This can probably dead-lock when the write blocks!
4117 p_more_save = p_more;
4118 p_more = FALSE;
4119 old_State = State;
4120 State = EXTERNCMD; /* don't redraw at window resize */
4122 if ((options & SHELL_WRITE) && toshell_fd >= 0)
4124 /* Fork a process that will write the lines to the
4125 * external program. */
4126 if ((wpid = fork()) == -1)
4128 MSG_PUTS(_("\nCannot fork\n"));
4130 else if (wpid == 0)
4132 linenr_T lnum = curbuf->b_op_start.lnum;
4133 int written = 0;
4134 char_u *lp = ml_get(lnum);
4135 char_u *s;
4136 size_t l;
4138 /* child */
4139 close(fromshell_fd);
4140 for (;;)
4142 l = STRLEN(lp + written);
4143 if (l == 0)
4144 len = 0;
4145 else if (lp[written] == NL)
4146 /* NL -> NUL translation */
4147 len = write(toshell_fd, "", (size_t)1);
4148 else
4150 s = vim_strchr(lp + written, NL);
4151 len = write(toshell_fd, (char *)lp + written,
4152 s == NULL ? l : s - (lp + written));
4154 if (len == l)
4156 /* Finished a line, add a NL, unless this line
4157 * should not have one. */
4158 if (lnum != curbuf->b_op_end.lnum
4159 || !curbuf->b_p_bin
4160 || (lnum != write_no_eol_lnum
4161 && (lnum !=
4162 curbuf->b_ml.ml_line_count
4163 || curbuf->b_p_eol)))
4164 write(toshell_fd, "\n", (size_t)1);
4165 ++lnum;
4166 if (lnum > curbuf->b_op_end.lnum)
4168 /* finished all the lines, close pipe */
4169 close(toshell_fd);
4170 toshell_fd = -1;
4171 break;
4173 lp = ml_get(lnum);
4174 written = 0;
4176 else if (len > 0)
4177 written += len;
4179 _exit(0);
4181 else
4183 close(toshell_fd);
4184 toshell_fd = -1;
4188 if (options & SHELL_READ)
4189 ga_init2(&ga, 1, BUFLEN);
4191 noread_cnt = 0;
4193 for (;;)
4196 * Check if keys have been typed, write them to the child
4197 * if there are any.
4198 * Don't do this if we are expanding wild cards (would eat
4199 * typeahead).
4200 * Don't do this when filtering and terminal is in cooked
4201 * mode, the shell command will handle the I/O. Avoids
4202 * that a typed password is echoed for ssh or gpg command.
4203 * Don't get characters when the child has already
4204 * finished (wait_pid == 0).
4205 * Don't get extra characters when we already have one.
4206 * Don't read characters unless we didn't get output for a
4207 * while, avoids that ":r !ls" eats typeahead.
4209 len = 0;
4210 if (!(options & SHELL_EXPAND)
4211 && ((options &
4212 (SHELL_READ|SHELL_WRITE|SHELL_COOKED))
4213 != (SHELL_READ|SHELL_WRITE|SHELL_COOKED)
4214 #ifdef FEAT_GUI
4215 || gui.in_use
4216 #endif
4218 && wait_pid == 0
4219 && (ta_len > 0
4220 || (noread_cnt > 4
4221 && (len = ui_inchar(ta_buf,
4222 BUFLEN, 10L, 0)) > 0)))
4225 * For pipes:
4226 * Check for CTRL-C: send interrupt signal to child.
4227 * Check for CTRL-D: EOF, close pipe to child.
4229 if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
4231 # ifdef SIGINT
4233 * Send SIGINT to the child's group or all
4234 * processes in our group.
4236 if (ta_buf[ta_len] == Ctrl_C
4237 || ta_buf[ta_len] == intr_char)
4239 # ifdef HAVE_SETSID
4240 kill(-pid, SIGINT);
4241 # else
4242 kill(0, SIGINT);
4243 # endif
4244 if (wpid > 0)
4245 kill(wpid, SIGINT);
4247 # endif
4248 if (pty_master_fd < 0 && toshell_fd >= 0
4249 && ta_buf[ta_len] == Ctrl_D)
4251 close(toshell_fd);
4252 toshell_fd = -1;
4256 /* replace K_BS by <BS> and K_DEL by <DEL> */
4257 for (i = ta_len; i < ta_len + len; ++i)
4259 if (ta_buf[i] == CSI && len - i > 2)
4261 c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]);
4262 if (c == K_DEL || c == K_KDEL || c == K_BS)
4264 mch_memmove(ta_buf + i + 1, ta_buf + i + 3,
4265 (size_t)(len - i - 2));
4266 if (c == K_DEL || c == K_KDEL)
4267 ta_buf[i] = DEL;
4268 else
4269 ta_buf[i] = Ctrl_H;
4270 len -= 2;
4273 else if (ta_buf[i] == '\r')
4274 ta_buf[i] = '\n';
4275 # ifdef FEAT_MBYTE
4276 if (has_mbyte)
4277 i += (*mb_ptr2len)(ta_buf + i) - 1;
4278 # endif
4282 * For pipes: echo the typed characters.
4283 * For a pty this does not seem to work.
4285 if (pty_master_fd < 0)
4287 for (i = ta_len; i < ta_len + len; ++i)
4289 if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
4290 msg_putchar(ta_buf[i]);
4291 # ifdef FEAT_MBYTE
4292 else if (has_mbyte)
4294 int l = (*mb_ptr2len)(ta_buf + i);
4296 msg_outtrans_len(ta_buf + i, l);
4297 i += l - 1;
4299 # endif
4300 else
4301 msg_outtrans_len(ta_buf + i, 1);
4303 windgoto(msg_row, msg_col);
4304 out_flush();
4307 ta_len += len;
4310 * Write the characters to the child, unless EOF has
4311 * been typed for pipes. Write one character at a
4312 * time, to avoid losing too much typeahead.
4313 * When writing buffer lines, drop the typed
4314 * characters (only check for CTRL-C).
4316 if (options & SHELL_WRITE)
4317 ta_len = 0;
4318 else if (toshell_fd >= 0)
4320 len = write(toshell_fd, (char *)ta_buf, (size_t)1);
4321 if (len > 0)
4323 ta_len -= len;
4324 mch_memmove(ta_buf, ta_buf + len, ta_len);
4325 noread_cnt = 0;
4330 if (got_int)
4332 /* CTRL-C sends a signal to the child, we ignore it
4333 * ourselves */
4334 # ifdef HAVE_SETSID
4335 kill(-pid, SIGINT);
4336 # else
4337 kill(0, SIGINT);
4338 # endif
4339 if (wpid > 0)
4340 kill(wpid, SIGINT);
4341 got_int = FALSE;
4345 * Check if the child has any characters to be printed.
4346 * Read them and write them to our window. Repeat this as
4347 * long as there is something to do, avoid the 10ms wait
4348 * for mch_inchar(), or sending typeahead characters to
4349 * the external process.
4350 * TODO: This should handle escape sequences, compatible
4351 * to some terminal (vt52?).
4353 ++noread_cnt;
4354 while (RealWaitForChar(fromshell_fd, 10L, NULL))
4356 len = read(fromshell_fd, (char *)buffer
4357 # ifdef FEAT_MBYTE
4358 + buffer_off, (size_t)(BUFLEN - buffer_off)
4359 # else
4360 , (size_t)BUFLEN
4361 # endif
4363 if (len <= 0) /* end of file or error */
4364 goto finished;
4366 noread_cnt = 0;
4367 if (options & SHELL_READ)
4369 /* Do NUL -> NL translation, append NL separated
4370 * lines to the current buffer. */
4371 for (i = 0; i < len; ++i)
4373 if (buffer[i] == NL)
4374 append_ga_line(&ga);
4375 else if (buffer[i] == NUL)
4376 ga_append(&ga, NL);
4377 else
4378 ga_append(&ga, buffer[i]);
4381 # ifdef FEAT_MBYTE
4382 else if (has_mbyte)
4384 int l;
4386 len += buffer_off;
4387 buffer[len] = NUL;
4389 /* Check if the last character in buffer[] is
4390 * incomplete, keep these bytes for the next
4391 * round. */
4392 for (p = buffer; p < buffer + len; p += l)
4394 l = mb_cptr2len(p);
4395 if (l == 0)
4396 l = 1; /* NUL byte? */
4397 else if (MB_BYTE2LEN(*p) != l)
4398 break;
4400 if (p == buffer) /* no complete character */
4402 /* avoid getting stuck at an illegal byte */
4403 if (len >= 12)
4404 ++p;
4405 else
4407 buffer_off = len;
4408 continue;
4411 c = *p;
4412 *p = NUL;
4413 msg_puts(buffer);
4414 if (p < buffer + len)
4416 *p = c;
4417 buffer_off = (buffer + len) - p;
4418 mch_memmove(buffer, p, buffer_off);
4419 continue;
4421 buffer_off = 0;
4423 # endif /* FEAT_MBYTE */
4424 else
4426 buffer[len] = NUL;
4427 msg_puts(buffer);
4430 windgoto(msg_row, msg_col);
4431 cursor_on();
4432 out_flush();
4433 if (got_int)
4434 break;
4437 /* If we already detected the child has finished break the
4438 * loop now. */
4439 if (wait_pid == pid)
4440 break;
4443 * Check if the child still exists, before checking for
4444 * typed characters (otherwise we would lose typeahead).
4446 # ifdef __NeXT__
4447 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *) 0);
4448 # else
4449 wait_pid = waitpid(pid, &status, WNOHANG);
4450 # endif
4451 if ((wait_pid == (pid_t)-1 && errno == ECHILD)
4452 || (wait_pid == pid && WIFEXITED(status)))
4454 /* Don't break the loop yet, try reading more
4455 * characters from "fromshell_fd" first. When using
4456 * pipes there might still be something to read and
4457 * then we'll break the loop at the "break" above. */
4458 wait_pid = pid;
4460 else
4461 wait_pid = 0;
4463 finished:
4464 p_more = p_more_save;
4465 if (options & SHELL_READ)
4467 if (ga.ga_len > 0)
4469 append_ga_line(&ga);
4470 /* remember that the NL was missing */
4471 write_no_eol_lnum = curwin->w_cursor.lnum;
4473 else
4474 write_no_eol_lnum = 0;
4475 ga_clear(&ga);
4479 * Give all typeahead that wasn't used back to ui_inchar().
4481 if (ta_len)
4482 ui_inchar_undo(ta_buf, ta_len);
4483 State = old_State;
4484 if (toshell_fd >= 0)
4485 close(toshell_fd);
4486 close(fromshell_fd);
4490 * Wait until our child has exited.
4491 * Ignore wait() returning pids of other children and returning
4492 * because of some signal like SIGWINCH.
4493 * Don't wait if wait_pid was already set above, indicating the
4494 * child already exited.
4496 while (wait_pid != pid)
4498 # ifdef _THREAD_SAFE
4499 /* Ugly hack: when compiled with Python threads are probably
4500 * used, in which case wait() sometimes hangs for no obvious
4501 * reason. Use waitpid() instead and loop (like the GUI). */
4502 # ifdef __NeXT__
4503 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0);
4504 # else
4505 wait_pid = waitpid(pid, &status, WNOHANG);
4506 # endif
4507 if (wait_pid == 0)
4509 /* Wait for 1/100 sec before trying again. */
4510 mch_delay(10L, TRUE);
4511 continue;
4513 # else
4514 wait_pid = wait(&status);
4515 # endif
4516 if (wait_pid <= 0
4517 # ifdef ECHILD
4518 && errno == ECHILD
4519 # endif
4521 break;
4524 /* Make sure the child that writes to the external program is
4525 * dead. */
4526 if (wpid > 0)
4527 kill(wpid, SIGKILL);
4530 * Set to raw mode right now, otherwise a CTRL-C after
4531 * catch_signals() will kill Vim.
4533 if (tmode == TMODE_RAW)
4534 settmode(TMODE_RAW);
4535 did_settmode = TRUE;
4536 set_signals();
4538 if (WIFEXITED(status))
4540 /* LINTED avoid "bitwise operation on signed value" */
4541 retval = WEXITSTATUS(status);
4542 if (retval && !emsg_silent)
4544 if (retval == EXEC_FAILED)
4546 MSG_PUTS(_("\nCannot execute shell "));
4547 msg_outtrans(p_sh);
4548 msg_putchar('\n');
4550 else if (!(options & SHELL_SILENT))
4552 MSG_PUTS(_("\nshell returned "));
4553 msg_outnum((long)retval);
4554 msg_putchar('\n');
4558 else
4559 MSG_PUTS(_("\nCommand terminated\n"));
4562 vim_free(argv);
4564 error:
4565 if (!did_settmode)
4566 if (tmode == TMODE_RAW)
4567 settmode(TMODE_RAW); /* set to raw mode */
4568 # ifdef FEAT_TITLE
4569 resettitle();
4570 # endif
4571 vim_free(newcmd);
4573 return retval;
4575 #endif /* USE_SYSTEM */
4579 * Check for CTRL-C typed by reading all available characters.
4580 * In cooked mode we should get SIGINT, no need to check.
4582 void
4583 mch_breakcheck()
4585 if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL))
4586 fill_input_buf(FALSE);
4590 * Wait "msec" msec until a character is available from the keyboard or from
4591 * inbuf[]. msec == -1 will block forever.
4592 * When a GUI is being used, this will never get called -- webb
4594 static int
4595 WaitForChar(msec)
4596 long msec;
4598 #ifdef FEAT_MOUSE_GPM
4599 int gpm_process_wanted;
4600 #endif
4601 #ifdef FEAT_XCLIPBOARD
4602 int rest;
4603 #endif
4604 int avail;
4606 if (input_available()) /* something in inbuf[] */
4607 return 1;
4609 #if defined(FEAT_MOUSE_DEC)
4610 /* May need to query the mouse position. */
4611 if (WantQueryMouse)
4613 WantQueryMouse = FALSE;
4614 mch_write((char_u *)IF_EB("\033[1'|", ESC_STR "[1'|"), 5);
4616 #endif
4619 * For FEAT_MOUSE_GPM and FEAT_XCLIPBOARD we loop here to process mouse
4620 * events. This is a bit complicated, because they might both be defined.
4622 #if defined(FEAT_MOUSE_GPM) || defined(FEAT_XCLIPBOARD)
4623 # ifdef FEAT_XCLIPBOARD
4624 rest = 0;
4625 if (do_xterm_trace())
4626 rest = msec;
4627 # endif
4630 # ifdef FEAT_XCLIPBOARD
4631 if (rest != 0)
4633 msec = XT_TRACE_DELAY;
4634 if (rest >= 0 && rest < XT_TRACE_DELAY)
4635 msec = rest;
4636 if (rest >= 0)
4637 rest -= msec;
4639 # endif
4640 # ifdef FEAT_MOUSE_GPM
4641 gpm_process_wanted = 0;
4642 avail = RealWaitForChar(read_cmd_fd, msec, &gpm_process_wanted);
4643 # else
4644 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4645 # endif
4646 if (!avail)
4648 if (input_available())
4649 return 1;
4650 # ifdef FEAT_XCLIPBOARD
4651 if (rest == 0 || !do_xterm_trace())
4652 # endif
4653 break;
4656 while (FALSE
4657 # ifdef FEAT_MOUSE_GPM
4658 || (gpm_process_wanted && mch_gpm_process() == 0)
4659 # endif
4660 # ifdef FEAT_XCLIPBOARD
4661 || (!avail && rest != 0)
4662 # endif
4665 #else
4666 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4667 #endif
4668 return avail;
4672 * Wait "msec" msec until a character is available from file descriptor "fd".
4673 * Time == -1 will block forever.
4674 * When a GUI is being used, this will not be used for input -- webb
4675 * Returns also, when a request from Sniff is waiting -- toni.
4676 * Or when a Linux GPM mouse event is waiting.
4678 /* ARGSUSED */
4679 #if defined(__BEOS__)
4681 #else
4682 static int
4683 #endif
4684 RealWaitForChar(fd, msec, check_for_gpm)
4685 int fd;
4686 long msec;
4687 int *check_for_gpm;
4689 int ret;
4690 #if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4691 static int busy = FALSE;
4693 /* May retry getting characters after an event was handled. */
4694 # define MAY_LOOP
4696 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4697 /* Remember at what time we started, so that we know how much longer we
4698 * should wait after being interrupted. */
4699 # define USE_START_TV
4700 struct timeval start_tv;
4702 if (msec > 0 && (
4703 # ifdef FEAT_XCLIPBOARD
4704 xterm_Shell != (Widget)0
4705 # if defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4707 # endif
4708 # endif
4709 # ifdef USE_XSMP
4710 xsmp_icefd != -1
4711 # ifdef FEAT_MZSCHEME
4713 # endif
4714 # endif
4715 # ifdef FEAT_MZSCHEME
4716 (mzthreads_allowed() && p_mzq > 0)
4717 # endif
4719 gettimeofday(&start_tv, NULL);
4720 # endif
4722 /* Handle being called recursively. This may happen for the session
4723 * manager stuff, it may save the file, which does a breakcheck. */
4724 if (busy)
4725 return 0;
4726 #endif
4728 #ifdef MAY_LOOP
4729 for (;;)
4730 #endif
4732 #ifdef MAY_LOOP
4733 int finished = TRUE; /* default is to 'loop' just once */
4734 # ifdef FEAT_MZSCHEME
4735 int mzquantum_used = FALSE;
4736 # endif
4737 #endif
4738 #ifndef HAVE_SELECT
4739 struct pollfd fds[5];
4740 int nfd;
4741 # ifdef FEAT_XCLIPBOARD
4742 int xterm_idx = -1;
4743 # endif
4744 # ifdef FEAT_MOUSE_GPM
4745 int gpm_idx = -1;
4746 # endif
4747 # ifdef USE_XSMP
4748 int xsmp_idx = -1;
4749 # endif
4750 int towait = (int)msec;
4752 # ifdef FEAT_MZSCHEME
4753 mzvim_check_threads();
4754 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4756 towait = (int)p_mzq; /* don't wait longer than 'mzquantum' */
4757 mzquantum_used = TRUE;
4759 # endif
4760 fds[0].fd = fd;
4761 fds[0].events = POLLIN;
4762 nfd = 1;
4764 # ifdef FEAT_SNIFF
4765 # define SNIFF_IDX 1
4766 if (want_sniff_request)
4768 fds[SNIFF_IDX].fd = fd_from_sniff;
4769 fds[SNIFF_IDX].events = POLLIN;
4770 nfd++;
4772 # endif
4773 # ifdef FEAT_XCLIPBOARD
4774 if (xterm_Shell != (Widget)0)
4776 xterm_idx = nfd;
4777 fds[nfd].fd = ConnectionNumber(xterm_dpy);
4778 fds[nfd].events = POLLIN;
4779 nfd++;
4781 # endif
4782 # ifdef FEAT_MOUSE_GPM
4783 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4785 gpm_idx = nfd;
4786 fds[nfd].fd = gpm_fd;
4787 fds[nfd].events = POLLIN;
4788 nfd++;
4790 # endif
4791 # ifdef USE_XSMP
4792 if (xsmp_icefd != -1)
4794 xsmp_idx = nfd;
4795 fds[nfd].fd = xsmp_icefd;
4796 fds[nfd].events = POLLIN;
4797 nfd++;
4799 # endif
4801 ret = poll(fds, nfd, towait);
4802 # ifdef FEAT_MZSCHEME
4803 if (ret == 0 && mzquantum_used)
4804 /* MzThreads scheduling is required and timeout occurred */
4805 finished = FALSE;
4806 # endif
4808 # ifdef FEAT_SNIFF
4809 if (ret < 0)
4810 sniff_disconnect(1);
4811 else if (want_sniff_request)
4813 if (fds[SNIFF_IDX].revents & POLLHUP)
4814 sniff_disconnect(1);
4815 if (fds[SNIFF_IDX].revents & POLLIN)
4816 sniff_request_waiting = 1;
4818 # endif
4819 # ifdef FEAT_XCLIPBOARD
4820 if (xterm_Shell != (Widget)0 && (fds[xterm_idx].revents & POLLIN))
4822 xterm_update(); /* Maybe we should hand out clipboard */
4823 if (--ret == 0 && !input_available())
4824 /* Try again */
4825 finished = FALSE;
4827 # endif
4828 # ifdef FEAT_MOUSE_GPM
4829 if (gpm_idx >= 0 && (fds[gpm_idx].revents & POLLIN))
4831 *check_for_gpm = 1;
4833 # endif
4834 # ifdef USE_XSMP
4835 if (xsmp_idx >= 0 && (fds[xsmp_idx].revents & (POLLIN | POLLHUP)))
4837 if (fds[xsmp_idx].revents & POLLIN)
4839 busy = TRUE;
4840 xsmp_handle_requests();
4841 busy = FALSE;
4843 else if (fds[xsmp_idx].revents & POLLHUP)
4845 if (p_verbose > 0)
4846 verb_msg((char_u *)_("XSMP lost ICE connection"));
4847 xsmp_close();
4849 if (--ret == 0)
4850 finished = FALSE; /* Try again */
4852 # endif
4855 #else /* HAVE_SELECT */
4857 struct timeval tv;
4858 struct timeval *tvp;
4859 fd_set rfds, efds;
4860 int maxfd;
4861 long towait = msec;
4863 # ifdef FEAT_MZSCHEME
4864 mzvim_check_threads();
4865 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4867 towait = p_mzq; /* don't wait longer than 'mzquantum' */
4868 mzquantum_used = TRUE;
4870 # endif
4871 # ifdef __EMX__
4872 /* don't check for incoming chars if not in raw mode, because select()
4873 * always returns TRUE then (in some version of emx.dll) */
4874 if (curr_tmode != TMODE_RAW)
4875 return 0;
4876 # endif
4878 if (towait >= 0)
4880 tv.tv_sec = towait / 1000;
4881 tv.tv_usec = (towait % 1000) * (1000000/1000);
4882 tvp = &tv;
4884 else
4885 tvp = NULL;
4888 * Select on ready for reading and exceptional condition (end of file).
4890 FD_ZERO(&rfds); /* calls bzero() on a sun */
4891 FD_ZERO(&efds);
4892 FD_SET(fd, &rfds);
4893 # if !defined(__QNX__) && !defined(__CYGWIN32__)
4894 /* For QNX select() always returns 1 if this is set. Why? */
4895 FD_SET(fd, &efds);
4896 # endif
4897 maxfd = fd;
4899 # ifdef FEAT_SNIFF
4900 if (want_sniff_request)
4902 FD_SET(fd_from_sniff, &rfds);
4903 FD_SET(fd_from_sniff, &efds);
4904 if (maxfd < fd_from_sniff)
4905 maxfd = fd_from_sniff;
4907 # endif
4908 # ifdef FEAT_XCLIPBOARD
4909 if (xterm_Shell != (Widget)0)
4911 FD_SET(ConnectionNumber(xterm_dpy), &rfds);
4912 if (maxfd < ConnectionNumber(xterm_dpy))
4913 maxfd = ConnectionNumber(xterm_dpy);
4915 # endif
4916 # ifdef FEAT_MOUSE_GPM
4917 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4919 FD_SET(gpm_fd, &rfds);
4920 FD_SET(gpm_fd, &efds);
4921 if (maxfd < gpm_fd)
4922 maxfd = gpm_fd;
4924 # endif
4925 # ifdef USE_XSMP
4926 if (xsmp_icefd != -1)
4928 FD_SET(xsmp_icefd, &rfds);
4929 FD_SET(xsmp_icefd, &efds);
4930 if (maxfd < xsmp_icefd)
4931 maxfd = xsmp_icefd;
4933 # endif
4935 # ifdef OLD_VMS
4936 /* Old VMS as v6.2 and older have broken select(). It waits more than
4937 * required. Should not be used */
4938 ret = 0;
4939 # else
4940 ret = select(maxfd + 1, &rfds, NULL, &efds, tvp);
4941 # endif
4942 # ifdef __TANDEM
4943 if (ret == -1 && errno == ENOTSUP)
4945 FD_ZERO(&rfds);
4946 FD_ZERO(&efds);
4947 ret = 0;
4949 #endif
4950 # ifdef FEAT_MZSCHEME
4951 if (ret == 0 && mzquantum_used)
4952 /* loop if MzThreads must be scheduled and timeout occurred */
4953 finished = FALSE;
4954 # endif
4956 # ifdef FEAT_SNIFF
4957 if (ret < 0 )
4958 sniff_disconnect(1);
4959 else if (ret > 0 && want_sniff_request)
4961 if (FD_ISSET(fd_from_sniff, &efds))
4962 sniff_disconnect(1);
4963 if (FD_ISSET(fd_from_sniff, &rfds))
4964 sniff_request_waiting = 1;
4966 # endif
4967 # ifdef FEAT_XCLIPBOARD
4968 if (ret > 0 && xterm_Shell != (Widget)0
4969 && FD_ISSET(ConnectionNumber(xterm_dpy), &rfds))
4971 xterm_update(); /* Maybe we should hand out clipboard */
4972 /* continue looping when we only got the X event and the input
4973 * buffer is empty */
4974 if (--ret == 0 && !input_available())
4976 /* Try again */
4977 finished = FALSE;
4980 # endif
4981 # ifdef FEAT_MOUSE_GPM
4982 if (ret > 0 && gpm_flag && check_for_gpm != NULL && gpm_fd >= 0)
4984 if (FD_ISSET(gpm_fd, &efds))
4985 gpm_close();
4986 else if (FD_ISSET(gpm_fd, &rfds))
4987 *check_for_gpm = 1;
4989 # endif
4990 # ifdef USE_XSMP
4991 if (ret > 0 && xsmp_icefd != -1)
4993 if (FD_ISSET(xsmp_icefd, &efds))
4995 if (p_verbose > 0)
4996 verb_msg((char_u *)_("XSMP lost ICE connection"));
4997 xsmp_close();
4998 if (--ret == 0)
4999 finished = FALSE; /* keep going if event was only one */
5001 else if (FD_ISSET(xsmp_icefd, &rfds))
5003 busy = TRUE;
5004 xsmp_handle_requests();
5005 busy = FALSE;
5006 if (--ret == 0)
5007 finished = FALSE; /* keep going if event was only one */
5010 # endif
5012 #endif /* HAVE_SELECT */
5014 #ifdef MAY_LOOP
5015 if (finished || msec == 0)
5016 break;
5018 /* We're going to loop around again, find out for how long */
5019 if (msec > 0)
5021 # ifdef USE_START_TV
5022 struct timeval mtv;
5024 /* Compute remaining wait time. */
5025 gettimeofday(&mtv, NULL);
5026 msec -= (mtv.tv_sec - start_tv.tv_sec) * 1000L
5027 + (mtv.tv_usec - start_tv.tv_usec) / 1000L;
5028 # else
5029 /* Guess we got interrupted halfway. */
5030 msec = msec / 2;
5031 # endif
5032 if (msec <= 0)
5033 break; /* waited long enough */
5035 #endif
5038 return (ret > 0);
5041 #ifndef VMS
5043 #ifndef NO_EXPANDPATH
5045 * Expand a path into all matching files and/or directories. Handles "*",
5046 * "?", "[a-z]", "**", etc.
5047 * "path" has backslashes before chars that are not to be expanded.
5048 * Returns the number of matches found.
5051 mch_expandpath(gap, path, flags)
5052 garray_T *gap;
5053 char_u *path;
5054 int flags; /* EW_* flags */
5056 return unix_expandpath(gap, path, 0, flags, FALSE);
5058 #endif
5061 * mch_expand_wildcards() - this code does wild-card pattern matching using
5062 * the shell
5064 * return OK for success, FAIL for error (you may lose some memory) and put
5065 * an error message in *file.
5067 * num_pat is number of input patterns
5068 * pat is array of pointers to input patterns
5069 * num_file is pointer to number of matched file names
5070 * file is pointer to array of pointers to matched file names
5073 #ifndef SEEK_SET
5074 # define SEEK_SET 0
5075 #endif
5076 #ifndef SEEK_END
5077 # define SEEK_END 2
5078 #endif
5080 #define SHELL_SPECIAL (char_u *)"\t \"&'$;<>()\\|"
5082 /* ARGSUSED */
5084 mch_expand_wildcards(num_pat, pat, num_file, file, flags)
5085 int num_pat;
5086 char_u **pat;
5087 int *num_file;
5088 char_u ***file;
5089 int flags; /* EW_* flags */
5091 int i;
5092 size_t len;
5093 char_u *p;
5094 int dir;
5095 #ifdef __EMX__
5097 * This is the OS/2 implementation.
5099 # define EXPL_ALLOC_INC 16
5100 char_u **expl_files;
5101 size_t files_alloced, files_free;
5102 char_u *buf;
5103 int has_wildcard;
5105 *num_file = 0; /* default: no files found */
5106 files_alloced = EXPL_ALLOC_INC; /* how much space is allocated */
5107 files_free = EXPL_ALLOC_INC; /* how much space is not used */
5108 *file = (char_u **)alloc(sizeof(char_u **) * files_alloced);
5109 if (*file == NULL)
5110 return FAIL;
5112 for (; num_pat > 0; num_pat--, pat++)
5114 expl_files = NULL;
5115 if (vim_strchr(*pat, '$') || vim_strchr(*pat, '~'))
5116 /* expand environment var or home dir */
5117 buf = expand_env_save(*pat);
5118 else
5119 buf = vim_strsave(*pat);
5120 expl_files = NULL;
5121 has_wildcard = mch_has_exp_wildcard(buf); /* (still) wildcards? */
5122 if (has_wildcard) /* yes, so expand them */
5123 expl_files = (char_u **)_fnexplode(buf);
5126 * return value of buf if no wildcards left,
5127 * OR if no match AND EW_NOTFOUND is set.
5129 if ((!has_wildcard && ((flags & EW_NOTFOUND) || mch_getperm(buf) >= 0))
5130 || (expl_files == NULL && (flags & EW_NOTFOUND)))
5131 { /* simply save the current contents of *buf */
5132 expl_files = (char_u **)alloc(sizeof(char_u **) * 2);
5133 if (expl_files != NULL)
5135 expl_files[0] = vim_strsave(buf);
5136 expl_files[1] = NULL;
5139 vim_free(buf);
5142 * Count number of names resulting from expansion,
5143 * At the same time add a backslash to the end of names that happen to
5144 * be directories, and replace slashes with backslashes.
5146 if (expl_files)
5148 for (i = 0; (p = expl_files[i]) != NULL; i++)
5150 dir = mch_isdir(p);
5151 /* If we don't want dirs and this is one, skip it */
5152 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5153 continue;
5155 /* Skip files that are not executable if we check for that. */
5156 if (!dir && (flags & EW_EXEC) && !mch_can_exe(p))
5157 continue;
5159 if (--files_free == 0)
5161 /* need more room in table of pointers */
5162 files_alloced += EXPL_ALLOC_INC;
5163 *file = (char_u **)vim_realloc(*file,
5164 sizeof(char_u **) * files_alloced);
5165 if (*file == NULL)
5167 EMSG(_(e_outofmem));
5168 *num_file = 0;
5169 return FAIL;
5171 files_free = EXPL_ALLOC_INC;
5173 slash_adjust(p);
5174 if (dir)
5176 /* For a directory we add a '/', unless it's already
5177 * there. */
5178 len = STRLEN(p);
5179 if (((*file)[*num_file] = alloc(len + 2)) != NULL)
5181 STRCPY((*file)[*num_file], p);
5182 if (!after_pathsep((*file)[*num_file],
5183 (*file)[*num_file] + len))
5185 (*file)[*num_file][len] = psepc;
5186 (*file)[*num_file][len + 1] = NUL;
5190 else
5192 (*file)[*num_file] = vim_strsave(p);
5196 * Error message already given by either alloc or vim_strsave.
5197 * Should return FAIL, but returning OK works also.
5199 if ((*file)[*num_file] == NULL)
5200 break;
5201 (*num_file)++;
5203 _fnexplodefree((char **)expl_files);
5206 return OK;
5208 #else /* __EMX__ */
5210 * This is the non-OS/2 implementation (really Unix).
5212 int j;
5213 char_u *tempname;
5214 char_u *command;
5215 FILE *fd;
5216 char_u *buffer;
5217 #define STYLE_ECHO 0 /* use "echo", the default */
5218 #define STYLE_GLOB 1 /* use "glob", for csh */
5219 #define STYLE_VIMGLOB 2 /* use "vimglob", for Posix sh */
5220 #define STYLE_PRINT 3 /* use "print -N", for zsh */
5221 #define STYLE_BT 4 /* `cmd` expansion, execute the pattern
5222 * directly */
5223 int shell_style = STYLE_ECHO;
5224 int check_spaces;
5225 static int did_find_nul = FALSE;
5226 int ampersent = FALSE;
5227 /* vimglob() function to define for Posix shell */
5228 static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo \"$1\"; shift; done }; vimglob >";
5230 *num_file = 0; /* default: no files found */
5231 *file = NULL;
5234 * If there are no wildcards, just copy the names to allocated memory.
5235 * Saves a lot of time, because we don't have to start a new shell.
5237 if (!have_wildcard(num_pat, pat))
5238 return save_patterns(num_pat, pat, num_file, file);
5240 # ifdef HAVE_SANDBOX
5241 /* Don't allow any shell command in the sandbox. */
5242 if (sandbox != 0 && check_secure())
5243 return FAIL;
5244 # endif
5247 * Don't allow the use of backticks in secure and restricted mode.
5249 if (secure || restricted)
5250 for (i = 0; i < num_pat; ++i)
5251 if (vim_strchr(pat[i], '`') != NULL
5252 && (check_restricted() || check_secure()))
5253 return FAIL;
5256 * get a name for the temp file
5258 if ((tempname = vim_tempname('o')) == NULL)
5260 EMSG(_(e_notmp));
5261 return FAIL;
5265 * Let the shell expand the patterns and write the result into the temp
5266 * file.
5267 * STYLE_BT: NL separated
5268 * If expanding `cmd` execute it directly.
5269 * STYLE_GLOB: NUL separated
5270 * If we use *csh, "glob" will work better than "echo".
5271 * STYLE_PRINT: NL or NUL separated
5272 * If we use *zsh, "print -N" will work better than "glob".
5273 * STYLE_VIMGLOB: NL separated
5274 * If we use *sh*, we define "vimglob()".
5275 * STYLE_ECHO: space separated.
5276 * A shell we don't know, stay safe and use "echo".
5278 if (num_pat == 1 && *pat[0] == '`'
5279 && (len = STRLEN(pat[0])) > 2
5280 && *(pat[0] + len - 1) == '`')
5281 shell_style = STYLE_BT;
5282 else if ((len = STRLEN(p_sh)) >= 3)
5284 if (STRCMP(p_sh + len - 3, "csh") == 0)
5285 shell_style = STYLE_GLOB;
5286 else if (STRCMP(p_sh + len - 3, "zsh") == 0)
5287 shell_style = STYLE_PRINT;
5289 if (shell_style == STYLE_ECHO && strstr((char *)gettail(p_sh),
5290 "sh") != NULL)
5291 shell_style = STYLE_VIMGLOB;
5293 /* Compute the length of the command. We need 2 extra bytes: for the
5294 * optional '&' and for the NUL.
5295 * Worst case: "unset nonomatch; print -N >" plus two is 29 */
5296 len = STRLEN(tempname) + 29;
5297 if (shell_style == STYLE_VIMGLOB)
5298 len += STRLEN(sh_vimglob_func);
5300 for (i = 0; i < num_pat; ++i)
5302 /* Count the length of the patterns in the same way as they are put in
5303 * "command" below. */
5304 #ifdef USE_SYSTEM
5305 len += STRLEN(pat[i]) + 3; /* add space and two quotes */
5306 #else
5307 ++len; /* add space */
5308 for (j = 0; pat[i][j] != NUL; ++j)
5310 if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL)
5311 ++len; /* may add a backslash */
5312 ++len;
5314 #endif
5316 command = alloc(len);
5317 if (command == NULL)
5319 /* out of memory */
5320 vim_free(tempname);
5321 return FAIL;
5325 * Build the shell command:
5326 * - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell
5327 * recognizes this).
5328 * - Add the shell command to print the expanded names.
5329 * - Add the temp file name.
5330 * - Add the file name patterns.
5332 if (shell_style == STYLE_BT)
5334 /* change `command; command& ` to (command; command ) */
5335 STRCPY(command, "(");
5336 STRCAT(command, pat[0] + 1); /* exclude first backtick */
5337 p = command + STRLEN(command) - 1;
5338 *p-- = ')'; /* remove last backtick */
5339 while (p > command && vim_iswhite(*p))
5340 --p;
5341 if (*p == '&') /* remove trailing '&' */
5343 ampersent = TRUE;
5344 *p = ' ';
5346 STRCAT(command, ">");
5348 else
5350 if (flags & EW_NOTFOUND)
5351 STRCPY(command, "set nonomatch; ");
5352 else
5353 STRCPY(command, "unset nonomatch; ");
5354 if (shell_style == STYLE_GLOB)
5355 STRCAT(command, "glob >");
5356 else if (shell_style == STYLE_PRINT)
5357 STRCAT(command, "print -N >");
5358 else if (shell_style == STYLE_VIMGLOB)
5359 STRCAT(command, sh_vimglob_func);
5360 else
5361 STRCAT(command, "echo >");
5364 STRCAT(command, tempname);
5366 if (shell_style != STYLE_BT)
5367 for (i = 0; i < num_pat; ++i)
5369 /* When using system() always add extra quotes, because the shell
5370 * is started twice. Otherwise put a backslash before special
5371 * characters, except inside ``. */
5372 #ifdef USE_SYSTEM
5373 STRCAT(command, " \"");
5374 STRCAT(command, pat[i]);
5375 STRCAT(command, "\"");
5376 #else
5377 int intick = FALSE;
5379 p = command + STRLEN(command);
5380 *p++ = ' ';
5381 for (j = 0; pat[i][j] != NUL; ++j)
5383 if (pat[i][j] == '`')
5384 intick = !intick;
5385 else if (pat[i][j] == '\\' && pat[i][j + 1] != NUL)
5387 /* Remove a backslash, take char literally. But keep
5388 * backslash inside backticks, before a special character
5389 * and before a backtick. */
5390 if (intick
5391 || vim_strchr(SHELL_SPECIAL, pat[i][j + 1]) != NULL
5392 || pat[i][j + 1] == '`')
5393 *p++ = '\\';
5394 ++j;
5396 else if (!intick && vim_strchr(SHELL_SPECIAL,
5397 pat[i][j]) != NULL)
5398 /* Put a backslash before a special character, but not
5399 * when inside ``. */
5400 *p++ = '\\';
5402 /* Copy one character. */
5403 *p++ = pat[i][j];
5405 *p = NUL;
5406 #endif
5408 if (flags & EW_SILENT)
5409 show_shell_mess = FALSE;
5410 if (ampersent)
5411 STRCAT(command, "&"); /* put the '&' after the redirection */
5414 * Using zsh -G: If a pattern has no matches, it is just deleted from
5415 * the argument list, otherwise zsh gives an error message and doesn't
5416 * expand any other pattern.
5418 if (shell_style == STYLE_PRINT)
5419 extra_shell_arg = (char_u *)"-G"; /* Use zsh NULL_GLOB option */
5422 * If we use -f then shell variables set in .cshrc won't get expanded.
5423 * vi can do it, so we will too, but it is only necessary if there is a "$"
5424 * in one of the patterns, otherwise we can still use the fast option.
5426 else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat))
5427 extra_shell_arg = (char_u *)"-f"; /* Use csh fast option */
5430 * execute the shell command
5432 i = call_shell(command, SHELL_EXPAND | SHELL_SILENT);
5434 /* When running in the background, give it some time to create the temp
5435 * file, but don't wait for it to finish. */
5436 if (ampersent)
5437 mch_delay(10L, TRUE);
5439 extra_shell_arg = NULL; /* cleanup */
5440 show_shell_mess = TRUE;
5441 vim_free(command);
5443 if (i != 0) /* mch_call_shell() failed */
5445 mch_remove(tempname);
5446 vim_free(tempname);
5448 * With interactive completion, the error message is not printed.
5449 * However with USE_SYSTEM, I don't know how to turn off error messages
5450 * from the shell, so screen may still get messed up -- webb.
5452 #ifndef USE_SYSTEM
5453 if (!(flags & EW_SILENT))
5454 #endif
5456 redraw_later_clear(); /* probably messed up screen */
5457 msg_putchar('\n'); /* clear bottom line quickly */
5458 cmdline_row = Rows - 1; /* continue on last line */
5459 #ifdef USE_SYSTEM
5460 if (!(flags & EW_SILENT))
5461 #endif
5463 MSG(_(e_wildexpand));
5464 msg_start(); /* don't overwrite this message */
5467 /* If a `cmd` expansion failed, don't list `cmd` as a match, even when
5468 * EW_NOTFOUND is given */
5469 if (shell_style == STYLE_BT)
5470 return FAIL;
5471 goto notfound;
5475 * read the names from the file into memory
5477 fd = fopen((char *)tempname, READBIN);
5478 if (fd == NULL)
5480 /* Something went wrong, perhaps a file name with a special char. */
5481 if (!(flags & EW_SILENT))
5483 MSG(_(e_wildexpand));
5484 msg_start(); /* don't overwrite this message */
5486 vim_free(tempname);
5487 goto notfound;
5489 fseek(fd, 0L, SEEK_END);
5490 len = ftell(fd); /* get size of temp file */
5491 fseek(fd, 0L, SEEK_SET);
5492 buffer = alloc(len + 1);
5493 if (buffer == NULL)
5495 /* out of memory */
5496 mch_remove(tempname);
5497 vim_free(tempname);
5498 fclose(fd);
5499 return FAIL;
5501 i = fread((char *)buffer, 1, len, fd);
5502 fclose(fd);
5503 mch_remove(tempname);
5504 if (i != len)
5506 /* unexpected read error */
5507 EMSG2(_(e_notread), tempname);
5508 vim_free(tempname);
5509 vim_free(buffer);
5510 return FAIL;
5512 vim_free(tempname);
5514 # if defined(__CYGWIN__) || defined(__CYGWIN32__)
5515 /* Translate <CR><NL> into <NL>. Caution, buffer may contain NUL. */
5516 p = buffer;
5517 for (i = 0; i < len; ++i)
5518 if (!(buffer[i] == CAR && buffer[i + 1] == NL))
5519 *p++ = buffer[i];
5520 len = p - buffer;
5521 # endif
5524 /* file names are separated with Space */
5525 if (shell_style == STYLE_ECHO)
5527 buffer[len] = '\n'; /* make sure the buffer ends in NL */
5528 p = buffer;
5529 for (i = 0; *p != '\n'; ++i) /* count number of entries */
5531 while (*p != ' ' && *p != '\n')
5532 ++p;
5533 p = skipwhite(p); /* skip to next entry */
5536 /* file names are separated with NL */
5537 else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB)
5539 buffer[len] = NUL; /* make sure the buffer ends in NUL */
5540 p = buffer;
5541 for (i = 0; *p != NUL; ++i) /* count number of entries */
5543 while (*p != '\n' && *p != NUL)
5544 ++p;
5545 if (*p != NUL)
5546 ++p;
5547 p = skipwhite(p); /* skip leading white space */
5550 /* file names are separated with NUL */
5551 else
5554 * Some versions of zsh use spaces instead of NULs to separate
5555 * results. Only do this when there is no NUL before the end of the
5556 * buffer, otherwise we would never be able to use file names with
5557 * embedded spaces when zsh does use NULs.
5558 * When we found a NUL once, we know zsh is OK, set did_find_nul and
5559 * don't check for spaces again.
5561 check_spaces = FALSE;
5562 if (shell_style == STYLE_PRINT && !did_find_nul)
5564 /* If there is a NUL, set did_find_nul, else set check_spaces */
5565 if (len && (int)STRLEN(buffer) < len - 1)
5566 did_find_nul = TRUE;
5567 else
5568 check_spaces = TRUE;
5572 * Make sure the buffer ends with a NUL. For STYLE_PRINT there
5573 * already is one, for STYLE_GLOB it needs to be added.
5575 if (len && buffer[len - 1] == NUL)
5576 --len;
5577 else
5578 buffer[len] = NUL;
5579 i = 0;
5580 for (p = buffer; p < buffer + len; ++p)
5581 if (*p == NUL || (*p == ' ' && check_spaces)) /* count entry */
5583 ++i;
5584 *p = NUL;
5586 if (len)
5587 ++i; /* count last entry */
5589 if (i == 0)
5592 * Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I".
5593 * /bin/sh will happily expand it to nothing rather than returning an
5594 * error; and hey, it's good to check anyway -- webb.
5596 vim_free(buffer);
5597 goto notfound;
5599 *num_file = i;
5600 *file = (char_u **)alloc(sizeof(char_u *) * i);
5601 if (*file == NULL)
5603 /* out of memory */
5604 vim_free(buffer);
5605 return FAIL;
5609 * Isolate the individual file names.
5611 p = buffer;
5612 for (i = 0; i < *num_file; ++i)
5614 (*file)[i] = p;
5615 /* Space or NL separates */
5616 if (shell_style == STYLE_ECHO || shell_style == STYLE_BT
5617 || shell_style == STYLE_VIMGLOB)
5619 while (!(shell_style == STYLE_ECHO && *p == ' ')
5620 && *p != '\n' && *p != NUL)
5621 ++p;
5622 if (p == buffer + len) /* last entry */
5623 *p = NUL;
5624 else
5626 *p++ = NUL;
5627 p = skipwhite(p); /* skip to next entry */
5630 else /* NUL separates */
5632 while (*p && p < buffer + len) /* skip entry */
5633 ++p;
5634 ++p; /* skip NUL */
5639 * Move the file names to allocated memory.
5641 for (j = 0, i = 0; i < *num_file; ++i)
5643 /* Require the files to exist. Helps when using /bin/sh */
5644 if (!(flags & EW_NOTFOUND) && mch_getperm((*file)[i]) < 0)
5645 continue;
5647 /* check if this entry should be included */
5648 dir = (mch_isdir((*file)[i]));
5649 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5650 continue;
5652 /* Skip files that are not executable if we check for that. */
5653 if (!dir && (flags & EW_EXEC) && !mch_can_exe((*file)[i]))
5654 continue;
5656 p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir));
5657 if (p)
5659 STRCPY(p, (*file)[i]);
5660 if (dir)
5661 add_pathsep(p); /* add '/' to a directory name */
5662 (*file)[j++] = p;
5665 vim_free(buffer);
5666 *num_file = j;
5668 if (*num_file == 0) /* rejected all entries */
5670 vim_free(*file);
5671 *file = NULL;
5672 goto notfound;
5675 return OK;
5677 notfound:
5678 if (flags & EW_NOTFOUND)
5679 return save_patterns(num_pat, pat, num_file, file);
5680 return FAIL;
5682 #endif /* __EMX__ */
5685 #endif /* VMS */
5687 #ifndef __EMX__
5688 static int
5689 save_patterns(num_pat, pat, num_file, file)
5690 int num_pat;
5691 char_u **pat;
5692 int *num_file;
5693 char_u ***file;
5695 int i;
5696 char_u *s;
5698 *file = (char_u **)alloc(num_pat * sizeof(char_u *));
5699 if (*file == NULL)
5700 return FAIL;
5701 for (i = 0; i < num_pat; i++)
5703 s = vim_strsave(pat[i]);
5704 if (s != NULL)
5705 /* Be compatible with expand_filename(): halve the number of
5706 * backslashes. */
5707 backslash_halve(s);
5708 (*file)[i] = s;
5710 *num_file = num_pat;
5711 return OK;
5713 #endif
5717 * Return TRUE if the string "p" contains a wildcard that mch_expandpath() can
5718 * expand.
5721 mch_has_exp_wildcard(p)
5722 char_u *p;
5724 for ( ; *p; mb_ptr_adv(p))
5726 #ifndef OS2
5727 if (*p == '\\' && p[1] != NUL)
5728 ++p;
5729 else
5730 #endif
5731 if (vim_strchr((char_u *)
5732 #ifdef VMS
5733 "*?%"
5734 #else
5735 # ifdef OS2
5736 "*?"
5737 # else
5738 "*?[{'"
5739 # endif
5740 #endif
5741 , *p) != NULL)
5742 return TRUE;
5744 return FALSE;
5748 * Return TRUE if the string "p" contains a wildcard.
5749 * Don't recognize '~' at the end as a wildcard.
5752 mch_has_wildcard(p)
5753 char_u *p;
5755 for ( ; *p; mb_ptr_adv(p))
5757 #ifndef OS2
5758 if (*p == '\\' && p[1] != NUL)
5759 ++p;
5760 else
5761 #endif
5762 if (vim_strchr((char_u *)
5763 #ifdef VMS
5764 "*?%$"
5765 #else
5766 # ifdef OS2
5767 # ifdef VIM_BACKTICK
5768 "*?$`"
5769 # else
5770 "*?$"
5771 # endif
5772 # else
5773 "*?[{`'$"
5774 # endif
5775 #endif
5776 , *p) != NULL
5777 || (*p == '~' && p[1] != NUL))
5778 return TRUE;
5780 return FALSE;
5783 #ifndef __EMX__
5784 static int
5785 have_wildcard(num, file)
5786 int num;
5787 char_u **file;
5789 int i;
5791 for (i = 0; i < num; i++)
5792 if (mch_has_wildcard(file[i]))
5793 return 1;
5794 return 0;
5797 static int
5798 have_dollars(num, file)
5799 int num;
5800 char_u **file;
5802 int i;
5804 for (i = 0; i < num; i++)
5805 if (vim_strchr(file[i], '$') != NULL)
5806 return TRUE;
5807 return FALSE;
5809 #endif /* ifndef __EMX__ */
5811 #ifndef HAVE_RENAME
5813 * Scaled-down version of rename(), which is missing in Xenix.
5814 * This version can only move regular files and will fail if the
5815 * destination exists.
5818 mch_rename(src, dest)
5819 const char *src, *dest;
5821 struct stat st;
5823 if (stat(dest, &st) >= 0) /* fail if destination exists */
5824 return -1;
5825 if (link(src, dest) != 0) /* link file to new name */
5826 return -1;
5827 if (mch_remove(src) == 0) /* delete link to old name */
5828 return 0;
5829 return -1;
5831 #endif /* !HAVE_RENAME */
5833 #ifdef FEAT_MOUSE_GPM
5835 * Initializes connection with gpm (if it isn't already opened)
5836 * Return 1 if succeeded (or connection already opened), 0 if failed
5838 static int
5839 gpm_open()
5841 static Gpm_Connect gpm_connect; /* Must it be kept till closing ? */
5843 if (!gpm_flag)
5845 gpm_connect.eventMask = (GPM_UP | GPM_DRAG | GPM_DOWN);
5846 gpm_connect.defaultMask = ~GPM_HARD;
5847 /* Default handling for mouse move*/
5848 gpm_connect.minMod = 0; /* Handle any modifier keys */
5849 gpm_connect.maxMod = 0xffff;
5850 if (Gpm_Open(&gpm_connect, 0) > 0)
5852 /* gpm library tries to handling TSTP causes
5853 * problems. Anyways, we close connection to Gpm whenever
5854 * we are going to suspend or starting an external process
5855 * so we shouldn't have problem with this
5857 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
5858 return 1; /* succeed */
5860 if (gpm_fd == -2)
5861 Gpm_Close(); /* We don't want to talk to xterm via gpm */
5862 return 0;
5864 return 1; /* already open */
5868 * Closes connection to gpm
5870 static void
5871 gpm_close()
5873 if (gpm_flag && gpm_fd >= 0) /* if Open */
5874 Gpm_Close();
5877 /* Reads gpm event and adds special keys to input buf. Returns length of
5878 * generated key sequence.
5879 * This function is made after gui_send_mouse_event
5881 static int
5882 mch_gpm_process()
5884 int button;
5885 static Gpm_Event gpm_event;
5886 char_u string[6];
5887 int_u vim_modifiers;
5888 int row,col;
5889 unsigned char buttons_mask;
5890 unsigned char gpm_modifiers;
5891 static unsigned char old_buttons = 0;
5893 Gpm_GetEvent(&gpm_event);
5895 #ifdef FEAT_GUI
5896 /* Don't put events in the input queue now. */
5897 if (hold_gui_events)
5898 return 0;
5899 #endif
5901 row = gpm_event.y - 1;
5902 col = gpm_event.x - 1;
5904 string[0] = ESC; /* Our termcode */
5905 string[1] = 'M';
5906 string[2] = 'G';
5907 switch (GPM_BARE_EVENTS(gpm_event.type))
5909 case GPM_DRAG:
5910 string[3] = MOUSE_DRAG;
5911 break;
5912 case GPM_DOWN:
5913 buttons_mask = gpm_event.buttons & ~old_buttons;
5914 old_buttons = gpm_event.buttons;
5915 switch (buttons_mask)
5917 case GPM_B_LEFT:
5918 button = MOUSE_LEFT;
5919 break;
5920 case GPM_B_MIDDLE:
5921 button = MOUSE_MIDDLE;
5922 break;
5923 case GPM_B_RIGHT:
5924 button = MOUSE_RIGHT;
5925 break;
5926 default:
5927 return 0;
5928 /*Don't know what to do. Can more than one button be
5929 * reported in one event? */
5931 string[3] = (char_u)(button | 0x20);
5932 SET_NUM_MOUSE_CLICKS(string[3], gpm_event.clicks + 1);
5933 break;
5934 case GPM_UP:
5935 string[3] = MOUSE_RELEASE;
5936 old_buttons &= ~gpm_event.buttons;
5937 break;
5938 default:
5939 return 0;
5941 /*This code is based on gui_x11_mouse_cb in gui_x11.c */
5942 gpm_modifiers = gpm_event.modifiers;
5943 vim_modifiers = 0x0;
5944 /* I ignore capslock stats. Aren't we all just hate capslock mixing with
5945 * Vim commands ? Besides, gpm_event.modifiers is unsigned char, and
5946 * K_CAPSSHIFT is defined 8, so it probably isn't even reported
5948 if (gpm_modifiers & ((1 << KG_SHIFT) | (1 << KG_SHIFTR) | (1 << KG_SHIFTL)))
5949 vim_modifiers |= MOUSE_SHIFT;
5951 if (gpm_modifiers & ((1 << KG_CTRL) | (1 << KG_CTRLR) | (1 << KG_CTRLL)))
5952 vim_modifiers |= MOUSE_CTRL;
5953 if (gpm_modifiers & ((1 << KG_ALT) | (1 << KG_ALTGR)))
5954 vim_modifiers |= MOUSE_ALT;
5955 string[3] |= vim_modifiers;
5956 string[4] = (char_u)(col + ' ' + 1);
5957 string[5] = (char_u)(row + ' ' + 1);
5958 add_to_input_buf(string, 6);
5959 return 6;
5961 #endif /* FEAT_MOUSE_GPM */
5963 #ifdef FEAT_SYSMOUSE
5965 * Initialize connection with sysmouse.
5966 * Let virtual console inform us with SIGUSR2 for pending sysmouse
5967 * output, any sysmouse output than will be processed via sig_sysmouse().
5968 * Return OK if succeeded, FAIL if failed.
5970 static int
5971 sysmouse_open()
5973 struct mouse_info mouse;
5975 mouse.operation = MOUSE_MODE;
5976 mouse.u.mode.mode = 0;
5977 mouse.u.mode.signal = SIGUSR2;
5978 if (ioctl(1, CONS_MOUSECTL, &mouse) != -1)
5980 signal(SIGUSR2, (RETSIGTYPE (*)())sig_sysmouse);
5981 mouse.operation = MOUSE_SHOW;
5982 ioctl(1, CONS_MOUSECTL, &mouse);
5983 return OK;
5985 return FAIL;
5989 * Stop processing SIGUSR2 signals, and also make sure that
5990 * virtual console do not send us any sysmouse related signal.
5992 static void
5993 sysmouse_close()
5995 struct mouse_info mouse;
5997 signal(SIGUSR2, restricted ? SIG_IGN : SIG_DFL);
5998 mouse.operation = MOUSE_MODE;
5999 mouse.u.mode.mode = 0;
6000 mouse.u.mode.signal = 0;
6001 ioctl(1, CONS_MOUSECTL, &mouse);
6005 * Gets info from sysmouse and adds special keys to input buf.
6007 /* ARGSUSED */
6008 static RETSIGTYPE
6009 sig_sysmouse SIGDEFARG(sigarg)
6011 struct mouse_info mouse;
6012 struct video_info video;
6013 char_u string[6];
6014 int row, col;
6015 int button;
6016 int buttons;
6017 static int oldbuttons = 0;
6019 #ifdef FEAT_GUI
6020 /* Don't put events in the input queue now. */
6021 if (hold_gui_events)
6022 return;
6023 #endif
6025 mouse.operation = MOUSE_GETINFO;
6026 if (ioctl(1, FBIO_GETMODE, &video.vi_mode) != -1
6027 && ioctl(1, FBIO_MODEINFO, &video) != -1
6028 && ioctl(1, CONS_MOUSECTL, &mouse) != -1
6029 && video.vi_cheight > 0 && video.vi_cwidth > 0)
6031 row = mouse.u.data.y / video.vi_cheight;
6032 col = mouse.u.data.x / video.vi_cwidth;
6033 buttons = mouse.u.data.buttons;
6034 string[0] = ESC; /* Our termcode */
6035 string[1] = 'M';
6036 string[2] = 'S';
6037 if (oldbuttons == buttons && buttons != 0)
6039 button = MOUSE_DRAG;
6041 else
6043 switch (buttons)
6045 case 0:
6046 button = MOUSE_RELEASE;
6047 break;
6048 case 1:
6049 button = MOUSE_LEFT;
6050 break;
6051 case 2:
6052 button = MOUSE_MIDDLE;
6053 break;
6054 case 4:
6055 button = MOUSE_RIGHT;
6056 break;
6057 default:
6058 return;
6060 oldbuttons = buttons;
6062 string[3] = (char_u)(button);
6063 string[4] = (char_u)(col + ' ' + 1);
6064 string[5] = (char_u)(row + ' ' + 1);
6065 add_to_input_buf(string, 6);
6067 return;
6069 #endif /* FEAT_SYSMOUSE */
6071 #if defined(FEAT_LIBCALL) || defined(PROTO)
6072 typedef char_u * (*STRPROCSTR)__ARGS((char_u *));
6073 typedef char_u * (*INTPROCSTR)__ARGS((int));
6074 typedef int (*STRPROCINT)__ARGS((char_u *));
6075 typedef int (*INTPROCINT)__ARGS((int));
6078 * Call a DLL routine which takes either a string or int param
6079 * and returns an allocated string.
6082 mch_libcall(libname, funcname, argstring, argint, string_result, number_result)
6083 char_u *libname;
6084 char_u *funcname;
6085 char_u *argstring; /* NULL when using a argint */
6086 int argint;
6087 char_u **string_result;/* NULL when using number_result */
6088 int *number_result;
6090 # if defined(USE_DLOPEN)
6091 void *hinstLib;
6092 char *dlerr = NULL;
6093 # else
6094 shl_t hinstLib;
6095 # endif
6096 STRPROCSTR ProcAdd;
6097 INTPROCSTR ProcAddI;
6098 char_u *retval_str = NULL;
6099 int retval_int = 0;
6100 int success = FALSE;
6103 * Get a handle to the DLL module.
6105 # if defined(USE_DLOPEN)
6106 /* First clear any error, it's not cleared by the dlopen() call. */
6107 (void)dlerror();
6109 hinstLib = dlopen((char *)libname, RTLD_LAZY
6110 # ifdef RTLD_LOCAL
6111 | RTLD_LOCAL
6112 # endif
6114 if (hinstLib == NULL)
6116 /* "dlerr" must be used before dlclose() */
6117 dlerr = (char *)dlerror();
6118 if (dlerr != NULL)
6119 EMSG2(_("dlerror = \"%s\""), dlerr);
6121 # else
6122 hinstLib = shl_load((const char*)libname, BIND_IMMEDIATE|BIND_VERBOSE, 0L);
6123 # endif
6125 /* If the handle is valid, try to get the function address. */
6126 if (hinstLib != NULL)
6128 # ifdef HAVE_SETJMP_H
6130 * Catch a crash when calling the library function. For example when
6131 * using a number where a string pointer is expected.
6133 mch_startjmp();
6134 if (SETJMP(lc_jump_env) != 0)
6136 success = FALSE;
6137 # if defined(USE_DLOPEN)
6138 dlerr = NULL;
6139 # endif
6140 mch_didjmp();
6142 else
6143 # endif
6145 retval_str = NULL;
6146 retval_int = 0;
6148 if (argstring != NULL)
6150 # if defined(USE_DLOPEN)
6151 ProcAdd = (STRPROCSTR)dlsym(hinstLib, (const char *)funcname);
6152 dlerr = (char *)dlerror();
6153 # else
6154 if (shl_findsym(&hinstLib, (const char *)funcname,
6155 TYPE_PROCEDURE, (void *)&ProcAdd) < 0)
6156 ProcAdd = NULL;
6157 # endif
6158 if ((success = (ProcAdd != NULL
6159 # if defined(USE_DLOPEN)
6160 && dlerr == NULL
6161 # endif
6164 if (string_result == NULL)
6165 retval_int = ((STRPROCINT)ProcAdd)(argstring);
6166 else
6167 retval_str = (ProcAdd)(argstring);
6170 else
6172 # if defined(USE_DLOPEN)
6173 ProcAddI = (INTPROCSTR)dlsym(hinstLib, (const char *)funcname);
6174 dlerr = (char *)dlerror();
6175 # else
6176 if (shl_findsym(&hinstLib, (const char *)funcname,
6177 TYPE_PROCEDURE, (void *)&ProcAddI) < 0)
6178 ProcAddI = NULL;
6179 # endif
6180 if ((success = (ProcAddI != NULL
6181 # if defined(USE_DLOPEN)
6182 && dlerr == NULL
6183 # endif
6186 if (string_result == NULL)
6187 retval_int = ((INTPROCINT)ProcAddI)(argint);
6188 else
6189 retval_str = (ProcAddI)(argint);
6193 /* Save the string before we free the library. */
6194 /* Assume that a "1" or "-1" result is an illegal pointer. */
6195 if (string_result == NULL)
6196 *number_result = retval_int;
6197 else if (retval_str != NULL
6198 && retval_str != (char_u *)1
6199 && retval_str != (char_u *)-1)
6200 *string_result = vim_strsave(retval_str);
6203 # ifdef HAVE_SETJMP_H
6204 mch_endjmp();
6205 # ifdef SIGHASARG
6206 if (lc_signal != 0)
6208 int i;
6210 /* try to find the name of this signal */
6211 for (i = 0; signal_info[i].sig != -1; i++)
6212 if (lc_signal == signal_info[i].sig)
6213 break;
6214 EMSG2("E368: got SIG%s in libcall()", signal_info[i].name);
6216 # endif
6217 # endif
6219 # if defined(USE_DLOPEN)
6220 /* "dlerr" must be used before dlclose() */
6221 if (dlerr != NULL)
6222 EMSG2(_("dlerror = \"%s\""), dlerr);
6224 /* Free the DLL module. */
6225 (void)dlclose(hinstLib);
6226 # else
6227 (void)shl_unload(hinstLib);
6228 # endif
6231 if (!success)
6233 EMSG2(_(e_libcall), funcname);
6234 return FAIL;
6237 return OK;
6239 #endif
6241 #if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
6242 static int xterm_trace = -1; /* default: disabled */
6243 static int xterm_button;
6246 * Setup a dummy window for X selections in a terminal.
6248 void
6249 setup_term_clip()
6251 int z = 0;
6252 char *strp = "";
6253 Widget AppShell;
6255 if (!x_connect_to_server())
6256 return;
6258 open_app_context();
6259 if (app_context != NULL && xterm_Shell == (Widget)0)
6261 int (*oldhandler)();
6262 #if defined(HAVE_SETJMP_H)
6263 int (*oldIOhandler)();
6264 #endif
6265 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
6266 struct timeval start_tv;
6268 if (p_verbose > 0)
6269 gettimeofday(&start_tv, NULL);
6270 # endif
6272 /* Ignore X errors while opening the display */
6273 oldhandler = XSetErrorHandler(x_error_check);
6275 #if defined(HAVE_SETJMP_H)
6276 /* Ignore X IO errors while opening the display */
6277 oldIOhandler = XSetIOErrorHandler(x_IOerror_check);
6278 mch_startjmp();
6279 if (SETJMP(lc_jump_env) != 0)
6281 mch_didjmp();
6282 xterm_dpy = NULL;
6284 else
6285 #endif
6287 xterm_dpy = XtOpenDisplay(app_context, xterm_display,
6288 "vim_xterm", "Vim_xterm", NULL, 0, &z, &strp);
6289 #if defined(HAVE_SETJMP_H)
6290 mch_endjmp();
6291 #endif
6294 #if defined(HAVE_SETJMP_H)
6295 /* Now handle X IO errors normally. */
6296 (void)XSetIOErrorHandler(oldIOhandler);
6297 #endif
6298 /* Now handle X errors normally. */
6299 (void)XSetErrorHandler(oldhandler);
6301 if (xterm_dpy == NULL)
6303 if (p_verbose > 0)
6304 verb_msg((char_u *)_("Opening the X display failed"));
6305 return;
6308 /* Catch terminating error of the X server connection. */
6309 (void)XSetIOErrorHandler(x_IOerror_handler);
6311 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
6312 if (p_verbose > 0)
6314 verbose_enter();
6315 xopen_message(&start_tv);
6316 verbose_leave();
6318 # endif
6320 /* Create a Shell to make converters work. */
6321 AppShell = XtVaAppCreateShell("vim_xterm", "Vim_xterm",
6322 applicationShellWidgetClass, xterm_dpy,
6323 NULL);
6324 if (AppShell == (Widget)0)
6325 return;
6326 xterm_Shell = XtVaCreatePopupShell("VIM",
6327 topLevelShellWidgetClass, AppShell,
6328 XtNmappedWhenManaged, 0,
6329 XtNwidth, 1,
6330 XtNheight, 1,
6331 NULL);
6332 if (xterm_Shell == (Widget)0)
6333 return;
6335 x11_setup_atoms(xterm_dpy);
6336 if (x11_display == NULL)
6337 x11_display = xterm_dpy;
6339 XtRealizeWidget(xterm_Shell);
6340 XSync(xterm_dpy, False);
6341 xterm_update();
6343 if (xterm_Shell != (Widget)0)
6345 clip_init(TRUE);
6346 if (x11_window == 0 && (strp = getenv("WINDOWID")) != NULL)
6347 x11_window = (Window)atol(strp);
6348 /* Check if $WINDOWID is valid. */
6349 if (test_x11_window(xterm_dpy) == FAIL)
6350 x11_window = 0;
6351 if (x11_window != 0)
6352 xterm_trace = 0;
6356 void
6357 start_xterm_trace(button)
6358 int button;
6360 if (x11_window == 0 || xterm_trace < 0 || xterm_Shell == (Widget)0)
6361 return;
6362 xterm_trace = 1;
6363 xterm_button = button;
6364 do_xterm_trace();
6368 void
6369 stop_xterm_trace()
6371 if (xterm_trace < 0)
6372 return;
6373 xterm_trace = 0;
6377 * Query the xterm pointer and generate mouse termcodes if necessary
6378 * return TRUE if dragging is active, else FALSE
6380 static int
6381 do_xterm_trace()
6383 Window root, child;
6384 int root_x, root_y;
6385 int win_x, win_y;
6386 int row, col;
6387 int_u mask_return;
6388 char_u buf[50];
6389 char_u *strp;
6390 long got_hints;
6391 static char_u *mouse_code;
6392 static char_u mouse_name[2] = {KS_MOUSE, KE_FILLER};
6393 static int prev_row = 0, prev_col = 0;
6394 static XSizeHints xterm_hints;
6396 if (xterm_trace <= 0)
6397 return FALSE;
6399 if (xterm_trace == 1)
6401 /* Get the hints just before tracking starts. The font size might
6402 * have changed recently. */
6403 if (!XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints)
6404 || !(got_hints & PResizeInc)
6405 || xterm_hints.width_inc <= 1
6406 || xterm_hints.height_inc <= 1)
6408 xterm_trace = -1; /* Not enough data -- disable tracing */
6409 return FALSE;
6412 /* Rely on the same mouse code for the duration of this */
6413 mouse_code = find_termcode(mouse_name);
6414 prev_row = mouse_row;
6415 prev_row = mouse_col;
6416 xterm_trace = 2;
6418 /* Find the offset of the chars, there might be a scrollbar on the
6419 * left of the window and/or a menu on the top (eterm etc.) */
6420 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
6421 &win_x, &win_y, &mask_return);
6422 xterm_hints.y = win_y - (xterm_hints.height_inc * mouse_row)
6423 - (xterm_hints.height_inc / 2);
6424 if (xterm_hints.y <= xterm_hints.height_inc / 2)
6425 xterm_hints.y = 2;
6426 xterm_hints.x = win_x - (xterm_hints.width_inc * mouse_col)
6427 - (xterm_hints.width_inc / 2);
6428 if (xterm_hints.x <= xterm_hints.width_inc / 2)
6429 xterm_hints.x = 2;
6430 return TRUE;
6432 if (mouse_code == NULL)
6434 xterm_trace = 0;
6435 return FALSE;
6438 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
6439 &win_x, &win_y, &mask_return);
6441 row = check_row((win_y - xterm_hints.y) / xterm_hints.height_inc);
6442 col = check_col((win_x - xterm_hints.x) / xterm_hints.width_inc);
6443 if (row == prev_row && col == prev_col)
6444 return TRUE;
6446 STRCPY(buf, mouse_code);
6447 strp = buf + STRLEN(buf);
6448 *strp++ = (xterm_button | MOUSE_DRAG) & ~0x20;
6449 *strp++ = (char_u)(col + ' ' + 1);
6450 *strp++ = (char_u)(row + ' ' + 1);
6451 *strp = 0;
6452 add_to_input_buf(buf, STRLEN(buf));
6454 prev_row = row;
6455 prev_col = col;
6456 return TRUE;
6459 # if defined(FEAT_GUI) || defined(PROTO)
6461 * Destroy the display, window and app_context. Required for GTK.
6463 void
6464 clear_xterm_clip()
6466 if (xterm_Shell != (Widget)0)
6468 XtDestroyWidget(xterm_Shell);
6469 xterm_Shell = (Widget)0;
6471 if (xterm_dpy != NULL)
6473 # if 0
6474 /* Lesstif and Solaris crash here, lose some memory */
6475 XtCloseDisplay(xterm_dpy);
6476 # endif
6477 if (x11_display == xterm_dpy)
6478 x11_display = NULL;
6479 xterm_dpy = NULL;
6481 # if 0
6482 if (app_context != (XtAppContext)NULL)
6484 /* Lesstif and Solaris crash here, lose some memory */
6485 XtDestroyApplicationContext(app_context);
6486 app_context = (XtAppContext)NULL;
6488 # endif
6490 # endif
6493 * Catch up with any queued X events. This may put keyboard input into the
6494 * input buffer, call resize call-backs, trigger timers etc. If there is
6495 * nothing in the X event queue (& no timers pending), then we return
6496 * immediately.
6498 static void
6499 xterm_update()
6501 XEvent event;
6503 while (XtAppPending(app_context) && !vim_is_input_buf_full())
6505 XtAppNextEvent(app_context, &event);
6506 #ifdef FEAT_CLIENTSERVER
6508 XPropertyEvent *e = (XPropertyEvent *)&event;
6510 if (e->type == PropertyNotify && e->window == commWindow
6511 && e->atom == commProperty && e->state == PropertyNewValue)
6512 serverEventProc(xterm_dpy, &event);
6514 #endif
6515 XtDispatchEvent(&event);
6520 clip_xterm_own_selection(cbd)
6521 VimClipboard *cbd;
6523 if (xterm_Shell != (Widget)0)
6524 return clip_x11_own_selection(xterm_Shell, cbd);
6525 return FAIL;
6528 void
6529 clip_xterm_lose_selection(cbd)
6530 VimClipboard *cbd;
6532 if (xterm_Shell != (Widget)0)
6533 clip_x11_lose_selection(xterm_Shell, cbd);
6536 void
6537 clip_xterm_request_selection(cbd)
6538 VimClipboard *cbd;
6540 if (xterm_Shell != (Widget)0)
6541 clip_x11_request_selection(xterm_Shell, xterm_dpy, cbd);
6544 void
6545 clip_xterm_set_selection(cbd)
6546 VimClipboard *cbd;
6548 clip_x11_set_selection(cbd);
6550 #endif
6553 #if defined(USE_XSMP) || defined(PROTO)
6555 * Code for X Session Management Protocol.
6557 static void xsmp_handle_save_yourself __ARGS((SmcConn smc_conn, SmPointer client_data, int save_type, Bool shutdown, int interact_style, Bool fast));
6558 static void xsmp_die __ARGS((SmcConn smc_conn, SmPointer client_data));
6559 static void xsmp_save_complete __ARGS((SmcConn smc_conn, SmPointer client_data));
6560 static void xsmp_shutdown_cancelled __ARGS((SmcConn smc_conn, SmPointer client_data));
6561 static void xsmp_ice_connection __ARGS((IceConn iceConn, IcePointer clientData, Bool opening, IcePointer *watchData));
6564 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6565 static void xsmp_handle_interaction __ARGS((SmcConn smc_conn, SmPointer client_data));
6568 * This is our chance to ask the user if they want to save,
6569 * or abort the logout
6571 /*ARGSUSED*/
6572 static void
6573 xsmp_handle_interaction(smc_conn, client_data)
6574 SmcConn smc_conn;
6575 SmPointer client_data;
6577 cmdmod_T save_cmdmod;
6578 int cancel_shutdown = False;
6580 save_cmdmod = cmdmod;
6581 cmdmod.confirm = TRUE;
6582 if (check_changed_any(FALSE))
6583 /* Mustn't logout */
6584 cancel_shutdown = True;
6585 cmdmod = save_cmdmod;
6586 setcursor(); /* position cursor */
6587 out_flush();
6589 /* Done interaction */
6590 SmcInteractDone(smc_conn, cancel_shutdown);
6592 /* Finish off
6593 * Only end save-yourself here if we're not cancelling shutdown;
6594 * we'll get a cancelled callback later in which we'll end it.
6595 * Hopefully get around glitchy SMs (like GNOME-1)
6597 if (!cancel_shutdown)
6599 xsmp.save_yourself = False;
6600 SmcSaveYourselfDone(smc_conn, True);
6603 # endif
6606 * Callback that starts save-yourself.
6608 /*ARGSUSED*/
6609 static void
6610 xsmp_handle_save_yourself(smc_conn, client_data, save_type,
6611 shutdown, interact_style, fast)
6612 SmcConn smc_conn;
6613 SmPointer client_data;
6614 int save_type;
6615 Bool shutdown;
6616 int interact_style;
6617 Bool fast;
6619 /* Handle already being in saveyourself */
6620 if (xsmp.save_yourself)
6621 SmcSaveYourselfDone(smc_conn, True);
6622 xsmp.save_yourself = True;
6623 xsmp.shutdown = shutdown;
6625 /* First up, preserve all files */
6626 out_flush();
6627 ml_sync_all(FALSE, FALSE); /* preserve all swap files */
6629 if (p_verbose > 0)
6630 verb_msg((char_u *)_("XSMP handling save-yourself request"));
6632 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6633 /* Now see if we can ask about unsaved files */
6634 if (shutdown && !fast && gui.in_use)
6635 /* Need to interact with user, but need SM's permission */
6636 SmcInteractRequest(smc_conn, SmDialogError,
6637 xsmp_handle_interaction, client_data);
6638 else
6639 # endif
6641 /* Can stop the cycle here */
6642 SmcSaveYourselfDone(smc_conn, True);
6643 xsmp.save_yourself = False;
6649 * Callback to warn us of imminent death.
6651 /*ARGSUSED*/
6652 static void
6653 xsmp_die(smc_conn, client_data)
6654 SmcConn smc_conn;
6655 SmPointer client_data;
6657 xsmp_close();
6659 /* quit quickly leaving swapfiles for modified buffers behind */
6660 getout_preserve_modified(0);
6665 * Callback to tell us that save-yourself has completed.
6667 /*ARGSUSED*/
6668 static void
6669 xsmp_save_complete(smc_conn, client_data)
6670 SmcConn smc_conn;
6671 SmPointer client_data;
6673 xsmp.save_yourself = False;
6678 * Callback to tell us that an instigated shutdown was cancelled
6679 * (maybe even by us)
6681 /*ARGSUSED*/
6682 static void
6683 xsmp_shutdown_cancelled(smc_conn, client_data)
6684 SmcConn smc_conn;
6685 SmPointer client_data;
6687 if (xsmp.save_yourself)
6688 SmcSaveYourselfDone(smc_conn, True);
6689 xsmp.save_yourself = False;
6690 xsmp.shutdown = False;
6695 * Callback to tell us that a new ICE connection has been established.
6697 /*ARGSUSED*/
6698 static void
6699 xsmp_ice_connection(iceConn, clientData, opening, watchData)
6700 IceConn iceConn;
6701 IcePointer clientData;
6702 Bool opening;
6703 IcePointer *watchData;
6705 /* Intercept creation of ICE connection fd */
6706 if (opening)
6708 xsmp_icefd = IceConnectionNumber(iceConn);
6709 IceRemoveConnectionWatch(xsmp_ice_connection, NULL);
6714 /* Handle any ICE processing that's required; return FAIL if SM lost */
6716 xsmp_handle_requests()
6718 Bool rep;
6720 if (IceProcessMessages(xsmp.iceconn, NULL, &rep)
6721 == IceProcessMessagesIOError)
6723 /* Lost ICE */
6724 if (p_verbose > 0)
6725 verb_msg((char_u *)_("XSMP lost ICE connection"));
6726 xsmp_close();
6727 return FAIL;
6729 else
6730 return OK;
6733 static int dummy;
6735 /* Set up X Session Management Protocol */
6736 void
6737 xsmp_init(void)
6739 char errorstring[80];
6740 SmcCallbacks smcallbacks;
6741 #if 0
6742 SmPropValue smname;
6743 SmProp smnameprop;
6744 SmProp *smprops[1];
6745 #endif
6747 if (p_verbose > 0)
6748 verb_msg((char_u *)_("XSMP opening connection"));
6750 xsmp.save_yourself = xsmp.shutdown = False;
6752 /* Set up SM callbacks - must have all, even if they're not used */
6753 smcallbacks.save_yourself.callback = xsmp_handle_save_yourself;
6754 smcallbacks.save_yourself.client_data = NULL;
6755 smcallbacks.die.callback = xsmp_die;
6756 smcallbacks.die.client_data = NULL;
6757 smcallbacks.save_complete.callback = xsmp_save_complete;
6758 smcallbacks.save_complete.client_data = NULL;
6759 smcallbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
6760 smcallbacks.shutdown_cancelled.client_data = NULL;
6762 /* Set up a watch on ICE connection creations. The "dummy" argument is
6763 * apparently required for FreeBSD (we get a BUS error when using NULL). */
6764 if (IceAddConnectionWatch(xsmp_ice_connection, &dummy) == 0)
6766 if (p_verbose > 0)
6767 verb_msg((char_u *)_("XSMP ICE connection watch failed"));
6768 return;
6771 /* Create an SM connection */
6772 xsmp.smcconn = SmcOpenConnection(
6773 NULL,
6774 NULL,
6775 SmProtoMajor,
6776 SmProtoMinor,
6777 SmcSaveYourselfProcMask | SmcDieProcMask
6778 | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
6779 &smcallbacks,
6780 NULL,
6781 &xsmp.clientid,
6782 sizeof(errorstring),
6783 errorstring);
6784 if (xsmp.smcconn == NULL)
6786 char errorreport[132];
6788 if (p_verbose > 0)
6790 vim_snprintf(errorreport, sizeof(errorreport),
6791 _("XSMP SmcOpenConnection failed: %s"), errorstring);
6792 verb_msg((char_u *)errorreport);
6794 return;
6796 xsmp.iceconn = SmcGetIceConnection(xsmp.smcconn);
6798 #if 0
6799 /* ID ourselves */
6800 smname.value = "vim";
6801 smname.length = 3;
6802 smnameprop.name = "SmProgram";
6803 smnameprop.type = "SmARRAY8";
6804 smnameprop.num_vals = 1;
6805 smnameprop.vals = &smname;
6807 smprops[0] = &smnameprop;
6808 SmcSetProperties(xsmp.smcconn, 1, smprops);
6809 #endif
6813 /* Shut down XSMP comms. */
6814 void
6815 xsmp_close()
6817 if (xsmp_icefd != -1)
6819 SmcCloseConnection(xsmp.smcconn, 0, NULL);
6820 if (xsmp.clientid != NULL)
6821 free(xsmp.clientid);
6822 xsmp.clientid = NULL;
6823 xsmp_icefd = -1;
6826 #endif /* USE_XSMP */
6829 #ifdef EBCDIC
6830 /* Translate character to its CTRL- value */
6831 char CtrlTable[] =
6833 /* 00 - 5E */
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, 0,
6838 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6839 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6840 /* ^ */ 0x1E,
6841 /* - */ 0x1F,
6842 /* 61 - 6C */
6843 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6844 /* _ */ 0x1F,
6845 /* 6E - 80 */
6846 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6847 /* a */ 0x01,
6848 /* b */ 0x02,
6849 /* c */ 0x03,
6850 /* d */ 0x37,
6851 /* e */ 0x2D,
6852 /* f */ 0x2E,
6853 /* g */ 0x2F,
6854 /* h */ 0x16,
6855 /* i */ 0x05,
6856 /* 8A - 90 */
6857 0, 0, 0, 0, 0, 0, 0,
6858 /* j */ 0x15,
6859 /* k */ 0x0B,
6860 /* l */ 0x0C,
6861 /* m */ 0x0D,
6862 /* n */ 0x0E,
6863 /* o */ 0x0F,
6864 /* p */ 0x10,
6865 /* q */ 0x11,
6866 /* r */ 0x12,
6867 /* 9A - A1 */
6868 0, 0, 0, 0, 0, 0, 0, 0,
6869 /* s */ 0x13,
6870 /* t */ 0x3C,
6871 /* u */ 0x3D,
6872 /* v */ 0x32,
6873 /* w */ 0x26,
6874 /* x */ 0x18,
6875 /* y */ 0x19,
6876 /* z */ 0x3F,
6877 /* AA - AC */
6878 0, 0, 0,
6879 /* [ */ 0x27,
6880 /* AE - BC */
6881 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6882 /* ] */ 0x1D,
6883 /* BE - C0 */ 0, 0, 0,
6884 /* A */ 0x01,
6885 /* B */ 0x02,
6886 /* C */ 0x03,
6887 /* D */ 0x37,
6888 /* E */ 0x2D,
6889 /* F */ 0x2E,
6890 /* G */ 0x2F,
6891 /* H */ 0x16,
6892 /* I */ 0x05,
6893 /* CA - D0 */ 0, 0, 0, 0, 0, 0, 0,
6894 /* J */ 0x15,
6895 /* K */ 0x0B,
6896 /* L */ 0x0C,
6897 /* M */ 0x0D,
6898 /* N */ 0x0E,
6899 /* O */ 0x0F,
6900 /* P */ 0x10,
6901 /* Q */ 0x11,
6902 /* R */ 0x12,
6903 /* DA - DF */ 0, 0, 0, 0, 0, 0,
6904 /* \ */ 0x1C,
6905 /* E1 */ 0,
6906 /* S */ 0x13,
6907 /* T */ 0x3C,
6908 /* U */ 0x3D,
6909 /* V */ 0x32,
6910 /* W */ 0x26,
6911 /* X */ 0x18,
6912 /* Y */ 0x19,
6913 /* Z */ 0x3F,
6914 /* EA - FF*/ 0, 0, 0, 0, 0, 0,
6915 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6918 char MetaCharTable[]=
6919 {/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6920 0, 0, 0, 0,'\\', 0,'F', 0,'W','M','N', 0, 0, 0, 0, 0,
6921 0, 0, 0, 0,']', 0, 0,'G', 0, 0,'R','O', 0, 0, 0, 0,
6922 '@','A','B','C','D','E', 0, 0,'H','I','J','K','L', 0, 0, 0,
6923 'P','Q', 0,'S','T','U','V', 0,'X','Y','Z','[', 0, 0,'^', 0
6927 /* TODO: Use characters NOT numbers!!! */
6928 char CtrlCharTable[]=
6929 {/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6930 124,193,194,195, 0,201, 0, 0, 0, 0, 0,210,211,212,213,214,
6931 215,216,217,226, 0,209,200, 0,231,232, 0, 0,224,189, 95,109,
6932 0, 0, 0, 0, 0, 0,230,173, 0, 0, 0, 0, 0,197,198,199,
6933 0, 0,229, 0, 0, 0, 0,196, 0, 0, 0, 0,227,228, 0,233,
6937 #endif