Merge upstream Edit in TextMate changes, remove a utf8 char
[MacVim.git] / src / os_unix.c
blob9a21782ebdd160ebb34892bbba2216d2fa61e166
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 #ifdef HAVE_FCNTL_H
39 # include <fcntl.h>
40 #endif
42 #include "os_unixx.h" /* unix includes for os_unix.c only */
44 #ifdef USE_XSMP
45 # include <X11/SM/SMlib.h>
46 #endif
49 * Use this prototype for select, some include files have a wrong prototype
51 #ifndef __TANDEM
52 # undef select
53 # ifdef __BEOS__
54 # define select beos_select
55 # endif
56 #endif
58 #ifdef __CYGWIN__
59 # ifndef WIN32
60 # include <sys/cygwin.h> /* for cygwin_conv_to_posix_path() */
61 # endif
62 #endif
64 #if defined(HAVE_SELECT)
65 extern int select __ARGS((int, fd_set *, fd_set *, fd_set *, struct timeval *));
66 #endif
68 #ifdef FEAT_MOUSE_GPM
69 # include <gpm.h>
70 /* <linux/keyboard.h> contains defines conflicting with "keymap.h",
71 * I just copied relevant defines here. A cleaner solution would be to put gpm
72 * code into separate file and include there linux/keyboard.h
74 /* #include <linux/keyboard.h> */
75 # define KG_SHIFT 0
76 # define KG_CTRL 2
77 # define KG_ALT 3
78 # define KG_ALTGR 1
79 # define KG_SHIFTL 4
80 # define KG_SHIFTR 5
81 # define KG_CTRLL 6
82 # define KG_CTRLR 7
83 # define KG_CAPSSHIFT 8
85 static void gpm_close __ARGS((void));
86 static int gpm_open __ARGS((void));
87 static int mch_gpm_process __ARGS((void));
88 #endif
91 * end of autoconf section. To be extended...
94 /* Are the following #ifdefs still required? And why? Is that for X11? */
96 #if defined(ESIX) || defined(M_UNIX) && !defined(SCO)
97 # ifdef SIGWINCH
98 # undef SIGWINCH
99 # endif
100 # ifdef TIOCGWINSZ
101 # undef TIOCGWINSZ
102 # endif
103 #endif
105 #if defined(SIGWINDOW) && !defined(SIGWINCH) /* hpux 9.01 has it */
106 # define SIGWINCH SIGWINDOW
107 #endif
109 #ifdef FEAT_X11
110 # include <X11/Xlib.h>
111 # include <X11/Xutil.h>
112 # include <X11/Xatom.h>
113 # ifdef FEAT_XCLIPBOARD
114 # include <X11/Intrinsic.h>
115 # include <X11/Shell.h>
116 # include <X11/StringDefs.h>
117 static Widget xterm_Shell = (Widget)0;
118 static void xterm_update __ARGS((void));
119 # endif
121 # if defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE)
122 Window x11_window = 0;
123 # endif
124 Display *x11_display = NULL;
126 # ifdef FEAT_TITLE
127 static int get_x11_windis __ARGS((void));
128 static void set_x11_title __ARGS((char_u *));
129 static void set_x11_icon __ARGS((char_u *));
130 # endif
131 #endif
133 #ifdef FEAT_TITLE
134 static int get_x11_title __ARGS((int));
135 static int get_x11_icon __ARGS((int));
137 static char_u *oldtitle = NULL;
138 static int did_set_title = FALSE;
139 static char_u *oldicon = NULL;
140 static int did_set_icon = FALSE;
141 #endif
143 static void may_core_dump __ARGS((void));
145 static int WaitForChar __ARGS((long));
146 #if defined(__BEOS__)
147 int RealWaitForChar __ARGS((int, long, int *));
148 #else
149 static int RealWaitForChar __ARGS((int, long, int *));
150 #endif
152 #ifdef FEAT_XCLIPBOARD
153 static int do_xterm_trace __ARGS((void));
154 # define XT_TRACE_DELAY 50 /* delay for xterm tracing */
155 #endif
157 static void handle_resize __ARGS((void));
159 #if defined(SIGWINCH)
160 static RETSIGTYPE sig_winch __ARGS(SIGPROTOARG);
161 #endif
162 #if defined(SIGINT)
163 static RETSIGTYPE catch_sigint __ARGS(SIGPROTOARG);
164 #endif
165 #if defined(SIGPWR)
166 static RETSIGTYPE catch_sigpwr __ARGS(SIGPROTOARG);
167 #endif
168 #if defined(SIGALRM) && defined(FEAT_X11) \
169 && defined(FEAT_TITLE) && !defined(FEAT_GUI_GTK)
170 # define SET_SIG_ALARM
171 static RETSIGTYPE sig_alarm __ARGS(SIGPROTOARG);
172 static int sig_alarm_called;
173 #endif
174 static RETSIGTYPE deathtrap __ARGS(SIGPROTOARG);
176 static void catch_int_signal __ARGS((void));
177 static void set_signals __ARGS((void));
178 static void catch_signals __ARGS((RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)()));
179 #ifndef __EMX__
180 static int have_wildcard __ARGS((int, char_u **));
181 static int have_dollars __ARGS((int, char_u **));
182 #endif
184 #ifndef __EMX__
185 static int save_patterns __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file));
186 #endif
188 #ifndef SIG_ERR
189 # define SIG_ERR ((RETSIGTYPE (*)())-1)
190 #endif
192 static int do_resize = FALSE;
193 #ifndef __EMX__
194 static char_u *extra_shell_arg = NULL;
195 static int show_shell_mess = TRUE;
196 #endif
197 static int deadly_signal = 0; /* The signal we caught */
198 static int in_mch_delay = FALSE; /* sleeping in mch_delay() */
200 static int curr_tmode = TMODE_COOK; /* contains current terminal mode */
202 #ifdef USE_XSMP
203 typedef struct
205 SmcConn smcconn; /* The SM connection ID */
206 IceConn iceconn; /* The ICE connection ID */
207 Bool save_yourself; /* If we're in the middle of a save_yourself */
208 Bool shutdown; /* If we're in shutdown mode */
209 } xsmp_config_T;
211 static xsmp_config_T xsmp;
212 #endif
214 #ifdef SYS_SIGLIST_DECLARED
216 * I have seen
217 * extern char *_sys_siglist[NSIG];
218 * on Irix, Linux, NetBSD and Solaris. It contains a nice list of strings
219 * that describe the signals. That is nearly what we want here. But
220 * autoconf does only check for sys_siglist (without the underscore), I
221 * do not want to change everything today.... jw.
222 * This is why AC_DECL_SYS_SIGLIST is commented out in configure.in
224 #endif
226 static struct signalinfo
228 int sig; /* Signal number, eg. SIGSEGV etc */
229 char *name; /* Signal name (not char_u!). */
230 char deadly; /* Catch as a deadly signal? */
231 } signal_info[] =
233 #ifdef SIGHUP
234 {SIGHUP, "HUP", TRUE},
235 #endif
236 #ifdef SIGQUIT
237 {SIGQUIT, "QUIT", TRUE},
238 #endif
239 #ifdef SIGILL
240 {SIGILL, "ILL", TRUE},
241 #endif
242 #ifdef SIGTRAP
243 {SIGTRAP, "TRAP", TRUE},
244 #endif
245 #ifdef SIGABRT
246 {SIGABRT, "ABRT", TRUE},
247 #endif
248 #ifdef SIGEMT
249 {SIGEMT, "EMT", TRUE},
250 #endif
251 #ifdef SIGFPE
252 {SIGFPE, "FPE", TRUE},
253 #endif
254 #ifdef SIGBUS
255 {SIGBUS, "BUS", TRUE},
256 #endif
257 #ifdef SIGSEGV
258 {SIGSEGV, "SEGV", TRUE},
259 #endif
260 #ifdef SIGSYS
261 {SIGSYS, "SYS", TRUE},
262 #endif
263 #ifdef SIGALRM
264 {SIGALRM, "ALRM", FALSE}, /* Perl's alarm() can trigger it */
265 #endif
266 #ifdef SIGTERM
267 {SIGTERM, "TERM", TRUE},
268 #endif
269 #ifdef SIGVTALRM
270 {SIGVTALRM, "VTALRM", TRUE},
271 #endif
272 #if defined(SIGPROF) && !defined(FEAT_MZSCHEME)
273 /* MzScheme uses SIGPROF for its own needs */
274 {SIGPROF, "PROF", TRUE},
275 #endif
276 #ifdef SIGXCPU
277 {SIGXCPU, "XCPU", TRUE},
278 #endif
279 #ifdef SIGXFSZ
280 {SIGXFSZ, "XFSZ", TRUE},
281 #endif
282 #ifdef SIGUSR1
283 {SIGUSR1, "USR1", TRUE},
284 #endif
285 #ifdef SIGUSR2
286 {SIGUSR2, "USR2", TRUE},
287 #endif
288 #ifdef SIGINT
289 {SIGINT, "INT", FALSE},
290 #endif
291 #ifdef SIGWINCH
292 {SIGWINCH, "WINCH", FALSE},
293 #endif
294 #ifdef SIGTSTP
295 {SIGTSTP, "TSTP", FALSE},
296 #endif
297 #ifdef SIGPIPE
298 {SIGPIPE, "PIPE", FALSE},
299 #endif
300 {-1, "Unknown!", FALSE}
303 void
304 mch_write(s, len)
305 char_u *s;
306 int len;
308 write(1, (char *)s, len);
309 if (p_wd) /* Unix is too fast, slow down a bit more */
310 RealWaitForChar(read_cmd_fd, p_wd, NULL);
314 * mch_inchar(): low level input function.
315 * Get a characters from the keyboard.
316 * Return the number of characters that are available.
317 * If wtime == 0 do not wait for characters.
318 * If wtime == n wait a short time for characters.
319 * If wtime == -1 wait forever for characters.
322 mch_inchar(buf, maxlen, wtime, tb_change_cnt)
323 char_u *buf;
324 int maxlen;
325 long wtime; /* don't use "time", MIPS cannot handle it */
326 int tb_change_cnt;
328 int len;
330 /* Check if window changed size while we were busy, perhaps the ":set
331 * columns=99" command was used. */
332 while (do_resize)
333 handle_resize();
335 if (wtime >= 0)
337 while (WaitForChar(wtime) == 0) /* no character available */
339 if (!do_resize) /* return if not interrupted by resize */
340 return 0;
341 handle_resize();
344 else /* wtime == -1 */
347 * If there is no character available within 'updatetime' seconds
348 * flush all the swap files to disk.
349 * Also done when interrupted by SIGWINCH.
351 if (WaitForChar(p_ut) == 0)
353 #ifdef FEAT_AUTOCMD
354 if (trigger_cursorhold() && maxlen >= 3
355 && !typebuf_changed(tb_change_cnt))
357 buf[0] = K_SPECIAL;
358 buf[1] = KS_EXTRA;
359 buf[2] = (int)KE_CURSORHOLD;
360 return 3;
362 #endif
363 before_blocking();
367 for (;;) /* repeat until we got a character */
369 while (do_resize) /* window changed size */
370 handle_resize();
372 * we want to be interrupted by the winch signal
374 WaitForChar(-1L);
375 if (do_resize) /* interrupted by SIGWINCH signal */
376 continue;
378 /* If input was put directly in typeahead buffer bail out here. */
379 if (typebuf_changed(tb_change_cnt))
380 return 0;
383 * For some terminals we only get one character at a time.
384 * We want the get all available characters, so we could keep on
385 * trying until none is available
386 * For some other terminals this is quite slow, that's why we don't do
387 * it.
389 len = read_from_input_buf(buf, (long)maxlen);
390 if (len > 0)
392 #ifdef OS2
393 int i;
395 for (i = 0; i < len; i++)
396 if (buf[i] == 0)
397 buf[i] = K_NUL;
398 #endif
399 return len;
404 static void
405 handle_resize()
407 do_resize = FALSE;
408 shell_resized();
412 * return non-zero if a character is available
415 mch_char_avail()
417 return WaitForChar(0L);
420 #if defined(HAVE_TOTAL_MEM) || defined(PROTO)
421 # ifdef HAVE_SYS_RESOURCE_H
422 # include <sys/resource.h>
423 # endif
424 # if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTL)
425 # include <sys/sysctl.h>
426 # endif
427 # if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
428 # include <sys/sysinfo.h>
429 # endif
432 * Return total amount of memory available in Kbyte.
433 * Doesn't change when memory has been allocated.
435 /* ARGSUSED */
436 long_u
437 mch_total_mem(special)
438 int special;
440 # ifdef __EMX__
441 return ulimit(3, 0L) >> 10; /* always 32MB? */
442 # else
443 long_u mem = 0;
444 long_u shiftright = 10; /* how much to shift "mem" right for Kbyte */
446 # ifdef HAVE_SYSCTL
447 int mib[2], physmem;
448 size_t len;
450 /* BSD way of getting the amount of RAM available. */
451 mib[0] = CTL_HW;
452 mib[1] = HW_USERMEM;
453 len = sizeof(physmem);
454 if (sysctl(mib, 2, &physmem, &len, NULL, 0) == 0)
455 mem = (long_u)physmem;
456 # endif
458 # if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
459 if (mem == 0)
461 struct sysinfo sinfo;
463 /* Linux way of getting amount of RAM available */
464 if (sysinfo(&sinfo) == 0)
466 # ifdef HAVE_SYSINFO_MEM_UNIT
467 /* avoid overflow as much as possible */
468 while (shiftright > 0 && (sinfo.mem_unit & 1) == 0)
470 sinfo.mem_unit = sinfo.mem_unit >> 1;
471 --shiftright;
473 mem = sinfo.totalram * sinfo.mem_unit;
474 # else
475 mem = sinfo.totalram;
476 # endif
479 # endif
481 # ifdef HAVE_SYSCONF
482 if (mem == 0)
484 long pagesize, pagecount;
486 /* Solaris way of getting amount of RAM available */
487 pagesize = sysconf(_SC_PAGESIZE);
488 pagecount = sysconf(_SC_PHYS_PAGES);
489 if (pagesize > 0 && pagecount > 0)
491 /* avoid overflow as much as possible */
492 while (shiftright > 0 && (pagesize & 1) == 0)
494 pagesize = (long_u)pagesize >> 1;
495 --shiftright;
497 mem = (long_u)pagesize * pagecount;
500 # endif
502 /* Return the minimum of the physical memory and the user limit, because
503 * using more than the user limit may cause Vim to be terminated. */
504 # if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT)
506 struct rlimit rlp;
508 if (getrlimit(RLIMIT_DATA, &rlp) == 0
509 && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
510 # ifdef RLIM_INFINITY
511 && rlp.rlim_cur != RLIM_INFINITY
512 # endif
513 && ((long_u)rlp.rlim_cur >> 10) < (mem >> shiftright)
516 mem = (long_u)rlp.rlim_cur;
517 shiftright = 10;
520 # endif
522 if (mem > 0)
523 return mem >> shiftright;
524 return (long_u)0x1fffff;
525 # endif
527 #endif
529 void
530 mch_delay(msec, ignoreinput)
531 long msec;
532 int ignoreinput;
534 int old_tmode;
535 #ifdef FEAT_MZSCHEME
536 long total = msec; /* remember original value */
537 #endif
539 if (ignoreinput)
541 /* Go to cooked mode without echo, to allow SIGINT interrupting us
542 * here. But we don't want QUIT to kill us (CTRL-\ used in a
543 * shell may produce SIGQUIT). */
544 in_mch_delay = TRUE;
545 old_tmode = curr_tmode;
546 if (curr_tmode == TMODE_RAW)
547 settmode(TMODE_SLEEP);
550 * Everybody sleeps in a different way...
551 * Prefer nanosleep(), some versions of usleep() can only sleep up to
552 * one second.
554 #ifdef FEAT_MZSCHEME
557 /* if total is large enough, wait by portions in p_mzq */
558 if (total > p_mzq)
559 msec = p_mzq;
560 else
561 msec = total;
562 total -= msec;
563 #endif
564 #ifdef HAVE_NANOSLEEP
566 struct timespec ts;
568 ts.tv_sec = msec / 1000;
569 ts.tv_nsec = (msec % 1000) * 1000000;
570 (void)nanosleep(&ts, NULL);
572 #else
573 # ifdef HAVE_USLEEP
574 while (msec >= 1000)
576 usleep((unsigned int)(999 * 1000));
577 msec -= 999;
579 usleep((unsigned int)(msec * 1000));
580 # else
581 # ifndef HAVE_SELECT
582 poll(NULL, 0, (int)msec);
583 # else
584 # ifdef __EMX__
585 _sleep2(msec);
586 # else
588 struct timeval tv;
590 tv.tv_sec = msec / 1000;
591 tv.tv_usec = (msec % 1000) * 1000;
593 * NOTE: Solaris 2.6 has a bug that makes select() hang here. Get
594 * a patch from Sun to fix this. Reported by Gunnar Pedersen.
596 select(0, NULL, NULL, NULL, &tv);
598 # endif /* __EMX__ */
599 # endif /* HAVE_SELECT */
600 # endif /* HAVE_NANOSLEEP */
601 #endif /* HAVE_USLEEP */
602 #ifdef FEAT_MZSCHEME
604 while (total > 0);
605 #endif
607 settmode(old_tmode);
608 in_mch_delay = FALSE;
610 else
611 WaitForChar(msec);
614 #if 0 /* disabled, no longer needed now that regmatch() is not recursive */
615 # if defined(HAVE_GETRLIMIT)
616 # define HAVE_STACK_LIMIT
617 # endif
618 #endif
620 #if defined(HAVE_STACK_LIMIT) \
621 || (!defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGSTACK))
622 # define HAVE_CHECK_STACK_GROWTH
624 * Support for checking for an almost-out-of-stack-space situation.
628 * Return a pointer to an item on the stack. Used to find out if the stack
629 * grows up or down.
631 static void check_stack_growth __ARGS((char *p));
632 static int stack_grows_downwards;
635 * Find out if the stack grows upwards or downwards.
636 * "p" points to a variable on the stack of the caller.
638 static void
639 check_stack_growth(p)
640 char *p;
642 int i;
644 stack_grows_downwards = (p > (char *)&i);
646 #endif
648 #if defined(HAVE_STACK_LIMIT) || defined(PROTO)
649 static char *stack_limit = NULL;
651 #if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
652 # include <pthread.h>
653 # include <pthread_np.h>
654 #endif
657 * Find out until how var the stack can grow without getting into trouble.
658 * Called when starting up and when switching to the signal stack in
659 * deathtrap().
661 static void
662 get_stack_limit()
664 struct rlimit rlp;
665 int i;
666 long lim;
668 /* Set the stack limit to 15/16 of the allowable size. Skip this when the
669 * limit doesn't fit in a long (rlim_cur might be "long long"). */
670 if (getrlimit(RLIMIT_STACK, &rlp) == 0
671 && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
672 # ifdef RLIM_INFINITY
673 && rlp.rlim_cur != RLIM_INFINITY
674 # endif
677 lim = (long)rlp.rlim_cur;
678 #if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
680 pthread_attr_t attr;
681 size_t size;
683 /* On FreeBSD the initial thread always has a fixed stack size, no
684 * matter what the limits are set to. Normally it's 1 Mbyte. */
685 pthread_attr_init(&attr);
686 if (pthread_attr_get_np(pthread_self(), &attr) == 0)
688 pthread_attr_getstacksize(&attr, &size);
689 if (lim > (long)size)
690 lim = (long)size;
692 pthread_attr_destroy(&attr);
694 #endif
695 if (stack_grows_downwards)
697 stack_limit = (char *)((long)&i - (lim / 16L * 15L));
698 if (stack_limit >= (char *)&i)
699 /* overflow, set to 1/16 of current stack position */
700 stack_limit = (char *)((long)&i / 16L);
702 else
704 stack_limit = (char *)((long)&i + (lim / 16L * 15L));
705 if (stack_limit <= (char *)&i)
706 stack_limit = NULL; /* overflow */
712 * Return FAIL when running out of stack space.
713 * "p" must point to any variable local to the caller that's on the stack.
716 mch_stackcheck(p)
717 char *p;
719 if (stack_limit != NULL)
721 if (stack_grows_downwards)
723 if (p < stack_limit)
724 return FAIL;
726 else if (p > stack_limit)
727 return FAIL;
729 return OK;
731 #endif
733 #if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
735 * Support for using the signal stack.
736 * This helps when we run out of stack space, which causes a SIGSEGV. The
737 * signal handler then must run on another stack, since the normal stack is
738 * completely full.
741 #ifndef SIGSTKSZ
742 # define SIGSTKSZ 8000 /* just a guess of how much stack is needed... */
743 #endif
745 # ifdef HAVE_SIGALTSTACK
746 static stack_t sigstk; /* for sigaltstack() */
747 # else
748 static struct sigstack sigstk; /* for sigstack() */
749 # endif
751 static void init_signal_stack __ARGS((void));
752 static char *signal_stack;
754 static void
755 init_signal_stack()
757 if (signal_stack != NULL)
759 # ifdef HAVE_SIGALTSTACK
760 # if defined(__APPLE__) && (!defined(MAC_OS_X_VERSION_MAX_ALLOWED) \
761 || MAC_OS_X_VERSION_MAX_ALLOWED <= 1040)
762 /* missing prototype. Adding it to osdef?.h.in doesn't work, because
763 * "struct sigaltstack" needs to be declared. */
764 extern int sigaltstack __ARGS((const struct sigaltstack *ss, struct sigaltstack *oss));
765 # endif
767 # ifdef HAVE_SS_BASE
768 sigstk.ss_base = signal_stack;
769 # else
770 sigstk.ss_sp = signal_stack;
771 # endif
772 sigstk.ss_size = SIGSTKSZ;
773 sigstk.ss_flags = 0;
774 (void)sigaltstack(&sigstk, NULL);
775 # else
776 sigstk.ss_sp = signal_stack;
777 if (stack_grows_downwards)
778 sigstk.ss_sp += SIGSTKSZ - 1;
779 sigstk.ss_onstack = 0;
780 (void)sigstack(&sigstk, NULL);
781 # endif
784 #endif
787 * We need correct potatotypes for a signal function, otherwise mean compilers
788 * will barf when the second argument to signal() is ``wrong''.
789 * Let me try it with a few tricky defines from my own osdef.h (jw).
791 #if defined(SIGWINCH)
792 /* ARGSUSED */
793 static RETSIGTYPE
794 sig_winch SIGDEFARG(sigarg)
796 /* this is not required on all systems, but it doesn't hurt anybody */
797 signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
798 do_resize = TRUE;
799 SIGRETURN;
801 #endif
803 #if defined(SIGINT)
804 /* ARGSUSED */
805 static RETSIGTYPE
806 catch_sigint SIGDEFARG(sigarg)
808 /* this is not required on all systems, but it doesn't hurt anybody */
809 signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
810 got_int = TRUE;
811 SIGRETURN;
813 #endif
815 #if defined(SIGPWR)
816 /* ARGSUSED */
817 static RETSIGTYPE
818 catch_sigpwr SIGDEFARG(sigarg)
820 /* this is not required on all systems, but it doesn't hurt anybody */
821 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
823 * I'm not sure we get the SIGPWR signal when the system is really going
824 * down or when the batteries are almost empty. Just preserve the swap
825 * files and don't exit, that can't do any harm.
827 ml_sync_all(FALSE, FALSE);
828 SIGRETURN;
830 #endif
832 #ifdef SET_SIG_ALARM
834 * signal function for alarm().
836 /* ARGSUSED */
837 static RETSIGTYPE
838 sig_alarm SIGDEFARG(sigarg)
840 /* doesn't do anything, just to break a system call */
841 sig_alarm_called = TRUE;
842 SIGRETURN;
844 #endif
846 #if (defined(HAVE_SETJMP_H) \
847 && ((defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) \
848 || defined(FEAT_LIBCALL))) \
849 || defined(PROTO)
851 * A simplistic version of setjmp() that only allows one level of using.
852 * Don't call twice before calling mch_endjmp()!.
853 * Usage:
854 * mch_startjmp();
855 * if (SETJMP(lc_jump_env) != 0)
857 * mch_didjmp();
858 * EMSG("crash!");
860 * else
862 * do_the_work;
863 * mch_endjmp();
865 * Note: Can't move SETJMP() here, because a function calling setjmp() must
866 * not return before the saved environment is used.
867 * Returns OK for normal return, FAIL when the protected code caused a
868 * problem and LONGJMP() was used.
870 void
871 mch_startjmp()
873 #ifdef SIGHASARG
874 lc_signal = 0;
875 #endif
876 lc_active = TRUE;
879 void
880 mch_endjmp()
882 lc_active = FALSE;
885 void
886 mch_didjmp()
888 # if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
889 /* On FreeBSD the signal stack has to be reset after using siglongjmp(),
890 * otherwise catching the signal only works once. */
891 init_signal_stack();
892 # endif
894 #endif
897 * This function handles deadly signals.
898 * It tries to preserve any swap file and exit properly.
899 * (partly from Elvis).
901 static RETSIGTYPE
902 deathtrap SIGDEFARG(sigarg)
904 static int entered = 0; /* count the number of times we got here.
905 Note: when memory has been corrupted
906 this may get an arbitrary value! */
907 #ifdef SIGHASARG
908 int i;
909 #endif
911 #if defined(HAVE_SETJMP_H)
913 * Catch a crash in protected code.
914 * Restores the environment saved in lc_jump_env, which looks like
915 * SETJMP() returns 1.
917 if (lc_active)
919 # if defined(SIGHASARG)
920 lc_signal = sigarg;
921 # endif
922 lc_active = FALSE; /* don't jump again */
923 LONGJMP(lc_jump_env, 1);
924 /* NOTREACHED */
926 #endif
928 #ifdef SIGHASARG
929 # ifdef SIGQUIT
930 /* While in mch_delay() we go to cooked mode to allow a CTRL-C to
931 * interrupt us. But in cooked mode we may also get SIGQUIT, e.g., when
932 * pressing CTRL-\, but we don't want Vim to exit then. */
933 if (in_mch_delay && sigarg == SIGQUIT)
934 SIGRETURN;
935 # endif
937 /* When SIGHUP, SIGQUIT, etc. are blocked: postpone the effect and return
938 * here. This avoids that a non-reentrant function is interrupted, e.g.,
939 * free(). Calling free() again may then cause a crash. */
940 if (entered == 0
941 && (0
942 # ifdef SIGHUP
943 || sigarg == SIGHUP
944 # endif
945 # ifdef SIGQUIT
946 || sigarg == SIGQUIT
947 # endif
948 # ifdef SIGTERM
949 || sigarg == SIGTERM
950 # endif
951 # ifdef SIGPWR
952 || sigarg == SIGPWR
953 # endif
954 # ifdef SIGUSR1
955 || sigarg == SIGUSR1
956 # endif
957 # ifdef SIGUSR2
958 || sigarg == SIGUSR2
959 # endif
961 && !vim_handle_signal(sigarg))
962 SIGRETURN;
963 #endif
965 /* Remember how often we have been called. */
966 ++entered;
968 #ifdef FEAT_EVAL
969 /* Set the v:dying variable. */
970 set_vim_var_nr(VV_DYING, (long)entered);
971 #endif
973 #ifdef HAVE_STACK_LIMIT
974 /* Since we are now using the signal stack, need to reset the stack
975 * limit. Otherwise using a regexp will fail. */
976 get_stack_limit();
977 #endif
979 #if 0
980 /* This is for opening gdb the moment Vim crashes.
981 * You need to manually adjust the file name and Vim executable name.
982 * Suggested by SungHyun Nam. */
984 # define VI_GDB_FILE "/tmp/vimgdb"
985 # define VIM_NAME "/usr/bin/vim"
986 FILE *fp = fopen(VI_GDB_FILE, "w");
987 if (fp)
989 fprintf(fp,
990 "file %s\n"
991 "attach %d\n"
992 "set height 1000\n"
993 "bt full\n"
994 , VIM_NAME, getpid());
995 fclose(fp);
996 system("xterm -e gdb -x "VI_GDB_FILE);
997 unlink(VI_GDB_FILE);
1000 #endif
1002 #ifdef SIGHASARG
1003 /* try to find the name of this signal */
1004 for (i = 0; signal_info[i].sig != -1; i++)
1005 if (sigarg == signal_info[i].sig)
1006 break;
1007 deadly_signal = sigarg;
1008 #endif
1010 full_screen = FALSE; /* don't write message to the GUI, it might be
1011 * part of the problem... */
1013 * If something goes wrong after entering here, we may get here again.
1014 * When this happens, give a message and try to exit nicely (resetting the
1015 * terminal mode, etc.)
1016 * When this happens twice, just exit, don't even try to give a message,
1017 * stack may be corrupt or something weird.
1018 * When this still happens again (or memory was corrupted in such a way
1019 * that "entered" was clobbered) use _exit(), don't try freeing resources.
1021 if (entered >= 3)
1023 reset_signals(); /* don't catch any signals anymore */
1024 may_core_dump();
1025 if (entered >= 4)
1026 _exit(8);
1027 exit(7);
1029 if (entered == 2)
1031 OUT_STR(_("Vim: Double signal, exiting\n"));
1032 out_flush();
1033 getout(1);
1036 #ifdef SIGHASARG
1037 sprintf((char *)IObuff, _("Vim: Caught deadly signal %s\n"),
1038 signal_info[i].name);
1039 #else
1040 sprintf((char *)IObuff, _("Vim: Caught deadly signal\n"));
1041 #endif
1042 preserve_exit(); /* preserve files and exit */
1044 #ifdef NBDEBUG
1045 reset_signals();
1046 may_core_dump();
1047 abort();
1048 #endif
1050 SIGRETURN;
1053 #ifdef _REENTRANT
1055 * On Solaris with multi-threading, suspending might not work immediately.
1056 * Catch the SIGCONT signal, which will be used as an indication whether the
1057 * suspending has been done or not.
1059 static int sigcont_received;
1060 static RETSIGTYPE sigcont_handler __ARGS(SIGPROTOARG);
1063 * signal handler for SIGCONT
1065 /* ARGSUSED */
1066 static RETSIGTYPE
1067 sigcont_handler SIGDEFARG(sigarg)
1069 sigcont_received = TRUE;
1070 SIGRETURN;
1072 #endif
1075 * If the machine has job control, use it to suspend the program,
1076 * otherwise fake it by starting a new shell.
1078 void
1079 mch_suspend()
1081 /* BeOS does have SIGTSTP, but it doesn't work. */
1082 #if defined(SIGTSTP) && !defined(__BEOS__)
1083 out_flush(); /* needed to make cursor visible on some systems */
1084 settmode(TMODE_COOK);
1085 out_flush(); /* needed to disable mouse on some systems */
1087 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
1088 /* Since we are going to sleep, we can't respond to requests for the X
1089 * selections. Lose them, otherwise other applications will hang. But
1090 * first copy the text to cut buffer 0. */
1091 if (clip_star.owned || clip_plus.owned)
1093 x11_export_final_selection();
1094 if (clip_star.owned)
1095 clip_lose_selection(&clip_star);
1096 if (clip_plus.owned)
1097 clip_lose_selection(&clip_plus);
1098 if (x11_display != NULL)
1099 XFlush(x11_display);
1101 # endif
1103 # ifdef _REENTRANT
1104 sigcont_received = FALSE;
1105 # endif
1106 kill(0, SIGTSTP); /* send ourselves a STOP signal */
1107 # ifdef _REENTRANT
1108 /* When we didn't suspend immediately in the kill(), do it now. Happens
1109 * on multi-threaded Solaris. */
1110 if (!sigcont_received)
1111 pause();
1112 # endif
1114 # ifdef FEAT_TITLE
1116 * Set oldtitle to NULL, so the current title is obtained again.
1118 vim_free(oldtitle);
1119 oldtitle = NULL;
1120 # endif
1121 settmode(TMODE_RAW);
1122 need_check_timestamps = TRUE;
1123 did_check_timestamps = FALSE;
1124 #else
1125 suspend_shell();
1126 #endif
1129 void
1130 mch_init()
1132 Columns = 80;
1133 Rows = 24;
1135 out_flush();
1136 set_signals();
1138 #ifdef MACOS_CONVERT
1139 mac_conv_init();
1140 #endif
1143 static void
1144 set_signals()
1146 #if defined(SIGWINCH)
1148 * WINDOW CHANGE signal is handled with sig_winch().
1150 signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
1151 #endif
1154 * We want the STOP signal to work, to make mch_suspend() work.
1155 * For "rvim" the STOP signal is ignored.
1157 #ifdef SIGTSTP
1158 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
1159 #endif
1160 #ifdef _REENTRANT
1161 signal(SIGCONT, sigcont_handler);
1162 #endif
1165 * We want to ignore breaking of PIPEs.
1167 #ifdef SIGPIPE
1168 signal(SIGPIPE, SIG_IGN);
1169 #endif
1171 #ifdef SIGINT
1172 catch_int_signal();
1173 #endif
1176 * Ignore alarm signals (Perl's alarm() generates it).
1178 #ifdef SIGALRM
1179 signal(SIGALRM, SIG_IGN);
1180 #endif
1183 * Catch SIGPWR (power failure?) to preserve the swap files, so that no
1184 * work will be lost.
1186 #ifdef SIGPWR
1187 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
1188 #endif
1191 * Arrange for other signals to gracefully shutdown Vim.
1193 catch_signals(deathtrap, SIG_ERR);
1195 #if defined(FEAT_GUI) && defined(SIGHUP)
1197 * When the GUI is running, ignore the hangup signal.
1199 if (gui.in_use)
1200 signal(SIGHUP, SIG_IGN);
1201 #endif
1204 #if defined(SIGINT) || defined(PROTO)
1206 * Catch CTRL-C (only works while in Cooked mode).
1208 static void
1209 catch_int_signal()
1211 signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
1213 #endif
1215 void
1216 reset_signals()
1218 catch_signals(SIG_DFL, SIG_DFL);
1219 #ifdef _REENTRANT
1220 /* SIGCONT isn't in the list, because its default action is ignore */
1221 signal(SIGCONT, SIG_DFL);
1222 #endif
1225 static void
1226 catch_signals(func_deadly, func_other)
1227 RETSIGTYPE (*func_deadly)();
1228 RETSIGTYPE (*func_other)();
1230 int i;
1232 for (i = 0; signal_info[i].sig != -1; i++)
1233 if (signal_info[i].deadly)
1235 #if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
1236 struct sigaction sa;
1238 /* Setup to use the alternate stack for the signal function. */
1239 sa.sa_handler = func_deadly;
1240 sigemptyset(&sa.sa_mask);
1241 # if defined(__linux__) && defined(_REENTRANT)
1242 /* On Linux, with glibc compiled for kernel 2.2, there is a bug in
1243 * thread handling in combination with using the alternate stack:
1244 * pthread library functions try to use the stack pointer to
1245 * identify the current thread, causing a SEGV signal, which
1246 * recursively calls deathtrap() and hangs. */
1247 sa.sa_flags = 0;
1248 # else
1249 sa.sa_flags = SA_ONSTACK;
1250 # endif
1251 sigaction(signal_info[i].sig, &sa, NULL);
1252 #else
1253 # if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGVEC)
1254 struct sigvec sv;
1256 /* Setup to use the alternate stack for the signal function. */
1257 sv.sv_handler = func_deadly;
1258 sv.sv_mask = 0;
1259 sv.sv_flags = SV_ONSTACK;
1260 sigvec(signal_info[i].sig, &sv, NULL);
1261 # else
1262 signal(signal_info[i].sig, func_deadly);
1263 # endif
1264 #endif
1266 else if (func_other != SIG_ERR)
1267 signal(signal_info[i].sig, func_other);
1271 * Handling of SIGHUP, SIGQUIT and SIGTERM:
1272 * "when" == a signal: when busy, postpone and return FALSE, otherwise
1273 * return TRUE
1274 * "when" == SIGNAL_BLOCK: Going to be busy, block signals
1275 * "when" == SIGNAL_UNBLOCK: Going to wait, unblock signals, use postponed
1276 * signal
1277 * Returns TRUE when Vim should exit.
1280 vim_handle_signal(sig)
1281 int sig;
1283 static int got_signal = 0;
1284 static int blocked = TRUE;
1286 switch (sig)
1288 case SIGNAL_BLOCK: blocked = TRUE;
1289 break;
1291 case SIGNAL_UNBLOCK: blocked = FALSE;
1292 if (got_signal != 0)
1294 kill(getpid(), got_signal);
1295 got_signal = 0;
1297 break;
1299 default: if (!blocked)
1300 return TRUE; /* exit! */
1301 got_signal = sig;
1302 #ifdef SIGPWR
1303 if (sig != SIGPWR)
1304 #endif
1305 got_int = TRUE; /* break any loops */
1306 break;
1308 return FALSE;
1312 * Check_win checks whether we have an interactive stdout.
1314 /* ARGSUSED */
1316 mch_check_win(argc, argv)
1317 int argc;
1318 char **argv;
1320 #ifdef OS2
1322 * Store argv[0], may be used for $VIM. Only use it if it is an absolute
1323 * name, mostly it's just "vim" and found in the path, which is unusable.
1325 if (mch_isFullName(argv[0]))
1326 exe_name = vim_strsave((char_u *)argv[0]);
1327 #endif
1328 if (isatty(1))
1329 return OK;
1330 return FAIL;
1334 * Return TRUE if the input comes from a terminal, FALSE otherwise.
1337 mch_input_isatty()
1339 if (isatty(read_cmd_fd))
1340 return TRUE;
1341 return FALSE;
1344 #ifdef FEAT_X11
1346 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) \
1347 && (defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE))
1349 static void xopen_message __ARGS((struct timeval *tvp));
1352 * Give a message about the elapsed time for opening the X window.
1354 static void
1355 xopen_message(tvp)
1356 struct timeval *tvp; /* must contain start time */
1358 struct timeval end_tv;
1360 /* Compute elapsed time. */
1361 gettimeofday(&end_tv, NULL);
1362 smsg((char_u *)_("Opening the X display took %ld msec"),
1363 (end_tv.tv_sec - tvp->tv_sec) * 1000L
1364 + (end_tv.tv_usec - tvp->tv_usec) / 1000L);
1366 # endif
1367 #endif
1369 #if defined(FEAT_X11) && (defined(FEAT_TITLE) || defined(FEAT_XCLIPBOARD))
1371 * A few functions shared by X11 title and clipboard code.
1373 static int x_error_handler __ARGS((Display *dpy, XErrorEvent *error_event));
1374 static int x_error_check __ARGS((Display *dpy, XErrorEvent *error_event));
1375 static int x_connect_to_server __ARGS((void));
1376 static int test_x11_window __ARGS((Display *dpy));
1378 static int got_x_error = FALSE;
1381 * X Error handler, otherwise X just exits! (very rude) -- webb
1383 static int
1384 x_error_handler(dpy, error_event)
1385 Display *dpy;
1386 XErrorEvent *error_event;
1388 XGetErrorText(dpy, error_event->error_code, (char *)IObuff, IOSIZE);
1389 STRCAT(IObuff, _("\nVim: Got X error\n"));
1391 /* We cannot print a message and continue, because no X calls are allowed
1392 * here (causes my system to hang). Silently continuing might be an
1393 * alternative... */
1394 preserve_exit(); /* preserve files and exit */
1396 return 0; /* NOTREACHED */
1400 * Another X Error handler, just used to check for errors.
1402 /* ARGSUSED */
1403 static int
1404 x_error_check(dpy, error_event)
1405 Display *dpy;
1406 XErrorEvent *error_event;
1408 got_x_error = TRUE;
1409 return 0;
1412 #if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
1413 # if defined(HAVE_SETJMP_H)
1415 * An X IO Error handler, used to catch error while opening the display.
1417 static int x_IOerror_check __ARGS((Display *dpy));
1419 /* ARGSUSED */
1420 static int
1421 x_IOerror_check(dpy)
1422 Display *dpy;
1424 /* This function should not return, it causes exit(). Longjump instead. */
1425 LONGJMP(lc_jump_env, 1);
1426 /*NOTREACHED*/
1427 return 0;
1429 # endif
1432 * An X IO Error handler, used to catch terminal errors.
1434 static int x_IOerror_handler __ARGS((Display *dpy));
1436 /* ARGSUSED */
1437 static int
1438 x_IOerror_handler(dpy)
1439 Display *dpy;
1441 xterm_dpy = NULL;
1442 x11_window = 0;
1443 x11_display = NULL;
1444 xterm_Shell = (Widget)0;
1446 /* This function should not return, it causes exit(). Longjump instead. */
1447 LONGJMP(x_jump_env, 1);
1448 /*NOTREACHED*/
1449 return 0;
1451 #endif
1454 * Return TRUE when connection to the X server is desired.
1456 static int
1457 x_connect_to_server()
1459 regmatch_T regmatch;
1461 #if defined(FEAT_CLIENTSERVER)
1462 if (x_force_connect)
1463 return TRUE;
1464 #endif
1465 if (x_no_connect)
1466 return FALSE;
1468 /* Check for a match with "exclude:" from 'clipboard'. */
1469 if (clip_exclude_prog != NULL)
1471 regmatch.rm_ic = FALSE; /* Don't ignore case */
1472 regmatch.regprog = clip_exclude_prog;
1473 if (vim_regexec(&regmatch, T_NAME, (colnr_T)0))
1474 return FALSE;
1476 return TRUE;
1480 * Test if "dpy" and x11_window are valid by getting the window title.
1481 * I don't actually want it yet, so there may be a simpler call to use, but
1482 * this will cause the error handler x_error_check() to be called if anything
1483 * is wrong, such as the window pointer being invalid (as can happen when the
1484 * user changes his DISPLAY, but not his WINDOWID) -- webb
1486 static int
1487 test_x11_window(dpy)
1488 Display *dpy;
1490 int (*old_handler)();
1491 XTextProperty text_prop;
1493 old_handler = XSetErrorHandler(x_error_check);
1494 got_x_error = FALSE;
1495 if (XGetWMName(dpy, x11_window, &text_prop))
1496 XFree((void *)text_prop.value);
1497 XSync(dpy, False);
1498 (void)XSetErrorHandler(old_handler);
1500 if (p_verbose > 0 && got_x_error)
1501 verb_msg((char_u *)_("Testing the X display failed"));
1503 return (got_x_error ? FAIL : OK);
1505 #endif
1507 #ifdef FEAT_TITLE
1509 #ifdef FEAT_X11
1511 static int get_x11_thing __ARGS((int get_title, int test_only));
1514 * try to get x11 window and display
1516 * return FAIL for failure, OK otherwise
1518 static int
1519 get_x11_windis()
1521 char *winid;
1522 static int result = -1;
1523 #define XD_NONE 0 /* x11_display not set here */
1524 #define XD_HERE 1 /* x11_display opened here */
1525 #define XD_GUI 2 /* x11_display used from gui.dpy */
1526 #define XD_XTERM 3 /* x11_display used from xterm_dpy */
1527 static int x11_display_from = XD_NONE;
1528 static int did_set_error_handler = FALSE;
1530 if (!did_set_error_handler)
1532 /* X just exits if it finds an error otherwise! */
1533 (void)XSetErrorHandler(x_error_handler);
1534 did_set_error_handler = TRUE;
1537 #if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
1538 if (gui.in_use)
1541 * If the X11 display was opened here before, for the window where Vim
1542 * was started, close that one now to avoid a memory leak.
1544 if (x11_display_from == XD_HERE && x11_display != NULL)
1546 XCloseDisplay(x11_display);
1547 x11_display_from = XD_NONE;
1549 if (gui_get_x11_windis(&x11_window, &x11_display) == OK)
1551 x11_display_from = XD_GUI;
1552 return OK;
1554 x11_display = NULL;
1555 return FAIL;
1557 else if (x11_display_from == XD_GUI)
1559 /* GUI must have stopped somehow, clear x11_display */
1560 x11_window = 0;
1561 x11_display = NULL;
1562 x11_display_from = XD_NONE;
1564 #endif
1566 /* When started with the "-X" argument, don't try connecting. */
1567 if (!x_connect_to_server())
1568 return FAIL;
1571 * If WINDOWID not set, should try another method to find out
1572 * what the current window number is. The only code I know for
1573 * this is very complicated.
1574 * We assume that zero is invalid for WINDOWID.
1576 if (x11_window == 0 && (winid = getenv("WINDOWID")) != NULL)
1577 x11_window = (Window)atol(winid);
1579 #ifdef FEAT_XCLIPBOARD
1580 if (xterm_dpy != NULL && x11_window != 0)
1582 /* We may have checked it already, but Gnome terminal can move us to
1583 * another window, so we need to check every time. */
1584 if (x11_display_from != XD_XTERM)
1587 * If the X11 display was opened here before, for the window where
1588 * Vim was started, close that one now to avoid a memory leak.
1590 if (x11_display_from == XD_HERE && x11_display != NULL)
1591 XCloseDisplay(x11_display);
1592 x11_display = xterm_dpy;
1593 x11_display_from = XD_XTERM;
1595 if (test_x11_window(x11_display) == FAIL)
1597 /* probably bad $WINDOWID */
1598 x11_window = 0;
1599 x11_display = NULL;
1600 x11_display_from = XD_NONE;
1601 return FAIL;
1603 return OK;
1605 #endif
1607 if (x11_window == 0 || x11_display == NULL)
1608 result = -1;
1610 if (result != -1) /* Have already been here and set this */
1611 return result; /* Don't do all these X calls again */
1613 if (x11_window != 0 && x11_display == NULL)
1615 #ifdef SET_SIG_ALARM
1616 RETSIGTYPE (*sig_save)();
1617 #endif
1618 #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1619 struct timeval start_tv;
1621 if (p_verbose > 0)
1622 gettimeofday(&start_tv, NULL);
1623 #endif
1625 #ifdef SET_SIG_ALARM
1627 * Opening the Display may hang if the DISPLAY setting is wrong, or
1628 * the network connection is bad. Set an alarm timer to get out.
1630 sig_alarm_called = FALSE;
1631 sig_save = (RETSIGTYPE (*)())signal(SIGALRM,
1632 (RETSIGTYPE (*)())sig_alarm);
1633 alarm(2);
1634 #endif
1635 x11_display = XOpenDisplay(NULL);
1637 #ifdef SET_SIG_ALARM
1638 alarm(0);
1639 signal(SIGALRM, (RETSIGTYPE (*)())sig_save);
1640 if (p_verbose > 0 && sig_alarm_called)
1641 verb_msg((char_u *)_("Opening the X display timed out"));
1642 #endif
1643 if (x11_display != NULL)
1645 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1646 if (p_verbose > 0)
1648 verbose_enter();
1649 xopen_message(&start_tv);
1650 verbose_leave();
1652 # endif
1653 if (test_x11_window(x11_display) == FAIL)
1655 /* Maybe window id is bad */
1656 x11_window = 0;
1657 XCloseDisplay(x11_display);
1658 x11_display = NULL;
1660 else
1661 x11_display_from = XD_HERE;
1664 if (x11_window == 0 || x11_display == NULL)
1665 return (result = FAIL);
1666 return (result = OK);
1670 * Determine original x11 Window Title
1672 static int
1673 get_x11_title(test_only)
1674 int test_only;
1676 return get_x11_thing(TRUE, test_only);
1680 * Determine original x11 Window icon
1682 static int
1683 get_x11_icon(test_only)
1684 int test_only;
1686 int retval = FALSE;
1688 retval = get_x11_thing(FALSE, test_only);
1690 /* could not get old icon, use terminal name */
1691 if (oldicon == NULL && !test_only)
1693 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1694 oldicon = T_NAME + 8;
1695 else
1696 oldicon = T_NAME;
1699 return retval;
1702 static int
1703 get_x11_thing(get_title, test_only)
1704 int get_title; /* get title string */
1705 int test_only;
1707 XTextProperty text_prop;
1708 int retval = FALSE;
1709 Status status;
1711 if (get_x11_windis() == OK)
1713 /* Get window/icon name if any */
1714 if (get_title)
1715 status = XGetWMName(x11_display, x11_window, &text_prop);
1716 else
1717 status = XGetWMIconName(x11_display, x11_window, &text_prop);
1720 * If terminal is xterm, then x11_window may be a child window of the
1721 * outer xterm window that actually contains the window/icon name, so
1722 * keep traversing up the tree until a window with a title/icon is
1723 * found.
1725 /* Previously this was only done for xterm and alikes. I don't see a
1726 * reason why it would fail for other terminal emulators.
1727 * if (term_is_xterm) */
1729 Window root;
1730 Window parent;
1731 Window win = x11_window;
1732 Window *children;
1733 unsigned int num_children;
1735 while (!status || text_prop.value == NULL)
1737 if (!XQueryTree(x11_display, win, &root, &parent, &children,
1738 &num_children))
1739 break;
1740 if (children)
1741 XFree((void *)children);
1742 if (parent == root || parent == 0)
1743 break;
1745 win = parent;
1746 if (get_title)
1747 status = XGetWMName(x11_display, win, &text_prop);
1748 else
1749 status = XGetWMIconName(x11_display, win, &text_prop);
1752 if (status && text_prop.value != NULL)
1754 retval = TRUE;
1755 if (!test_only)
1757 #ifdef FEAT_XFONTSET
1758 if (text_prop.encoding == XA_STRING)
1760 #endif
1761 if (get_title)
1762 oldtitle = vim_strsave((char_u *)text_prop.value);
1763 else
1764 oldicon = vim_strsave((char_u *)text_prop.value);
1765 #ifdef FEAT_XFONTSET
1767 else
1769 char **cl;
1770 Status transform_status;
1771 int n = 0;
1773 transform_status = XmbTextPropertyToTextList(x11_display,
1774 &text_prop,
1775 &cl, &n);
1776 if (transform_status >= Success && n > 0 && cl[0])
1778 if (get_title)
1779 oldtitle = vim_strsave((char_u *) cl[0]);
1780 else
1781 oldicon = vim_strsave((char_u *) cl[0]);
1782 XFreeStringList(cl);
1784 else
1786 if (get_title)
1787 oldtitle = vim_strsave((char_u *)text_prop.value);
1788 else
1789 oldicon = vim_strsave((char_u *)text_prop.value);
1792 #endif
1794 XFree((void *)text_prop.value);
1797 return retval;
1800 /* Are Xutf8 functions available? Avoid error from old compilers. */
1801 #if defined(X_HAVE_UTF8_STRING) && defined(FEAT_MBYTE)
1802 # if X_HAVE_UTF8_STRING
1803 # define USE_UTF8_STRING
1804 # endif
1805 #endif
1808 * Set x11 Window Title
1810 * get_x11_windis() must be called before this and have returned OK
1812 static void
1813 set_x11_title(title)
1814 char_u *title;
1816 /* XmbSetWMProperties() and Xutf8SetWMProperties() should use a STRING
1817 * when possible, COMPOUND_TEXT otherwise. COMPOUND_TEXT isn't
1818 * supported everywhere and STRING doesn't work for multi-byte titles.
1820 #ifdef USE_UTF8_STRING
1821 if (enc_utf8)
1822 Xutf8SetWMProperties(x11_display, x11_window, (const char *)title,
1823 NULL, NULL, 0, NULL, NULL, NULL);
1824 else
1825 #endif
1827 #if XtSpecificationRelease >= 4
1828 # ifdef FEAT_XFONTSET
1829 XmbSetWMProperties(x11_display, x11_window, (const char *)title,
1830 NULL, NULL, 0, NULL, NULL, NULL);
1831 # else
1832 XTextProperty text_prop;
1833 char *c_title = (char *)title;
1835 /* directly from example 3-18 "basicwin" of Xlib Programming Manual */
1836 (void)XStringListToTextProperty(&c_title, 1, &text_prop);
1837 XSetWMProperties(x11_display, x11_window, &text_prop,
1838 NULL, NULL, 0, NULL, NULL, NULL);
1839 # endif
1840 #else
1841 XStoreName(x11_display, x11_window, (char *)title);
1842 #endif
1844 XFlush(x11_display);
1848 * Set x11 Window icon
1850 * get_x11_windis() must be called before this and have returned OK
1852 static void
1853 set_x11_icon(icon)
1854 char_u *icon;
1856 /* See above for comments about using X*SetWMProperties(). */
1857 #ifdef USE_UTF8_STRING
1858 if (enc_utf8)
1859 Xutf8SetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
1860 NULL, 0, NULL, NULL, NULL);
1861 else
1862 #endif
1864 #if XtSpecificationRelease >= 4
1865 # ifdef FEAT_XFONTSET
1866 XmbSetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
1867 NULL, 0, NULL, NULL, NULL);
1868 # else
1869 XTextProperty text_prop;
1870 char *c_icon = (char *)icon;
1872 (void)XStringListToTextProperty(&c_icon, 1, &text_prop);
1873 XSetWMProperties(x11_display, x11_window, NULL, &text_prop,
1874 NULL, 0, NULL, NULL, NULL);
1875 # endif
1876 #else
1877 XSetIconName(x11_display, x11_window, (char *)icon);
1878 #endif
1880 XFlush(x11_display);
1883 #else /* FEAT_X11 */
1885 /*ARGSUSED*/
1886 static int
1887 get_x11_title(test_only)
1888 int test_only;
1890 return FALSE;
1893 static int
1894 get_x11_icon(test_only)
1895 int test_only;
1897 if (!test_only)
1899 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1900 oldicon = T_NAME + 8;
1901 else
1902 oldicon = T_NAME;
1904 return FALSE;
1907 #endif /* FEAT_X11 */
1910 mch_can_restore_title()
1912 return get_x11_title(TRUE);
1916 mch_can_restore_icon()
1918 return get_x11_icon(TRUE);
1922 * Set the window title and icon.
1924 void
1925 mch_settitle(title, icon)
1926 char_u *title;
1927 char_u *icon;
1929 int type = 0;
1930 static int recursive = 0;
1932 if (T_NAME == NULL) /* no terminal name (yet) */
1933 return;
1934 if (title == NULL && icon == NULL) /* nothing to do */
1935 return;
1937 /* When one of the X11 functions causes a deadly signal, we get here again
1938 * recursively. Avoid hanging then (something is probably locked). */
1939 if (recursive)
1940 return;
1941 ++recursive;
1944 * if the window ID and the display is known, we may use X11 calls
1946 #ifdef FEAT_X11
1947 if (get_x11_windis() == OK)
1948 type = 1;
1949 #else
1950 # if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) \
1951 || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MACVIM)
1952 if (gui.in_use)
1953 type = 1;
1954 # endif
1955 #endif
1958 * Note: if "t_TS" is set, title is set with escape sequence rather
1959 * than x11 calls, because the x11 calls don't always work
1961 if ((type || *T_TS != NUL) && title != NULL)
1963 if (oldtitle == NULL
1964 #ifdef FEAT_GUI
1965 && !gui.in_use
1966 #endif
1967 ) /* first call but not in GUI, save title */
1968 (void)get_x11_title(FALSE);
1970 if (*T_TS != NUL) /* it's OK if t_fs is empty */
1971 term_settitle(title);
1972 #ifdef FEAT_X11
1973 else
1974 # ifdef FEAT_GUI_GTK
1975 if (!gui.in_use) /* don't do this if GTK+ is running */
1976 # endif
1977 set_x11_title(title); /* x11 */
1978 #endif
1979 #if defined(FEAT_GUI_GTK) \
1980 || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) \
1981 || defined(FEAT_GUI_MACVIM)
1982 else
1983 gui_mch_settitle(title, icon);
1984 #endif
1985 did_set_title = TRUE;
1988 if ((type || *T_CIS != NUL) && icon != NULL)
1990 if (oldicon == NULL
1991 #ifdef FEAT_GUI
1992 && !gui.in_use
1993 #endif
1994 ) /* first call, save icon */
1995 get_x11_icon(FALSE);
1997 if (*T_CIS != NUL)
1999 out_str(T_CIS); /* set icon start */
2000 out_str_nf(icon);
2001 out_str(T_CIE); /* set icon end */
2002 out_flush();
2004 #ifdef FEAT_X11
2005 else
2006 # ifdef FEAT_GUI_GTK
2007 if (!gui.in_use) /* don't do this if GTK+ is running */
2008 # endif
2009 set_x11_icon(icon); /* x11 */
2010 #endif
2011 did_set_icon = TRUE;
2013 --recursive;
2017 * Restore the window/icon title.
2018 * "which" is one of:
2019 * 1 only restore title
2020 * 2 only restore icon
2021 * 3 restore title and icon
2023 void
2024 mch_restore_title(which)
2025 int which;
2027 /* only restore the title or icon when it has been set */
2028 mch_settitle(((which & 1) && did_set_title) ?
2029 (oldtitle ? oldtitle : p_titleold) : NULL,
2030 ((which & 2) && did_set_icon) ? oldicon : NULL);
2033 #endif /* FEAT_TITLE */
2036 * Return TRUE if "name" looks like some xterm name.
2037 * Seiichi Sato mentioned that "mlterm" works like xterm.
2040 vim_is_xterm(name)
2041 char_u *name;
2043 if (name == NULL)
2044 return FALSE;
2045 return (STRNICMP(name, "xterm", 5) == 0
2046 || STRNICMP(name, "nxterm", 6) == 0
2047 || STRNICMP(name, "kterm", 5) == 0
2048 || STRNICMP(name, "mlterm", 6) == 0
2049 || STRNICMP(name, "rxvt", 4) == 0
2050 || STRCMP(name, "builtin_xterm") == 0);
2053 #if defined(FEAT_MOUSE_TTY) || defined(PROTO)
2055 * Return non-zero when using an xterm mouse, according to 'ttymouse'.
2056 * Return 1 for "xterm".
2057 * Return 2 for "xterm2".
2060 use_xterm_mouse()
2062 if (ttym_flags == TTYM_XTERM2)
2063 return 2;
2064 if (ttym_flags == TTYM_XTERM)
2065 return 1;
2066 return 0;
2068 #endif
2071 vim_is_iris(name)
2072 char_u *name;
2074 if (name == NULL)
2075 return FALSE;
2076 return (STRNICMP(name, "iris-ansi", 9) == 0
2077 || STRCMP(name, "builtin_iris-ansi") == 0);
2081 vim_is_vt300(name)
2082 char_u *name;
2084 if (name == NULL)
2085 return FALSE; /* actually all ANSI comp. terminals should be here */
2086 /* catch VT100 - VT5xx */
2087 return ((STRNICMP(name, "vt", 2) == 0
2088 && vim_strchr((char_u *)"12345", name[2]) != NULL)
2089 || STRCMP(name, "builtin_vt320") == 0);
2093 * Return TRUE if "name" is a terminal for which 'ttyfast' should be set.
2094 * This should include all windowed terminal emulators.
2097 vim_is_fastterm(name)
2098 char_u *name;
2100 if (name == NULL)
2101 return FALSE;
2102 if (vim_is_xterm(name) || vim_is_vt300(name) || vim_is_iris(name))
2103 return TRUE;
2104 return ( STRNICMP(name, "hpterm", 6) == 0
2105 || STRNICMP(name, "sun-cmd", 7) == 0
2106 || STRNICMP(name, "screen", 6) == 0
2107 || STRNICMP(name, "dtterm", 6) == 0);
2111 * Insert user name in s[len].
2112 * Return OK if a name found.
2115 mch_get_user_name(s, len)
2116 char_u *s;
2117 int len;
2119 #ifdef VMS
2120 vim_strncpy(s, (char_u *)cuserid(NULL), len - 1);
2121 return OK;
2122 #else
2123 return mch_get_uname(getuid(), s, len);
2124 #endif
2128 * Insert user name for "uid" in s[len].
2129 * Return OK if a name found.
2132 mch_get_uname(uid, s, len)
2133 uid_t uid;
2134 char_u *s;
2135 int len;
2137 #if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
2138 struct passwd *pw;
2140 if ((pw = getpwuid(uid)) != NULL
2141 && pw->pw_name != NULL && *(pw->pw_name) != NUL)
2143 vim_strncpy(s, (char_u *)pw->pw_name, len - 1);
2144 return OK;
2146 #endif
2147 sprintf((char *)s, "%d", (int)uid); /* assumes s is long enough */
2148 return FAIL; /* a number is not a name */
2152 * Insert host name is s[len].
2155 #ifdef HAVE_SYS_UTSNAME_H
2156 void
2157 mch_get_host_name(s, len)
2158 char_u *s;
2159 int len;
2161 struct utsname vutsname;
2163 if (uname(&vutsname) < 0)
2164 *s = NUL;
2165 else
2166 vim_strncpy(s, (char_u *)vutsname.nodename, len - 1);
2168 #else /* HAVE_SYS_UTSNAME_H */
2170 # ifdef HAVE_SYS_SYSTEMINFO_H
2171 # define gethostname(nam, len) sysinfo(SI_HOSTNAME, nam, len)
2172 # endif
2174 void
2175 mch_get_host_name(s, len)
2176 char_u *s;
2177 int len;
2179 # ifdef VAXC
2180 vaxc$gethostname((char *)s, len);
2181 # else
2182 gethostname((char *)s, len);
2183 # endif
2184 s[len - 1] = NUL; /* make sure it's terminated */
2186 #endif /* HAVE_SYS_UTSNAME_H */
2189 * return process ID
2191 long
2192 mch_get_pid()
2194 return (long)getpid();
2197 #if !defined(HAVE_STRERROR) && defined(USE_GETCWD)
2198 static char *strerror __ARGS((int));
2200 static char *
2201 strerror(err)
2202 int err;
2204 extern int sys_nerr;
2205 extern char *sys_errlist[];
2206 static char er[20];
2208 if (err > 0 && err < sys_nerr)
2209 return (sys_errlist[err]);
2210 sprintf(er, "Error %d", err);
2211 return er;
2213 #endif
2216 * Get name of current directory into buffer 'buf' of length 'len' bytes.
2217 * Return OK for success, FAIL for failure.
2220 mch_dirname(buf, len)
2221 char_u *buf;
2222 int len;
2224 #if defined(USE_GETCWD)
2225 if (getcwd((char *)buf, len) == NULL)
2227 STRCPY(buf, strerror(errno));
2228 return FAIL;
2230 return OK;
2231 #else
2232 return (getwd((char *)buf) != NULL ? OK : FAIL);
2233 #endif
2236 #if defined(OS2) || defined(PROTO)
2238 * Replace all slashes by backslashes.
2239 * When 'shellslash' set do it the other way around.
2241 void
2242 slash_adjust(p)
2243 char_u *p;
2245 while (*p)
2247 if (*p == psepcN)
2248 *p = psepc;
2249 mb_ptr_adv(p);
2252 #endif
2255 * Get absolute file name into "buf[len]".
2257 * return FAIL for failure, OK for success
2260 mch_FullName(fname, buf, len, force)
2261 char_u *fname, *buf;
2262 int len;
2263 int force; /* also expand when already absolute path */
2265 int l;
2266 #ifdef OS2
2267 int only_drive; /* file name is only a drive letter */
2268 #endif
2269 #ifdef HAVE_FCHDIR
2270 int fd = -1;
2271 static int dont_fchdir = FALSE; /* TRUE when fchdir() doesn't work */
2272 #endif
2273 char_u olddir[MAXPATHL];
2274 char_u *p;
2275 int retval = OK;
2277 #ifdef VMS
2278 fname = vms_fixfilename(fname);
2279 #endif
2281 #ifdef __CYGWIN__
2283 * This helps for when "/etc/hosts" is a symlink to "c:/something/hosts".
2285 cygwin_conv_to_posix_path(fname, fname);
2286 #endif
2288 /* expand it if forced or not an absolute path */
2289 if (force || !mch_isFullName(fname))
2292 * If the file name has a path, change to that directory for a moment,
2293 * and then do the getwd() (and get back to where we were).
2294 * This will get the correct path name with "../" things.
2296 #ifdef OS2
2297 only_drive = 0;
2298 if (((p = vim_strrchr(fname, '/')) != NULL)
2299 || ((p = vim_strrchr(fname, '\\')) != NULL)
2300 || (((p = vim_strchr(fname, ':')) != NULL) && ++only_drive))
2301 #else
2302 if ((p = vim_strrchr(fname, '/')) != NULL)
2303 #endif
2305 #ifdef HAVE_FCHDIR
2307 * Use fchdir() if possible, it's said to be faster and more
2308 * reliable. But on SunOS 4 it might not work. Check this by
2309 * doing a fchdir() right now.
2311 if (!dont_fchdir)
2313 fd = open(".", O_RDONLY | O_EXTRA, 0);
2314 if (fd >= 0 && fchdir(fd) < 0)
2316 close(fd);
2317 fd = -1;
2318 dont_fchdir = TRUE; /* don't try again */
2321 #endif
2323 /* Only change directory when we are sure we can return to where
2324 * we are now. After doing "su" chdir(".") might not work. */
2325 if (
2326 #ifdef HAVE_FCHDIR
2327 fd < 0 &&
2328 #endif
2329 (mch_dirname(olddir, MAXPATHL) == FAIL
2330 || mch_chdir((char *)olddir) != 0))
2332 p = NULL; /* can't get current dir: don't chdir */
2333 retval = FAIL;
2335 else
2337 #ifdef OS2
2339 * compensate for case where ':' from "D:" was the only
2340 * path separator detected in the file name; the _next_
2341 * character has to be removed, and then restored later.
2343 if (only_drive)
2344 p++;
2345 #endif
2346 /* The directory is copied into buf[], to be able to remove
2347 * the file name without changing it (could be a string in
2348 * read-only memory) */
2349 if (p - fname >= len)
2350 retval = FAIL;
2351 else
2353 vim_strncpy(buf, fname, p - fname);
2354 if (mch_chdir((char *)buf))
2355 retval = FAIL;
2356 else
2357 fname = p + 1;
2358 *buf = NUL;
2360 #ifdef OS2
2361 if (only_drive)
2363 p--;
2364 if (retval != FAIL)
2365 fname--;
2367 #endif
2370 if (mch_dirname(buf, len) == FAIL)
2372 retval = FAIL;
2373 *buf = NUL;
2375 if (p != NULL)
2377 #ifdef HAVE_FCHDIR
2378 if (fd >= 0)
2380 l = fchdir(fd);
2381 close(fd);
2383 else
2384 #endif
2385 l = mch_chdir((char *)olddir);
2386 if (l != 0)
2387 EMSG(_(e_prev_dir));
2390 l = STRLEN(buf);
2391 if (l >= len)
2392 retval = FAIL;
2393 #ifndef VMS
2394 else
2396 if (l > 0 && buf[l - 1] != '/' && *fname != NUL
2397 && STRCMP(fname, ".") != 0)
2398 STRCAT(buf, "/");
2400 #endif
2403 /* Catch file names which are too long. */
2404 if (retval == FAIL || STRLEN(buf) + STRLEN(fname) >= len)
2405 return FAIL;
2407 /* Do not append ".", "/dir/." is equal to "/dir". */
2408 if (STRCMP(fname, ".") != 0)
2409 STRCAT(buf, fname);
2411 return OK;
2415 * Return TRUE if "fname" does not depend on the current directory.
2418 mch_isFullName(fname)
2419 char_u *fname;
2421 #ifdef __EMX__
2422 return _fnisabs(fname);
2423 #else
2424 # ifdef VMS
2425 return ( fname[0] == '/' || fname[0] == '.' ||
2426 strchr((char *)fname,':') || strchr((char *)fname,'"') ||
2427 (strchr((char *)fname,'[') && strchr((char *)fname,']'))||
2428 (strchr((char *)fname,'<') && strchr((char *)fname,'>')) );
2429 # else
2430 return (*fname == '/' || *fname == '~');
2431 # endif
2432 #endif
2435 #if defined(USE_FNAME_CASE) || defined(PROTO)
2437 * Set the case of the file name, if it already exists. This will cause the
2438 * file name to remain exactly the same.
2439 * Only required for file systems where case is ignored and preserved.
2441 /*ARGSUSED*/
2442 void
2443 fname_case(name, len)
2444 char_u *name;
2445 int len; /* buffer size, only used when name gets longer */
2447 struct stat st;
2448 char_u *slash, *tail;
2449 DIR *dirp;
2450 struct dirent *dp;
2452 if (lstat((char *)name, &st) >= 0)
2454 /* Open the directory where the file is located. */
2455 slash = vim_strrchr(name, '/');
2456 if (slash == NULL)
2458 dirp = opendir(".");
2459 tail = name;
2461 else
2463 *slash = NUL;
2464 dirp = opendir((char *)name);
2465 *slash = '/';
2466 tail = slash + 1;
2469 if (dirp != NULL)
2471 while ((dp = readdir(dirp)) != NULL)
2473 /* Only accept names that differ in case and are the same byte
2474 * length. TODO: accept different length name. */
2475 if (STRICMP(tail, dp->d_name) == 0
2476 && STRLEN(tail) == STRLEN(dp->d_name))
2478 char_u newname[MAXPATHL + 1];
2479 struct stat st2;
2481 /* Verify the inode is equal. */
2482 vim_strncpy(newname, name, MAXPATHL);
2483 vim_strncpy(newname + (tail - name), (char_u *)dp->d_name,
2484 MAXPATHL - (tail - name));
2485 if (lstat((char *)newname, &st2) >= 0
2486 && st.st_ino == st2.st_ino
2487 && st.st_dev == st2.st_dev)
2489 STRCPY(tail, dp->d_name);
2490 break;
2495 closedir(dirp);
2499 #endif
2502 * Get file permissions for 'name'.
2503 * Returns -1 when it doesn't exist.
2505 long
2506 mch_getperm(name)
2507 char_u *name;
2509 struct stat statb;
2511 /* Keep the #ifdef outside of stat(), it may be a macro. */
2512 #ifdef VMS
2513 if (stat((char *)vms_fixfilename(name), &statb))
2514 #else
2515 if (stat((char *)name, &statb))
2516 #endif
2517 return -1;
2518 #ifdef __INTERIX
2519 /* The top bit makes the value negative, which means the file doesn't
2520 * exist. Remove the bit, we don't use it. */
2521 return statb.st_mode & ~S_ADDACE;
2522 #else
2523 return statb.st_mode;
2524 #endif
2528 * set file permission for 'name' to 'perm'
2530 * return FAIL for failure, OK otherwise
2533 mch_setperm(name, perm)
2534 char_u *name;
2535 long perm;
2537 return (chmod((char *)
2538 #ifdef VMS
2539 vms_fixfilename(name),
2540 #else
2541 name,
2542 #endif
2543 (mode_t)perm) == 0 ? OK : FAIL);
2546 #if defined(HAVE_ACL) || defined(PROTO)
2547 # ifdef HAVE_SYS_ACL_H
2548 # include <sys/acl.h>
2549 # endif
2550 # ifdef HAVE_SYS_ACCESS_H
2551 # include <sys/access.h>
2552 # endif
2554 # ifdef HAVE_SOLARIS_ACL
2555 typedef struct vim_acl_solaris_T {
2556 int acl_cnt;
2557 aclent_t *acl_entry;
2558 } vim_acl_solaris_T;
2559 # endif
2562 * Return a pointer to the ACL of file "fname" in allocated memory.
2563 * Return NULL if the ACL is not available for whatever reason.
2565 vim_acl_T
2566 mch_get_acl(fname)
2567 char_u *fname;
2569 vim_acl_T ret = NULL;
2570 #ifdef HAVE_POSIX_ACL
2571 ret = (vim_acl_T)acl_get_file((char *)fname, ACL_TYPE_ACCESS);
2572 #else
2573 #ifdef HAVE_SOLARIS_ACL
2574 vim_acl_solaris_T *aclent;
2576 aclent = malloc(sizeof(vim_acl_solaris_T));
2577 if ((aclent->acl_cnt = acl((char *)fname, GETACLCNT, 0, NULL)) < 0)
2579 free(aclent);
2580 return NULL;
2582 aclent->acl_entry = malloc(aclent->acl_cnt * sizeof(aclent_t));
2583 if (acl((char *)fname, GETACL, aclent->acl_cnt, aclent->acl_entry) < 0)
2585 free(aclent->acl_entry);
2586 free(aclent);
2587 return NULL;
2589 ret = (vim_acl_T)aclent;
2590 #else
2591 #if defined(HAVE_AIX_ACL)
2592 int aclsize;
2593 struct acl *aclent;
2595 aclsize = sizeof(struct acl);
2596 aclent = malloc(aclsize);
2597 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2599 if (errno == ENOSPC)
2601 aclsize = aclent->acl_len;
2602 aclent = realloc(aclent, aclsize);
2603 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2605 free(aclent);
2606 return NULL;
2609 else
2611 free(aclent);
2612 return NULL;
2615 ret = (vim_acl_T)aclent;
2616 #endif /* HAVE_AIX_ACL */
2617 #endif /* HAVE_SOLARIS_ACL */
2618 #endif /* HAVE_POSIX_ACL */
2619 return ret;
2623 * Set the ACL of file "fname" to "acl" (unless it's NULL).
2625 void
2626 mch_set_acl(fname, aclent)
2627 char_u *fname;
2628 vim_acl_T aclent;
2630 if (aclent == NULL)
2631 return;
2632 #ifdef HAVE_POSIX_ACL
2633 acl_set_file((char *)fname, ACL_TYPE_ACCESS, (acl_t)aclent);
2634 #else
2635 #ifdef HAVE_SOLARIS_ACL
2636 acl((char *)fname, SETACL, ((vim_acl_solaris_T *)aclent)->acl_cnt,
2637 ((vim_acl_solaris_T *)aclent)->acl_entry);
2638 #else
2639 #ifdef HAVE_AIX_ACL
2640 chacl((char *)fname, aclent, ((struct acl *)aclent)->acl_len);
2641 #endif /* HAVE_AIX_ACL */
2642 #endif /* HAVE_SOLARIS_ACL */
2643 #endif /* HAVE_POSIX_ACL */
2646 void
2647 mch_free_acl(aclent)
2648 vim_acl_T aclent;
2650 if (aclent == NULL)
2651 return;
2652 #ifdef HAVE_POSIX_ACL
2653 acl_free((acl_t)aclent);
2654 #else
2655 #ifdef HAVE_SOLARIS_ACL
2656 free(((vim_acl_solaris_T *)aclent)->acl_entry);
2657 free(aclent);
2658 #else
2659 #ifdef HAVE_AIX_ACL
2660 free(aclent);
2661 #endif /* HAVE_AIX_ACL */
2662 #endif /* HAVE_SOLARIS_ACL */
2663 #endif /* HAVE_POSIX_ACL */
2665 #endif
2668 * Set hidden flag for "name".
2670 /* ARGSUSED */
2671 void
2672 mch_hide(name)
2673 char_u *name;
2675 /* can't hide a file */
2679 * return TRUE if "name" is a directory
2680 * return FALSE if "name" is not a directory
2681 * return FALSE for error
2684 mch_isdir(name)
2685 char_u *name;
2687 struct stat statb;
2689 if (*name == NUL) /* Some stat()s don't flag "" as an error. */
2690 return FALSE;
2691 if (stat((char *)name, &statb))
2692 return FALSE;
2693 #ifdef _POSIX_SOURCE
2694 return (S_ISDIR(statb.st_mode) ? TRUE : FALSE);
2695 #else
2696 return ((statb.st_mode & S_IFMT) == S_IFDIR ? TRUE : FALSE);
2697 #endif
2700 static int executable_file __ARGS((char_u *name));
2703 * Return 1 if "name" is an executable file, 0 if not or it doesn't exist.
2705 static int
2706 executable_file(name)
2707 char_u *name;
2709 struct stat st;
2711 if (stat((char *)name, &st))
2712 return 0;
2713 return S_ISREG(st.st_mode) && mch_access((char *)name, X_OK) == 0;
2717 * Return 1 if "name" can be found in $PATH and executed, 0 if not.
2718 * Return -1 if unknown.
2721 mch_can_exe(name)
2722 char_u *name;
2724 char_u *buf;
2725 char_u *p, *e;
2726 int retval;
2728 /* If it's an absolute or relative path don't need to use $PATH. */
2729 if (mch_isFullName(name) || (name[0] == '.' && (name[1] == '/'
2730 || (name[1] == '.' && name[2] == '/'))))
2731 return executable_file(name);
2733 p = (char_u *)getenv("PATH");
2734 if (p == NULL || *p == NUL)
2735 return -1;
2736 buf = alloc((unsigned)(STRLEN(name) + STRLEN(p) + 2));
2737 if (buf == NULL)
2738 return -1;
2741 * Walk through all entries in $PATH to check if "name" exists there and
2742 * is an executable file.
2744 for (;;)
2746 e = (char_u *)strchr((char *)p, ':');
2747 if (e == NULL)
2748 e = p + STRLEN(p);
2749 if (e - p <= 1) /* empty entry means current dir */
2750 STRCPY(buf, "./");
2751 else
2753 vim_strncpy(buf, p, e - p);
2754 add_pathsep(buf);
2756 STRCAT(buf, name);
2757 retval = executable_file(buf);
2758 if (retval == 1)
2759 break;
2761 if (*e != ':')
2762 break;
2763 p = e + 1;
2766 vim_free(buf);
2767 return retval;
2771 * Check what "name" is:
2772 * NODE_NORMAL: file or directory (or doesn't exist)
2773 * NODE_WRITABLE: writable device, socket, fifo, etc.
2774 * NODE_OTHER: non-writable things
2777 mch_nodetype(name)
2778 char_u *name;
2780 struct stat st;
2782 if (stat((char *)name, &st))
2783 return NODE_NORMAL;
2784 if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
2785 return NODE_NORMAL;
2786 #ifndef OS2
2787 if (S_ISBLK(st.st_mode)) /* block device isn't writable */
2788 return NODE_OTHER;
2789 #endif
2790 /* Everything else is writable? */
2791 return NODE_WRITABLE;
2794 void
2795 mch_early_init()
2797 #ifdef HAVE_CHECK_STACK_GROWTH
2798 int i;
2800 check_stack_growth((char *)&i);
2802 # ifdef HAVE_STACK_LIMIT
2803 get_stack_limit();
2804 # endif
2806 #endif
2809 * Setup an alternative stack for signals. Helps to catch signals when
2810 * running out of stack space.
2811 * Use of sigaltstack() is preferred, it's more portable.
2812 * Ignore any errors.
2814 #if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2815 signal_stack = malloc(SIGSTKSZ);
2816 init_signal_stack();
2817 #endif
2820 #if defined(EXITFREE) || defined(PROTO)
2821 void
2822 mch_free_mem()
2824 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
2825 if (clip_star.owned)
2826 clip_lose_selection(&clip_star);
2827 if (clip_plus.owned)
2828 clip_lose_selection(&clip_plus);
2829 # endif
2830 # if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
2831 if (xterm_Shell != (Widget)0)
2832 XtDestroyWidget(xterm_Shell);
2833 if (xterm_dpy != NULL)
2834 XtCloseDisplay(xterm_dpy);
2835 if (app_context != (XtAppContext)NULL)
2836 XtDestroyApplicationContext(app_context);
2837 # endif
2838 # ifdef FEAT_X11
2839 if (x11_display != NULL && x11_display != xterm_dpy)
2840 XCloseDisplay(x11_display);
2841 # endif
2842 # if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2843 vim_free(signal_stack);
2844 signal_stack = NULL;
2845 # endif
2846 # ifdef FEAT_TITLE
2847 vim_free(oldtitle);
2848 vim_free(oldicon);
2849 # endif
2851 #endif
2853 static void exit_scroll __ARGS((void));
2856 * Output a newline when exiting.
2857 * Make sure the newline goes to the same stream as the text.
2859 static void
2860 exit_scroll()
2862 if (silent_mode)
2863 return;
2864 if (newline_on_exit || msg_didout)
2866 if (msg_use_printf())
2868 if (info_message)
2869 mch_msg("\n");
2870 else
2871 mch_errmsg("\r\n");
2873 else
2874 out_char('\n');
2876 else
2878 restore_cterm_colors(); /* get original colors back */
2879 msg_clr_eos_force(); /* clear the rest of the display */
2880 windgoto((int)Rows - 1, 0); /* may have moved the cursor */
2884 void
2885 mch_exit(r)
2886 int r;
2888 exiting = TRUE;
2890 #if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
2891 x11_export_final_selection();
2892 #endif
2894 #ifdef FEAT_GUI
2895 if (!gui.in_use)
2896 #endif
2898 settmode(TMODE_COOK);
2899 #ifdef FEAT_TITLE
2900 mch_restore_title(3); /* restore xterm title and icon name */
2901 #endif
2903 * When t_ti is not empty but it doesn't cause swapping terminal
2904 * pages, need to output a newline when msg_didout is set. But when
2905 * t_ti does swap pages it should not go to the shell page. Do this
2906 * before stoptermcap().
2908 if (swapping_screen() && !newline_on_exit)
2909 exit_scroll();
2911 /* Stop termcap: May need to check for T_CRV response, which
2912 * requires RAW mode. */
2913 stoptermcap();
2916 * A newline is only required after a message in the alternate screen.
2917 * This is set to TRUE by wait_return().
2919 if (!swapping_screen() || newline_on_exit)
2920 exit_scroll();
2922 /* Cursor may have been switched off without calling starttermcap()
2923 * when doing "vim -u vimrc" and vimrc contains ":q". */
2924 if (full_screen)
2925 cursor_on();
2927 out_flush();
2928 ml_close_all(TRUE); /* remove all memfiles */
2929 may_core_dump();
2930 #ifdef FEAT_GUI
2931 if (gui.in_use)
2932 gui_exit(r);
2933 #endif
2935 #ifdef MACOS_CONVERT
2936 mac_conv_cleanup();
2937 #endif
2939 #ifdef __QNX__
2940 /* A core dump won't be created if the signal handler
2941 * doesn't return, so we can't call exit() */
2942 if (deadly_signal != 0)
2943 return;
2944 #endif
2946 #ifdef FEAT_NETBEANS_INTG
2947 if (usingNetbeans)
2948 netbeans_send_disconnect();
2949 #endif
2951 #ifdef EXITFREE
2952 free_all_mem();
2953 #endif
2955 exit(r);
2958 static void
2959 may_core_dump()
2961 if (deadly_signal != 0)
2963 signal(deadly_signal, SIG_DFL);
2964 kill(getpid(), deadly_signal); /* Die using the signal we caught */
2968 #ifndef VMS
2970 void
2971 mch_settmode(tmode)
2972 int tmode;
2974 static int first = TRUE;
2976 /* Why is NeXT excluded here (and not in os_unixx.h)? */
2977 #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
2979 * for "new" tty systems
2981 # ifdef HAVE_TERMIOS_H
2982 static struct termios told;
2983 struct termios tnew;
2984 # else
2985 static struct termio told;
2986 struct termio tnew;
2987 # endif
2989 if (first)
2991 first = FALSE;
2992 # if defined(HAVE_TERMIOS_H)
2993 tcgetattr(read_cmd_fd, &told);
2994 # else
2995 ioctl(read_cmd_fd, TCGETA, &told);
2996 # endif
2999 tnew = told;
3000 if (tmode == TMODE_RAW)
3003 * ~ICRNL enables typing ^V^M
3005 tnew.c_iflag &= ~ICRNL;
3006 tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE
3007 # if defined(IEXTEN) && !defined(__MINT__)
3008 | IEXTEN /* IEXTEN enables typing ^V on SOLARIS */
3009 /* but it breaks function keys on MINT */
3010 # endif
3012 # ifdef ONLCR /* don't map NL -> CR NL, we do it ourselves */
3013 tnew.c_oflag &= ~ONLCR;
3014 # endif
3015 tnew.c_cc[VMIN] = 1; /* return after 1 char */
3016 tnew.c_cc[VTIME] = 0; /* don't wait */
3018 else if (tmode == TMODE_SLEEP)
3019 tnew.c_lflag &= ~(ECHO);
3021 # if defined(HAVE_TERMIOS_H)
3023 int n = 10;
3025 /* A signal may cause tcsetattr() to fail (e.g., SIGCONT). Retry a
3026 * few times. */
3027 while (tcsetattr(read_cmd_fd, TCSANOW, &tnew) == -1
3028 && errno == EINTR && n > 0)
3029 --n;
3031 # else
3032 ioctl(read_cmd_fd, TCSETA, &tnew);
3033 # endif
3035 #else
3038 * for "old" tty systems
3040 # ifndef TIOCSETN
3041 # define TIOCSETN TIOCSETP /* for hpux 9.0 */
3042 # endif
3043 static struct sgttyb ttybold;
3044 struct sgttyb ttybnew;
3046 if (first)
3048 first = FALSE;
3049 ioctl(read_cmd_fd, TIOCGETP, &ttybold);
3052 ttybnew = ttybold;
3053 if (tmode == TMODE_RAW)
3055 ttybnew.sg_flags &= ~(CRMOD | ECHO);
3056 ttybnew.sg_flags |= RAW;
3058 else if (tmode == TMODE_SLEEP)
3059 ttybnew.sg_flags &= ~(ECHO);
3060 ioctl(read_cmd_fd, TIOCSETN, &ttybnew);
3061 #endif
3062 curr_tmode = tmode;
3066 * Try to get the code for "t_kb" from the stty setting
3068 * Even if termcap claims a backspace key, the user's setting *should*
3069 * prevail. stty knows more about reality than termcap does, and if
3070 * somebody's usual erase key is DEL (which, for most BSD users, it will
3071 * be), they're going to get really annoyed if their erase key starts
3072 * doing forward deletes for no reason. (Eric Fischer)
3074 void
3075 get_stty()
3077 char_u buf[2];
3078 char_u *p;
3080 /* Why is NeXT excluded here (and not in os_unixx.h)? */
3081 #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
3082 /* for "new" tty systems */
3083 # ifdef HAVE_TERMIOS_H
3084 struct termios keys;
3085 # else
3086 struct termio keys;
3087 # endif
3089 # if defined(HAVE_TERMIOS_H)
3090 if (tcgetattr(read_cmd_fd, &keys) != -1)
3091 # else
3092 if (ioctl(read_cmd_fd, TCGETA, &keys) != -1)
3093 # endif
3095 buf[0] = keys.c_cc[VERASE];
3096 intr_char = keys.c_cc[VINTR];
3097 #else
3098 /* for "old" tty systems */
3099 struct sgttyb keys;
3101 if (ioctl(read_cmd_fd, TIOCGETP, &keys) != -1)
3103 buf[0] = keys.sg_erase;
3104 intr_char = keys.sg_kill;
3105 #endif
3106 buf[1] = NUL;
3107 add_termcode((char_u *)"kb", buf, FALSE);
3110 * If <BS> and <DEL> are now the same, redefine <DEL>.
3112 p = find_termcode((char_u *)"kD");
3113 if (p != NULL && p[0] == buf[0] && p[1] == buf[1])
3114 do_fixdel(NULL);
3116 #if 0
3117 } /* to keep cindent happy */
3118 #endif
3121 #endif /* VMS */
3123 #if defined(FEAT_MOUSE_TTY) || defined(PROTO)
3125 * Set mouse clicks on or off.
3127 void
3128 mch_setmouse(on)
3129 int on;
3131 static int ison = FALSE;
3132 int xterm_mouse_vers;
3134 if (on == ison) /* return quickly if nothing to do */
3135 return;
3137 xterm_mouse_vers = use_xterm_mouse();
3138 if (xterm_mouse_vers > 0)
3140 if (on) /* enable mouse events, use mouse tracking if available */
3141 out_str_nf((char_u *)
3142 (xterm_mouse_vers > 1
3143 ? IF_EB("\033[?1002h", ESC_STR "[?1002h")
3144 : IF_EB("\033[?1000h", ESC_STR "[?1000h")));
3145 else /* disable mouse events, could probably always send the same */
3146 out_str_nf((char_u *)
3147 (xterm_mouse_vers > 1
3148 ? IF_EB("\033[?1002l", ESC_STR "[?1002l")
3149 : IF_EB("\033[?1000l", ESC_STR "[?1000l")));
3150 ison = on;
3153 # ifdef FEAT_MOUSE_DEC
3154 else if (ttym_flags == TTYM_DEC)
3156 if (on) /* enable mouse events */
3157 out_str_nf((char_u *)"\033[1;2'z\033[1;3'{");
3158 else /* disable mouse events */
3159 out_str_nf((char_u *)"\033['z");
3160 ison = on;
3162 # endif
3164 # ifdef FEAT_MOUSE_GPM
3165 else
3167 if (on)
3169 if (gpm_open())
3170 ison = TRUE;
3172 else
3174 gpm_close();
3175 ison = FALSE;
3178 # endif
3180 # ifdef FEAT_MOUSE_JSB
3181 else
3183 if (on)
3185 /* D - Enable Mouse up/down messages
3186 * L - Enable Left Button Reporting
3187 * M - Enable Middle Button Reporting
3188 * R - Enable Right Button Reporting
3189 * K - Enable SHIFT and CTRL key Reporting
3190 * + - Enable Advanced messaging of mouse moves and up/down messages
3191 * Q - Quiet No Ack
3192 * # - Numeric value of mouse pointer required
3193 * 0 = Multiview 2000 cursor, used as standard
3194 * 1 = Windows Arrow
3195 * 2 = Windows I Beam
3196 * 3 = Windows Hour Glass
3197 * 4 = Windows Cross Hair
3198 * 5 = Windows UP Arrow
3200 #ifdef JSBTERM_MOUSE_NONADVANCED /* Disables full feedback of pointer movements */
3201 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK1Q\033\\",
3202 ESC_STR "[0~ZwLMRK1Q" ESC_STR "\\"));
3203 #else
3204 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK+1Q\033\\",
3205 ESC_STR "[0~ZwLMRK+1Q" ESC_STR "\\"));
3206 #endif
3207 ison = TRUE;
3209 else
3211 out_str_nf((char_u *)IF_EB("\033[0~ZwQ\033\\",
3212 ESC_STR "[0~ZwQ" ESC_STR "\\"));
3213 ison = FALSE;
3216 # endif
3217 # ifdef FEAT_MOUSE_PTERM
3218 else
3220 /* 1 = button press, 6 = release, 7 = drag, 1h...9l = right button */
3221 if (on)
3222 out_str_nf("\033[>1h\033[>6h\033[>7h\033[>1h\033[>9l");
3223 else
3224 out_str_nf("\033[>1l\033[>6l\033[>7l\033[>1l\033[>9h");
3225 ison = on;
3227 # endif
3231 * Set the mouse termcode, depending on the 'term' and 'ttymouse' options.
3233 void
3234 check_mouse_termcode()
3236 # ifdef FEAT_MOUSE_XTERM
3237 if (use_xterm_mouse()
3238 # ifdef FEAT_GUI
3239 && !gui.in_use
3240 # endif
3243 set_mouse_termcode(KS_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3244 ? IF_EB("\233M", CSI_STR "M")
3245 : IF_EB("\033[M", ESC_STR "[M")));
3246 if (*p_mouse != NUL)
3248 /* force mouse off and maybe on to send possibly new mouse
3249 * activation sequence to the xterm, with(out) drag tracing. */
3250 mch_setmouse(FALSE);
3251 setmouse();
3254 else
3255 del_mouse_termcode(KS_MOUSE);
3256 # endif
3258 # ifdef FEAT_MOUSE_GPM
3259 if (!use_xterm_mouse()
3260 # ifdef FEAT_GUI
3261 && !gui.in_use
3262 # endif
3264 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MG", ESC_STR "MG"));
3265 # endif
3267 # ifdef FEAT_MOUSE_JSB
3268 /* conflicts with xterm mouse: "\033[" and "\033[M" ??? */
3269 if (!use_xterm_mouse()
3270 # ifdef FEAT_GUI
3271 && !gui.in_use
3272 # endif
3274 set_mouse_termcode(KS_JSBTERM_MOUSE,
3275 (char_u *)IF_EB("\033[0~zw", ESC_STR "[0~zw"));
3276 else
3277 del_mouse_termcode(KS_JSBTERM_MOUSE);
3278 # endif
3280 # ifdef FEAT_MOUSE_NET
3281 /* There is no conflict, but one may type "ESC }" from Insert mode. Don't
3282 * define it in the GUI or when using an xterm. */
3283 if (!use_xterm_mouse()
3284 # ifdef FEAT_GUI
3285 && !gui.in_use
3286 # endif
3288 set_mouse_termcode(KS_NETTERM_MOUSE,
3289 (char_u *)IF_EB("\033}", ESC_STR "}"));
3290 else
3291 del_mouse_termcode(KS_NETTERM_MOUSE);
3292 # endif
3294 # ifdef FEAT_MOUSE_DEC
3295 /* conflicts with xterm mouse: "\033[" and "\033[M" */
3296 if (!use_xterm_mouse()
3297 # ifdef FEAT_GUI
3298 && !gui.in_use
3299 # endif
3301 set_mouse_termcode(KS_DEC_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3302 ? IF_EB("\233", CSI_STR) : IF_EB("\033[", ESC_STR "[")));
3303 else
3304 del_mouse_termcode(KS_DEC_MOUSE);
3305 # endif
3306 # ifdef FEAT_MOUSE_PTERM
3307 /* same as the dec mouse */
3308 if (!use_xterm_mouse()
3309 # ifdef FEAT_GUI
3310 && !gui.in_use
3311 # endif
3313 set_mouse_termcode(KS_PTERM_MOUSE,
3314 (char_u *) IF_EB("\033[", ESC_STR "["));
3315 else
3316 del_mouse_termcode(KS_PTERM_MOUSE);
3317 # endif
3319 #endif
3322 * set screen mode, always fails.
3324 /* ARGSUSED */
3326 mch_screenmode(arg)
3327 char_u *arg;
3329 EMSG(_(e_screenmode));
3330 return FAIL;
3333 #ifndef VMS
3336 * Try to get the current window size:
3337 * 1. with an ioctl(), most accurate method
3338 * 2. from the environment variables LINES and COLUMNS
3339 * 3. from the termcap
3340 * 4. keep using the old values
3341 * Return OK when size could be determined, FAIL otherwise.
3344 mch_get_shellsize()
3346 long rows = 0;
3347 long columns = 0;
3348 char_u *p;
3351 * For OS/2 use _scrsize().
3353 # ifdef __EMX__
3355 int s[2];
3357 _scrsize(s);
3358 columns = s[0];
3359 rows = s[1];
3361 # endif
3364 * 1. try using an ioctl. It is the most accurate method.
3366 * Try using TIOCGWINSZ first, some systems that have it also define
3367 * TIOCGSIZE but don't have a struct ttysize.
3369 # ifdef TIOCGWINSZ
3371 struct winsize ws;
3372 int fd = 1;
3374 /* When stdout is not a tty, use stdin for the ioctl(). */
3375 if (!isatty(fd) && isatty(read_cmd_fd))
3376 fd = read_cmd_fd;
3377 if (ioctl(fd, TIOCGWINSZ, &ws) == 0)
3379 columns = ws.ws_col;
3380 rows = ws.ws_row;
3383 # else /* TIOCGWINSZ */
3384 # ifdef TIOCGSIZE
3386 struct ttysize ts;
3387 int fd = 1;
3389 /* When stdout is not a tty, use stdin for the ioctl(). */
3390 if (!isatty(fd) && isatty(read_cmd_fd))
3391 fd = read_cmd_fd;
3392 if (ioctl(fd, TIOCGSIZE, &ts) == 0)
3394 columns = ts.ts_cols;
3395 rows = ts.ts_lines;
3398 # endif /* TIOCGSIZE */
3399 # endif /* TIOCGWINSZ */
3402 * 2. get size from environment
3403 * When being POSIX compliant ('|' flag in 'cpoptions') this overrules
3404 * the ioctl() values!
3406 if (columns == 0 || rows == 0 || vim_strchr(p_cpo, CPO_TSIZE) != NULL)
3408 if ((p = (char_u *)getenv("LINES")))
3409 rows = atoi((char *)p);
3410 if ((p = (char_u *)getenv("COLUMNS")))
3411 columns = atoi((char *)p);
3414 #ifdef HAVE_TGETENT
3416 * 3. try reading "co" and "li" entries from termcap
3418 if (columns == 0 || rows == 0)
3419 getlinecol(&columns, &rows);
3420 #endif
3423 * 4. If everything fails, use the old values
3425 if (columns <= 0 || rows <= 0)
3426 return FAIL;
3428 Rows = rows;
3429 Columns = columns;
3430 return OK;
3434 * Try to set the window size to Rows and Columns.
3436 void
3437 mch_set_shellsize()
3439 if (*T_CWS)
3442 * NOTE: if you get an error here that term_set_winsize() is
3443 * undefined, check the output of configure. It could probably not
3444 * find a ncurses, termcap or termlib library.
3446 term_set_winsize((int)Rows, (int)Columns);
3447 out_flush();
3448 screen_start(); /* don't know where cursor is now */
3452 #endif /* VMS */
3455 * Rows and/or Columns has changed.
3457 void
3458 mch_new_shellsize()
3460 /* Nothing to do. */
3463 #ifndef USE_SYSTEM
3464 static void append_ga_line __ARGS((garray_T *gap));
3467 * Append the text in "gap" below the cursor line and clear "gap".
3469 static void
3470 append_ga_line(gap)
3471 garray_T *gap;
3473 /* Remove trailing CR. */
3474 if (gap->ga_len > 0
3475 && !curbuf->b_p_bin
3476 && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR)
3477 --gap->ga_len;
3478 ga_append(gap, NUL);
3479 ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE);
3480 gap->ga_len = 0;
3482 #endif
3485 mch_call_shell(cmd, options)
3486 char_u *cmd;
3487 int options; /* SHELL_*, see vim.h */
3489 #ifdef VMS
3490 char *ifn = NULL;
3491 char *ofn = NULL;
3492 #endif
3493 int tmode = cur_tmode;
3494 #ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
3495 int x;
3496 # ifndef __EMX__
3497 char_u *newcmd; /* only needed for unix */
3498 # else
3500 * Set the preferred shell in the EMXSHELL environment variable (but
3501 * only if it is different from what is already in the environment).
3502 * Emx then takes care of whether to use "/c" or "-c" in an
3503 * intelligent way. Simply pass the whole thing to emx's system() call.
3504 * Emx also starts an interactive shell if system() is passed an empty
3505 * string.
3507 char_u *p, *old;
3509 if (((old = (char_u *)getenv("EMXSHELL")) == NULL) || STRCMP(old, p_sh))
3511 /* should check HAVE_SETENV, but I know we don't have it. */
3512 p = alloc(10 + strlen(p_sh));
3513 if (p)
3515 sprintf((char *)p, "EMXSHELL=%s", p_sh);
3516 putenv((char *)p); /* don't free the pointer! */
3519 # endif
3521 out_flush();
3523 if (options & SHELL_COOKED)
3524 settmode(TMODE_COOK); /* set to normal mode */
3526 # ifdef __EMX__
3527 if (cmd == NULL)
3528 x = system(""); /* this starts an interactive shell in emx */
3529 else
3530 x = system((char *)cmd);
3531 /* system() returns -1 when error occurs in starting shell */
3532 if (x == -1 && !emsg_silent)
3534 MSG_PUTS(_("\nCannot execute shell "));
3535 msg_outtrans(p_sh);
3536 msg_putchar('\n');
3538 # else /* not __EMX__ */
3539 if (cmd == NULL)
3540 x = system((char *)p_sh);
3541 else
3543 # ifdef VMS
3544 if (ofn = strchr((char *)cmd, '>'))
3545 *ofn++ = '\0';
3546 if (ifn = strchr((char *)cmd, '<'))
3548 char *p;
3550 *ifn++ = '\0';
3551 p = strchr(ifn,' '); /* chop off any trailing spaces */
3552 if (p)
3553 *p = '\0';
3555 if (ofn)
3556 x = vms_sys((char *)cmd, ofn, ifn);
3557 else
3558 x = system((char *)cmd);
3559 # else
3560 newcmd = lalloc(STRLEN(p_sh)
3561 + (extra_shell_arg == NULL ? 0 : STRLEN(extra_shell_arg))
3562 + STRLEN(p_shcf) + STRLEN(cmd) + 4, TRUE);
3563 if (newcmd == NULL)
3564 x = 0;
3565 else
3567 sprintf((char *)newcmd, "%s %s %s %s", p_sh,
3568 extra_shell_arg == NULL ? "" : (char *)extra_shell_arg,
3569 (char *)p_shcf,
3570 (char *)cmd);
3571 x = system((char *)newcmd);
3572 vim_free(newcmd);
3574 # endif
3576 # ifdef VMS
3577 x = vms_sys_status(x);
3578 # endif
3579 if (emsg_silent)
3581 else if (x == 127)
3582 MSG_PUTS(_("\nCannot execute shell sh\n"));
3583 # endif /* __EMX__ */
3584 else if (x && !(options & SHELL_SILENT))
3586 MSG_PUTS(_("\nshell returned "));
3587 msg_outnum((long)x);
3588 msg_putchar('\n');
3591 if (tmode == TMODE_RAW)
3592 settmode(TMODE_RAW); /* set to raw mode */
3593 # ifdef FEAT_TITLE
3594 resettitle();
3595 # endif
3596 return x;
3598 #else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
3600 # define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
3601 127, some shells use that already */
3603 char_u *newcmd = NULL;
3604 pid_t pid;
3605 pid_t wpid = 0;
3606 pid_t wait_pid = 0;
3607 # ifdef HAVE_UNION_WAIT
3608 union wait status;
3609 # else
3610 int status = -1;
3611 # endif
3612 int retval = -1;
3613 char **argv = NULL;
3614 int argc;
3615 int i;
3616 char_u *p;
3617 int inquote;
3618 int pty_master_fd = -1; /* for pty's */
3619 # ifdef FEAT_GUI
3620 int pty_slave_fd = -1;
3621 char *tty_name;
3622 # endif
3623 int fd_toshell[2]; /* for pipes */
3624 int fd_fromshell[2];
3625 int pipe_error = FALSE;
3626 # ifdef HAVE_SETENV
3627 char envbuf[50];
3628 # else
3629 static char envbuf_Rows[20];
3630 static char envbuf_Columns[20];
3631 # endif
3632 int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
3634 out_flush();
3635 if (options & SHELL_COOKED)
3636 settmode(TMODE_COOK); /* set to normal mode */
3638 newcmd = vim_strsave(p_sh);
3639 if (newcmd == NULL) /* out of memory */
3640 goto error;
3643 * Do this loop twice:
3644 * 1: find number of arguments
3645 * 2: separate them and build argv[]
3647 for (i = 0; i < 2; ++i)
3649 p = newcmd;
3650 inquote = FALSE;
3651 argc = 0;
3652 for (;;)
3654 if (i == 1)
3655 argv[argc] = (char *)p;
3656 ++argc;
3657 while (*p && (inquote || (*p != ' ' && *p != TAB)))
3659 if (*p == '"')
3660 inquote = !inquote;
3661 ++p;
3663 if (*p == NUL)
3664 break;
3665 if (i == 1)
3666 *p++ = NUL;
3667 p = skipwhite(p);
3669 if (argv == NULL)
3671 argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *)));
3672 if (argv == NULL) /* out of memory */
3673 goto error;
3676 if (cmd != NULL)
3678 if (extra_shell_arg != NULL)
3679 argv[argc++] = (char *)extra_shell_arg;
3680 argv[argc++] = (char *)p_shcf;
3681 argv[argc++] = (char *)cmd;
3683 argv[argc] = NULL;
3686 * For the GUI, when writing the output into the buffer and when reading
3687 * input from the buffer: Try using a pseudo-tty to get the stdin/stdout
3688 * of the executed command into the Vim window. Or use a pipe.
3690 if ((options & (SHELL_READ|SHELL_WRITE))
3691 # ifdef FEAT_GUI
3692 || (gui.in_use && show_shell_mess)
3693 # endif
3696 # ifdef FEAT_GUI
3698 * Try to open a master pty.
3699 * If this works, open the slave pty.
3700 * If the slave can't be opened, close the master pty.
3702 if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
3704 pty_master_fd = OpenPTY(&tty_name); /* open pty */
3705 if (pty_master_fd >= 0 && ((pty_slave_fd =
3706 open(tty_name, O_RDWR | O_EXTRA, 0)) < 0))
3708 close(pty_master_fd);
3709 pty_master_fd = -1;
3713 * If not opening a pty or it didn't work, try using pipes.
3715 if (pty_master_fd < 0)
3716 # endif
3718 pipe_error = (pipe(fd_toshell) < 0);
3719 if (!pipe_error) /* pipe create OK */
3721 pipe_error = (pipe(fd_fromshell) < 0);
3722 if (pipe_error) /* pipe create failed */
3724 close(fd_toshell[0]);
3725 close(fd_toshell[1]);
3728 if (pipe_error)
3730 MSG_PUTS(_("\nCannot create pipes\n"));
3731 out_flush();
3736 if (!pipe_error) /* pty or pipe opened or not used */
3738 # ifdef __BEOS__
3739 beos_cleanup_read_thread();
3740 # endif
3742 if ((pid = fork()) == -1) /* maybe we should use vfork() */
3744 MSG_PUTS(_("\nCannot fork\n"));
3745 if ((options & (SHELL_READ|SHELL_WRITE))
3746 # ifdef FEAT_GUI
3747 || (gui.in_use && show_shell_mess)
3748 # endif
3751 # ifdef FEAT_GUI
3752 if (pty_master_fd >= 0) /* close the pseudo tty */
3754 close(pty_master_fd);
3755 close(pty_slave_fd);
3757 else /* close the pipes */
3758 # endif
3760 close(fd_toshell[0]);
3761 close(fd_toshell[1]);
3762 close(fd_fromshell[0]);
3763 close(fd_fromshell[1]);
3767 else if (pid == 0) /* child */
3769 reset_signals(); /* handle signals normally */
3771 if (!show_shell_mess || (options & SHELL_EXPAND))
3773 int fd;
3776 * Don't want to show any message from the shell. Can't just
3777 * close stdout and stderr though, because some systems will
3778 * break if you try to write to them after that, so we must
3779 * use dup() to replace them with something else -- webb
3780 * Connect stdin to /dev/null too, so ":n `cat`" doesn't hang,
3781 * waiting for input.
3783 fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
3784 fclose(stdin);
3785 fclose(stdout);
3786 fclose(stderr);
3789 * If any of these open()'s and dup()'s fail, we just continue
3790 * anyway. It's not fatal, and on most systems it will make
3791 * no difference at all. On a few it will cause the execvp()
3792 * to exit with a non-zero status even when the completion
3793 * could be done, which is nothing too serious. If the open()
3794 * or dup() failed we'd just do the same thing ourselves
3795 * anyway -- webb
3797 if (fd >= 0)
3799 dup(fd); /* To replace stdin (file descriptor 0) */
3800 dup(fd); /* To replace stdout (file descriptor 1) */
3801 dup(fd); /* To replace stderr (file descriptor 2) */
3803 /* Don't need this now that we've duplicated it */
3804 close(fd);
3807 else if ((options & (SHELL_READ|SHELL_WRITE))
3808 # ifdef FEAT_GUI
3809 || gui.in_use
3810 # endif
3814 # ifdef HAVE_SETSID
3815 /* Create our own process group, so that the child and all its
3816 * children can be kill()ed. Don't do this when using pipes,
3817 * because stdin is not a tty, we would loose /dev/tty. */
3818 if (p_stmp)
3819 (void)setsid();
3820 # endif
3821 # ifdef FEAT_GUI
3822 if (pty_slave_fd >= 0)
3824 /* push stream discipline modules */
3825 if (options & SHELL_COOKED)
3826 SetupSlavePTY(pty_slave_fd);
3827 # ifdef TIOCSCTTY
3828 /* Try to become controlling tty (probably doesn't work,
3829 * unless run by root) */
3830 ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
3831 # endif
3833 # endif
3834 /* Simulate to have a dumb terminal (for now) */
3835 # ifdef HAVE_SETENV
3836 setenv("TERM", "dumb", 1);
3837 sprintf((char *)envbuf, "%ld", Rows);
3838 setenv("ROWS", (char *)envbuf, 1);
3839 sprintf((char *)envbuf, "%ld", Rows);
3840 setenv("LINES", (char *)envbuf, 1);
3841 sprintf((char *)envbuf, "%ld", Columns);
3842 setenv("COLUMNS", (char *)envbuf, 1);
3843 # else
3845 * Putenv does not copy the string, it has to remain valid.
3846 * Use a static array to avoid loosing allocated memory.
3848 putenv("TERM=dumb");
3849 sprintf(envbuf_Rows, "ROWS=%ld", Rows);
3850 putenv(envbuf_Rows);
3851 sprintf(envbuf_Rows, "LINES=%ld", Rows);
3852 putenv(envbuf_Rows);
3853 sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
3854 putenv(envbuf_Columns);
3855 # endif
3858 * stderr is only redirected when using the GUI, so that a
3859 * program like gpg can still access the terminal to get a
3860 * passphrase using stderr.
3862 # ifdef FEAT_GUI
3863 if (pty_master_fd >= 0)
3865 close(pty_master_fd); /* close master side of pty */
3867 /* set up stdin/stdout/stderr for the child */
3868 close(0);
3869 dup(pty_slave_fd);
3870 close(1);
3871 dup(pty_slave_fd);
3872 if (gui.in_use)
3874 close(2);
3875 dup(pty_slave_fd);
3878 close(pty_slave_fd); /* has been dupped, close it now */
3880 else
3881 # endif
3883 /* set up stdin for the child */
3884 close(fd_toshell[1]);
3885 close(0);
3886 dup(fd_toshell[0]);
3887 close(fd_toshell[0]);
3889 /* set up stdout for the child */
3890 close(fd_fromshell[0]);
3891 close(1);
3892 dup(fd_fromshell[1]);
3893 close(fd_fromshell[1]);
3895 # ifdef FEAT_GUI
3896 if (gui.in_use)
3898 /* set up stderr for the child */
3899 close(2);
3900 dup(1);
3902 # endif
3907 * There is no type cast for the argv, because the type may be
3908 * different on different machines. This may cause a warning
3909 * message with strict compilers, don't worry about it.
3910 * Call _exit() instead of exit() to avoid closing the connection
3911 * to the X server (esp. with GTK, which uses atexit()).
3913 execvp(argv[0], argv);
3914 _exit(EXEC_FAILED); /* exec failed, return failure code */
3916 else /* parent */
3919 * While child is running, ignore terminating signals.
3920 * Do catch CTRL-C, so that "got_int" is set.
3922 catch_signals(SIG_IGN, SIG_ERR);
3923 catch_int_signal();
3926 * For the GUI we redirect stdin, stdout and stderr to our window.
3927 * This is also used to pipe stdin/stdout to/from the external
3928 * command.
3930 if ((options & (SHELL_READ|SHELL_WRITE))
3931 # ifdef FEAT_GUI
3932 || (gui.in_use && show_shell_mess)
3933 # endif
3936 # define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
3937 char_u buffer[BUFLEN + 1];
3938 # ifdef FEAT_MBYTE
3939 int buffer_off = 0; /* valid bytes in buffer[] */
3940 # endif
3941 char_u ta_buf[BUFLEN + 1]; /* TypeAHead */
3942 int ta_len = 0; /* valid bytes in ta_buf[] */
3943 int len;
3944 int p_more_save;
3945 int old_State;
3946 int c;
3947 int toshell_fd;
3948 int fromshell_fd;
3949 garray_T ga;
3950 int noread_cnt;
3952 # ifdef FEAT_GUI
3953 if (pty_master_fd >= 0)
3955 close(pty_slave_fd); /* close slave side of pty */
3956 fromshell_fd = pty_master_fd;
3957 toshell_fd = dup(pty_master_fd);
3959 else
3960 # endif
3962 close(fd_toshell[0]);
3963 close(fd_fromshell[1]);
3964 toshell_fd = fd_toshell[1];
3965 fromshell_fd = fd_fromshell[0];
3969 * Write to the child if there are typed characters.
3970 * Read from the child if there are characters available.
3971 * Repeat the reading a few times if more characters are
3972 * available. Need to check for typed keys now and then, but
3973 * not too often (delays when no chars are available).
3974 * This loop is quit if no characters can be read from the pty
3975 * (WaitForChar detected special condition), or there are no
3976 * characters available and the child has exited.
3977 * Only check if the child has exited when there is no more
3978 * output. The child may exit before all the output has
3979 * been printed.
3981 * Currently this busy loops!
3982 * This can probably dead-lock when the write blocks!
3984 p_more_save = p_more;
3985 p_more = FALSE;
3986 old_State = State;
3987 State = EXTERNCMD; /* don't redraw at window resize */
3989 if ((options & SHELL_WRITE) && toshell_fd >= 0)
3991 /* Fork a process that will write the lines to the
3992 * external program. */
3993 if ((wpid = fork()) == -1)
3995 MSG_PUTS(_("\nCannot fork\n"));
3997 else if (wpid == 0)
3999 linenr_T lnum = curbuf->b_op_start.lnum;
4000 int written = 0;
4001 char_u *lp = ml_get(lnum);
4002 char_u *s;
4003 size_t l;
4005 /* child */
4006 close(fromshell_fd);
4007 for (;;)
4009 l = STRLEN(lp + written);
4010 if (l == 0)
4011 len = 0;
4012 else if (lp[written] == NL)
4013 /* NL -> NUL translation */
4014 len = write(toshell_fd, "", (size_t)1);
4015 else
4017 s = vim_strchr(lp + written, NL);
4018 len = write(toshell_fd, (char *)lp + written,
4019 s == NULL ? l : s - (lp + written));
4021 if (len == l)
4023 /* Finished a line, add a NL, unless this line
4024 * should not have one. */
4025 if (lnum != curbuf->b_op_end.lnum
4026 || !curbuf->b_p_bin
4027 || (lnum != write_no_eol_lnum
4028 && (lnum !=
4029 curbuf->b_ml.ml_line_count
4030 || curbuf->b_p_eol)))
4031 write(toshell_fd, "\n", (size_t)1);
4032 ++lnum;
4033 if (lnum > curbuf->b_op_end.lnum)
4035 /* finished all the lines, close pipe */
4036 close(toshell_fd);
4037 toshell_fd = -1;
4038 break;
4040 lp = ml_get(lnum);
4041 written = 0;
4043 else if (len > 0)
4044 written += len;
4046 _exit(0);
4048 else
4050 close(toshell_fd);
4051 toshell_fd = -1;
4055 if (options & SHELL_READ)
4056 ga_init2(&ga, 1, BUFLEN);
4058 noread_cnt = 0;
4060 for (;;)
4063 * Check if keys have been typed, write them to the child
4064 * if there are any.
4065 * Don't do this if we are expanding wild cards (would eat
4066 * typeahead).
4067 * Don't do this when filtering and terminal is in cooked
4068 * mode, the shell command will handle the I/O. Avoids
4069 * that a typed password is echoed for ssh or gpg command.
4070 * Don't get characters when the child has already
4071 * finished (wait_pid == 0).
4072 * Don't get extra characters when we already have one.
4073 * Don't read characters unless we didn't get output for a
4074 * while, avoids that ":r !ls" eats typeahead.
4076 len = 0;
4077 if (!(options & SHELL_EXPAND)
4078 && ((options &
4079 (SHELL_READ|SHELL_WRITE|SHELL_COOKED))
4080 != (SHELL_READ|SHELL_WRITE|SHELL_COOKED)
4081 #ifdef FEAT_GUI
4082 || gui.in_use
4083 #endif
4085 && wait_pid == 0
4086 && (ta_len > 0
4087 || (noread_cnt > 4
4088 && (len = ui_inchar(ta_buf,
4089 BUFLEN, 10L, 0)) > 0)))
4092 * For pipes:
4093 * Check for CTRL-C: send interrupt signal to child.
4094 * Check for CTRL-D: EOF, close pipe to child.
4096 if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
4098 # ifdef SIGINT
4100 * Send SIGINT to the child's group or all
4101 * processes in our group.
4103 if (ta_buf[ta_len] == Ctrl_C
4104 || ta_buf[ta_len] == intr_char)
4106 # ifdef HAVE_SETSID
4107 kill(-pid, SIGINT);
4108 # else
4109 kill(0, SIGINT);
4110 # endif
4111 if (wpid > 0)
4112 kill(wpid, SIGINT);
4114 # endif
4115 if (pty_master_fd < 0 && toshell_fd >= 0
4116 && ta_buf[ta_len] == Ctrl_D)
4118 close(toshell_fd);
4119 toshell_fd = -1;
4123 /* replace K_BS by <BS> and K_DEL by <DEL> */
4124 for (i = ta_len; i < ta_len + len; ++i)
4126 if (ta_buf[i] == CSI && len - i > 2)
4128 c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]);
4129 if (c == K_DEL || c == K_KDEL || c == K_BS)
4131 mch_memmove(ta_buf + i + 1, ta_buf + i + 3,
4132 (size_t)(len - i - 2));
4133 if (c == K_DEL || c == K_KDEL)
4134 ta_buf[i] = DEL;
4135 else
4136 ta_buf[i] = Ctrl_H;
4137 len -= 2;
4140 else if (ta_buf[i] == '\r')
4141 ta_buf[i] = '\n';
4142 # ifdef FEAT_MBYTE
4143 if (has_mbyte)
4144 i += (*mb_ptr2len)(ta_buf + i) - 1;
4145 # endif
4149 * For pipes: echo the typed characters.
4150 * For a pty this does not seem to work.
4152 if (pty_master_fd < 0)
4154 for (i = ta_len; i < ta_len + len; ++i)
4156 if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
4157 msg_putchar(ta_buf[i]);
4158 # ifdef FEAT_MBYTE
4159 else if (has_mbyte)
4161 int l = (*mb_ptr2len)(ta_buf + i);
4163 msg_outtrans_len(ta_buf + i, l);
4164 i += l - 1;
4166 # endif
4167 else
4168 msg_outtrans_len(ta_buf + i, 1);
4170 windgoto(msg_row, msg_col);
4171 out_flush();
4174 ta_len += len;
4177 * Write the characters to the child, unless EOF has
4178 * been typed for pipes. Write one character at a
4179 * time, to avoid loosing too much typeahead.
4180 * When writing buffer lines, drop the typed
4181 * characters (only check for CTRL-C).
4183 if (options & SHELL_WRITE)
4184 ta_len = 0;
4185 else if (toshell_fd >= 0)
4187 len = write(toshell_fd, (char *)ta_buf, (size_t)1);
4188 if (len > 0)
4190 ta_len -= len;
4191 mch_memmove(ta_buf, ta_buf + len, ta_len);
4192 noread_cnt = 0;
4197 if (got_int)
4199 /* CTRL-C sends a signal to the child, we ignore it
4200 * ourselves */
4201 # ifdef HAVE_SETSID
4202 kill(-pid, SIGINT);
4203 # else
4204 kill(0, SIGINT);
4205 # endif
4206 if (wpid > 0)
4207 kill(wpid, SIGINT);
4208 got_int = FALSE;
4212 * Check if the child has any characters to be printed.
4213 * Read them and write them to our window. Repeat this as
4214 * long as there is something to do, avoid the 10ms wait
4215 * for mch_inchar(), or sending typeahead characters to
4216 * the external process.
4217 * TODO: This should handle escape sequences, compatible
4218 * to some terminal (vt52?).
4220 ++noread_cnt;
4221 while (RealWaitForChar(fromshell_fd, 10L, NULL))
4223 len = read(fromshell_fd, (char *)buffer
4224 # ifdef FEAT_MBYTE
4225 + buffer_off, (size_t)(BUFLEN - buffer_off)
4226 # else
4227 , (size_t)BUFLEN
4228 # endif
4230 if (len <= 0) /* end of file or error */
4231 goto finished;
4233 noread_cnt = 0;
4234 if (options & SHELL_READ)
4236 /* Do NUL -> NL translation, append NL separated
4237 * lines to the current buffer. */
4238 for (i = 0; i < len; ++i)
4240 if (buffer[i] == NL)
4241 append_ga_line(&ga);
4242 else if (buffer[i] == NUL)
4243 ga_append(&ga, NL);
4244 else
4245 ga_append(&ga, buffer[i]);
4248 # ifdef FEAT_MBYTE
4249 else if (has_mbyte)
4251 int l;
4253 len += buffer_off;
4254 buffer[len] = NUL;
4256 /* Check if the last character in buffer[] is
4257 * incomplete, keep these bytes for the next
4258 * round. */
4259 for (p = buffer; p < buffer + len; p += l)
4261 l = mb_cptr2len(p);
4262 if (l == 0)
4263 l = 1; /* NUL byte? */
4264 else if (MB_BYTE2LEN(*p) != l)
4265 break;
4267 if (p == buffer) /* no complete character */
4269 /* avoid getting stuck at an illegal byte */
4270 if (len >= 12)
4271 ++p;
4272 else
4274 buffer_off = len;
4275 continue;
4278 c = *p;
4279 *p = NUL;
4280 msg_puts(buffer);
4281 if (p < buffer + len)
4283 *p = c;
4284 buffer_off = (buffer + len) - p;
4285 mch_memmove(buffer, p, buffer_off);
4286 continue;
4288 buffer_off = 0;
4290 # endif /* FEAT_MBYTE */
4291 else
4293 buffer[len] = NUL;
4294 msg_puts(buffer);
4297 windgoto(msg_row, msg_col);
4298 cursor_on();
4299 out_flush();
4300 if (got_int)
4301 break;
4304 /* If we already detected the child has finished break the
4305 * loop now. */
4306 if (wait_pid == pid)
4307 break;
4310 * Check if the child still exists, before checking for
4311 * typed characters (otherwise we would loose typeahead).
4313 # ifdef __NeXT__
4314 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *) 0);
4315 # else
4316 wait_pid = waitpid(pid, &status, WNOHANG);
4317 # endif
4318 if ((wait_pid == (pid_t)-1 && errno == ECHILD)
4319 || (wait_pid == pid && WIFEXITED(status)))
4321 /* Don't break the loop yet, try reading more
4322 * characters from "fromshell_fd" first. When using
4323 * pipes there might still be something to read and
4324 * then we'll break the loop at the "break" above. */
4325 wait_pid = pid;
4327 else
4328 wait_pid = 0;
4330 finished:
4331 p_more = p_more_save;
4332 if (options & SHELL_READ)
4334 if (ga.ga_len > 0)
4336 append_ga_line(&ga);
4337 /* remember that the NL was missing */
4338 write_no_eol_lnum = curwin->w_cursor.lnum;
4340 else
4341 write_no_eol_lnum = 0;
4342 ga_clear(&ga);
4346 * Give all typeahead that wasn't used back to ui_inchar().
4348 if (ta_len)
4349 ui_inchar_undo(ta_buf, ta_len);
4350 State = old_State;
4351 if (toshell_fd >= 0)
4352 close(toshell_fd);
4353 close(fromshell_fd);
4357 * Wait until our child has exited.
4358 * Ignore wait() returning pids of other children and returning
4359 * because of some signal like SIGWINCH.
4360 * Don't wait if wait_pid was already set above, indicating the
4361 * child already exited.
4363 while (wait_pid != pid)
4365 # ifdef _THREAD_SAFE
4366 /* Ugly hack: when compiled with Python threads are probably
4367 * used, in which case wait() sometimes hangs for no obvious
4368 * reason. Use waitpid() instead and loop (like the GUI). */
4369 # ifdef __NeXT__
4370 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0);
4371 # else
4372 wait_pid = waitpid(pid, &status, WNOHANG);
4373 # endif
4374 if (wait_pid == 0)
4376 /* Wait for 1/100 sec before trying again. */
4377 mch_delay(10L, TRUE);
4378 continue;
4380 # else
4381 wait_pid = wait(&status);
4382 # endif
4383 if (wait_pid <= 0
4384 # ifdef ECHILD
4385 && errno == ECHILD
4386 # endif
4388 break;
4391 /* Make sure the child that writes to the external program is
4392 * dead. */
4393 if (wpid > 0)
4394 kill(wpid, SIGKILL);
4397 * Set to raw mode right now, otherwise a CTRL-C after
4398 * catch_signals() will kill Vim.
4400 if (tmode == TMODE_RAW)
4401 settmode(TMODE_RAW);
4402 did_settmode = TRUE;
4403 set_signals();
4405 if (WIFEXITED(status))
4407 /* LINTED avoid "bitwise operation on signed value" */
4408 retval = WEXITSTATUS(status);
4409 if (retval && !emsg_silent)
4411 if (retval == EXEC_FAILED)
4413 MSG_PUTS(_("\nCannot execute shell "));
4414 msg_outtrans(p_sh);
4415 msg_putchar('\n');
4417 else if (!(options & SHELL_SILENT))
4419 MSG_PUTS(_("\nshell returned "));
4420 msg_outnum((long)retval);
4421 msg_putchar('\n');
4425 else
4426 MSG_PUTS(_("\nCommand terminated\n"));
4429 vim_free(argv);
4431 error:
4432 if (!did_settmode)
4433 if (tmode == TMODE_RAW)
4434 settmode(TMODE_RAW); /* set to raw mode */
4435 # ifdef FEAT_TITLE
4436 resettitle();
4437 # endif
4438 vim_free(newcmd);
4440 return retval;
4442 #endif /* USE_SYSTEM */
4446 * Check for CTRL-C typed by reading all available characters.
4447 * In cooked mode we should get SIGINT, no need to check.
4449 void
4450 mch_breakcheck()
4452 if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL))
4453 fill_input_buf(FALSE);
4457 * Wait "msec" msec until a character is available from the keyboard or from
4458 * inbuf[]. msec == -1 will block forever.
4459 * When a GUI is being used, this will never get called -- webb
4461 static int
4462 WaitForChar(msec)
4463 long msec;
4465 #ifdef FEAT_MOUSE_GPM
4466 int gpm_process_wanted;
4467 #endif
4468 #ifdef FEAT_XCLIPBOARD
4469 int rest;
4470 #endif
4471 int avail;
4473 if (input_available()) /* something in inbuf[] */
4474 return 1;
4476 #if defined(FEAT_MOUSE_DEC)
4477 /* May need to query the mouse position. */
4478 if (WantQueryMouse)
4480 WantQueryMouse = FALSE;
4481 mch_write((char_u *)IF_EB("\033[1'|", ESC_STR "[1'|"), 5);
4483 #endif
4486 * For FEAT_MOUSE_GPM and FEAT_XCLIPBOARD we loop here to process mouse
4487 * events. This is a bit complicated, because they might both be defined.
4489 #if defined(FEAT_MOUSE_GPM) || defined(FEAT_XCLIPBOARD)
4490 # ifdef FEAT_XCLIPBOARD
4491 rest = 0;
4492 if (do_xterm_trace())
4493 rest = msec;
4494 # endif
4497 # ifdef FEAT_XCLIPBOARD
4498 if (rest != 0)
4500 msec = XT_TRACE_DELAY;
4501 if (rest >= 0 && rest < XT_TRACE_DELAY)
4502 msec = rest;
4503 if (rest >= 0)
4504 rest -= msec;
4506 # endif
4507 # ifdef FEAT_MOUSE_GPM
4508 gpm_process_wanted = 0;
4509 avail = RealWaitForChar(read_cmd_fd, msec, &gpm_process_wanted);
4510 # else
4511 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4512 # endif
4513 if (!avail)
4515 if (input_available())
4516 return 1;
4517 # ifdef FEAT_XCLIPBOARD
4518 if (rest == 0 || !do_xterm_trace())
4519 # endif
4520 break;
4523 while (FALSE
4524 # ifdef FEAT_MOUSE_GPM
4525 || (gpm_process_wanted && mch_gpm_process() == 0)
4526 # endif
4527 # ifdef FEAT_XCLIPBOARD
4528 || (!avail && rest != 0)
4529 # endif
4532 #else
4533 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4534 #endif
4535 return avail;
4539 * Wait "msec" msec until a character is available from file descriptor "fd".
4540 * Time == -1 will block forever.
4541 * When a GUI is being used, this will not be used for input -- webb
4542 * Returns also, when a request from Sniff is waiting -- toni.
4543 * Or when a Linux GPM mouse event is waiting.
4545 /* ARGSUSED */
4546 #if defined(__BEOS__)
4548 #else
4549 static int
4550 #endif
4551 RealWaitForChar(fd, msec, check_for_gpm)
4552 int fd;
4553 long msec;
4554 int *check_for_gpm;
4556 int ret;
4557 #if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4558 static int busy = FALSE;
4560 /* May retry getting characters after an event was handled. */
4561 # define MAY_LOOP
4563 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4564 /* Remember at what time we started, so that we know how much longer we
4565 * should wait after being interrupted. */
4566 # define USE_START_TV
4567 struct timeval start_tv;
4569 if (msec > 0 && (
4570 # ifdef FEAT_XCLIPBOARD
4571 xterm_Shell != (Widget)0
4572 # if defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4574 # endif
4575 # endif
4576 # ifdef USE_XSMP
4577 xsmp_icefd != -1
4578 # ifdef FEAT_MZSCHEME
4580 # endif
4581 # endif
4582 # ifdef FEAT_MZSCHEME
4583 (mzthreads_allowed() && p_mzq > 0)
4584 # endif
4586 gettimeofday(&start_tv, NULL);
4587 # endif
4589 /* Handle being called recursively. This may happen for the session
4590 * manager stuff, it may save the file, which does a breakcheck. */
4591 if (busy)
4592 return 0;
4593 #endif
4595 #ifdef MAY_LOOP
4596 for (;;)
4597 #endif
4599 #ifdef MAY_LOOP
4600 int finished = TRUE; /* default is to 'loop' just once */
4601 # ifdef FEAT_MZSCHEME
4602 int mzquantum_used = FALSE;
4603 # endif
4604 #endif
4605 #ifndef HAVE_SELECT
4606 struct pollfd fds[5];
4607 int nfd;
4608 # ifdef FEAT_XCLIPBOARD
4609 int xterm_idx = -1;
4610 # endif
4611 # ifdef FEAT_MOUSE_GPM
4612 int gpm_idx = -1;
4613 # endif
4614 # ifdef USE_XSMP
4615 int xsmp_idx = -1;
4616 # endif
4617 int towait = (int)msec;
4619 # ifdef FEAT_MZSCHEME
4620 mzvim_check_threads();
4621 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4623 towait = (int)p_mzq; /* don't wait longer than 'mzquantum' */
4624 mzquantum_used = TRUE;
4626 # endif
4627 fds[0].fd = fd;
4628 fds[0].events = POLLIN;
4629 nfd = 1;
4631 # ifdef FEAT_SNIFF
4632 # define SNIFF_IDX 1
4633 if (want_sniff_request)
4635 fds[SNIFF_IDX].fd = fd_from_sniff;
4636 fds[SNIFF_IDX].events = POLLIN;
4637 nfd++;
4639 # endif
4640 # ifdef FEAT_XCLIPBOARD
4641 if (xterm_Shell != (Widget)0)
4643 xterm_idx = nfd;
4644 fds[nfd].fd = ConnectionNumber(xterm_dpy);
4645 fds[nfd].events = POLLIN;
4646 nfd++;
4648 # endif
4649 # ifdef FEAT_MOUSE_GPM
4650 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4652 gpm_idx = nfd;
4653 fds[nfd].fd = gpm_fd;
4654 fds[nfd].events = POLLIN;
4655 nfd++;
4657 # endif
4658 # ifdef USE_XSMP
4659 if (xsmp_icefd != -1)
4661 xsmp_idx = nfd;
4662 fds[nfd].fd = xsmp_icefd;
4663 fds[nfd].events = POLLIN;
4664 nfd++;
4666 # endif
4668 ret = poll(fds, nfd, towait);
4669 # ifdef FEAT_MZSCHEME
4670 if (ret == 0 && mzquantum_used)
4671 /* MzThreads scheduling is required and timeout occurred */
4672 finished = FALSE;
4673 # endif
4675 # ifdef FEAT_SNIFF
4676 if (ret < 0)
4677 sniff_disconnect(1);
4678 else if (want_sniff_request)
4680 if (fds[SNIFF_IDX].revents & POLLHUP)
4681 sniff_disconnect(1);
4682 if (fds[SNIFF_IDX].revents & POLLIN)
4683 sniff_request_waiting = 1;
4685 # endif
4686 # ifdef FEAT_XCLIPBOARD
4687 if (xterm_Shell != (Widget)0 && (fds[xterm_idx].revents & POLLIN))
4689 xterm_update(); /* Maybe we should hand out clipboard */
4690 if (--ret == 0 && !input_available())
4691 /* Try again */
4692 finished = FALSE;
4694 # endif
4695 # ifdef FEAT_MOUSE_GPM
4696 if (gpm_idx >= 0 && (fds[gpm_idx].revents & POLLIN))
4698 *check_for_gpm = 1;
4700 # endif
4701 # ifdef USE_XSMP
4702 if (xsmp_idx >= 0 && (fds[xsmp_idx].revents & (POLLIN | POLLHUP)))
4704 if (fds[xsmp_idx].revents & POLLIN)
4706 busy = TRUE;
4707 xsmp_handle_requests();
4708 busy = FALSE;
4710 else if (fds[xsmp_idx].revents & POLLHUP)
4712 if (p_verbose > 0)
4713 verb_msg((char_u *)_("XSMP lost ICE connection"));
4714 xsmp_close();
4716 if (--ret == 0)
4717 finished = FALSE; /* Try again */
4719 # endif
4722 #else /* HAVE_SELECT */
4724 struct timeval tv;
4725 struct timeval *tvp;
4726 fd_set rfds, efds;
4727 int maxfd;
4728 long towait = msec;
4730 # ifdef FEAT_MZSCHEME
4731 mzvim_check_threads();
4732 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4734 towait = p_mzq; /* don't wait longer than 'mzquantum' */
4735 mzquantum_used = TRUE;
4737 # endif
4738 # ifdef __EMX__
4739 /* don't check for incoming chars if not in raw mode, because select()
4740 * always returns TRUE then (in some version of emx.dll) */
4741 if (curr_tmode != TMODE_RAW)
4742 return 0;
4743 # endif
4745 if (towait >= 0)
4747 tv.tv_sec = towait / 1000;
4748 tv.tv_usec = (towait % 1000) * (1000000/1000);
4749 tvp = &tv;
4751 else
4752 tvp = NULL;
4755 * Select on ready for reading and exceptional condition (end of file).
4757 FD_ZERO(&rfds); /* calls bzero() on a sun */
4758 FD_ZERO(&efds);
4759 FD_SET(fd, &rfds);
4760 # if !defined(__QNX__) && !defined(__CYGWIN32__)
4761 /* For QNX select() always returns 1 if this is set. Why? */
4762 FD_SET(fd, &efds);
4763 # endif
4764 maxfd = fd;
4766 # ifdef FEAT_SNIFF
4767 if (want_sniff_request)
4769 FD_SET(fd_from_sniff, &rfds);
4770 FD_SET(fd_from_sniff, &efds);
4771 if (maxfd < fd_from_sniff)
4772 maxfd = fd_from_sniff;
4774 # endif
4775 # ifdef FEAT_XCLIPBOARD
4776 if (xterm_Shell != (Widget)0)
4778 FD_SET(ConnectionNumber(xterm_dpy), &rfds);
4779 if (maxfd < ConnectionNumber(xterm_dpy))
4780 maxfd = ConnectionNumber(xterm_dpy);
4782 # endif
4783 # ifdef FEAT_MOUSE_GPM
4784 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4786 FD_SET(gpm_fd, &rfds);
4787 FD_SET(gpm_fd, &efds);
4788 if (maxfd < gpm_fd)
4789 maxfd = gpm_fd;
4791 # endif
4792 # ifdef USE_XSMP
4793 if (xsmp_icefd != -1)
4795 FD_SET(xsmp_icefd, &rfds);
4796 FD_SET(xsmp_icefd, &efds);
4797 if (maxfd < xsmp_icefd)
4798 maxfd = xsmp_icefd;
4800 # endif
4802 # ifdef OLD_VMS
4803 /* Old VMS as v6.2 and older have broken select(). It waits more than
4804 * required. Should not be used */
4805 ret = 0;
4806 # else
4807 ret = select(maxfd + 1, &rfds, NULL, &efds, tvp);
4808 # endif
4809 # ifdef __TANDEM
4810 if (ret == -1 && errno == ENOTSUP)
4812 FD_ZERO(&rfds);
4813 FD_ZERO(&efds);
4814 ret = 0;
4816 #endif
4817 # ifdef FEAT_MZSCHEME
4818 if (ret == 0 && mzquantum_used)
4819 /* loop if MzThreads must be scheduled and timeout occurred */
4820 finished = FALSE;
4821 # endif
4823 # ifdef FEAT_SNIFF
4824 if (ret < 0 )
4825 sniff_disconnect(1);
4826 else if (ret > 0 && want_sniff_request)
4828 if (FD_ISSET(fd_from_sniff, &efds))
4829 sniff_disconnect(1);
4830 if (FD_ISSET(fd_from_sniff, &rfds))
4831 sniff_request_waiting = 1;
4833 # endif
4834 # ifdef FEAT_XCLIPBOARD
4835 if (ret > 0 && xterm_Shell != (Widget)0
4836 && FD_ISSET(ConnectionNumber(xterm_dpy), &rfds))
4838 xterm_update(); /* Maybe we should hand out clipboard */
4839 /* continue looping when we only got the X event and the input
4840 * buffer is empty */
4841 if (--ret == 0 && !input_available())
4843 /* Try again */
4844 finished = FALSE;
4847 # endif
4848 # ifdef FEAT_MOUSE_GPM
4849 if (ret > 0 && gpm_flag && check_for_gpm != NULL && gpm_fd >= 0)
4851 if (FD_ISSET(gpm_fd, &efds))
4852 gpm_close();
4853 else if (FD_ISSET(gpm_fd, &rfds))
4854 *check_for_gpm = 1;
4856 # endif
4857 # ifdef USE_XSMP
4858 if (ret > 0 && xsmp_icefd != -1)
4860 if (FD_ISSET(xsmp_icefd, &efds))
4862 if (p_verbose > 0)
4863 verb_msg((char_u *)_("XSMP lost ICE connection"));
4864 xsmp_close();
4865 if (--ret == 0)
4866 finished = FALSE; /* keep going if event was only one */
4868 else if (FD_ISSET(xsmp_icefd, &rfds))
4870 busy = TRUE;
4871 xsmp_handle_requests();
4872 busy = FALSE;
4873 if (--ret == 0)
4874 finished = FALSE; /* keep going if event was only one */
4877 # endif
4879 #endif /* HAVE_SELECT */
4881 #ifdef MAY_LOOP
4882 if (finished || msec == 0)
4883 break;
4885 /* We're going to loop around again, find out for how long */
4886 if (msec > 0)
4888 # ifdef USE_START_TV
4889 struct timeval mtv;
4891 /* Compute remaining wait time. */
4892 gettimeofday(&mtv, NULL);
4893 msec -= (mtv.tv_sec - start_tv.tv_sec) * 1000L
4894 + (mtv.tv_usec - start_tv.tv_usec) / 1000L;
4895 # else
4896 /* Guess we got interrupted halfway. */
4897 msec = msec / 2;
4898 # endif
4899 if (msec <= 0)
4900 break; /* waited long enough */
4902 #endif
4905 return (ret > 0);
4908 #ifndef VMS
4910 #ifndef NO_EXPANDPATH
4912 * Expand a path into all matching files and/or directories. Handles "*",
4913 * "?", "[a-z]", "**", etc.
4914 * "path" has backslashes before chars that are not to be expanded.
4915 * Returns the number of matches found.
4918 mch_expandpath(gap, path, flags)
4919 garray_T *gap;
4920 char_u *path;
4921 int flags; /* EW_* flags */
4923 return unix_expandpath(gap, path, 0, flags, FALSE);
4925 #endif
4928 * mch_expand_wildcards() - this code does wild-card pattern matching using
4929 * the shell
4931 * return OK for success, FAIL for error (you may lose some memory) and put
4932 * an error message in *file.
4934 * num_pat is number of input patterns
4935 * pat is array of pointers to input patterns
4936 * num_file is pointer to number of matched file names
4937 * file is pointer to array of pointers to matched file names
4940 #ifndef SEEK_SET
4941 # define SEEK_SET 0
4942 #endif
4943 #ifndef SEEK_END
4944 # define SEEK_END 2
4945 #endif
4947 #define SHELL_SPECIAL (char_u *)"\t \"&'$;<>()\\|"
4949 /* ARGSUSED */
4951 mch_expand_wildcards(num_pat, pat, num_file, file, flags)
4952 int num_pat;
4953 char_u **pat;
4954 int *num_file;
4955 char_u ***file;
4956 int flags; /* EW_* flags */
4958 int i;
4959 size_t len;
4960 char_u *p;
4961 int dir;
4962 #ifdef __EMX__
4964 * This is the OS/2 implementation.
4966 # define EXPL_ALLOC_INC 16
4967 char_u **expl_files;
4968 size_t files_alloced, files_free;
4969 char_u *buf;
4970 int has_wildcard;
4972 *num_file = 0; /* default: no files found */
4973 files_alloced = EXPL_ALLOC_INC; /* how much space is allocated */
4974 files_free = EXPL_ALLOC_INC; /* how much space is not used */
4975 *file = (char_u **)alloc(sizeof(char_u **) * files_alloced);
4976 if (*file == NULL)
4977 return FAIL;
4979 for (; num_pat > 0; num_pat--, pat++)
4981 expl_files = NULL;
4982 if (vim_strchr(*pat, '$') || vim_strchr(*pat, '~'))
4983 /* expand environment var or home dir */
4984 buf = expand_env_save(*pat);
4985 else
4986 buf = vim_strsave(*pat);
4987 expl_files = NULL;
4988 has_wildcard = mch_has_exp_wildcard(buf); /* (still) wildcards? */
4989 if (has_wildcard) /* yes, so expand them */
4990 expl_files = (char_u **)_fnexplode(buf);
4993 * return value of buf if no wildcards left,
4994 * OR if no match AND EW_NOTFOUND is set.
4996 if ((!has_wildcard && ((flags & EW_NOTFOUND) || mch_getperm(buf) >= 0))
4997 || (expl_files == NULL && (flags & EW_NOTFOUND)))
4998 { /* simply save the current contents of *buf */
4999 expl_files = (char_u **)alloc(sizeof(char_u **) * 2);
5000 if (expl_files != NULL)
5002 expl_files[0] = vim_strsave(buf);
5003 expl_files[1] = NULL;
5006 vim_free(buf);
5009 * Count number of names resulting from expansion,
5010 * At the same time add a backslash to the end of names that happen to
5011 * be directories, and replace slashes with backslashes.
5013 if (expl_files)
5015 for (i = 0; (p = expl_files[i]) != NULL; i++)
5017 dir = mch_isdir(p);
5018 /* If we don't want dirs and this is one, skip it */
5019 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5020 continue;
5022 /* Skip files that are not executable if we check for that. */
5023 if (!dir && (flags & EW_EXEC) && !mch_can_exe(p))
5024 continue;
5026 if (--files_free == 0)
5028 /* need more room in table of pointers */
5029 files_alloced += EXPL_ALLOC_INC;
5030 *file = (char_u **)vim_realloc(*file,
5031 sizeof(char_u **) * files_alloced);
5032 if (*file == NULL)
5034 EMSG(_(e_outofmem));
5035 *num_file = 0;
5036 return FAIL;
5038 files_free = EXPL_ALLOC_INC;
5040 slash_adjust(p);
5041 if (dir)
5043 /* For a directory we add a '/', unless it's already
5044 * there. */
5045 len = STRLEN(p);
5046 if (((*file)[*num_file] = alloc(len + 2)) != NULL)
5048 STRCPY((*file)[*num_file], p);
5049 if (!after_pathsep((*file)[*num_file],
5050 (*file)[*num_file] + len))
5052 (*file)[*num_file][len] = psepc;
5053 (*file)[*num_file][len + 1] = NUL;
5057 else
5059 (*file)[*num_file] = vim_strsave(p);
5063 * Error message already given by either alloc or vim_strsave.
5064 * Should return FAIL, but returning OK works also.
5066 if ((*file)[*num_file] == NULL)
5067 break;
5068 (*num_file)++;
5070 _fnexplodefree((char **)expl_files);
5073 return OK;
5075 #else /* __EMX__ */
5077 * This is the non-OS/2 implementation (really Unix).
5079 int j;
5080 char_u *tempname;
5081 char_u *command;
5082 FILE *fd;
5083 char_u *buffer;
5084 #define STYLE_ECHO 0 /* use "echo", the default */
5085 #define STYLE_GLOB 1 /* use "glob", for csh */
5086 #define STYLE_VIMGLOB 2 /* use "vimglob", for Posix sh */
5087 #define STYLE_PRINT 3 /* use "print -N", for zsh */
5088 #define STYLE_BT 4 /* `cmd` expansion, execute the pattern
5089 * directly */
5090 int shell_style = STYLE_ECHO;
5091 int check_spaces;
5092 static int did_find_nul = FALSE;
5093 int ampersent = FALSE;
5094 /* vimglob() function to define for Posix shell */
5095 static char *sh_vimglob_func = "vimglob() { while [ $# -ge 1 ]; do echo -n \"$1\"; echo; shift; done }; vimglob >";
5097 *num_file = 0; /* default: no files found */
5098 *file = NULL;
5101 * If there are no wildcards, just copy the names to allocated memory.
5102 * Saves a lot of time, because we don't have to start a new shell.
5104 if (!have_wildcard(num_pat, pat))
5105 return save_patterns(num_pat, pat, num_file, file);
5107 # ifdef HAVE_SANDBOX
5108 /* Don't allow any shell command in the sandbox. */
5109 if (sandbox != 0 && check_secure())
5110 return FAIL;
5111 # endif
5114 * Don't allow the use of backticks in secure and restricted mode.
5116 if (secure || restricted)
5117 for (i = 0; i < num_pat; ++i)
5118 if (vim_strchr(pat[i], '`') != NULL
5119 && (check_restricted() || check_secure()))
5120 return FAIL;
5123 * get a name for the temp file
5125 if ((tempname = vim_tempname('o')) == NULL)
5127 EMSG(_(e_notmp));
5128 return FAIL;
5132 * Let the shell expand the patterns and write the result into the temp
5133 * file.
5134 * STYLE_BT: NL separated
5135 * If expanding `cmd` execute it directly.
5136 * STYLE_GLOB: NUL separated
5137 * If we use *csh, "glob" will work better than "echo".
5138 * STYLE_PRINT: NL or NUL separated
5139 * If we use *zsh, "print -N" will work better than "glob".
5140 * STYLE_VIMGLOB: NL separated
5141 * If we use *sh*, we define "vimglob()".
5142 * STYLE_ECHO: space separated.
5143 * A shell we don't know, stay safe and use "echo".
5145 if (num_pat == 1 && *pat[0] == '`'
5146 && (len = STRLEN(pat[0])) > 2
5147 && *(pat[0] + len - 1) == '`')
5148 shell_style = STYLE_BT;
5149 else if ((len = STRLEN(p_sh)) >= 3)
5151 if (STRCMP(p_sh + len - 3, "csh") == 0)
5152 shell_style = STYLE_GLOB;
5153 else if (STRCMP(p_sh + len - 3, "zsh") == 0)
5154 shell_style = STYLE_PRINT;
5156 if (shell_style == STYLE_ECHO && strstr((char *)gettail(p_sh),
5157 "sh") != NULL)
5158 shell_style = STYLE_VIMGLOB;
5160 /* Compute the length of the command. We need 2 extra bytes: for the
5161 * optional '&' and for the NUL.
5162 * Worst case: "unset nonomatch; print -N >" plus two is 29 */
5163 len = STRLEN(tempname) + 29;
5164 if (shell_style == STYLE_VIMGLOB)
5165 len += STRLEN(sh_vimglob_func);
5167 for (i = 0; i < num_pat; ++i)
5169 /* Count the length of the patterns in the same way as they are put in
5170 * "command" below. */
5171 #ifdef USE_SYSTEM
5172 len += STRLEN(pat[i]) + 3; /* add space and two quotes */
5173 #else
5174 ++len; /* add space */
5175 for (j = 0; pat[i][j] != NUL; ++j)
5177 if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL)
5178 ++len; /* may add a backslash */
5179 ++len;
5181 #endif
5183 command = alloc(len);
5184 if (command == NULL)
5186 /* out of memory */
5187 vim_free(tempname);
5188 return FAIL;
5192 * Build the shell command:
5193 * - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell
5194 * recognizes this).
5195 * - Add the shell command to print the expanded names.
5196 * - Add the temp file name.
5197 * - Add the file name patterns.
5199 if (shell_style == STYLE_BT)
5201 /* change `command; command& ` to (command; command ) */
5202 STRCPY(command, "(");
5203 STRCAT(command, pat[0] + 1); /* exclude first backtick */
5204 p = command + STRLEN(command) - 1;
5205 *p-- = ')'; /* remove last backtick */
5206 while (p > command && vim_iswhite(*p))
5207 --p;
5208 if (*p == '&') /* remove trailing '&' */
5210 ampersent = TRUE;
5211 *p = ' ';
5213 STRCAT(command, ">");
5215 else
5217 if (flags & EW_NOTFOUND)
5218 STRCPY(command, "set nonomatch; ");
5219 else
5220 STRCPY(command, "unset nonomatch; ");
5221 if (shell_style == STYLE_GLOB)
5222 STRCAT(command, "glob >");
5223 else if (shell_style == STYLE_PRINT)
5224 STRCAT(command, "print -N >");
5225 else if (shell_style == STYLE_VIMGLOB)
5226 STRCAT(command, sh_vimglob_func);
5227 else
5228 STRCAT(command, "echo >");
5231 STRCAT(command, tempname);
5233 if (shell_style != STYLE_BT)
5234 for (i = 0; i < num_pat; ++i)
5236 /* When using system() always add extra quotes, because the shell
5237 * is started twice. Otherwise put a backslash before special
5238 * characters, except inside ``. */
5239 #ifdef USE_SYSTEM
5240 STRCAT(command, " \"");
5241 STRCAT(command, pat[i]);
5242 STRCAT(command, "\"");
5243 #else
5244 int intick = FALSE;
5246 p = command + STRLEN(command);
5247 *p++ = ' ';
5248 for (j = 0; pat[i][j] != NUL; ++j)
5250 if (pat[i][j] == '`')
5251 intick = !intick;
5252 else if (pat[i][j] == '\\' && pat[i][j + 1] != NUL)
5254 /* Remove a backslash, take char literally. But keep
5255 * backslash inside backticks, before a special character
5256 * and before a backtick. */
5257 if (intick
5258 || vim_strchr(SHELL_SPECIAL, pat[i][j + 1]) != NULL
5259 || pat[i][j + 1] == '`')
5260 *p++ = '\\';
5261 ++j;
5263 else if (!intick && vim_strchr(SHELL_SPECIAL,
5264 pat[i][j]) != NULL)
5265 /* Put a backslash before a special character, but not
5266 * when inside ``. */
5267 *p++ = '\\';
5269 /* Copy one character. */
5270 *p++ = pat[i][j];
5272 *p = NUL;
5273 #endif
5275 if (flags & EW_SILENT)
5276 show_shell_mess = FALSE;
5277 if (ampersent)
5278 STRCAT(command, "&"); /* put the '&' after the redirection */
5281 * Using zsh -G: If a pattern has no matches, it is just deleted from
5282 * the argument list, otherwise zsh gives an error message and doesn't
5283 * expand any other pattern.
5285 if (shell_style == STYLE_PRINT)
5286 extra_shell_arg = (char_u *)"-G"; /* Use zsh NULL_GLOB option */
5289 * If we use -f then shell variables set in .cshrc won't get expanded.
5290 * vi can do it, so we will too, but it is only necessary if there is a "$"
5291 * in one of the patterns, otherwise we can still use the fast option.
5293 else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat))
5294 extra_shell_arg = (char_u *)"-f"; /* Use csh fast option */
5297 * execute the shell command
5299 i = call_shell(command, SHELL_EXPAND | SHELL_SILENT);
5301 /* When running in the background, give it some time to create the temp
5302 * file, but don't wait for it to finish. */
5303 if (ampersent)
5304 mch_delay(10L, TRUE);
5306 extra_shell_arg = NULL; /* cleanup */
5307 show_shell_mess = TRUE;
5308 vim_free(command);
5310 if (i != 0) /* mch_call_shell() failed */
5312 mch_remove(tempname);
5313 vim_free(tempname);
5315 * With interactive completion, the error message is not printed.
5316 * However with USE_SYSTEM, I don't know how to turn off error messages
5317 * from the shell, so screen may still get messed up -- webb.
5319 #ifndef USE_SYSTEM
5320 if (!(flags & EW_SILENT))
5321 #endif
5323 redraw_later_clear(); /* probably messed up screen */
5324 msg_putchar('\n'); /* clear bottom line quickly */
5325 cmdline_row = Rows - 1; /* continue on last line */
5326 #ifdef USE_SYSTEM
5327 if (!(flags & EW_SILENT))
5328 #endif
5330 MSG(_(e_wildexpand));
5331 msg_start(); /* don't overwrite this message */
5334 /* If a `cmd` expansion failed, don't list `cmd` as a match, even when
5335 * EW_NOTFOUND is given */
5336 if (shell_style == STYLE_BT)
5337 return FAIL;
5338 goto notfound;
5342 * read the names from the file into memory
5344 fd = fopen((char *)tempname, READBIN);
5345 if (fd == NULL)
5347 /* Something went wrong, perhaps a file name with a special char. */
5348 if (!(flags & EW_SILENT))
5350 MSG(_(e_wildexpand));
5351 msg_start(); /* don't overwrite this message */
5353 vim_free(tempname);
5354 goto notfound;
5356 fseek(fd, 0L, SEEK_END);
5357 len = ftell(fd); /* get size of temp file */
5358 fseek(fd, 0L, SEEK_SET);
5359 buffer = alloc(len + 1);
5360 if (buffer == NULL)
5362 /* out of memory */
5363 mch_remove(tempname);
5364 vim_free(tempname);
5365 fclose(fd);
5366 return FAIL;
5368 i = fread((char *)buffer, 1, len, fd);
5369 fclose(fd);
5370 mch_remove(tempname);
5371 if (i != len)
5373 /* unexpected read error */
5374 EMSG2(_(e_notread), tempname);
5375 vim_free(tempname);
5376 vim_free(buffer);
5377 return FAIL;
5379 vim_free(tempname);
5381 # if defined(__CYGWIN__) || defined(__CYGWIN32__)
5382 /* Translate <CR><NL> into <NL>. Caution, buffer may contain NUL. */
5383 p = buffer;
5384 for (i = 0; i < len; ++i)
5385 if (!(buffer[i] == CAR && buffer[i + 1] == NL))
5386 *p++ = buffer[i];
5387 len = p - buffer;
5388 # endif
5391 /* file names are separated with Space */
5392 if (shell_style == STYLE_ECHO)
5394 buffer[len] = '\n'; /* make sure the buffer ends in NL */
5395 p = buffer;
5396 for (i = 0; *p != '\n'; ++i) /* count number of entries */
5398 while (*p != ' ' && *p != '\n')
5399 ++p;
5400 p = skipwhite(p); /* skip to next entry */
5403 /* file names are separated with NL */
5404 else if (shell_style == STYLE_BT || shell_style == STYLE_VIMGLOB)
5406 buffer[len] = NUL; /* make sure the buffer ends in NUL */
5407 p = buffer;
5408 for (i = 0; *p != NUL; ++i) /* count number of entries */
5410 while (*p != '\n' && *p != NUL)
5411 ++p;
5412 if (*p != NUL)
5413 ++p;
5414 p = skipwhite(p); /* skip leading white space */
5417 /* file names are separated with NUL */
5418 else
5421 * Some versions of zsh use spaces instead of NULs to separate
5422 * results. Only do this when there is no NUL before the end of the
5423 * buffer, otherwise we would never be able to use file names with
5424 * embedded spaces when zsh does use NULs.
5425 * When we found a NUL once, we know zsh is OK, set did_find_nul and
5426 * don't check for spaces again.
5428 check_spaces = FALSE;
5429 if (shell_style == STYLE_PRINT && !did_find_nul)
5431 /* If there is a NUL, set did_find_nul, else set check_spaces */
5432 if (len && (int)STRLEN(buffer) < len - 1)
5433 did_find_nul = TRUE;
5434 else
5435 check_spaces = TRUE;
5439 * Make sure the buffer ends with a NUL. For STYLE_PRINT there
5440 * already is one, for STYLE_GLOB it needs to be added.
5442 if (len && buffer[len - 1] == NUL)
5443 --len;
5444 else
5445 buffer[len] = NUL;
5446 i = 0;
5447 for (p = buffer; p < buffer + len; ++p)
5448 if (*p == NUL || (*p == ' ' && check_spaces)) /* count entry */
5450 ++i;
5451 *p = NUL;
5453 if (len)
5454 ++i; /* count last entry */
5456 if (i == 0)
5459 * Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I".
5460 * /bin/sh will happily expand it to nothing rather than returning an
5461 * error; and hey, it's good to check anyway -- webb.
5463 vim_free(buffer);
5464 goto notfound;
5466 *num_file = i;
5467 *file = (char_u **)alloc(sizeof(char_u *) * i);
5468 if (*file == NULL)
5470 /* out of memory */
5471 vim_free(buffer);
5472 return FAIL;
5476 * Isolate the individual file names.
5478 p = buffer;
5479 for (i = 0; i < *num_file; ++i)
5481 (*file)[i] = p;
5482 /* Space or NL separates */
5483 if (shell_style == STYLE_ECHO || shell_style == STYLE_BT
5484 || shell_style == STYLE_VIMGLOB)
5486 while (!(shell_style == STYLE_ECHO && *p == ' ')
5487 && *p != '\n' && *p != NUL)
5488 ++p;
5489 if (p == buffer + len) /* last entry */
5490 *p = NUL;
5491 else
5493 *p++ = NUL;
5494 p = skipwhite(p); /* skip to next entry */
5497 else /* NUL separates */
5499 while (*p && p < buffer + len) /* skip entry */
5500 ++p;
5501 ++p; /* skip NUL */
5506 * Move the file names to allocated memory.
5508 for (j = 0, i = 0; i < *num_file; ++i)
5510 /* Require the files to exist. Helps when using /bin/sh */
5511 if (!(flags & EW_NOTFOUND) && mch_getperm((*file)[i]) < 0)
5512 continue;
5514 /* check if this entry should be included */
5515 dir = (mch_isdir((*file)[i]));
5516 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5517 continue;
5519 /* Skip files that are not executable if we check for that. */
5520 if (!dir && (flags & EW_EXEC) && !mch_can_exe((*file)[i]))
5521 continue;
5523 p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir));
5524 if (p)
5526 STRCPY(p, (*file)[i]);
5527 if (dir)
5528 add_pathsep(p); /* add '/' to a directory name */
5529 (*file)[j++] = p;
5532 vim_free(buffer);
5533 *num_file = j;
5535 if (*num_file == 0) /* rejected all entries */
5537 vim_free(*file);
5538 *file = NULL;
5539 goto notfound;
5542 return OK;
5544 notfound:
5545 if (flags & EW_NOTFOUND)
5546 return save_patterns(num_pat, pat, num_file, file);
5547 return FAIL;
5549 #endif /* __EMX__ */
5552 #endif /* VMS */
5554 #ifndef __EMX__
5555 static int
5556 save_patterns(num_pat, pat, num_file, file)
5557 int num_pat;
5558 char_u **pat;
5559 int *num_file;
5560 char_u ***file;
5562 int i;
5563 char_u *s;
5565 *file = (char_u **)alloc(num_pat * sizeof(char_u *));
5566 if (*file == NULL)
5567 return FAIL;
5568 for (i = 0; i < num_pat; i++)
5570 s = vim_strsave(pat[i]);
5571 if (s != NULL)
5572 /* Be compatible with expand_filename(): halve the number of
5573 * backslashes. */
5574 backslash_halve(s);
5575 (*file)[i] = s;
5577 *num_file = num_pat;
5578 return OK;
5580 #endif
5584 * Return TRUE if the string "p" contains a wildcard that mch_expandpath() can
5585 * expand.
5588 mch_has_exp_wildcard(p)
5589 char_u *p;
5591 for ( ; *p; mb_ptr_adv(p))
5593 #ifndef OS2
5594 if (*p == '\\' && p[1] != NUL)
5595 ++p;
5596 else
5597 #endif
5598 if (vim_strchr((char_u *)
5599 #ifdef VMS
5600 "*?%"
5601 #else
5602 # ifdef OS2
5603 "*?"
5604 # else
5605 "*?[{'"
5606 # endif
5607 #endif
5608 , *p) != NULL)
5609 return TRUE;
5611 return FALSE;
5615 * Return TRUE if the string "p" contains a wildcard.
5616 * Don't recognize '~' at the end as a wildcard.
5619 mch_has_wildcard(p)
5620 char_u *p;
5622 for ( ; *p; mb_ptr_adv(p))
5624 #ifndef OS2
5625 if (*p == '\\' && p[1] != NUL)
5626 ++p;
5627 else
5628 #endif
5629 if (vim_strchr((char_u *)
5630 #ifdef VMS
5631 "*?%$"
5632 #else
5633 # ifdef OS2
5634 # ifdef VIM_BACKTICK
5635 "*?$`"
5636 # else
5637 "*?$"
5638 # endif
5639 # else
5640 "*?[{`'$"
5641 # endif
5642 #endif
5643 , *p) != NULL
5644 || (*p == '~' && p[1] != NUL))
5645 return TRUE;
5647 return FALSE;
5650 #ifndef __EMX__
5651 static int
5652 have_wildcard(num, file)
5653 int num;
5654 char_u **file;
5656 int i;
5658 for (i = 0; i < num; i++)
5659 if (mch_has_wildcard(file[i]))
5660 return 1;
5661 return 0;
5664 static int
5665 have_dollars(num, file)
5666 int num;
5667 char_u **file;
5669 int i;
5671 for (i = 0; i < num; i++)
5672 if (vim_strchr(file[i], '$') != NULL)
5673 return TRUE;
5674 return FALSE;
5676 #endif /* ifndef __EMX__ */
5678 #ifndef HAVE_RENAME
5680 * Scaled-down version of rename(), which is missing in Xenix.
5681 * This version can only move regular files and will fail if the
5682 * destination exists.
5685 mch_rename(src, dest)
5686 const char *src, *dest;
5688 struct stat st;
5690 if (stat(dest, &st) >= 0) /* fail if destination exists */
5691 return -1;
5692 if (link(src, dest) != 0) /* link file to new name */
5693 return -1;
5694 if (mch_remove(src) == 0) /* delete link to old name */
5695 return 0;
5696 return -1;
5698 #endif /* !HAVE_RENAME */
5700 #ifdef FEAT_MOUSE_GPM
5702 * Initializes connection with gpm (if it isn't already opened)
5703 * Return 1 if succeeded (or connection already opened), 0 if failed
5705 static int
5706 gpm_open()
5708 static Gpm_Connect gpm_connect; /* Must it be kept till closing ? */
5710 if (!gpm_flag)
5712 gpm_connect.eventMask = (GPM_UP | GPM_DRAG | GPM_DOWN);
5713 gpm_connect.defaultMask = ~GPM_HARD;
5714 /* Default handling for mouse move*/
5715 gpm_connect.minMod = 0; /* Handle any modifier keys */
5716 gpm_connect.maxMod = 0xffff;
5717 if (Gpm_Open(&gpm_connect, 0) > 0)
5719 /* gpm library tries to handling TSTP causes
5720 * problems. Anyways, we close connection to Gpm whenever
5721 * we are going to suspend or starting an external process
5722 * so we shouldn't have problem with this
5724 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
5725 return 1; /* succeed */
5727 if (gpm_fd == -2)
5728 Gpm_Close(); /* We don't want to talk to xterm via gpm */
5729 return 0;
5731 return 1; /* already open */
5735 * Closes connection to gpm
5736 * returns non-zero if connection successfully closed
5738 static void
5739 gpm_close()
5741 if (gpm_flag && gpm_fd >= 0) /* if Open */
5742 Gpm_Close();
5745 /* Reads gpm event and adds special keys to input buf. Returns length of
5746 * generated key sequence.
5747 * This function is made after gui_send_mouse_event
5749 static int
5750 mch_gpm_process()
5752 int button;
5753 static Gpm_Event gpm_event;
5754 char_u string[6];
5755 int_u vim_modifiers;
5756 int row,col;
5757 unsigned char buttons_mask;
5758 unsigned char gpm_modifiers;
5759 static unsigned char old_buttons = 0;
5761 Gpm_GetEvent(&gpm_event);
5763 #ifdef FEAT_GUI
5764 /* Don't put events in the input queue now. */
5765 if (hold_gui_events)
5766 return 0;
5767 #endif
5769 row = gpm_event.y - 1;
5770 col = gpm_event.x - 1;
5772 string[0] = ESC; /* Our termcode */
5773 string[1] = 'M';
5774 string[2] = 'G';
5775 switch (GPM_BARE_EVENTS(gpm_event.type))
5777 case GPM_DRAG:
5778 string[3] = MOUSE_DRAG;
5779 break;
5780 case GPM_DOWN:
5781 buttons_mask = gpm_event.buttons & ~old_buttons;
5782 old_buttons = gpm_event.buttons;
5783 switch (buttons_mask)
5785 case GPM_B_LEFT:
5786 button = MOUSE_LEFT;
5787 break;
5788 case GPM_B_MIDDLE:
5789 button = MOUSE_MIDDLE;
5790 break;
5791 case GPM_B_RIGHT:
5792 button = MOUSE_RIGHT;
5793 break;
5794 default:
5795 return 0;
5796 /*Don't know what to do. Can more than one button be
5797 * reported in one event? */
5799 string[3] = (char_u)(button | 0x20);
5800 SET_NUM_MOUSE_CLICKS(string[3], gpm_event.clicks + 1);
5801 break;
5802 case GPM_UP:
5803 string[3] = MOUSE_RELEASE;
5804 old_buttons &= ~gpm_event.buttons;
5805 break;
5806 default:
5807 return 0;
5809 /*This code is based on gui_x11_mouse_cb in gui_x11.c */
5810 gpm_modifiers = gpm_event.modifiers;
5811 vim_modifiers = 0x0;
5812 /* I ignore capslock stats. Aren't we all just hate capslock mixing with
5813 * Vim commands ? Besides, gpm_event.modifiers is unsigned char, and
5814 * K_CAPSSHIFT is defined 8, so it probably isn't even reported
5816 if (gpm_modifiers & ((1 << KG_SHIFT) | (1 << KG_SHIFTR) | (1 << KG_SHIFTL)))
5817 vim_modifiers |= MOUSE_SHIFT;
5819 if (gpm_modifiers & ((1 << KG_CTRL) | (1 << KG_CTRLR) | (1 << KG_CTRLL)))
5820 vim_modifiers |= MOUSE_CTRL;
5821 if (gpm_modifiers & ((1 << KG_ALT) | (1 << KG_ALTGR)))
5822 vim_modifiers |= MOUSE_ALT;
5823 string[3] |= vim_modifiers;
5824 string[4] = (char_u)(col + ' ' + 1);
5825 string[5] = (char_u)(row + ' ' + 1);
5826 add_to_input_buf(string, 6);
5827 return 6;
5829 #endif /* FEAT_MOUSE_GPM */
5831 #if defined(FEAT_LIBCALL) || defined(PROTO)
5832 typedef char_u * (*STRPROCSTR)__ARGS((char_u *));
5833 typedef char_u * (*INTPROCSTR)__ARGS((int));
5834 typedef int (*STRPROCINT)__ARGS((char_u *));
5835 typedef int (*INTPROCINT)__ARGS((int));
5838 * Call a DLL routine which takes either a string or int param
5839 * and returns an allocated string.
5842 mch_libcall(libname, funcname, argstring, argint, string_result, number_result)
5843 char_u *libname;
5844 char_u *funcname;
5845 char_u *argstring; /* NULL when using a argint */
5846 int argint;
5847 char_u **string_result;/* NULL when using number_result */
5848 int *number_result;
5850 # if defined(USE_DLOPEN)
5851 void *hinstLib;
5852 char *dlerr = NULL;
5853 # else
5854 shl_t hinstLib;
5855 # endif
5856 STRPROCSTR ProcAdd;
5857 INTPROCSTR ProcAddI;
5858 char_u *retval_str = NULL;
5859 int retval_int = 0;
5860 int success = FALSE;
5863 * Get a handle to the DLL module.
5865 # if defined(USE_DLOPEN)
5866 /* First clear any error, it's not cleared by the dlopen() call. */
5867 (void)dlerror();
5869 hinstLib = dlopen((char *)libname, RTLD_LAZY
5870 # ifdef RTLD_LOCAL
5871 | RTLD_LOCAL
5872 # endif
5874 if (hinstLib == NULL)
5876 /* "dlerr" must be used before dlclose() */
5877 dlerr = (char *)dlerror();
5878 if (dlerr != NULL)
5879 EMSG2(_("dlerror = \"%s\""), dlerr);
5881 # else
5882 hinstLib = shl_load((const char*)libname, BIND_IMMEDIATE|BIND_VERBOSE, 0L);
5883 # endif
5885 /* If the handle is valid, try to get the function address. */
5886 if (hinstLib != NULL)
5888 # ifdef HAVE_SETJMP_H
5890 * Catch a crash when calling the library function. For example when
5891 * using a number where a string pointer is expected.
5893 mch_startjmp();
5894 if (SETJMP(lc_jump_env) != 0)
5896 success = FALSE;
5897 # if defined(USE_DLOPEN)
5898 dlerr = NULL;
5899 # endif
5900 mch_didjmp();
5902 else
5903 # endif
5905 retval_str = NULL;
5906 retval_int = 0;
5908 if (argstring != NULL)
5910 # if defined(USE_DLOPEN)
5911 ProcAdd = (STRPROCSTR)dlsym(hinstLib, (const char *)funcname);
5912 dlerr = (char *)dlerror();
5913 # else
5914 if (shl_findsym(&hinstLib, (const char *)funcname,
5915 TYPE_PROCEDURE, (void *)&ProcAdd) < 0)
5916 ProcAdd = NULL;
5917 # endif
5918 if ((success = (ProcAdd != NULL
5919 # if defined(USE_DLOPEN)
5920 && dlerr == NULL
5921 # endif
5924 if (string_result == NULL)
5925 retval_int = ((STRPROCINT)ProcAdd)(argstring);
5926 else
5927 retval_str = (ProcAdd)(argstring);
5930 else
5932 # if defined(USE_DLOPEN)
5933 ProcAddI = (INTPROCSTR)dlsym(hinstLib, (const char *)funcname);
5934 dlerr = (char *)dlerror();
5935 # else
5936 if (shl_findsym(&hinstLib, (const char *)funcname,
5937 TYPE_PROCEDURE, (void *)&ProcAddI) < 0)
5938 ProcAddI = NULL;
5939 # endif
5940 if ((success = (ProcAddI != NULL
5941 # if defined(USE_DLOPEN)
5942 && dlerr == NULL
5943 # endif
5946 if (string_result == NULL)
5947 retval_int = ((INTPROCINT)ProcAddI)(argint);
5948 else
5949 retval_str = (ProcAddI)(argint);
5953 /* Save the string before we free the library. */
5954 /* Assume that a "1" or "-1" result is an illegal pointer. */
5955 if (string_result == NULL)
5956 *number_result = retval_int;
5957 else if (retval_str != NULL
5958 && retval_str != (char_u *)1
5959 && retval_str != (char_u *)-1)
5960 *string_result = vim_strsave(retval_str);
5963 # ifdef HAVE_SETJMP_H
5964 mch_endjmp();
5965 # ifdef SIGHASARG
5966 if (lc_signal != 0)
5968 int i;
5970 /* try to find the name of this signal */
5971 for (i = 0; signal_info[i].sig != -1; i++)
5972 if (lc_signal == signal_info[i].sig)
5973 break;
5974 EMSG2("E368: got SIG%s in libcall()", signal_info[i].name);
5976 # endif
5977 # endif
5979 # if defined(USE_DLOPEN)
5980 /* "dlerr" must be used before dlclose() */
5981 if (dlerr != NULL)
5982 EMSG2(_("dlerror = \"%s\""), dlerr);
5984 /* Free the DLL module. */
5985 (void)dlclose(hinstLib);
5986 # else
5987 (void)shl_unload(hinstLib);
5988 # endif
5991 if (!success)
5993 EMSG2(_(e_libcall), funcname);
5994 return FAIL;
5997 return OK;
5999 #endif
6001 #if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
6002 static int xterm_trace = -1; /* default: disabled */
6003 static int xterm_button;
6006 * Setup a dummy window for X selections in a terminal.
6008 void
6009 setup_term_clip()
6011 int z = 0;
6012 char *strp = "";
6013 Widget AppShell;
6015 if (!x_connect_to_server())
6016 return;
6018 open_app_context();
6019 if (app_context != NULL && xterm_Shell == (Widget)0)
6021 int (*oldhandler)();
6022 #if defined(HAVE_SETJMP_H)
6023 int (*oldIOhandler)();
6024 #endif
6025 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
6026 struct timeval start_tv;
6028 if (p_verbose > 0)
6029 gettimeofday(&start_tv, NULL);
6030 # endif
6032 /* Ignore X errors while opening the display */
6033 oldhandler = XSetErrorHandler(x_error_check);
6035 #if defined(HAVE_SETJMP_H)
6036 /* Ignore X IO errors while opening the display */
6037 oldIOhandler = XSetIOErrorHandler(x_IOerror_check);
6038 mch_startjmp();
6039 if (SETJMP(lc_jump_env) != 0)
6041 mch_didjmp();
6042 xterm_dpy = NULL;
6044 else
6045 #endif
6047 xterm_dpy = XtOpenDisplay(app_context, xterm_display,
6048 "vim_xterm", "Vim_xterm", NULL, 0, &z, &strp);
6049 #if defined(HAVE_SETJMP_H)
6050 mch_endjmp();
6051 #endif
6054 #if defined(HAVE_SETJMP_H)
6055 /* Now handle X IO errors normally. */
6056 (void)XSetIOErrorHandler(oldIOhandler);
6057 #endif
6058 /* Now handle X errors normally. */
6059 (void)XSetErrorHandler(oldhandler);
6061 if (xterm_dpy == NULL)
6063 if (p_verbose > 0)
6064 verb_msg((char_u *)_("Opening the X display failed"));
6065 return;
6068 /* Catch terminating error of the X server connection. */
6069 (void)XSetIOErrorHandler(x_IOerror_handler);
6071 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
6072 if (p_verbose > 0)
6074 verbose_enter();
6075 xopen_message(&start_tv);
6076 verbose_leave();
6078 # endif
6080 /* Create a Shell to make converters work. */
6081 AppShell = XtVaAppCreateShell("vim_xterm", "Vim_xterm",
6082 applicationShellWidgetClass, xterm_dpy,
6083 NULL);
6084 if (AppShell == (Widget)0)
6085 return;
6086 xterm_Shell = XtVaCreatePopupShell("VIM",
6087 topLevelShellWidgetClass, AppShell,
6088 XtNmappedWhenManaged, 0,
6089 XtNwidth, 1,
6090 XtNheight, 1,
6091 NULL);
6092 if (xterm_Shell == (Widget)0)
6093 return;
6095 x11_setup_atoms(xterm_dpy);
6096 if (x11_display == NULL)
6097 x11_display = xterm_dpy;
6099 XtRealizeWidget(xterm_Shell);
6100 XSync(xterm_dpy, False);
6101 xterm_update();
6103 if (xterm_Shell != (Widget)0)
6105 clip_init(TRUE);
6106 if (x11_window == 0 && (strp = getenv("WINDOWID")) != NULL)
6107 x11_window = (Window)atol(strp);
6108 /* Check if $WINDOWID is valid. */
6109 if (test_x11_window(xterm_dpy) == FAIL)
6110 x11_window = 0;
6111 if (x11_window != 0)
6112 xterm_trace = 0;
6116 void
6117 start_xterm_trace(button)
6118 int button;
6120 if (x11_window == 0 || xterm_trace < 0 || xterm_Shell == (Widget)0)
6121 return;
6122 xterm_trace = 1;
6123 xterm_button = button;
6124 do_xterm_trace();
6128 void
6129 stop_xterm_trace()
6131 if (xterm_trace < 0)
6132 return;
6133 xterm_trace = 0;
6137 * Query the xterm pointer and generate mouse termcodes if necessary
6138 * return TRUE if dragging is active, else FALSE
6140 static int
6141 do_xterm_trace()
6143 Window root, child;
6144 int root_x, root_y;
6145 int win_x, win_y;
6146 int row, col;
6147 int_u mask_return;
6148 char_u buf[50];
6149 char_u *strp;
6150 long got_hints;
6151 static char_u *mouse_code;
6152 static char_u mouse_name[2] = {KS_MOUSE, KE_FILLER};
6153 static int prev_row = 0, prev_col = 0;
6154 static XSizeHints xterm_hints;
6156 if (xterm_trace <= 0)
6157 return FALSE;
6159 if (xterm_trace == 1)
6161 /* Get the hints just before tracking starts. The font size might
6162 * have changed recently. */
6163 if (!XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints)
6164 || !(got_hints & PResizeInc)
6165 || xterm_hints.width_inc <= 1
6166 || xterm_hints.height_inc <= 1)
6168 xterm_trace = -1; /* Not enough data -- disable tracing */
6169 return FALSE;
6172 /* Rely on the same mouse code for the duration of this */
6173 mouse_code = find_termcode(mouse_name);
6174 prev_row = mouse_row;
6175 prev_row = mouse_col;
6176 xterm_trace = 2;
6178 /* Find the offset of the chars, there might be a scrollbar on the
6179 * left of the window and/or a menu on the top (eterm etc.) */
6180 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
6181 &win_x, &win_y, &mask_return);
6182 xterm_hints.y = win_y - (xterm_hints.height_inc * mouse_row)
6183 - (xterm_hints.height_inc / 2);
6184 if (xterm_hints.y <= xterm_hints.height_inc / 2)
6185 xterm_hints.y = 2;
6186 xterm_hints.x = win_x - (xterm_hints.width_inc * mouse_col)
6187 - (xterm_hints.width_inc / 2);
6188 if (xterm_hints.x <= xterm_hints.width_inc / 2)
6189 xterm_hints.x = 2;
6190 return TRUE;
6192 if (mouse_code == NULL)
6194 xterm_trace = 0;
6195 return FALSE;
6198 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
6199 &win_x, &win_y, &mask_return);
6201 row = check_row((win_y - xterm_hints.y) / xterm_hints.height_inc);
6202 col = check_col((win_x - xterm_hints.x) / xterm_hints.width_inc);
6203 if (row == prev_row && col == prev_col)
6204 return TRUE;
6206 STRCPY(buf, mouse_code);
6207 strp = buf + STRLEN(buf);
6208 *strp++ = (xterm_button | MOUSE_DRAG) & ~0x20;
6209 *strp++ = (char_u)(col + ' ' + 1);
6210 *strp++ = (char_u)(row + ' ' + 1);
6211 *strp = 0;
6212 add_to_input_buf(buf, STRLEN(buf));
6214 prev_row = row;
6215 prev_col = col;
6216 return TRUE;
6219 # if defined(FEAT_GUI) || defined(PROTO)
6221 * Destroy the display, window and app_context. Required for GTK.
6223 void
6224 clear_xterm_clip()
6226 if (xterm_Shell != (Widget)0)
6228 XtDestroyWidget(xterm_Shell);
6229 xterm_Shell = (Widget)0;
6231 if (xterm_dpy != NULL)
6233 #if 0
6234 /* Lesstif and Solaris crash here, lose some memory */
6235 XtCloseDisplay(xterm_dpy);
6236 #endif
6237 if (x11_display == xterm_dpy)
6238 x11_display = NULL;
6239 xterm_dpy = NULL;
6241 #if 0
6242 if (app_context != (XtAppContext)NULL)
6244 /* Lesstif and Solaris crash here, lose some memory */
6245 XtDestroyApplicationContext(app_context);
6246 app_context = (XtAppContext)NULL;
6248 #endif
6250 # endif
6253 * Catch up with any queued X events. This may put keyboard input into the
6254 * input buffer, call resize call-backs, trigger timers etc. If there is
6255 * nothing in the X event queue (& no timers pending), then we return
6256 * immediately.
6258 static void
6259 xterm_update()
6261 XEvent event;
6263 while (XtAppPending(app_context) && !vim_is_input_buf_full())
6265 XtAppNextEvent(app_context, &event);
6266 #ifdef FEAT_CLIENTSERVER
6268 XPropertyEvent *e = (XPropertyEvent *)&event;
6270 if (e->type == PropertyNotify && e->window == commWindow
6271 && e->atom == commProperty && e->state == PropertyNewValue)
6272 serverEventProc(xterm_dpy, &event);
6274 #endif
6275 XtDispatchEvent(&event);
6280 clip_xterm_own_selection(cbd)
6281 VimClipboard *cbd;
6283 if (xterm_Shell != (Widget)0)
6284 return clip_x11_own_selection(xterm_Shell, cbd);
6285 return FAIL;
6288 void
6289 clip_xterm_lose_selection(cbd)
6290 VimClipboard *cbd;
6292 if (xterm_Shell != (Widget)0)
6293 clip_x11_lose_selection(xterm_Shell, cbd);
6296 void
6297 clip_xterm_request_selection(cbd)
6298 VimClipboard *cbd;
6300 if (xterm_Shell != (Widget)0)
6301 clip_x11_request_selection(xterm_Shell, xterm_dpy, cbd);
6304 void
6305 clip_xterm_set_selection(cbd)
6306 VimClipboard *cbd;
6308 clip_x11_set_selection(cbd);
6310 #endif
6313 #if defined(USE_XSMP) || defined(PROTO)
6315 * Code for X Session Management Protocol.
6317 static void xsmp_handle_save_yourself __ARGS((SmcConn smc_conn, SmPointer client_data, int save_type, Bool shutdown, int interact_style, Bool fast));
6318 static void xsmp_die __ARGS((SmcConn smc_conn, SmPointer client_data));
6319 static void xsmp_save_complete __ARGS((SmcConn smc_conn, SmPointer client_data));
6320 static void xsmp_shutdown_cancelled __ARGS((SmcConn smc_conn, SmPointer client_data));
6321 static void xsmp_ice_connection __ARGS((IceConn iceConn, IcePointer clientData, Bool opening, IcePointer *watchData));
6324 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6325 static void xsmp_handle_interaction __ARGS((SmcConn smc_conn, SmPointer client_data));
6328 * This is our chance to ask the user if they want to save,
6329 * or abort the logout
6331 /*ARGSUSED*/
6332 static void
6333 xsmp_handle_interaction(smc_conn, client_data)
6334 SmcConn smc_conn;
6335 SmPointer client_data;
6337 cmdmod_T save_cmdmod;
6338 int cancel_shutdown = False;
6340 save_cmdmod = cmdmod;
6341 cmdmod.confirm = TRUE;
6342 if (check_changed_any(FALSE))
6343 /* Mustn't logout */
6344 cancel_shutdown = True;
6345 cmdmod = save_cmdmod;
6346 setcursor(); /* position cursor */
6347 out_flush();
6349 /* Done interaction */
6350 SmcInteractDone(smc_conn, cancel_shutdown);
6352 /* Finish off
6353 * Only end save-yourself here if we're not cancelling shutdown;
6354 * we'll get a cancelled callback later in which we'll end it.
6355 * Hopefully get around glitchy SMs (like GNOME-1)
6357 if (!cancel_shutdown)
6359 xsmp.save_yourself = False;
6360 SmcSaveYourselfDone(smc_conn, True);
6363 # endif
6366 * Callback that starts save-yourself.
6368 /*ARGSUSED*/
6369 static void
6370 xsmp_handle_save_yourself(smc_conn, client_data, save_type,
6371 shutdown, interact_style, fast)
6372 SmcConn smc_conn;
6373 SmPointer client_data;
6374 int save_type;
6375 Bool shutdown;
6376 int interact_style;
6377 Bool fast;
6379 /* Handle already being in saveyourself */
6380 if (xsmp.save_yourself)
6381 SmcSaveYourselfDone(smc_conn, True);
6382 xsmp.save_yourself = True;
6383 xsmp.shutdown = shutdown;
6385 /* First up, preserve all files */
6386 out_flush();
6387 ml_sync_all(FALSE, FALSE); /* preserve all swap files */
6389 if (p_verbose > 0)
6390 verb_msg((char_u *)_("XSMP handling save-yourself request"));
6392 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6393 /* Now see if we can ask about unsaved files */
6394 if (shutdown && !fast && gui.in_use)
6395 /* Need to interact with user, but need SM's permission */
6396 SmcInteractRequest(smc_conn, SmDialogError,
6397 xsmp_handle_interaction, client_data);
6398 else
6399 # endif
6401 /* Can stop the cycle here */
6402 SmcSaveYourselfDone(smc_conn, True);
6403 xsmp.save_yourself = False;
6409 * Callback to warn us of imminent death.
6411 /*ARGSUSED*/
6412 static void
6413 xsmp_die(smc_conn, client_data)
6414 SmcConn smc_conn;
6415 SmPointer client_data;
6417 xsmp_close();
6419 /* quit quickly leaving swapfiles for modified buffers behind */
6420 getout_preserve_modified(0);
6425 * Callback to tell us that save-yourself has completed.
6427 /*ARGSUSED*/
6428 static void
6429 xsmp_save_complete(smc_conn, client_data)
6430 SmcConn smc_conn;
6431 SmPointer client_data;
6433 xsmp.save_yourself = False;
6438 * Callback to tell us that an instigated shutdown was cancelled
6439 * (maybe even by us)
6441 /*ARGSUSED*/
6442 static void
6443 xsmp_shutdown_cancelled(smc_conn, client_data)
6444 SmcConn smc_conn;
6445 SmPointer client_data;
6447 if (xsmp.save_yourself)
6448 SmcSaveYourselfDone(smc_conn, True);
6449 xsmp.save_yourself = False;
6450 xsmp.shutdown = False;
6455 * Callback to tell us that a new ICE connection has been established.
6457 /*ARGSUSED*/
6458 static void
6459 xsmp_ice_connection(iceConn, clientData, opening, watchData)
6460 IceConn iceConn;
6461 IcePointer clientData;
6462 Bool opening;
6463 IcePointer *watchData;
6465 /* Intercept creation of ICE connection fd */
6466 if (opening)
6468 xsmp_icefd = IceConnectionNumber(iceConn);
6469 IceRemoveConnectionWatch(xsmp_ice_connection, NULL);
6474 /* Handle any ICE processing that's required; return FAIL if SM lost */
6476 xsmp_handle_requests()
6478 Bool rep;
6480 if (IceProcessMessages(xsmp.iceconn, NULL, &rep)
6481 == IceProcessMessagesIOError)
6483 /* Lost ICE */
6484 if (p_verbose > 0)
6485 verb_msg((char_u *)_("XSMP lost ICE connection"));
6486 xsmp_close();
6487 return FAIL;
6489 else
6490 return OK;
6493 static int dummy;
6495 /* Set up X Session Management Protocol */
6496 void
6497 xsmp_init(void)
6499 char errorstring[80];
6500 char *clientid;
6501 SmcCallbacks smcallbacks;
6502 #if 0
6503 SmPropValue smname;
6504 SmProp smnameprop;
6505 SmProp *smprops[1];
6506 #endif
6508 if (p_verbose > 0)
6509 verb_msg((char_u *)_("XSMP opening connection"));
6511 xsmp.save_yourself = xsmp.shutdown = False;
6513 /* Set up SM callbacks - must have all, even if they're not used */
6514 smcallbacks.save_yourself.callback = xsmp_handle_save_yourself;
6515 smcallbacks.save_yourself.client_data = NULL;
6516 smcallbacks.die.callback = xsmp_die;
6517 smcallbacks.die.client_data = NULL;
6518 smcallbacks.save_complete.callback = xsmp_save_complete;
6519 smcallbacks.save_complete.client_data = NULL;
6520 smcallbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
6521 smcallbacks.shutdown_cancelled.client_data = NULL;
6523 /* Set up a watch on ICE connection creations. The "dummy" argument is
6524 * apparently required for FreeBSD (we get a BUS error when using NULL). */
6525 if (IceAddConnectionWatch(xsmp_ice_connection, &dummy) == 0)
6527 if (p_verbose > 0)
6528 verb_msg((char_u *)_("XSMP ICE connection watch failed"));
6529 return;
6532 /* Create an SM connection */
6533 xsmp.smcconn = SmcOpenConnection(
6534 NULL,
6535 NULL,
6536 SmProtoMajor,
6537 SmProtoMinor,
6538 SmcSaveYourselfProcMask | SmcDieProcMask
6539 | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
6540 &smcallbacks,
6541 NULL,
6542 &clientid,
6543 sizeof(errorstring),
6544 errorstring);
6545 if (xsmp.smcconn == NULL)
6547 char errorreport[132];
6549 if (p_verbose > 0)
6551 vim_snprintf(errorreport, sizeof(errorreport),
6552 _("XSMP SmcOpenConnection failed: %s"), errorstring);
6553 verb_msg((char_u *)errorreport);
6555 return;
6557 xsmp.iceconn = SmcGetIceConnection(xsmp.smcconn);
6559 #if 0
6560 /* ID ourselves */
6561 smname.value = "vim";
6562 smname.length = 3;
6563 smnameprop.name = "SmProgram";
6564 smnameprop.type = "SmARRAY8";
6565 smnameprop.num_vals = 1;
6566 smnameprop.vals = &smname;
6568 smprops[0] = &smnameprop;
6569 SmcSetProperties(xsmp.smcconn, 1, smprops);
6570 #endif
6574 /* Shut down XSMP comms. */
6575 void
6576 xsmp_close()
6578 if (xsmp_icefd != -1)
6580 SmcCloseConnection(xsmp.smcconn, 0, NULL);
6581 xsmp_icefd = -1;
6584 #endif /* USE_XSMP */
6587 #ifdef EBCDIC
6588 /* Translate character to its CTRL- value */
6589 char CtrlTable[] =
6591 /* 00 - 5E */
6592 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6593 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6594 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6595 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6596 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6597 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6598 /* ^ */ 0x1E,
6599 /* - */ 0x1F,
6600 /* 61 - 6C */
6601 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6602 /* _ */ 0x1F,
6603 /* 6E - 80 */
6604 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6605 /* a */ 0x01,
6606 /* b */ 0x02,
6607 /* c */ 0x03,
6608 /* d */ 0x37,
6609 /* e */ 0x2D,
6610 /* f */ 0x2E,
6611 /* g */ 0x2F,
6612 /* h */ 0x16,
6613 /* i */ 0x05,
6614 /* 8A - 90 */
6615 0, 0, 0, 0, 0, 0, 0,
6616 /* j */ 0x15,
6617 /* k */ 0x0B,
6618 /* l */ 0x0C,
6619 /* m */ 0x0D,
6620 /* n */ 0x0E,
6621 /* o */ 0x0F,
6622 /* p */ 0x10,
6623 /* q */ 0x11,
6624 /* r */ 0x12,
6625 /* 9A - A1 */
6626 0, 0, 0, 0, 0, 0, 0, 0,
6627 /* s */ 0x13,
6628 /* t */ 0x3C,
6629 /* u */ 0x3D,
6630 /* v */ 0x32,
6631 /* w */ 0x26,
6632 /* x */ 0x18,
6633 /* y */ 0x19,
6634 /* z */ 0x3F,
6635 /* AA - AC */
6636 0, 0, 0,
6637 /* [ */ 0x27,
6638 /* AE - BC */
6639 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6640 /* ] */ 0x1D,
6641 /* BE - C0 */ 0, 0, 0,
6642 /* A */ 0x01,
6643 /* B */ 0x02,
6644 /* C */ 0x03,
6645 /* D */ 0x37,
6646 /* E */ 0x2D,
6647 /* F */ 0x2E,
6648 /* G */ 0x2F,
6649 /* H */ 0x16,
6650 /* I */ 0x05,
6651 /* CA - D0 */ 0, 0, 0, 0, 0, 0, 0,
6652 /* J */ 0x15,
6653 /* K */ 0x0B,
6654 /* L */ 0x0C,
6655 /* M */ 0x0D,
6656 /* N */ 0x0E,
6657 /* O */ 0x0F,
6658 /* P */ 0x10,
6659 /* Q */ 0x11,
6660 /* R */ 0x12,
6661 /* DA - DF */ 0, 0, 0, 0, 0, 0,
6662 /* \ */ 0x1C,
6663 /* E1 */ 0,
6664 /* S */ 0x13,
6665 /* T */ 0x3C,
6666 /* U */ 0x3D,
6667 /* V */ 0x32,
6668 /* W */ 0x26,
6669 /* X */ 0x18,
6670 /* Y */ 0x19,
6671 /* Z */ 0x3F,
6672 /* EA - FF*/ 0, 0, 0, 0, 0, 0,
6673 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6676 char MetaCharTable[]=
6677 {/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6678 0, 0, 0, 0,'\\', 0,'F', 0,'W','M','N', 0, 0, 0, 0, 0,
6679 0, 0, 0, 0,']', 0, 0,'G', 0, 0,'R','O', 0, 0, 0, 0,
6680 '@','A','B','C','D','E', 0, 0,'H','I','J','K','L', 0, 0, 0,
6681 'P','Q', 0,'S','T','U','V', 0,'X','Y','Z','[', 0, 0,'^', 0
6685 /* TODO: Use characters NOT numbers!!! */
6686 char CtrlCharTable[]=
6687 {/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6688 124,193,194,195, 0,201, 0, 0, 0, 0, 0,210,211,212,213,214,
6689 215,216,217,226, 0,209,200, 0,231,232, 0, 0,224,189, 95,109,
6690 0, 0, 0, 0, 0, 0,230,173, 0, 0, 0, 0, 0,197,198,199,
6691 0, 0,229, 0, 0, 0, 0,196, 0, 0, 0, 0,227,228, 0,233,
6695 #endif