blob: e808d6e7b03790843e5bb50091e8795eb53b6d36 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 * OS/2 port by Paul Slootman
5 * VMS merge by Zoltan Arpadffy
6 *
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.
10 */
11
12/*
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.
16 *
17 * A lot of this file was originally written by Juergen Weigert and later
18 * changed beyond recognition.
19 */
20
21/*
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?
27 */
28#ifndef __APPLE__
29# define select select_declared_wrong
30#endif
31
32#include "vim.h"
33
Bram Moolenaar325b7a22004-07-05 15:58:32 +000034#ifdef FEAT_MZSCHEME
35# include "if_mzsch.h"
36#endif
37
Bram Moolenaar071d4272004-06-13 20:20:40 +000038#ifdef HAVE_FCNTL_H
39# include <fcntl.h>
40#endif
41
42#include "os_unixx.h" /* unix includes for os_unix.c only */
43
44#ifdef USE_XSMP
45# include <X11/SM/SMlib.h>
46#endif
47
48/*
49 * Use this prototype for select, some include files have a wrong prototype
50 */
51#undef select
52#ifdef __BEOS__
53# define select beos_select
54#endif
55
56#if defined(HAVE_SELECT)
57extern int select __ARGS((int, fd_set *, fd_set *, fd_set *, struct timeval *));
58#endif
59
60#ifdef FEAT_MOUSE_GPM
61# include <gpm.h>
62/* <linux/keyboard.h> contains defines conflicting with "keymap.h",
63 * I just copied relevant defines here. A cleaner solution would be to put gpm
64 * code into separate file and include there linux/keyboard.h
65 */
66/* #include <linux/keyboard.h> */
67# define KG_SHIFT 0
68# define KG_CTRL 2
69# define KG_ALT 3
70# define KG_ALTGR 1
71# define KG_SHIFTL 4
72# define KG_SHIFTR 5
73# define KG_CTRLL 6
74# define KG_CTRLR 7
75# define KG_CAPSSHIFT 8
76
77static void gpm_close __ARGS((void));
78static int gpm_open __ARGS((void));
79static int mch_gpm_process __ARGS((void));
80#endif
81
82/*
83 * end of autoconf section. To be extended...
84 */
85
86/* Are the following #ifdefs still required? And why? Is that for X11? */
87
88#if defined(ESIX) || defined(M_UNIX) && !defined(SCO)
89# ifdef SIGWINCH
90# undef SIGWINCH
91# endif
92# ifdef TIOCGWINSZ
93# undef TIOCGWINSZ
94# endif
95#endif
96
97#if defined(SIGWINDOW) && !defined(SIGWINCH) /* hpux 9.01 has it */
98# define SIGWINCH SIGWINDOW
99#endif
100
101#ifdef FEAT_X11
102# include <X11/Xlib.h>
103# include <X11/Xutil.h>
104# include <X11/Xatom.h>
105# ifdef FEAT_XCLIPBOARD
106# include <X11/Intrinsic.h>
107# include <X11/Shell.h>
108# include <X11/StringDefs.h>
109static Widget xterm_Shell = (Widget)0;
110static void xterm_update __ARGS((void));
111# endif
112
113# if defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE)
114Window x11_window = 0;
115# endif
116Display *x11_display = NULL;
117
118# ifdef FEAT_TITLE
119static int get_x11_windis __ARGS((void));
120static void set_x11_title __ARGS((char_u *));
121static void set_x11_icon __ARGS((char_u *));
122# endif
123#endif
124
125#ifdef FEAT_TITLE
126static int get_x11_title __ARGS((int));
127static int get_x11_icon __ARGS((int));
128
129static char_u *oldtitle = NULL;
130static int did_set_title = FALSE;
131static char_u *oldicon = NULL;
132static int did_set_icon = FALSE;
133#endif
134
135static void may_core_dump __ARGS((void));
136
137static int WaitForChar __ARGS((long));
138#if defined(__BEOS__)
139int RealWaitForChar __ARGS((int, long, int *));
140#else
141static int RealWaitForChar __ARGS((int, long, int *));
142#endif
143
144#ifdef FEAT_XCLIPBOARD
145static int do_xterm_trace __ARGS((void));
146#define XT_TRACE_DELAY 50 /* delay for xterm tracing */
147#endif
148
149static void handle_resize __ARGS((void));
150
151#if defined(SIGWINCH)
152static RETSIGTYPE sig_winch __ARGS(SIGPROTOARG);
153#endif
154#if defined(SIGINT)
155static RETSIGTYPE catch_sigint __ARGS(SIGPROTOARG);
156#endif
157#if defined(SIGPWR)
158static RETSIGTYPE catch_sigpwr __ARGS(SIGPROTOARG);
159#endif
160#if defined(SIGALRM) && defined(FEAT_X11) \
161 && defined(FEAT_TITLE) && !defined(FEAT_GUI_GTK)
162# define SET_SIG_ALARM
163static RETSIGTYPE sig_alarm __ARGS(SIGPROTOARG);
164static int sig_alarm_called;
165#endif
166static RETSIGTYPE deathtrap __ARGS(SIGPROTOARG);
167
168static void set_signals __ARGS((void));
169static void catch_signals __ARGS((RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)()));
170#ifndef __EMX__
171static int have_wildcard __ARGS((int, char_u **));
172static int have_dollars __ARGS((int, char_u **));
173#endif
174
175#ifndef NO_EXPANDPATH
176static int pstrcmp __ARGS((const void *, const void *));
177static int unix_expandpath __ARGS((garray_T *gap, char_u *path, int wildoff, int flags));
178#endif
179
180#ifndef __EMX__
181static int save_patterns __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file));
182#endif
183
184#ifndef SIG_ERR
185# define SIG_ERR ((RETSIGTYPE (*)())-1)
186#endif
187
188static int do_resize = FALSE;
189#ifndef __EMX__
190static char_u *extra_shell_arg = NULL;
191static int show_shell_mess = TRUE;
192#endif
193static int deadly_signal = 0; /* The signal we caught */
194
195static int curr_tmode = TMODE_COOK; /* contains current terminal mode */
196
197#ifdef USE_XSMP
198typedef struct
199{
200 SmcConn smcconn; /* The SM connection ID */
201 IceConn iceconn; /* The ICE connection ID */
202 Bool save_yourself; /* If we're in the middle of a save_yourself */
203 Bool shutdown; /* If we're in shutdown mode */
204} xsmp_config_T;
205
206static xsmp_config_T xsmp;
207#endif
208
209#ifdef SYS_SIGLIST_DECLARED
210/*
211 * I have seen
212 * extern char *_sys_siglist[NSIG];
213 * on Irix, Linux, NetBSD and Solaris. It contains a nice list of strings
214 * that describe the signals. That is nearly what we want here. But
215 * autoconf does only check for sys_siglist (without the underscore), I
216 * do not want to change everything today.... jw.
217 * This is why AC_DECL_SYS_SIGLIST is commented out in configure.in
218 */
219#endif
220
221static struct signalinfo
222{
223 int sig; /* Signal number, eg. SIGSEGV etc */
224 char *name; /* Signal name (not char_u!). */
225 char deadly; /* Catch as a deadly signal? */
226} signal_info[] =
227{
228#ifdef SIGHUP
229 {SIGHUP, "HUP", TRUE},
230#endif
231#ifdef SIGQUIT
232 {SIGQUIT, "QUIT", TRUE},
233#endif
234#ifdef SIGILL
235 {SIGILL, "ILL", TRUE},
236#endif
237#ifdef SIGTRAP
238 {SIGTRAP, "TRAP", TRUE},
239#endif
240#ifdef SIGABRT
241 {SIGABRT, "ABRT", TRUE},
242#endif
243#ifdef SIGEMT
244 {SIGEMT, "EMT", TRUE},
245#endif
246#ifdef SIGFPE
247 {SIGFPE, "FPE", TRUE},
248#endif
249#ifdef SIGBUS
250 {SIGBUS, "BUS", TRUE},
251#endif
252#ifdef SIGSEGV
253 {SIGSEGV, "SEGV", TRUE},
254#endif
255#ifdef SIGSYS
256 {SIGSYS, "SYS", TRUE},
257#endif
258#ifdef SIGALRM
259 {SIGALRM, "ALRM", FALSE}, /* Perl's alarm() can trigger it */
260#endif
261#ifdef SIGTERM
262 {SIGTERM, "TERM", TRUE},
263#endif
264#ifdef SIGVTALRM
265 {SIGVTALRM, "VTALRM", TRUE},
266#endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +0000267#if defined(SIGPROF) && !defined(FEAT_MZSCHEME)
268 /* MzScheme uses SIGPROF for its own needs */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000269 {SIGPROF, "PROF", TRUE},
270#endif
271#ifdef SIGXCPU
272 {SIGXCPU, "XCPU", TRUE},
273#endif
274#ifdef SIGXFSZ
275 {SIGXFSZ, "XFSZ", TRUE},
276#endif
277#ifdef SIGUSR1
278 {SIGUSR1, "USR1", TRUE},
279#endif
280#ifdef SIGUSR2
281 {SIGUSR2, "USR2", TRUE},
282#endif
283#ifdef SIGINT
284 {SIGINT, "INT", FALSE},
285#endif
286#ifdef SIGWINCH
287 {SIGWINCH, "WINCH", FALSE},
288#endif
289#ifdef SIGTSTP
290 {SIGTSTP, "TSTP", FALSE},
291#endif
292#ifdef SIGPIPE
293 {SIGPIPE, "PIPE", FALSE},
294#endif
295 {-1, "Unknown!", FALSE}
296};
297
298 void
299mch_write(s, len)
300 char_u *s;
301 int len;
302{
303 write(1, (char *)s, len);
304 if (p_wd) /* Unix is too fast, slow down a bit more */
305 RealWaitForChar(read_cmd_fd, p_wd, NULL);
306}
307
308/*
309 * mch_inchar(): low level input funcion.
310 * Get a characters from the keyboard.
311 * Return the number of characters that are available.
312 * If wtime == 0 do not wait for characters.
313 * If wtime == n wait a short time for characters.
314 * If wtime == -1 wait forever for characters.
315 */
316 int
317mch_inchar(buf, maxlen, wtime, tb_change_cnt)
318 char_u *buf;
319 int maxlen;
320 long wtime; /* don't use "time", MIPS cannot handle it */
321 int tb_change_cnt;
322{
323 int len;
324#ifdef FEAT_AUTOCMD
325 static int once_already = 0;
326#endif
327
328 /* Check if window changed size while we were busy, perhaps the ":set
329 * columns=99" command was used. */
330 while (do_resize)
331 handle_resize();
332
333 if (wtime >= 0)
334 {
335 while (WaitForChar(wtime) == 0) /* no character available */
336 {
337 if (!do_resize) /* return if not interrupted by resize */
338 {
339#ifdef FEAT_AUTOCMD
340 once_already = 0;
341#endif
342 return 0;
343 }
344 handle_resize();
345 }
346 }
347 else /* wtime == -1 */
348 {
349#ifdef FEAT_AUTOCMD
350 if (once_already == 2)
351 updatescript(0);
352 else if (once_already == 1)
353 {
354 setcursor();
355 once_already = 2;
356 return 0;
357 }
358 else
359#endif
360 /*
361 * If there is no character available within 'updatetime' seconds
362 * flush all the swap files to disk
363 * Also done when interrupted by SIGWINCH.
364 */
365 if (WaitForChar(p_ut) == 0)
366 {
367#ifdef FEAT_AUTOCMD
368 if (has_cursorhold() && get_real_state() == NORMAL_BUSY)
369 {
370 apply_autocmds(EVENT_CURSORHOLD, NULL, NULL, FALSE, curbuf);
371 update_screen(VALID);
372 once_already = 1;
373 return 0;
374 }
375 else
376#endif
377 updatescript(0);
378 }
379 }
380
381 for (;;) /* repeat until we got a character */
382 {
383 while (do_resize) /* window changed size */
384 handle_resize();
385 /*
386 * we want to be interrupted by the winch signal
387 */
388 WaitForChar(-1L);
389 if (do_resize) /* interrupted by SIGWINCH signal */
390 continue;
391
392 /* If input was put directly in typeahead buffer bail out here. */
393 if (typebuf_changed(tb_change_cnt))
394 return 0;
395
396 /*
397 * For some terminals we only get one character at a time.
398 * We want the get all available characters, so we could keep on
399 * trying until none is available
400 * For some other terminals this is quite slow, that's why we don't do
401 * it.
402 */
403 len = read_from_input_buf(buf, (long)maxlen);
404 if (len > 0)
405 {
406#ifdef OS2
407 int i;
408
409 for (i = 0; i < len; i++)
410 if (buf[i] == 0)
411 buf[i] = K_NUL;
412#endif
413#ifdef FEAT_AUTOCMD
414 once_already = 0;
415#endif
416 return len;
417 }
418 }
419}
420
421 static void
422handle_resize()
423{
424 do_resize = FALSE;
425 shell_resized();
426}
427
428/*
429 * return non-zero if a character is available
430 */
431 int
432mch_char_avail()
433{
434 return WaitForChar(0L);
435}
436
437#if defined(HAVE_TOTAL_MEM) || defined(PROTO)
438# ifdef HAVE_SYS_RESOURCE_H
439# include <sys/resource.h>
440# endif
441# if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTL)
442# include <sys/sysctl.h>
443# endif
444# if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
445# include <sys/sysinfo.h>
446# endif
447
448/*
449 * Return total amount of memory available. Doesn't change when memory has
450 * been allocated.
451 */
452/* ARGSUSED */
453 long_u
454mch_total_mem(special)
455 int special;
456{
457# ifdef __EMX__
458 return ulimit(3, 0L); /* always 32MB? */
459# else
460 long_u mem = 0;
461
462# ifdef HAVE_SYSCTL
463 int mib[2], physmem;
464 size_t len;
465
466 /* BSD way of getting the amount of RAM available. */
467 mib[0] = CTL_HW;
468 mib[1] = HW_USERMEM;
469 len = sizeof(physmem);
470 if (sysctl(mib, 2, &physmem, &len, NULL, 0) == 0)
471 mem = (long_u)physmem;
472# endif
473
474# if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
475 if (mem == 0)
476 {
477 struct sysinfo sinfo;
478
479 /* Linux way of getting amount of RAM available */
480 if (sysinfo(&sinfo) == 0)
481 mem = sinfo.totalram;
482 }
483# endif
484
485# ifdef HAVE_SYSCONF
486 if (mem == 0)
487 {
488 long pagesize, pagecount;
489
490 /* Solaris way of getting amount of RAM available */
491 pagesize = sysconf(_SC_PAGESIZE);
492 pagecount = sysconf(_SC_PHYS_PAGES);
493 if (pagesize > 0 && pagecount > 0)
494 mem = (long_u)pagesize * pagecount;
495 }
496# endif
497
498 /* Return the minimum of the physical memory and the user limit, because
499 * using more than the user limit may cause Vim to be terminated. */
500# if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT)
501 {
502 struct rlimit rlp;
503
504 if (getrlimit(RLIMIT_DATA, &rlp) == 0
505 && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
506# ifdef RLIM_INFINITY
507 && rlp.rlim_cur != RLIM_INFINITY
508# endif
509 && (long_u)rlp.rlim_cur < mem
510 )
511 return (long_u)rlp.rlim_cur;
512 }
513# endif
514
515 if (mem > 0)
516 return mem;
517 return (long_u)0x7fffffff;
518# endif
519}
520#endif
521
522 void
523mch_delay(msec, ignoreinput)
524 long msec;
525 int ignoreinput;
526{
527 int old_tmode;
Bram Moolenaar325b7a22004-07-05 15:58:32 +0000528#ifdef FEAT_MZSCHEME
529 long total = msec; /* remember original value */
530#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000531
532 if (ignoreinput)
533 {
534 /* Go to cooked mode without echo, to allow SIGINT interrupting us
535 * here */
536 old_tmode = curr_tmode;
537 if (curr_tmode == TMODE_RAW)
538 settmode(TMODE_SLEEP);
539
540 /*
541 * Everybody sleeps in a different way...
542 * Prefer nanosleep(), some versions of usleep() can only sleep up to
543 * one second.
544 */
Bram Moolenaar325b7a22004-07-05 15:58:32 +0000545#ifdef FEAT_MZSCHEME
546 do
547 {
548 /* if total is large enough, wait by portions in p_mzq */
549 if (total > p_mzq)
550 msec = p_mzq;
551 else
552 msec = total;
553 total -= msec;
554#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000555#ifdef HAVE_NANOSLEEP
556 {
557 struct timespec ts;
558
559 ts.tv_sec = msec / 1000;
560 ts.tv_nsec = (msec % 1000) * 1000000;
561 (void)nanosleep(&ts, NULL);
562 }
563#else
564# ifdef HAVE_USLEEP
565 while (msec >= 1000)
566 {
567 usleep((unsigned int)(999 * 1000));
568 msec -= 999;
569 }
570 usleep((unsigned int)(msec * 1000));
571# else
572# ifndef HAVE_SELECT
573 poll(NULL, 0, (int)msec);
574# else
575# ifdef __EMX__
576 _sleep2(msec);
577# else
578 {
579 struct timeval tv;
580
581 tv.tv_sec = msec / 1000;
582 tv.tv_usec = (msec % 1000) * 1000;
583 /*
584 * NOTE: Solaris 2.6 has a bug that makes select() hang here. Get
585 * a patch from Sun to fix this. Reported by Gunnar Pedersen.
586 */
587 select(0, NULL, NULL, NULL, &tv);
588 }
589# endif /* __EMX__ */
590# endif /* HAVE_SELECT */
591# endif /* HAVE_NANOSLEEP */
592#endif /* HAVE_USLEEP */
Bram Moolenaar325b7a22004-07-05 15:58:32 +0000593#ifdef FEAT_MZSCHEME
594 }
595 while (total > 0);
596#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000597
598 settmode(old_tmode);
599 }
600 else
601 WaitForChar(msec);
602}
603
604#if defined(HAVE_GETRLIMIT) \
605 || (!defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGSTACK))
606# define HAVE_CHECK_STACK_GROWTH
607/*
608 * Support for checking for an almost-out-of-stack-space situation.
609 */
610
611/*
612 * Return a pointer to an item on the stack. Used to find out if the stack
613 * grows up or down.
614 */
615static void check_stack_growth __ARGS((char *p));
616static int stack_grows_downwards;
617
618/*
619 * Find out if the stack grows upwards or downwards.
620 * "p" points to a variable on the stack of the caller.
621 */
622 static void
623check_stack_growth(p)
624 char *p;
625{
626 int i;
627
628 stack_grows_downwards = (p > (char *)&i);
629}
630#endif
631
632#if defined(HAVE_GETRLIMIT) || defined(PROTO)
633static char *stack_limit = NULL;
634
635#if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
636# include <pthread.h>
637# include <pthread_np.h>
638#endif
639
640/*
641 * Find out until how var the stack can grow without getting into trouble.
642 * Called when starting up and when switching to the signal stack in
643 * deathtrap().
644 */
645 static void
646get_stack_limit()
647{
648 struct rlimit rlp;
649 int i;
650 long lim;
651
652 /* Set the stack limit to 15/16 of the allowable size. Skip this when the
653 * limit doesn't fit in a long (rlim_cur might be "long long"). */
654 if (getrlimit(RLIMIT_STACK, &rlp) == 0
655 && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
656# ifdef RLIM_INFINITY
657 && rlp.rlim_cur != RLIM_INFINITY
658# endif
659 )
660 {
661 lim = (long)rlp.rlim_cur;
662#if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
663 {
664 pthread_attr_t attr;
665 size_t size;
666
667 /* On FreeBSD the initial thread always has a fixed stack size, no
668 * matter what the limits are set to. Normally it's 1 Mbyte. */
669 pthread_attr_init(&attr);
670 if (pthread_attr_get_np(pthread_self(), &attr) == 0)
671 {
672 pthread_attr_getstacksize(&attr, &size);
673 if (lim > (long)size)
674 lim = (long)size;
675 }
676 pthread_attr_destroy(&attr);
677 }
678#endif
679 if (stack_grows_downwards)
680 {
681 stack_limit = (char *)((long)&i - (lim / 16L * 15L));
682 if (stack_limit >= (char *)&i)
683 /* overflow, set to 1/16 of current stack position */
684 stack_limit = (char *)((long)&i / 16L);
685 }
686 else
687 {
688 stack_limit = (char *)((long)&i + (lim / 16L * 15L));
689 if (stack_limit <= (char *)&i)
690 stack_limit = NULL; /* overflow */
691 }
692 }
693}
694
695/*
696 * Return FAIL when running out of stack space.
697 * "p" must point to any variable local to the caller that's on the stack.
698 */
699 int
700mch_stackcheck(p)
701 char *p;
702{
703 if (stack_limit != NULL)
704 {
705 if (stack_grows_downwards)
706 {
707 if (p < stack_limit)
708 return FAIL;
709 }
710 else if (p > stack_limit)
711 return FAIL;
712 }
713 return OK;
714}
715#endif
716
717#if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
718/*
719 * Support for using the signal stack.
720 * This helps when we run out of stack space, which causes a SIGSEGV. The
721 * signal handler then must run on another stack, since the normal stack is
722 * completely full.
723 */
724
725#ifndef SIGSTKSZ
726# define SIGSTKSZ 8000 /* just a guess of how much stack is needed... */
727#endif
728
729# ifdef HAVE_SIGALTSTACK
730static stack_t sigstk; /* for sigaltstack() */
731# else
732static struct sigstack sigstk; /* for sigstack() */
733# endif
734
735static void init_signal_stack __ARGS((void));
736static char *signal_stack;
737
738 static void
739init_signal_stack()
740{
741 if (signal_stack != NULL)
742 {
743# ifdef HAVE_SIGALTSTACK
744# ifdef __APPLE__
745 /* missing prototype. Adding it to osdef?.h.in doesn't work, because
746 * "struct sigaltstack" needs to be declared. */
747 extern int sigaltstack __ARGS((const struct sigaltstack *ss, struct sigaltstack *oss));
748# endif
749
750# ifdef HAVE_SS_BASE
751 sigstk.ss_base = signal_stack;
752# else
753 sigstk.ss_sp = signal_stack;
754# endif
755 sigstk.ss_size = SIGSTKSZ;
756 sigstk.ss_flags = 0;
757 (void)sigaltstack(&sigstk, NULL);
758# else
759 sigstk.ss_sp = signal_stack;
760 if (stack_grows_downwards)
761 sigstk.ss_sp += SIGSTKSZ - 1;
762 sigstk.ss_onstack = 0;
763 (void)sigstack(&sigstk, NULL);
764# endif
765 }
766}
767#endif
768
769/*
770 * We need correct potatotypes for a signal function, otherwise mean compilers
771 * will barf when the second argument to signal() is ``wrong''.
772 * Let me try it with a few tricky defines from my own osdef.h (jw).
773 */
774#if defined(SIGWINCH)
775/* ARGSUSED */
776 static RETSIGTYPE
777sig_winch SIGDEFARG(sigarg)
778{
779 /* this is not required on all systems, but it doesn't hurt anybody */
780 signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
781 do_resize = TRUE;
782 SIGRETURN;
783}
784#endif
785
786#if defined(SIGINT)
787/* ARGSUSED */
788 static RETSIGTYPE
789catch_sigint SIGDEFARG(sigarg)
790{
791 /* this is not required on all systems, but it doesn't hurt anybody */
792 signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
793 got_int = TRUE;
794 SIGRETURN;
795}
796#endif
797
798#if defined(SIGPWR)
799/* ARGSUSED */
800 static RETSIGTYPE
801catch_sigpwr SIGDEFARG(sigarg)
802{
Bram Moolenaard8b0cf12004-12-12 11:33:30 +0000803 /* this is not required on all systems, but it doesn't hurt anybody */
804 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000805 /*
806 * I'm not sure we get the SIGPWR signal when the system is really going
807 * down or when the batteries are almost empty. Just preserve the swap
808 * files and don't exit, that can't do any harm.
809 */
810 ml_sync_all(FALSE, FALSE);
811 SIGRETURN;
812}
813#endif
814
815#ifdef SET_SIG_ALARM
816/*
817 * signal function for alarm().
818 */
819/* ARGSUSED */
820 static RETSIGTYPE
821sig_alarm SIGDEFARG(sigarg)
822{
823 /* doesn't do anything, just to break a system call */
824 sig_alarm_called = TRUE;
825 SIGRETURN;
826}
827#endif
828
829#if defined(HAVE_SETJMP_H) || defined(PROTO)
830/*
831 * A simplistic version of setjmp() that only allows one level of using.
832 * Don't call twice before calling mch_endjmp()!.
833 * Usage:
834 * mch_startjmp();
835 * if (SETJMP(lc_jump_env) != 0)
836 * {
837 * mch_didjmp();
838 * EMSG("crash!");
839 * }
840 * else
841 * {
842 * do_the_work;
843 * mch_endjmp();
844 * }
845 * Note: Can't move SETJMP() here, because a function calling setjmp() must
846 * not return before the saved environment is used.
847 * Returns OK for normal return, FAIL when the protected code caused a
848 * problem and LONGJMP() was used.
849 */
850 void
851mch_startjmp()
852{
853#ifdef SIGHASARG
854 lc_signal = 0;
855#endif
856 lc_active = TRUE;
857}
858
859 void
860mch_endjmp()
861{
862 lc_active = FALSE;
863}
864
865 void
866mch_didjmp()
867{
868# if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
869 /* On FreeBSD the signal stack has to be reset after using siglongjmp(),
870 * otherwise catching the signal only works once. */
871 init_signal_stack();
872# endif
873}
874#endif
875
876/*
877 * This function handles deadly signals.
878 * It tries to preserve any swap file and exit properly.
879 * (partly from Elvis).
880 */
881 static RETSIGTYPE
882deathtrap SIGDEFARG(sigarg)
883{
884 static int entered = 0; /* count the number of times we got here.
885 Note: when memory has been corrupted
886 this may get an arbitrary value! */
887#ifdef SIGHASARG
888 int i;
889#endif
890
891#if defined(HAVE_SETJMP_H)
892 /*
893 * Catch a crash in protected code.
894 * Restores the environment saved in lc_jump_env, which looks like
895 * SETJMP() returns 1.
896 */
897 if (lc_active)
898 {
899# if defined(SIGHASARG)
900 lc_signal = sigarg;
901# endif
902 lc_active = FALSE; /* don't jump again */
903 LONGJMP(lc_jump_env, 1);
904 /* NOTREACHED */
905 }
906#endif
907
Bram Moolenaar293ee4d2004-12-09 21:34:53 +0000908#ifdef SIGHASARG
Bram Moolenaard8b0cf12004-12-12 11:33:30 +0000909 /* When SIGHUP, SIGQUIT, etc. are blocked: postpone the effect and return
910 * here. This avoids that a non-reentrant function is interrupted, e.g.,
911 * free(). Calling free() again may then cause a crash. */
912 if (entered == 0
913 && (0
914# ifdef SIGHUP
915 || sigarg == SIGHUP
916# endif
917# ifdef SIGQUIT
918 || sigarg == SIGQUIT
919# endif
920# ifdef SIGTERM
921 || sigarg == SIGTERM
922# endif
923# ifdef SIGPWR
924 || sigarg == SIGPWR
925# endif
926# ifdef SIGUSR1
927 || sigarg == SIGUSR1
928# endif
929# ifdef SIGUSR2
930 || sigarg == SIGUSR2
931# endif
932 )
933 && !handle_signal(sigarg))
Bram Moolenaar293ee4d2004-12-09 21:34:53 +0000934 SIGRETURN;
935#endif
936
Bram Moolenaar071d4272004-06-13 20:20:40 +0000937 /* Remember how often we have been called. */
938 ++entered;
939
940#ifdef FEAT_EVAL
941 /* Set the v:dying variable. */
942 set_vim_var_nr(VV_DYING, (long)entered);
943#endif
944
945#ifdef HAVE_GETRLIMIT
946 /* Since we are now using the signal stack, need to reset the stack
947 * limit. Otherwise using a regexp will fail. */
948 get_stack_limit();
949#endif
950
951#ifdef SIGHASARG
952 /* try to find the name of this signal */
953 for (i = 0; signal_info[i].sig != -1; i++)
954 if (sigarg == signal_info[i].sig)
955 break;
956 deadly_signal = sigarg;
957#endif
958
959 full_screen = FALSE; /* don't write message to the GUI, it might be
960 * part of the problem... */
961 /*
962 * If something goes wrong after entering here, we may get here again.
963 * When this happens, give a message and try to exit nicely (resetting the
964 * terminal mode, etc.)
965 * When this happens twice, just exit, don't even try to give a message,
966 * stack may be corrupt or something weird.
967 * When this still happens again (or memory was corrupted in such a way
968 * that "entered" was clobbered) use _exit(), don't try freeing resources.
969 */
970 if (entered >= 3)
971 {
972 reset_signals(); /* don't catch any signals anymore */
973 may_core_dump();
974 if (entered >= 4)
975 _exit(8);
976 exit(7);
977 }
978 if (entered == 2)
979 {
980 OUT_STR(_("Vim: Double signal, exiting\n"));
981 out_flush();
982 getout(1);
983 }
984
985#ifdef SIGHASARG
986 sprintf((char *)IObuff, _("Vim: Caught deadly signal %s\n"),
987 signal_info[i].name);
988#else
989 sprintf((char *)IObuff, _("Vim: Caught deadly signal\n"));
990#endif
991 preserve_exit(); /* preserve files and exit */
992
Bram Moolenaar009b2592004-10-24 19:18:58 +0000993#ifdef NBDEBUG
994 reset_signals();
995 may_core_dump();
996 abort();
997#endif
998
Bram Moolenaar071d4272004-06-13 20:20:40 +0000999 SIGRETURN;
1000}
1001
1002#ifdef _REENTRANT
1003/*
1004 * On Solaris with multi-threading, suspending might not work immediately.
1005 * Catch the SIGCONT signal, which will be used as an indication whether the
1006 * suspending has been done or not.
1007 */
1008static int sigcont_received;
1009static RETSIGTYPE sigcont_handler __ARGS(SIGPROTOARG);
1010
1011/*
1012 * signal handler for SIGCONT
1013 */
1014/* ARGSUSED */
1015 static RETSIGTYPE
1016sigcont_handler SIGDEFARG(sigarg)
1017{
1018 sigcont_received = TRUE;
1019 SIGRETURN;
1020}
1021#endif
1022
1023/*
1024 * If the machine has job control, use it to suspend the program,
1025 * otherwise fake it by starting a new shell.
1026 */
1027 void
1028mch_suspend()
1029{
1030 /* BeOS does have SIGTSTP, but it doesn't work. */
1031#if defined(SIGTSTP) && !defined(__BEOS__)
1032 out_flush(); /* needed to make cursor visible on some systems */
1033 settmode(TMODE_COOK);
1034 out_flush(); /* needed to disable mouse on some systems */
1035
1036# if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
1037 /* Since we are going to sleep, we can't respond to requests for the X
1038 * selections. Lose them, otherwise other applications will hang. But
1039 * first copy the text to cut buffer 0. */
1040 if (clip_star.owned || clip_plus.owned)
1041 {
1042 x11_export_final_selection();
1043 if (clip_star.owned)
1044 clip_lose_selection(&clip_star);
1045 if (clip_plus.owned)
1046 clip_lose_selection(&clip_plus);
1047 if (x11_display != NULL)
1048 XFlush(x11_display);
1049 }
1050# endif
1051
1052# ifdef _REENTRANT
1053 sigcont_received = FALSE;
1054# endif
1055 kill(0, SIGTSTP); /* send ourselves a STOP signal */
1056# ifdef _REENTRANT
1057 /* When we didn't suspend immediately in the kill(), do it now. Happens
1058 * on multi-threaded Solaris. */
1059 if (!sigcont_received)
1060 pause();
1061# endif
1062
1063# ifdef FEAT_TITLE
1064 /*
1065 * Set oldtitle to NULL, so the current title is obtained again.
1066 */
1067 vim_free(oldtitle);
1068 oldtitle = NULL;
1069# endif
1070 settmode(TMODE_RAW);
1071 need_check_timestamps = TRUE;
1072 did_check_timestamps = FALSE;
1073#else
1074 suspend_shell();
1075#endif
1076}
1077
1078 void
1079mch_init()
1080{
1081 Columns = 80;
1082 Rows = 24;
1083
1084 out_flush();
1085 set_signals();
1086}
1087
1088 static void
1089set_signals()
1090{
1091#if defined(SIGWINCH)
1092 /*
1093 * WINDOW CHANGE signal is handled with sig_winch().
1094 */
1095 signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
1096#endif
1097
1098 /*
1099 * We want the STOP signal to work, to make mch_suspend() work.
1100 * For "rvim" the STOP signal is ignored.
1101 */
1102#ifdef SIGTSTP
1103 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
1104#endif
1105#ifdef _REENTRANT
1106 signal(SIGCONT, sigcont_handler);
1107#endif
1108
1109 /*
1110 * We want to ignore breaking of PIPEs.
1111 */
1112#ifdef SIGPIPE
1113 signal(SIGPIPE, SIG_IGN);
1114#endif
1115
1116 /*
1117 * We want to catch CTRL-C (only works while in Cooked mode).
1118 */
1119#ifdef SIGINT
1120 signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
1121#endif
1122
1123 /*
1124 * Ignore alarm signals (Perl's alarm() generates it).
1125 */
1126#ifdef SIGALRM
1127 signal(SIGALRM, SIG_IGN);
1128#endif
1129
1130 /*
1131 * Catch SIGPWR (power failure?) to preserve the swap files, so that no
1132 * work will be lost.
1133 */
1134#ifdef SIGPWR
1135 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
1136#endif
1137
1138 /*
1139 * Arrange for other signals to gracefully shutdown Vim.
1140 */
1141 catch_signals(deathtrap, SIG_ERR);
1142
1143#if defined(FEAT_GUI) && defined(SIGHUP)
1144 /*
1145 * When the GUI is running, ignore the hangup signal.
1146 */
1147 if (gui.in_use)
1148 signal(SIGHUP, SIG_IGN);
1149#endif
1150}
1151
1152 void
1153reset_signals()
1154{
1155 catch_signals(SIG_DFL, SIG_DFL);
1156#ifdef _REENTRANT
1157 /* SIGCONT isn't in the list, because its default action is ignore */
1158 signal(SIGCONT, SIG_DFL);
1159#endif
1160}
1161
1162 static void
1163catch_signals(func_deadly, func_other)
1164 RETSIGTYPE (*func_deadly)();
1165 RETSIGTYPE (*func_other)();
1166{
1167 int i;
1168
1169 for (i = 0; signal_info[i].sig != -1; i++)
1170 if (signal_info[i].deadly)
1171 {
1172#if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
1173 struct sigaction sa;
1174
1175 /* Setup to use the alternate stack for the signal function. */
1176 sa.sa_handler = func_deadly;
1177 sigemptyset(&sa.sa_mask);
1178# if defined(__linux__) && defined(_REENTRANT)
1179 /* On Linux, with glibc compiled for kernel 2.2, there is a bug in
1180 * thread handling in combination with using the alternate stack:
1181 * pthread library functions try to use the stack pointer to
1182 * identify the current thread, causing a SEGV signal, which
1183 * recursively calls deathtrap() and hangs. */
1184 sa.sa_flags = 0;
1185# else
1186 sa.sa_flags = SA_ONSTACK;
1187# endif
1188 sigaction(signal_info[i].sig, &sa, NULL);
1189#else
1190# if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGVEC)
1191 struct sigvec sv;
1192
1193 /* Setup to use the alternate stack for the signal function. */
1194 sv.sv_handler = func_deadly;
1195 sv.sv_mask = 0;
1196 sv.sv_flags = SV_ONSTACK;
1197 sigvec(signal_info[i].sig, &sv, NULL);
1198# else
1199 signal(signal_info[i].sig, func_deadly);
1200# endif
1201#endif
1202 }
1203 else if (func_other != SIG_ERR)
1204 signal(signal_info[i].sig, func_other);
1205}
1206
1207/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001208 * Handling of SIGHUP, SIGQUIT and SIGTERM:
1209 * "when" == a signal: when busy, postpone, otherwise return TRUE
1210 * "when" == SIGNAL_BLOCK: Going to be busy, block signals
1211 * "when" == SIGNAL_UNBLOCK: Going wait, unblock signals
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001212 * Returns TRUE when Vim should exit.
1213 */
1214 int
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001215handle_signal(sig)
1216 int sig;
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001217{
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001218 static int got_signal = 0;
1219 static int blocked = TRUE;
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001220
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001221 switch (sig)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001222 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001223 case SIGNAL_BLOCK: blocked = TRUE;
1224 break;
1225
1226 case SIGNAL_UNBLOCK: blocked = FALSE;
1227 if (got_signal != 0)
1228 {
1229 kill(getpid(), got_signal);
1230 got_signal = 0;
1231 }
1232 break;
1233
1234 default: if (!blocked)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001235 return TRUE; /* exit! */
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001236 got_signal = sig;
1237#ifdef SIGPWR
1238 if (sig != SIGPWR)
1239#endif
1240 got_int = TRUE; /* break any loops */
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00001241 break;
1242 }
1243 return FALSE;
1244}
1245
1246/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00001247 * Check_win checks whether we have an interactive stdout.
1248 */
1249/* ARGSUSED */
1250 int
1251mch_check_win(argc, argv)
1252 int argc;
1253 char **argv;
1254{
1255#ifdef OS2
1256 /*
1257 * Store argv[0], may be used for $VIM. Only use it if it is an absolute
1258 * name, mostly it's just "vim" and found in the path, which is unusable.
1259 */
1260 if (mch_isFullName(argv[0]))
1261 exe_name = vim_strsave((char_u *)argv[0]);
1262#endif
1263 if (isatty(1))
1264 return OK;
1265 return FAIL;
1266}
1267
1268/*
1269 * Return TRUE if the input comes from a terminal, FALSE otherwise.
1270 */
1271 int
1272mch_input_isatty()
1273{
1274 if (isatty(read_cmd_fd))
1275 return TRUE;
1276 return FALSE;
1277}
1278
1279#ifdef FEAT_X11
1280
1281# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) \
1282 && (defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE))
1283
1284static void xopen_message __ARGS((struct timeval *tvp));
1285
1286/*
1287 * Give a message about the elapsed time for opening the X window.
1288 */
1289 static void
1290xopen_message(tvp)
1291 struct timeval *tvp; /* must contain start time */
1292{
1293 struct timeval end_tv;
1294
1295 /* Compute elapsed time. */
1296 gettimeofday(&end_tv, NULL);
1297 smsg((char_u *)_("Opening the X display took %ld msec"),
1298 (end_tv.tv_sec - tvp->tv_sec) * 1000L
1299 + (end_tv.tv_usec - tvp->tv_usec) / 1000L);
1300}
1301# endif
1302#endif
1303
1304#if defined(FEAT_X11) && (defined(FEAT_TITLE) || defined(FEAT_XCLIPBOARD))
1305/*
1306 * A few functions shared by X11 title and clipboard code.
1307 */
1308static int x_error_handler __ARGS((Display *dpy, XErrorEvent *error_event));
1309static int x_error_check __ARGS((Display *dpy, XErrorEvent *error_event));
1310static int x_connect_to_server __ARGS((void));
1311static int test_x11_window __ARGS((Display *dpy));
1312
1313static int got_x_error = FALSE;
1314
1315/*
1316 * X Error handler, otherwise X just exits! (very rude) -- webb
1317 */
1318 static int
1319x_error_handler(dpy, error_event)
1320 Display *dpy;
1321 XErrorEvent *error_event;
1322{
Bram Moolenaar843ee412004-06-30 16:16:41 +00001323 /* KDE sometimes produces X error that we want to ignore */
1324#if defined(FEAT_GUI_KDE)
1325 XGetErrorText(dpy, error_event->error_code, (char *)IObuff, IOSIZE);
1326 STRCAT(IObuff, "\nVim: Got X error but we continue...\n");
1327 fprintf(stderr, IObuff);
1328 return 0;
1329#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001330 XGetErrorText(dpy, error_event->error_code, (char *)IObuff, IOSIZE);
1331 STRCAT(IObuff, _("\nVim: Got X error\n"));
1332
1333 /* We cannot print a message and continue, because no X calls are allowed
1334 * here (causes my system to hang). Silently continuing might be an
1335 * alternative... */
1336 preserve_exit(); /* preserve files and exit */
1337
1338 return 0; /* NOTREACHED */
Bram Moolenaar843ee412004-06-30 16:16:41 +00001339#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001340}
1341
1342/*
1343 * Another X Error handler, just used to check for errors.
1344 */
1345/* ARGSUSED */
1346 static int
1347x_error_check(dpy, error_event)
1348 Display *dpy;
1349 XErrorEvent *error_event;
1350{
1351 got_x_error = TRUE;
1352 return 0;
1353}
1354
1355#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
1356# if defined(HAVE_SETJMP_H)
1357/*
1358 * An X IO Error handler, used to catch error while opening the display.
1359 */
1360static int x_IOerror_check __ARGS((Display *dpy));
1361
1362/* ARGSUSED */
1363 static int
1364x_IOerror_check(dpy)
1365 Display *dpy;
1366{
1367 /* This function should not return, it causes exit(). Longjump instead. */
1368 LONGJMP(lc_jump_env, 1);
1369 /*NOTREACHED*/
1370 return 0;
1371}
1372# endif
1373
1374/*
1375 * An X IO Error handler, used to catch terminal errors.
1376 */
1377static int x_IOerror_handler __ARGS((Display *dpy));
1378
1379/* ARGSUSED */
1380 static int
1381x_IOerror_handler(dpy)
1382 Display *dpy;
1383{
1384 xterm_dpy = NULL;
1385 x11_window = 0;
1386 x11_display = NULL;
1387 xterm_Shell = (Widget)0;
1388
1389 /* This function should not return, it causes exit(). Longjump instead. */
1390 LONGJMP(x_jump_env, 1);
1391 /*NOTREACHED*/
1392 return 0;
1393}
1394#endif
1395
1396/*
1397 * Return TRUE when connection to the X server is desired.
1398 */
1399 static int
1400x_connect_to_server()
1401{
1402 regmatch_T regmatch;
1403
1404#if defined(FEAT_CLIENTSERVER)
1405 if (x_force_connect)
1406 return TRUE;
1407#endif
1408 if (x_no_connect)
1409 return FALSE;
1410
1411 /* Check for a match with "exclude:" from 'clipboard'. */
1412 if (clip_exclude_prog != NULL)
1413 {
1414 regmatch.rm_ic = FALSE; /* Don't ignore case */
1415 regmatch.regprog = clip_exclude_prog;
1416 if (vim_regexec(&regmatch, T_NAME, (colnr_T)0))
1417 return FALSE;
1418 }
1419 return TRUE;
1420}
1421
1422/*
1423 * Test if "dpy" and x11_window are valid by getting the window title.
1424 * I don't actually want it yet, so there may be a simpler call to use, but
1425 * this will cause the error handler x_error_check() to be called if anything
1426 * is wrong, such as the window pointer being invalid (as can happen when the
1427 * user changes his DISPLAY, but not his WINDOWID) -- webb
1428 */
1429 static int
1430test_x11_window(dpy)
1431 Display *dpy;
1432{
1433 int (*old_handler)();
1434 XTextProperty text_prop;
1435
1436 old_handler = XSetErrorHandler(x_error_check);
1437 got_x_error = FALSE;
1438 if (XGetWMName(dpy, x11_window, &text_prop))
1439 XFree((void *)text_prop.value);
1440 XSync(dpy, False);
1441 (void)XSetErrorHandler(old_handler);
1442
1443 if (p_verbose > 0 && got_x_error)
1444 MSG(_("Testing the X display failed"));
1445
1446 return (got_x_error ? FAIL : OK);
1447}
1448#endif
1449
1450#ifdef FEAT_TITLE
1451
1452#ifdef FEAT_X11
1453
1454static int get_x11_thing __ARGS((int get_title, int test_only));
1455
1456/*
1457 * try to get x11 window and display
1458 *
1459 * return FAIL for failure, OK otherwise
1460 */
1461 static int
1462get_x11_windis()
1463{
1464 char *winid;
1465 static int result = -1;
1466#define XD_NONE 0 /* x11_display not set here */
1467#define XD_HERE 1 /* x11_display opened here */
1468#define XD_GUI 2 /* x11_display used from gui.dpy */
1469#define XD_XTERM 3 /* x11_display used from xterm_dpy */
1470 static int x11_display_from = XD_NONE;
1471 static int did_set_error_handler = FALSE;
1472
1473 if (!did_set_error_handler)
1474 {
1475 /* X just exits if it finds an error otherwise! */
1476 (void)XSetErrorHandler(x_error_handler);
1477 did_set_error_handler = TRUE;
1478 }
1479
Bram Moolenaar843ee412004-06-30 16:16:41 +00001480#if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_KDE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001481 if (gui.in_use)
1482 {
1483 /*
1484 * If the X11 display was opened here before, for the window where Vim
1485 * was started, close that one now to avoid a memory leak.
1486 */
1487 if (x11_display_from == XD_HERE && x11_display != NULL)
1488 {
1489 XCloseDisplay(x11_display);
1490 x11_display_from = XD_NONE;
1491 }
1492 if (gui_get_x11_windis(&x11_window, &x11_display) == OK)
1493 {
1494 x11_display_from = XD_GUI;
1495 return OK;
1496 }
1497 x11_display = NULL;
1498 return FAIL;
1499 }
1500 else if (x11_display_from == XD_GUI)
1501 {
1502 /* GUI must have stopped somehow, clear x11_display */
1503 x11_window = 0;
1504 x11_display = NULL;
1505 x11_display_from = XD_NONE;
1506 }
1507#endif
1508
1509 /* When started with the "-X" argument, don't try connecting. */
1510 if (!x_connect_to_server())
1511 return FAIL;
1512
1513 /*
1514 * If WINDOWID not set, should try another method to find out
1515 * what the current window number is. The only code I know for
1516 * this is very complicated.
1517 * We assume that zero is invalid for WINDOWID.
1518 */
1519 if (x11_window == 0 && (winid = getenv("WINDOWID")) != NULL)
1520 x11_window = (Window)atol(winid);
1521
1522#ifdef FEAT_XCLIPBOARD
1523 if (xterm_dpy != NULL && x11_window != 0)
1524 {
1525 /* Checked it already. */
1526 if (x11_display_from == XD_XTERM)
1527 return OK;
1528
1529 /*
1530 * If the X11 display was opened here before, for the window where Vim
1531 * was started, close that one now to avoid a memory leak.
1532 */
1533 if (x11_display_from == XD_HERE && x11_display != NULL)
1534 XCloseDisplay(x11_display);
1535 x11_display = xterm_dpy;
1536 x11_display_from = XD_XTERM;
1537 if (test_x11_window(x11_display) == FAIL)
1538 {
1539 /* probably bad $WINDOWID */
1540 x11_window = 0;
1541 x11_display = NULL;
1542 x11_display_from = XD_NONE;
1543 return FAIL;
1544 }
1545 return OK;
1546 }
1547#endif
1548
1549 if (x11_window == 0 || x11_display == NULL)
1550 result = -1;
1551
1552 if (result != -1) /* Have already been here and set this */
1553 return result; /* Don't do all these X calls again */
1554
1555 if (x11_window != 0 && x11_display == NULL)
1556 {
1557#ifdef SET_SIG_ALARM
1558 RETSIGTYPE (*sig_save)();
1559#endif
1560#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1561 struct timeval start_tv;
1562
1563 if (p_verbose > 0)
1564 gettimeofday(&start_tv, NULL);
1565#endif
1566
1567#ifdef SET_SIG_ALARM
1568 /*
1569 * Opening the Display may hang if the DISPLAY setting is wrong, or
1570 * the network connection is bad. Set an alarm timer to get out.
1571 */
1572 sig_alarm_called = FALSE;
1573 sig_save = (RETSIGTYPE (*)())signal(SIGALRM,
1574 (RETSIGTYPE (*)())sig_alarm);
1575 alarm(2);
1576#endif
1577 x11_display = XOpenDisplay(NULL);
1578
1579#ifdef SET_SIG_ALARM
1580 alarm(0);
1581 signal(SIGALRM, (RETSIGTYPE (*)())sig_save);
1582 if (p_verbose > 0 && sig_alarm_called)
1583 MSG(_("Opening the X display timed out"));
1584#endif
1585 if (x11_display != NULL)
1586 {
1587# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1588 if (p_verbose > 0)
1589 xopen_message(&start_tv);
1590# endif
1591 if (test_x11_window(x11_display) == FAIL)
1592 {
1593 /* Maybe window id is bad */
1594 x11_window = 0;
1595 XCloseDisplay(x11_display);
1596 x11_display = NULL;
1597 }
1598 else
1599 x11_display_from = XD_HERE;
1600 }
1601 }
1602 if (x11_window == 0 || x11_display == NULL)
1603 return (result = FAIL);
1604 return (result = OK);
1605}
1606
1607/*
1608 * Determine original x11 Window Title
1609 */
1610 static int
1611get_x11_title(test_only)
1612 int test_only;
1613{
Bram Moolenaar47136d72004-10-12 20:02:24 +00001614 return get_x11_thing(TRUE, test_only);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001615}
1616
1617/*
1618 * Determine original x11 Window icon
1619 */
1620 static int
1621get_x11_icon(test_only)
1622 int test_only;
1623{
1624 int retval = FALSE;
1625
1626 retval = get_x11_thing(FALSE, test_only);
1627
1628 /* could not get old icon, use terminal name */
1629 if (oldicon == NULL && !test_only)
1630 {
1631 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1632 oldicon = T_NAME + 8;
1633 else
1634 oldicon = T_NAME;
1635 }
1636
1637 return retval;
1638}
1639
1640 static int
1641get_x11_thing(get_title, test_only)
1642 int get_title; /* get title string */
1643 int test_only;
1644{
1645 XTextProperty text_prop;
1646 int retval = FALSE;
1647 Status status;
1648
1649 if (get_x11_windis() == OK)
1650 {
1651 /* Get window/icon name if any */
1652 if (get_title)
1653 status = XGetWMName(x11_display, x11_window, &text_prop);
1654 else
1655 status = XGetWMIconName(x11_display, x11_window, &text_prop);
1656
1657 /*
1658 * If terminal is xterm, then x11_window may be a child window of the
1659 * outer xterm window that actually contains the window/icon name, so
1660 * keep traversing up the tree until a window with a title/icon is
1661 * found.
1662 */
1663 /* Previously this was only done for xterm and alikes. I don't see a
1664 * reason why it would fail for other terminal emulators.
1665 * if (term_is_xterm) */
1666 {
1667 Window root;
1668 Window parent;
1669 Window win = x11_window;
1670 Window *children;
1671 unsigned int num_children;
1672
1673 while (!status || text_prop.value == NULL)
1674 {
1675 if (!XQueryTree(x11_display, win, &root, &parent, &children,
1676 &num_children))
1677 break;
1678 if (children)
1679 XFree((void *)children);
1680 if (parent == root || parent == 0)
1681 break;
1682
1683 win = parent;
1684 if (get_title)
1685 status = XGetWMName(x11_display, win, &text_prop);
1686 else
1687 status = XGetWMIconName(x11_display, win, &text_prop);
1688 }
1689 }
1690 if (status && text_prop.value != NULL)
1691 {
1692 retval = TRUE;
1693 if (!test_only)
1694 {
1695#ifdef FEAT_XFONTSET
1696 if (text_prop.encoding == XA_STRING)
1697 {
1698#endif
1699 if (get_title)
1700 oldtitle = vim_strsave((char_u *)text_prop.value);
1701 else
1702 oldicon = vim_strsave((char_u *)text_prop.value);
1703#ifdef FEAT_XFONTSET
1704 }
1705 else
1706 {
1707 char **cl;
1708 Status transform_status;
1709 int n = 0;
1710
1711 transform_status = XmbTextPropertyToTextList(x11_display,
1712 &text_prop,
1713 &cl, &n);
1714 if (transform_status >= Success && n > 0 && cl[0])
1715 {
1716 if (get_title)
1717 oldtitle = vim_strsave((char_u *) cl[0]);
1718 else
1719 oldicon = vim_strsave((char_u *) cl[0]);
1720 XFreeStringList(cl);
1721 }
1722 else
1723 {
1724 if (get_title)
1725 oldtitle = vim_strsave((char_u *)text_prop.value);
1726 else
1727 oldicon = vim_strsave((char_u *)text_prop.value);
1728 }
1729 }
1730#endif
1731 }
1732 XFree((void *)text_prop.value);
1733 }
1734 }
1735 return retval;
1736}
1737
1738/* Are Xutf8 functions available? Avoid error from old compilers. */
1739#if defined(X_HAVE_UTF8_STRING) && defined(FEAT_MBYTE)
1740# if X_HAVE_UTF8_STRING
1741# define USE_UTF8_STRING
1742# endif
1743#endif
1744
1745/*
1746 * Set x11 Window Title
1747 *
1748 * get_x11_windis() must be called before this and have returned OK
1749 */
1750 static void
1751set_x11_title(title)
1752 char_u *title;
1753{
1754 /* XmbSetWMProperties() and Xutf8SetWMProperties() should use a STRING
1755 * when possible, COMPOUND_TEXT otherwise. COMPOUND_TEXT isn't
1756 * supported everywhere and STRING doesn't work for multi-byte titles.
1757 */
1758#ifdef USE_UTF8_STRING
1759 if (enc_utf8)
1760 Xutf8SetWMProperties(x11_display, x11_window, (const char *)title,
1761 NULL, NULL, 0, NULL, NULL, NULL);
1762 else
1763#endif
1764 {
1765#if XtSpecificationRelease >= 4
1766# ifdef FEAT_XFONTSET
1767 XmbSetWMProperties(x11_display, x11_window, (const char *)title,
1768 NULL, NULL, 0, NULL, NULL, NULL);
1769# else
1770 XTextProperty text_prop;
1771
1772 /* directly from example 3-18 "basicwin" of Xlib Programming Manual */
1773 (void)XStringListToTextProperty((char **)&title, 1, &text_prop);
1774 XSetWMProperties(x11_display, x11_window, &text_prop,
1775 NULL, NULL, 0, NULL, NULL, NULL);
1776# endif
1777#else
1778 XStoreName(x11_display, x11_window, (char *)title);
1779#endif
1780 }
1781 XFlush(x11_display);
1782}
1783
1784/*
1785 * Set x11 Window icon
1786 *
1787 * get_x11_windis() must be called before this and have returned OK
1788 */
1789 static void
1790set_x11_icon(icon)
1791 char_u *icon;
1792{
1793 /* See above for comments about using X*SetWMProperties(). */
1794#ifdef USE_UTF8_STRING
1795 if (enc_utf8)
1796 Xutf8SetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
1797 NULL, 0, NULL, NULL, NULL);
1798 else
1799#endif
1800 {
1801#if XtSpecificationRelease >= 4
1802# ifdef FEAT_XFONTSET
1803 XmbSetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
1804 NULL, 0, NULL, NULL, NULL);
1805# else
1806 XTextProperty text_prop;
1807
1808 (void)XStringListToTextProperty((char **)&icon, 1, &text_prop);
1809 XSetWMProperties(x11_display, x11_window, NULL, &text_prop,
1810 NULL, 0, NULL, NULL, NULL);
1811# endif
1812#else
1813 XSetIconName(x11_display, x11_window, (char *)icon);
1814#endif
1815 }
1816 XFlush(x11_display);
1817}
1818
1819#else /* FEAT_X11 */
1820
1821/*ARGSUSED*/
1822 static int
1823get_x11_title(test_only)
1824 int test_only;
1825{
1826 return FALSE;
1827}
1828
1829 static int
1830get_x11_icon(test_only)
1831 int test_only;
1832{
1833 if (!test_only)
1834 {
1835 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1836 oldicon = T_NAME + 8;
1837 else
1838 oldicon = T_NAME;
1839 }
1840 return FALSE;
1841}
1842
1843#endif /* FEAT_X11 */
1844
1845 int
1846mch_can_restore_title()
1847{
1848 return get_x11_title(TRUE);
1849}
1850
1851 int
1852mch_can_restore_icon()
1853{
1854 return get_x11_icon(TRUE);
1855}
1856
1857/*
1858 * Set the window title and icon.
1859 */
1860 void
1861mch_settitle(title, icon)
1862 char_u *title;
1863 char_u *icon;
1864{
1865 int type = 0;
1866 static int recursive = 0;
1867
1868 if (T_NAME == NULL) /* no terminal name (yet) */
1869 return;
1870 if (title == NULL && icon == NULL) /* nothing to do */
1871 return;
1872
1873 /* When one of the X11 functions causes a deadly signal, we get here again
1874 * recursively. Avoid hanging then (something is probably locked). */
1875 if (recursive)
1876 return;
1877 ++recursive;
1878
1879 /*
1880 * if the window ID and the display is known, we may use X11 calls
1881 */
1882#ifdef FEAT_X11
1883 if (get_x11_windis() == OK)
1884 type = 1;
1885#else
1886# if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_GTK)
1887 if (gui.in_use)
1888 type = 1;
1889# endif
1890# ifdef FEAT_GUI_BEOS
1891 /* TODO: If this means (gui.in_use) why not merge with above? (Dany) */
1892 /* we always have a 'window' */
1893 type = 1;
1894# endif
1895#endif
1896
1897 /*
1898 * Note: if "t_TS" is set, title is set with escape sequence rather
1899 * than x11 calls, because the x11 calls don't always work
1900 */
Bram Moolenaar843ee412004-06-30 16:16:41 +00001901#ifdef FEAT_GUI_KDE
Bram Moolenaar47136d72004-10-12 20:02:24 +00001902 /* dont know why but KDE needs this one as we don't go through the next
1903 * function... */
Bram Moolenaar843ee412004-06-30 16:16:41 +00001904 gui_mch_settitle(title, icon);
1905#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001906 if ((type || *T_TS != NUL) && title != NULL)
1907 {
1908 if (oldtitle == NULL
1909#ifdef FEAT_GUI
1910 && !gui.in_use
1911#endif
1912 ) /* first call but not in GUI, save title */
1913 (void)get_x11_title(FALSE);
1914
1915 if (*T_TS != NUL) /* it's OK if t_fs is empty */
1916 term_settitle(title);
1917#ifdef FEAT_X11
1918 else
1919# ifdef FEAT_GUI_GTK
1920 if (!gui.in_use) /* don't do this if GTK+ is running */
1921# endif
1922 set_x11_title(title); /* x11 */
1923#endif
1924#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_BEOS) \
1925 || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
1926 else
1927 gui_mch_settitle(title, icon);
1928#endif
1929 did_set_title = TRUE;
1930 }
1931
1932 if ((type || *T_CIS != NUL) && icon != NULL)
1933 {
1934 if (oldicon == NULL
1935#ifdef FEAT_GUI
1936 && !gui.in_use
1937#endif
1938 ) /* first call, save icon */
1939 get_x11_icon(FALSE);
1940
1941 if (*T_CIS != NUL)
1942 {
1943 out_str(T_CIS); /* set icon start */
1944 out_str_nf(icon);
1945 out_str(T_CIE); /* set icon end */
1946 out_flush();
1947 }
1948#ifdef FEAT_X11
1949 else
1950# ifdef FEAT_GUI_GTK
1951 if (!gui.in_use) /* don't do this if GTK+ is running */
1952# endif
1953 set_x11_icon(icon); /* x11 */
1954#endif
1955 did_set_icon = TRUE;
1956 }
1957 --recursive;
1958}
1959
1960/*
1961 * Restore the window/icon title.
1962 * "which" is one of:
1963 * 1 only restore title
1964 * 2 only restore icon
1965 * 3 restore title and icon
1966 */
1967 void
1968mch_restore_title(which)
1969 int which;
1970{
1971 /* only restore the title or icon when it has been set */
1972 mch_settitle(((which & 1) && did_set_title) ?
1973 (oldtitle ? oldtitle : p_titleold) : NULL,
1974 ((which & 2) && did_set_icon) ? oldicon : NULL);
1975}
1976
1977#endif /* FEAT_TITLE */
1978
1979/*
1980 * Return TRUE if "name" looks like some xterm name.
1981 */
1982 int
1983vim_is_xterm(name)
1984 char_u *name;
1985{
1986 if (name == NULL)
1987 return FALSE;
1988 return (STRNICMP(name, "xterm", 5) == 0
1989 || STRNICMP(name, "nxterm", 6) == 0
1990 || STRNICMP(name, "kterm", 5) == 0
1991 || STRNICMP(name, "rxvt", 4) == 0
1992 || STRCMP(name, "builtin_xterm") == 0);
1993}
1994
1995#if defined(FEAT_MOUSE_TTY) || defined(PROTO)
1996/*
1997 * Return non-zero when using an xterm mouse, according to 'ttymouse'.
1998 * Return 1 for "xterm".
1999 * Return 2 for "xterm2".
2000 */
2001 int
2002use_xterm_mouse()
2003{
2004 if (ttym_flags == TTYM_XTERM2)
2005 return 2;
2006 if (ttym_flags == TTYM_XTERM)
2007 return 1;
2008 return 0;
2009}
2010#endif
2011
2012 int
2013vim_is_iris(name)
2014 char_u *name;
2015{
2016 if (name == NULL)
2017 return FALSE;
2018 return (STRNICMP(name, "iris-ansi", 9) == 0
2019 || STRCMP(name, "builtin_iris-ansi") == 0);
2020}
2021
2022 int
2023vim_is_vt300(name)
2024 char_u *name;
2025{
2026 if (name == NULL)
2027 return FALSE; /* actually all ANSI comp. terminals should be here */
Bram Moolenaard4755bb2004-09-02 19:12:26 +00002028 /* catch VT100 - VT5xx */
2029 return ((STRNICMP(name, "vt", 2) == 0
2030 && vim_strchr((char_u *)"12345", name[2]) != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002031 || STRCMP(name, "builtin_vt320") == 0);
2032}
2033
2034/*
2035 * Return TRUE if "name" is a terminal for which 'ttyfast' should be set.
2036 * This should include all windowed terminal emulators.
2037 */
2038 int
2039vim_is_fastterm(name)
2040 char_u *name;
2041{
2042 if (name == NULL)
2043 return FALSE;
2044 if (vim_is_xterm(name) || vim_is_vt300(name) || vim_is_iris(name))
2045 return TRUE;
2046 return ( STRNICMP(name, "hpterm", 6) == 0
2047 || STRNICMP(name, "sun-cmd", 7) == 0
2048 || STRNICMP(name, "screen", 6) == 0
2049 || STRNICMP(name, "dtterm", 6) == 0);
2050}
2051
2052/*
2053 * Insert user name in s[len].
2054 * Return OK if a name found.
2055 */
2056 int
2057mch_get_user_name(s, len)
2058 char_u *s;
2059 int len;
2060{
2061#ifdef VMS
2062 STRNCPY((char *)s, cuserid(NULL), len);
2063 return OK;
2064#else
2065 return mch_get_uname(getuid(), s, len);
2066#endif
2067}
2068
2069/*
2070 * Insert user name for "uid" in s[len].
2071 * Return OK if a name found.
2072 */
2073 int
2074mch_get_uname(uid, s, len)
2075 uid_t uid;
2076 char_u *s;
2077 int len;
2078{
2079#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
2080 struct passwd *pw;
2081
2082 if ((pw = getpwuid(uid)) != NULL
2083 && pw->pw_name != NULL && *(pw->pw_name) != NUL)
2084 {
2085 STRNCPY(s, pw->pw_name, len);
2086 return OK;
2087 }
2088#endif
2089 sprintf((char *)s, "%d", (int)uid); /* assumes s is long enough */
2090 return FAIL; /* a number is not a name */
2091}
2092
2093/*
2094 * Insert host name is s[len].
2095 */
2096
2097#ifdef HAVE_SYS_UTSNAME_H
2098 void
2099mch_get_host_name(s, len)
2100 char_u *s;
2101 int len;
2102{
2103 struct utsname vutsname;
2104
2105 if (uname(&vutsname) < 0)
2106 *s = NUL;
2107 else
2108 STRNCPY(s, vutsname.nodename, len);
2109 s[len - 1] = NUL; /* make sure it's terminated */
2110}
2111#else /* HAVE_SYS_UTSNAME_H */
2112
2113# ifdef HAVE_SYS_SYSTEMINFO_H
2114# define gethostname(nam, len) sysinfo(SI_HOSTNAME, nam, len)
2115# endif
2116
2117 void
2118mch_get_host_name(s, len)
2119 char_u *s;
2120 int len;
2121{
2122# ifdef VAXC
2123 vaxc$gethostname((char *)s, len);
2124# else
2125 gethostname((char *)s, len);
2126# endif
2127 s[len - 1] = NUL; /* make sure it's terminated */
2128}
2129#endif /* HAVE_SYS_UTSNAME_H */
2130
2131/*
2132 * return process ID
2133 */
2134 long
2135mch_get_pid()
2136{
2137 return (long)getpid();
2138}
2139
2140#if !defined(HAVE_STRERROR) && defined(USE_GETCWD)
2141static char *strerror __ARGS((int));
2142
2143 static char *
2144strerror(err)
2145 int err;
2146{
2147 extern int sys_nerr;
2148 extern char *sys_errlist[];
2149 static char er[20];
2150
2151 if (err > 0 && err < sys_nerr)
2152 return (sys_errlist[err]);
2153 sprintf(er, "Error %d", err);
2154 return er;
2155}
2156#endif
2157
2158/*
2159 * Get name of current directory into buffer 'buf' of length 'len' bytes.
2160 * Return OK for success, FAIL for failure.
2161 */
2162 int
2163mch_dirname(buf, len)
2164 char_u *buf;
2165 int len;
2166{
2167#if defined(USE_GETCWD)
2168 if (getcwd((char *)buf, len) == NULL)
2169 {
2170 STRCPY(buf, strerror(errno));
2171 return FAIL;
2172 }
2173 return OK;
2174#else
2175 return (getwd((char *)buf) != NULL ? OK : FAIL);
2176#endif
2177}
2178
2179#if defined(OS2) || defined(PROTO)
2180/*
2181 * Replace all slashes by backslashes.
2182 * When 'shellslash' set do it the other way around.
2183 */
2184 void
2185slash_adjust(p)
2186 char_u *p;
2187{
2188 while (*p)
2189 {
2190 if (*p == psepcN)
2191 *p = psepc;
2192#ifdef FEAT_MBYTE
2193 if (has_mbyte)
2194 p += (*mb_ptr2len_check)(p);
2195 else
2196#endif
2197 ++p;
2198 }
2199}
2200#endif
2201
2202/*
2203 * Get absolute file name into buffer 'buf' of length 'len' bytes.
2204 *
2205 * return FAIL for failure, OK for success
2206 */
2207 int
2208mch_FullName(fname, buf, len, force)
2209 char_u *fname, *buf;
2210 int len;
2211 int force; /* also expand when already absolute path */
2212{
2213 int l;
2214#ifdef OS2
2215 int only_drive; /* file name is only a drive letter */
2216#endif
2217#ifdef HAVE_FCHDIR
2218 int fd = -1;
2219 static int dont_fchdir = FALSE; /* TRUE when fchdir() doesn't work */
2220#endif
2221 char_u olddir[MAXPATHL];
2222 char_u *p;
2223 int retval = OK;
2224
2225#ifdef VMS
2226 fname = vms_fixfilename(fname);
2227#endif
2228
2229 /* expand it if forced or not an absolute path */
2230 if (force || !mch_isFullName(fname))
2231 {
2232 /*
2233 * If the file name has a path, change to that directory for a moment,
2234 * and then do the getwd() (and get back to where we were).
2235 * This will get the correct path name with "../" things.
2236 */
2237#ifdef OS2
2238 only_drive = 0;
2239 if (((p = vim_strrchr(fname, '/')) != NULL)
2240 || ((p = vim_strrchr(fname, '\\')) != NULL)
2241 || (((p = vim_strchr(fname, ':')) != NULL) && ++only_drive))
2242#else
2243 if ((p = vim_strrchr(fname, '/')) != NULL)
2244#endif
2245 {
2246#ifdef HAVE_FCHDIR
2247 /*
2248 * Use fchdir() if possible, it's said to be faster and more
2249 * reliable. But on SunOS 4 it might not work. Check this by
2250 * doing a fchdir() right now.
2251 */
2252 if (!dont_fchdir)
2253 {
2254 fd = open(".", O_RDONLY | O_EXTRA, 0);
2255 if (fd >= 0 && fchdir(fd) < 0)
2256 {
2257 close(fd);
2258 fd = -1;
2259 dont_fchdir = TRUE; /* don't try again */
2260 }
2261 }
2262#endif
2263
2264 /* Only change directory when we are sure we can return to where
2265 * we are now. After doing "su" chdir(".") might not work. */
2266 if (
2267#ifdef HAVE_FCHDIR
2268 fd < 0 &&
2269#endif
2270 (mch_dirname(olddir, MAXPATHL) == FAIL
2271 || mch_chdir((char *)olddir) != 0))
2272 {
2273 p = NULL; /* can't get current dir: don't chdir */
2274 retval = FAIL;
2275 }
2276 else
2277 {
2278#ifdef OS2
2279 /*
2280 * compensate for case where ':' from "D:" was the only
2281 * path separator detected in the file name; the _next_
2282 * character has to be removed, and then restored later.
2283 */
2284 if (only_drive)
2285 p++;
2286#endif
2287 /* The directory is copied into buf[], to be able to remove
2288 * the file name without changing it (could be a string in
2289 * read-only memory) */
2290 if (p - fname >= len)
2291 retval = FAIL;
2292 else
2293 {
2294 STRNCPY(buf, fname, p - fname);
2295 buf[p - fname] = NUL;
2296 if (mch_chdir((char *)buf))
2297 retval = FAIL;
2298 else
2299 fname = p + 1;
2300 *buf = NUL;
2301 }
2302#ifdef OS2
2303 if (only_drive)
2304 {
2305 p--;
2306 if (retval != FAIL)
2307 fname--;
2308 }
2309#endif
2310 }
2311 }
2312 if (mch_dirname(buf, len) == FAIL)
2313 {
2314 retval = FAIL;
2315 *buf = NUL;
2316 }
2317 if (p != NULL)
2318 {
2319#ifdef HAVE_FCHDIR
2320 if (fd >= 0)
2321 {
2322 l = fchdir(fd);
2323 close(fd);
2324 }
2325 else
2326#endif
2327 l = mch_chdir((char *)olddir);
2328 if (l != 0)
2329 EMSG(_(e_prev_dir));
2330 }
2331
2332 l = STRLEN(buf);
2333 if (l >= len)
2334 retval = FAIL;
2335#ifndef VMS
2336 else
2337 {
2338 if (l > 0 && buf[l - 1] != '/' && *fname != NUL
2339 && STRCMP(fname, ".") != 0)
2340 STRCAT(buf, "/");
2341 }
2342#endif
2343 }
2344 /* Catch file names which are too long. */
2345 if (retval == FAIL || STRLEN(buf) + STRLEN(fname) >= len)
2346 return FAIL;
2347
2348 /* Do not append ".", "/dir/." is equal to "/dir". */
2349 if (STRCMP(fname, ".") != 0)
2350 STRCAT(buf, fname);
2351
2352 return OK;
2353}
2354
2355/*
2356 * Return TRUE if "fname" does not depend on the current directory.
2357 */
2358 int
2359mch_isFullName(fname)
2360 char_u *fname;
2361{
2362#ifdef __EMX__
2363 return _fnisabs(fname);
2364#else
2365# ifdef VMS
2366 return ( fname[0] == '/' || fname[0] == '.' ||
2367 strchr((char *)fname,':') || strchr((char *)fname,'"') ||
2368 (strchr((char *)fname,'[') && strchr((char *)fname,']'))||
2369 (strchr((char *)fname,'<') && strchr((char *)fname,'>')) );
2370# else
2371 return (*fname == '/' || *fname == '~');
2372# endif
2373#endif
2374}
2375
2376/*
2377 * Get file permissions for 'name'.
2378 * Returns -1 when it doesn't exist.
2379 */
2380 long
2381mch_getperm(name)
2382 char_u *name;
2383{
2384 struct stat statb;
2385
2386 /* Keep the #ifdef outside of stat(), it may be a macro. */
2387#ifdef VMS
2388 if (stat((char *)vms_fixfilename(name), &statb))
2389#else
2390 if (stat((char *)name, &statb))
2391#endif
2392 return -1;
2393 return statb.st_mode;
2394}
2395
2396/*
2397 * set file permission for 'name' to 'perm'
2398 *
2399 * return FAIL for failure, OK otherwise
2400 */
2401 int
2402mch_setperm(name, perm)
2403 char_u *name;
2404 long perm;
2405{
2406 return (chmod((char *)
2407#ifdef VMS
2408 vms_fixfilename(name),
2409#else
2410 name,
2411#endif
2412 (mode_t)perm) == 0 ? OK : FAIL);
2413}
2414
2415#if defined(HAVE_ACL) || defined(PROTO)
2416# ifdef HAVE_SYS_ACL_H
2417# include <sys/acl.h>
2418# endif
2419# ifdef HAVE_SYS_ACCESS_H
2420# include <sys/access.h>
2421# endif
2422
2423# ifdef HAVE_SOLARIS_ACL
2424typedef struct vim_acl_solaris_T {
2425 int acl_cnt;
2426 aclent_t *acl_entry;
2427} vim_acl_solaris_T;
2428# endif
2429
2430/*
2431 * Return a pointer to the ACL of file "fname" in allocated memory.
2432 * Return NULL if the ACL is not available for whatever reason.
2433 */
2434 vim_acl_T
2435mch_get_acl(fname)
2436 char_u *fname;
2437{
2438 vim_acl_T ret = NULL;
2439#ifdef HAVE_POSIX_ACL
2440 ret = (vim_acl_T)acl_get_file((char *)fname, ACL_TYPE_ACCESS);
2441#else
2442#ifdef HAVE_SOLARIS_ACL
2443 vim_acl_solaris_T *aclent;
2444
2445 aclent = malloc(sizeof(vim_acl_solaris_T));
2446 if ((aclent->acl_cnt = acl((char *)fname, GETACLCNT, 0, NULL)) < 0)
2447 {
2448 free(aclent);
2449 return NULL;
2450 }
2451 aclent->acl_entry = malloc(aclent->acl_cnt * sizeof(aclent_t));
2452 if (acl((char *)fname, GETACL, aclent->acl_cnt, aclent->acl_entry) < 0)
2453 {
2454 free(aclent->acl_entry);
2455 free(aclent);
2456 return NULL;
2457 }
2458 ret = (vim_acl_T)aclent;
2459#else
2460#if defined(HAVE_AIX_ACL)
2461 int aclsize;
2462 struct acl *aclent;
2463
2464 aclsize = sizeof(struct acl);
2465 aclent = malloc(aclsize);
2466 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2467 {
2468 if (errno == ENOSPC)
2469 {
2470 aclsize = aclent->acl_len;
2471 aclent = realloc(aclent, aclsize);
2472 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2473 {
2474 free(aclent);
2475 return NULL;
2476 }
2477 }
2478 else
2479 {
2480 free(aclent);
2481 return NULL;
2482 }
2483 }
2484 ret = (vim_acl_T)aclent;
2485#endif /* HAVE_AIX_ACL */
2486#endif /* HAVE_SOLARIS_ACL */
2487#endif /* HAVE_POSIX_ACL */
2488 return ret;
2489}
2490
2491/*
2492 * Set the ACL of file "fname" to "acl" (unless it's NULL).
2493 */
2494 void
2495mch_set_acl(fname, aclent)
2496 char_u *fname;
2497 vim_acl_T aclent;
2498{
2499 if (aclent == NULL)
2500 return;
2501#ifdef HAVE_POSIX_ACL
2502 acl_set_file((char *)fname, ACL_TYPE_ACCESS, (acl_t)aclent);
2503#else
2504#ifdef HAVE_SOLARIS_ACL
2505 acl((char *)fname, SETACL, ((vim_acl_solaris_T *)aclent)->acl_cnt,
2506 ((vim_acl_solaris_T *)aclent)->acl_entry);
2507#else
2508#ifdef HAVE_AIX_ACL
2509 chacl((char *)fname, aclent, ((struct acl *)aclent)->acl_len);
2510#endif /* HAVE_AIX_ACL */
2511#endif /* HAVE_SOLARIS_ACL */
2512#endif /* HAVE_POSIX_ACL */
2513}
2514
2515 void
2516mch_free_acl(aclent)
2517 vim_acl_T aclent;
2518{
2519 if (aclent == NULL)
2520 return;
2521#ifdef HAVE_POSIX_ACL
2522 acl_free((acl_t)aclent);
2523#else
2524#ifdef HAVE_SOLARIS_ACL
2525 free(((vim_acl_solaris_T *)aclent)->acl_entry);
2526 free(aclent);
2527#else
2528#ifdef HAVE_AIX_ACL
2529 free(aclent);
2530#endif /* HAVE_AIX_ACL */
2531#endif /* HAVE_SOLARIS_ACL */
2532#endif /* HAVE_POSIX_ACL */
2533}
2534#endif
2535
2536/*
2537 * Set hidden flag for "name".
2538 */
2539/* ARGSUSED */
2540 void
2541mch_hide(name)
2542 char_u *name;
2543{
2544 /* can't hide a file */
2545}
2546
2547/*
2548 * return TRUE if "name" is a directory
2549 * return FALSE if "name" is not a directory
2550 * return FALSE for error
2551 */
2552 int
2553mch_isdir(name)
2554 char_u *name;
2555{
2556 struct stat statb;
2557
2558 if (*name == NUL) /* Some stat()s don't flag "" as an error. */
2559 return FALSE;
2560 if (stat((char *)name, &statb))
2561 return FALSE;
2562#ifdef _POSIX_SOURCE
2563 return (S_ISDIR(statb.st_mode) ? TRUE : FALSE);
2564#else
2565 return ((statb.st_mode & S_IFMT) == S_IFDIR ? TRUE : FALSE);
2566#endif
2567}
2568
2569#if defined(FEAT_EVAL) || defined(PROTO)
2570
2571static int executable_file __ARGS((char_u *name));
2572
2573/*
2574 * Return 1 if "name" is an executable file, 0 if not or it doesn't exist.
2575 */
2576 static int
2577executable_file(name)
2578 char_u *name;
2579{
2580 struct stat st;
2581
2582 if (stat((char *)name, &st))
2583 return 0;
2584 return S_ISREG(st.st_mode) && mch_access((char *)name, X_OK) == 0;
2585}
2586
2587/*
2588 * Return 1 if "name" can be found in $PATH and executed, 0 if not.
2589 * Return -1 if unknown.
2590 */
2591 int
2592mch_can_exe(name)
2593 char_u *name;
2594{
2595 char_u *buf;
2596 char_u *p, *e;
2597 int retval;
2598
2599 /* If it's an absolute or relative path don't need to use $PATH. */
2600 if (mch_isFullName(name) || (name[0] == '.' && (name[1] == '/'
2601 || (name[1] == '.' && name[2] == '/'))))
2602 return executable_file(name);
2603
2604 p = (char_u *)getenv("PATH");
2605 if (p == NULL || *p == NUL)
2606 return -1;
2607 buf = alloc((unsigned)(STRLEN(name) + STRLEN(p) + 2));
2608 if (buf == NULL)
2609 return -1;
2610
2611 /*
2612 * Walk through all entries in $PATH to check if "name" exists there and
2613 * is an executable file.
2614 */
2615 for (;;)
2616 {
2617 e = (char_u *)strchr((char *)p, ':');
2618 if (e == NULL)
2619 e = p + STRLEN(p);
2620 if (e - p <= 1) /* empty entry means current dir */
2621 STRCPY(buf, "./");
2622 else
2623 {
2624 STRNCPY(buf, p, e - p);
2625 buf[e - p] = NUL;
2626 add_pathsep(buf);
2627 }
2628 STRCAT(buf, name);
2629 retval = executable_file(buf);
2630 if (retval == 1)
2631 break;
2632
2633 if (*e != ':')
2634 break;
2635 p = e + 1;
2636 }
2637
2638 vim_free(buf);
2639 return retval;
2640}
2641#endif
2642
2643/*
2644 * Check what "name" is:
2645 * NODE_NORMAL: file or directory (or doesn't exist)
2646 * NODE_WRITABLE: writable device, socket, fifo, etc.
2647 * NODE_OTHER: non-writable things
2648 */
2649 int
2650mch_nodetype(name)
2651 char_u *name;
2652{
2653 struct stat st;
2654
2655 if (stat((char *)name, &st))
2656 return NODE_NORMAL;
2657 if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
2658 return NODE_NORMAL;
2659#ifndef OS2
2660 if (S_ISBLK(st.st_mode)) /* block device isn't writable */
2661 return NODE_OTHER;
2662#endif
2663 /* Everything else is writable? */
2664 return NODE_WRITABLE;
2665}
2666
2667 void
2668mch_early_init()
2669{
2670#ifdef HAVE_CHECK_STACK_GROWTH
2671 int i;
2672#endif
2673
2674#ifdef HAVE_CHECK_STACK_GROWTH
2675 check_stack_growth((char *)&i);
2676
2677# ifdef HAVE_GETRLIMIT
2678 get_stack_limit();
2679# endif
2680
2681#endif
2682
2683 /*
2684 * Setup an alternative stack for signals. Helps to catch signals when
2685 * running out of stack space.
2686 * Use of sigaltstack() is preferred, it's more portable.
2687 * Ignore any errors.
2688 */
2689#if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2690 signal_stack = malloc(SIGSTKSZ);
2691 init_signal_stack();
2692#endif
2693}
2694
2695static void exit_scroll __ARGS((void));
2696
2697/*
2698 * Output a newline when exiting.
2699 * Make sure the newline goes to the same stream as the text.
2700 */
2701 static void
2702exit_scroll()
2703{
2704 if (newline_on_exit || msg_didout)
2705 {
2706 if (msg_use_printf())
2707 {
2708 if (info_message)
2709 mch_msg("\n");
2710 else
2711 mch_errmsg("\r\n");
2712 }
2713 else
2714 out_char('\n');
2715 }
2716 else
2717 {
2718 restore_cterm_colors(); /* get original colors back */
2719 msg_clr_eos_force(); /* clear the rest of the display */
2720 windgoto((int)Rows - 1, 0); /* may have moved the cursor */
2721 }
2722}
2723
2724 void
2725mch_exit(r)
2726 int r;
2727{
2728 exiting = TRUE;
2729
2730#if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
2731 x11_export_final_selection();
2732#endif
2733
2734#ifdef FEAT_GUI
2735 if (!gui.in_use)
2736#endif
2737 {
2738 settmode(TMODE_COOK);
2739#ifdef FEAT_TITLE
2740 mch_restore_title(3); /* restore xterm title and icon name */
2741#endif
2742 /*
2743 * When t_ti is not empty but it doesn't cause swapping terminal
2744 * pages, need to output a newline when msg_didout is set. But when
2745 * t_ti does swap pages it should not go to the shell page. Do this
2746 * before stoptermcap().
2747 */
2748 if (swapping_screen() && !newline_on_exit)
2749 exit_scroll();
2750
2751 /* Stop termcap: May need to check for T_CRV response, which
2752 * requires RAW mode. */
2753 stoptermcap();
2754
2755 /*
2756 * A newline is only required after a message in the alternate screen.
2757 * This is set to TRUE by wait_return().
2758 */
2759 if (!swapping_screen() || newline_on_exit)
2760 exit_scroll();
2761
2762 /* Cursor may have been switched off without calling starttermcap()
2763 * when doing "vim -u vimrc" and vimrc contains ":q". */
2764 if (full_screen)
2765 cursor_on();
2766 }
2767 out_flush();
2768 ml_close_all(TRUE); /* remove all memfiles */
2769 may_core_dump();
2770#ifdef FEAT_GUI
2771# ifndef FEAT_GUI_BEOS /* BeOS always has GUI */
2772 if (gui.in_use)
2773# endif
2774 gui_exit(r);
2775#endif
2776#ifdef __QNX__
2777 /* A core dump won't be created if the signal handler
2778 * doesn't return, so we can't call exit() */
2779 if (deadly_signal != 0)
2780 return;
2781#endif
2782
Bram Moolenaar009b2592004-10-24 19:18:58 +00002783#ifdef FEAT_NETBEANS_INTG
2784 if (usingNetbeans)
2785 netbeans_send_disconnect();
2786#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002787 exit(r);
2788}
2789
2790 static void
2791may_core_dump()
2792{
2793 if (deadly_signal != 0)
2794 {
2795 signal(deadly_signal, SIG_DFL);
2796 kill(getpid(), deadly_signal); /* Die using the signal we caught */
2797 }
2798}
2799
2800#ifndef VMS
2801
2802 void
2803mch_settmode(tmode)
2804 int tmode;
2805{
2806 static int first = TRUE;
2807
2808 /* Why is NeXT excluded here (and not in os_unixx.h)? */
2809#if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
2810 /*
2811 * for "new" tty systems
2812 */
2813# ifdef HAVE_TERMIOS_H
2814 static struct termios told;
2815 struct termios tnew;
2816# else
2817 static struct termio told;
2818 struct termio tnew;
2819# endif
2820
2821 if (first)
2822 {
2823 first = FALSE;
2824# if defined(HAVE_TERMIOS_H)
2825 tcgetattr(read_cmd_fd, &told);
2826# else
2827 ioctl(read_cmd_fd, TCGETA, &told);
2828# endif
2829 }
2830
2831 tnew = told;
2832 if (tmode == TMODE_RAW)
2833 {
2834 /*
2835 * ~ICRNL enables typing ^V^M
2836 */
2837 tnew.c_iflag &= ~ICRNL;
2838 tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE
2839# if defined(IEXTEN) && !defined(__MINT__)
2840 | IEXTEN /* IEXTEN enables typing ^V on SOLARIS */
2841 /* but it breaks function keys on MINT */
2842# endif
2843 );
2844# ifdef ONLCR /* don't map NL -> CR NL, we do it ourselves */
2845 tnew.c_oflag &= ~ONLCR;
2846# endif
2847 tnew.c_cc[VMIN] = 1; /* return after 1 char */
2848 tnew.c_cc[VTIME] = 0; /* don't wait */
2849 }
2850 else if (tmode == TMODE_SLEEP)
2851 tnew.c_lflag &= ~(ECHO);
2852
2853# if defined(HAVE_TERMIOS_H)
2854 {
2855 int n = 10;
2856
2857 /* A signal may cause tcsetattr() to fail (e.g., SIGCONT). Retry a
2858 * few times. */
2859 while (tcsetattr(read_cmd_fd, TCSANOW, &tnew) == -1
2860 && errno == EINTR && n > 0)
2861 --n;
2862 }
2863# else
2864 ioctl(read_cmd_fd, TCSETA, &tnew);
2865# endif
2866
2867#else
2868
2869 /*
2870 * for "old" tty systems
2871 */
2872# ifndef TIOCSETN
2873# define TIOCSETN TIOCSETP /* for hpux 9.0 */
2874# endif
2875 static struct sgttyb ttybold;
2876 struct sgttyb ttybnew;
2877
2878 if (first)
2879 {
2880 first = FALSE;
2881 ioctl(read_cmd_fd, TIOCGETP, &ttybold);
2882 }
2883
2884 ttybnew = ttybold;
2885 if (tmode == TMODE_RAW)
2886 {
2887 ttybnew.sg_flags &= ~(CRMOD | ECHO);
2888 ttybnew.sg_flags |= RAW;
2889 }
2890 else if (tmode == TMODE_SLEEP)
2891 ttybnew.sg_flags &= ~(ECHO);
2892 ioctl(read_cmd_fd, TIOCSETN, &ttybnew);
2893#endif
2894 curr_tmode = tmode;
2895}
2896
2897/*
2898 * Try to get the code for "t_kb" from the stty setting
2899 *
2900 * Even if termcap claims a backspace key, the user's setting *should*
2901 * prevail. stty knows more about reality than termcap does, and if
2902 * somebody's usual erase key is DEL (which, for most BSD users, it will
2903 * be), they're going to get really annoyed if their erase key starts
2904 * doing forward deletes for no reason. (Eric Fischer)
2905 */
2906 void
2907get_stty()
2908{
2909 char_u buf[2];
2910 char_u *p;
2911
2912 /* Why is NeXT excluded here (and not in os_unixx.h)? */
2913#if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
2914 /* for "new" tty systems */
2915# ifdef HAVE_TERMIOS_H
2916 struct termios keys;
2917# else
2918 struct termio keys;
2919# endif
2920
2921# if defined(HAVE_TERMIOS_H)
2922 if (tcgetattr(read_cmd_fd, &keys) != -1)
2923# else
2924 if (ioctl(read_cmd_fd, TCGETA, &keys) != -1)
2925# endif
2926 {
2927 buf[0] = keys.c_cc[VERASE];
2928 intr_char = keys.c_cc[VINTR];
2929#else
2930 /* for "old" tty systems */
2931 struct sgttyb keys;
2932
2933 if (ioctl(read_cmd_fd, TIOCGETP, &keys) != -1)
2934 {
2935 buf[0] = keys.sg_erase;
2936 intr_char = keys.sg_kill;
2937#endif
2938 buf[1] = NUL;
2939 add_termcode((char_u *)"kb", buf, FALSE);
2940
2941 /*
2942 * If <BS> and <DEL> are now the same, redefine <DEL>.
2943 */
2944 p = find_termcode((char_u *)"kD");
2945 if (p != NULL && p[0] == buf[0] && p[1] == buf[1])
2946 do_fixdel(NULL);
2947 }
2948#if 0
2949 } /* to keep cindent happy */
2950#endif
2951}
2952
2953#endif /* VMS */
2954
2955#if defined(FEAT_MOUSE_TTY) || defined(PROTO)
2956/*
2957 * Set mouse clicks on or off.
2958 */
2959 void
2960mch_setmouse(on)
2961 int on;
2962{
2963 static int ison = FALSE;
2964 int xterm_mouse_vers;
2965
2966 if (on == ison) /* return quickly if nothing to do */
2967 return;
2968
2969 xterm_mouse_vers = use_xterm_mouse();
2970 if (xterm_mouse_vers > 0)
2971 {
2972 if (on) /* enable mouse events, use mouse tracking if available */
2973 out_str_nf((char_u *)
2974 (xterm_mouse_vers > 1
2975 ? IF_EB("\033[?1002h", ESC_STR "[?1002h")
2976 : IF_EB("\033[?1000h", ESC_STR "[?1000h")));
2977 else /* disable mouse events, could probably always send the same */
2978 out_str_nf((char_u *)
2979 (xterm_mouse_vers > 1
2980 ? IF_EB("\033[?1002l", ESC_STR "[?1002l")
2981 : IF_EB("\033[?1000l", ESC_STR "[?1000l")));
2982 ison = on;
2983 }
2984
2985# ifdef FEAT_MOUSE_DEC
2986 else if (ttym_flags == TTYM_DEC)
2987 {
2988 if (on) /* enable mouse events */
2989 out_str_nf((char_u *)"\033[1;2'z\033[1;3'{");
2990 else /* disable mouse events */
2991 out_str_nf((char_u *)"\033['z");
2992 ison = on;
2993 }
2994# endif
2995
2996# ifdef FEAT_MOUSE_GPM
2997 else
2998 {
2999 if (on)
3000 {
3001 if (gpm_open())
3002 ison = TRUE;
3003 }
3004 else
3005 {
3006 gpm_close();
3007 ison = FALSE;
3008 }
3009 }
3010# endif
3011
3012# ifdef FEAT_MOUSE_JSB
3013 else
3014 {
3015 if (on)
3016 {
3017 /* D - Enable Mouse up/down messages
3018 * L - Enable Left Button Reporting
3019 * M - Enable Middle Button Reporting
3020 * R - Enable Right Button Reporting
3021 * K - Enable SHIFT and CTRL key Reporting
3022 * + - Enable Advanced messaging of mouse moves and up/down messages
3023 * Q - Quiet No Ack
3024 * # - Numeric value of mouse pointer required
3025 * 0 = Multiview 2000 cursor, used as standard
3026 * 1 = Windows Arrow
3027 * 2 = Windows I Beam
3028 * 3 = Windows Hour Glass
3029 * 4 = Windows Cross Hair
3030 * 5 = Windows UP Arrow
3031 */
3032#ifdef JSBTERM_MOUSE_NONADVANCED /* Disables full feedback of pointer movements */
3033 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK1Q\033\\",
3034 ESC_STR "[0~ZwLMRK1Q" ESC_STR "\\"));
3035#else
3036 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK+1Q\033\\",
3037 ESC_STR "[0~ZwLMRK+1Q" ESC_STR "\\"));
3038#endif
3039 ison = TRUE;
3040 }
3041 else
3042 {
3043 out_str_nf((char_u *)IF_EB("\033[0~ZwQ\033\\",
3044 ESC_STR "[0~ZwQ" ESC_STR "\\"));
3045 ison = FALSE;
3046 }
3047 }
3048# endif
3049# ifdef FEAT_MOUSE_PTERM
3050 else
3051 {
3052 /* 1 = button press, 6 = release, 7 = drag, 1h...9l = right button */
3053 if (on)
3054 out_str_nf("\033[>1h\033[>6h\033[>7h\033[>1h\033[>9l");
3055 else
3056 out_str_nf("\033[>1l\033[>6l\033[>7l\033[>1l\033[>9h");
3057 ison = on;
3058 }
3059# endif
3060}
3061
3062/*
3063 * Set the mouse termcode, depending on the 'term' and 'ttymouse' options.
3064 */
3065 void
3066check_mouse_termcode()
3067{
3068# ifdef FEAT_MOUSE_XTERM
3069 if (use_xterm_mouse()
3070# ifdef FEAT_GUI
3071 && !gui.in_use
3072# endif
3073 )
3074 {
3075 set_mouse_termcode(KS_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3076 ? IF_EB("\233M", CSI_STR "M") : IF_EB("\033[M", ESC_STR "[M")));
3077 if (*p_mouse != NUL)
3078 {
3079 /* force mouse off and maybe on to send possibly new mouse
3080 * activation sequence to the xterm, with(out) drag tracing. */
3081 mch_setmouse(FALSE);
3082 setmouse();
3083 }
3084 }
3085 else
3086 del_mouse_termcode(KS_MOUSE);
3087# endif
3088
3089# ifdef FEAT_MOUSE_GPM
3090 if (!use_xterm_mouse()
3091# ifdef FEAT_GUI
3092 && !gui.in_use
3093# endif
3094 )
3095 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MG", ESC_STR "MG"));
3096# endif
3097
3098# ifdef FEAT_MOUSE_JSB
3099 /* conflicts with xterm mouse: "\033[" and "\033[M" ??? */
3100 if (!use_xterm_mouse()
3101# ifdef FEAT_GUI
3102 && !gui.in_use
3103# endif
3104 )
3105 set_mouse_termcode(KS_JSBTERM_MOUSE,
3106 (char_u *)IF_EB("\033[0~zw", ESC_STR "[0~zw"));
3107 else
3108 del_mouse_termcode(KS_JSBTERM_MOUSE);
3109# endif
3110
3111# ifdef FEAT_MOUSE_NET
3112 /* There is no conflict, but one may type ESC } from Insert mode. Don't
3113 * define it in the GUI or when using an xterm. */
3114 if (!use_xterm_mouse()
3115# ifdef FEAT_GUI
3116 && !gui.in_use
3117# endif
3118 )
3119 set_mouse_termcode(KS_NETTERM_MOUSE,
3120 (char_u *)IF_EB("\033}", ESC_STR "}"));
3121 else
3122 del_mouse_termcode(KS_NETTERM_MOUSE);
3123# endif
3124
3125# ifdef FEAT_MOUSE_DEC
3126 /* conflicts with xterm mouse: "\033[" and "\033[M" */
3127 if (!use_xterm_mouse()
3128# ifdef FEAT_GUI
3129 && !gui.in_use
3130# endif
3131 )
3132 set_mouse_termcode(KS_DEC_MOUSE,
3133 (char_u *)IF_EB("\033[", ESC_STR "["));
3134 else
3135 del_mouse_termcode(KS_DEC_MOUSE);
3136# endif
3137# ifdef FEAT_MOUSE_PTERM
3138 /* same as the dec mouse */
3139 if (!use_xterm_mouse()
3140# ifdef FEAT_GUI
3141 && !gui.in_use
3142# endif
3143 )
3144 set_mouse_termcode(KS_PTERM_MOUSE,
3145 (char_u *) IF_EB("\033[", ESC_STR "["));
3146 else
3147 del_mouse_termcode(KS_PTERM_MOUSE);
3148# endif
3149}
3150#endif
3151
3152/*
3153 * set screen mode, always fails.
3154 */
3155/* ARGSUSED */
3156 int
3157mch_screenmode(arg)
3158 char_u *arg;
3159{
3160 EMSG(_(e_screenmode));
3161 return FAIL;
3162}
3163
3164#ifndef VMS
3165
3166/*
3167 * Try to get the current window size:
3168 * 1. with an ioctl(), most accurate method
3169 * 2. from the environment variables LINES and COLUMNS
3170 * 3. from the termcap
3171 * 4. keep using the old values
3172 * Return OK when size could be determined, FAIL otherwise.
3173 */
3174 int
3175mch_get_shellsize()
3176{
3177 long rows = 0;
3178 long columns = 0;
3179 char_u *p;
3180
3181 /*
3182 * For OS/2 use _scrsize().
3183 */
3184# ifdef __EMX__
3185 {
3186 int s[2];
3187
3188 _scrsize(s);
3189 columns = s[0];
3190 rows = s[1];
3191 }
3192# endif
3193
3194 /*
3195 * 1. try using an ioctl. It is the most accurate method.
3196 *
3197 * Try using TIOCGWINSZ first, some systems that have it also define
3198 * TIOCGSIZE but don't have a struct ttysize.
3199 */
3200# ifdef TIOCGWINSZ
3201 {
3202 struct winsize ws;
3203 int fd = 1;
3204
3205 /* When stdout is not a tty, use stdin for the ioctl(). */
3206 if (!isatty(fd) && isatty(read_cmd_fd))
3207 fd = read_cmd_fd;
3208 if (ioctl(fd, TIOCGWINSZ, &ws) == 0)
3209 {
3210 columns = ws.ws_col;
3211 rows = ws.ws_row;
3212 }
3213 }
3214# else /* TIOCGWINSZ */
3215# ifdef TIOCGSIZE
3216 {
3217 struct ttysize ts;
3218 int fd = 1;
3219
3220 /* When stdout is not a tty, use stdin for the ioctl(). */
3221 if (!isatty(fd) && isatty(read_cmd_fd))
3222 fd = read_cmd_fd;
3223 if (ioctl(fd, TIOCGSIZE, &ts) == 0)
3224 {
3225 columns = ts.ts_cols;
3226 rows = ts.ts_lines;
3227 }
3228 }
3229# endif /* TIOCGSIZE */
3230# endif /* TIOCGWINSZ */
3231
3232 /*
3233 * 2. get size from environment
3234 */
3235 if (columns == 0 || rows == 0)
3236 {
3237 if ((p = (char_u *)getenv("LINES")))
3238 rows = atoi((char *)p);
3239 if ((p = (char_u *)getenv("COLUMNS")))
3240 columns = atoi((char *)p);
3241 }
3242
3243#ifdef HAVE_TGETENT
3244 /*
3245 * 3. try reading "co" and "li" entries from termcap
3246 */
3247 if (columns == 0 || rows == 0)
3248 getlinecol(&columns, &rows);
3249#endif
3250
3251 /*
3252 * 4. If everything fails, use the old values
3253 */
3254 if (columns <= 0 || rows <= 0)
3255 return FAIL;
3256
3257 Rows = rows;
3258 Columns = columns;
3259 return OK;
3260}
3261
3262/*
3263 * Try to set the window size to Rows and Columns.
3264 */
3265 void
3266mch_set_shellsize()
3267{
3268 if (*T_CWS)
3269 {
3270 /*
3271 * NOTE: if you get an error here that term_set_winsize() is
3272 * undefined, check the output of configure. It could probably not
3273 * find a ncurses, termcap or termlib library.
3274 */
3275 term_set_winsize((int)Rows, (int)Columns);
3276 out_flush();
3277 screen_start(); /* don't know where cursor is now */
3278 }
3279}
3280
3281#endif /* VMS */
3282
3283/*
3284 * Rows and/or Columns has changed.
3285 */
3286 void
3287mch_new_shellsize()
3288{
3289 /* Nothing to do. */
3290}
3291
3292 int
3293mch_call_shell(cmd, options)
3294 char_u *cmd;
3295 int options; /* SHELL_*, see vim.h */
3296{
3297#ifdef VMS
3298 char *ifn = NULL;
3299 char *ofn = NULL;
3300#endif
3301 int tmode = cur_tmode;
3302#ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
3303 int x;
3304# ifndef __EMX__
3305 char_u *newcmd; /* only needed for unix */
3306# else
3307 /*
3308 * Set the preferred shell in the EMXSHELL environment variable (but
3309 * only if it is different from what is already in the environment).
3310 * Emx then takes care of whether to use "/c" or "-c" in an
3311 * intelligent way. Simply pass the whole thing to emx's system() call.
3312 * Emx also starts an interactive shell if system() is passed an empty
3313 * string.
3314 */
3315 char_u *p, *old;
3316
3317 if (((old = (char_u *)getenv("EMXSHELL")) == NULL) || STRCMP(old, p_sh))
3318 {
3319 /* should check HAVE_SETENV, but I know we don't have it. */
3320 p = alloc(10 + strlen(p_sh));
3321 if (p)
3322 {
3323 sprintf((char *)p, "EMXSHELL=%s", p_sh);
3324 putenv((char *)p); /* don't free the pointer! */
3325 }
3326 }
3327# endif
3328
3329 out_flush();
3330
3331 if (options & SHELL_COOKED)
3332 settmode(TMODE_COOK); /* set to normal mode */
3333
3334# ifdef __EMX__
3335 if (cmd == NULL)
3336 x = system(""); /* this starts an interactive shell in emx */
3337 else
3338 x = system((char *)cmd);
3339 /* system() returns -1 when error occurs in starting shell */
3340 if (x == -1 && !emsg_silent)
3341 {
3342 MSG_PUTS(_("\nCannot execute shell "));
3343 msg_outtrans(p_sh);
3344 msg_putchar('\n');
3345 }
3346# else /* not __EMX__ */
3347 if (cmd == NULL)
3348 x = system((char *)p_sh);
3349 else
3350 {
3351# ifdef VMS
3352 if (ofn = strchr((char *)cmd, '>'))
3353 *ofn++ = '\0';
3354 if (ifn = strchr((char *)cmd, '<'))
3355 {
3356 char *p;
3357
3358 *ifn++ = '\0';
3359 p = strchr(ifn,' '); /* chop off any trailing spaces */
3360 if (p)
3361 *p = '\0';
3362 }
3363 if (ofn)
3364 x = vms_sys((char *)cmd, ofn, ifn);
3365 else
3366 x = system((char *)cmd);
3367# else
3368 newcmd = lalloc(STRLEN(p_sh)
3369 + (extra_shell_arg == NULL ? 0 : STRLEN(extra_shell_arg))
3370 + STRLEN(p_shcf) + STRLEN(cmd) + 4, TRUE);
3371 if (newcmd == NULL)
3372 x = 0;
3373 else
3374 {
3375 sprintf((char *)newcmd, "%s %s %s %s", p_sh,
3376 extra_shell_arg == NULL ? "" : (char *)extra_shell_arg,
3377 (char *)p_shcf,
3378 (char *)cmd);
3379 x = system((char *)newcmd);
3380 vim_free(newcmd);
3381 }
3382# endif
3383 }
3384# ifdef VMS
3385 x = vms_sys_status(x);
3386# endif
3387 if (emsg_silent)
3388 ;
3389 else if (x == 127)
3390 MSG_PUTS(_("\nCannot execute shell sh\n"));
3391# endif /* __EMX__ */
3392 else if (x && !(options & SHELL_SILENT))
3393 {
3394 MSG_PUTS(_("\nshell returned "));
3395 msg_outnum((long)x);
3396 msg_putchar('\n');
3397 }
3398
3399 if (tmode == TMODE_RAW)
3400 settmode(TMODE_RAW); /* set to raw mode */
3401# ifdef FEAT_TITLE
3402 resettitle();
3403# endif
3404 return x;
3405
3406#else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
3407
3408#define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
3409 127, some shell use that already */
3410
3411 char_u *newcmd = NULL;
3412 pid_t pid;
3413 pid_t wait_pid = 0;
3414# ifdef HAVE_UNION_WAIT
3415 union wait status;
3416# else
3417 int status = -1;
3418# endif
3419 int retval = -1;
3420 char **argv = NULL;
3421 int argc;
3422 int i;
3423 char_u *p;
3424 int inquote;
3425# ifdef FEAT_GUI
3426 int pty_master_fd = -1; /* for pty's */
3427 int pty_slave_fd = -1;
3428 char *tty_name;
3429 int fd_toshell[2]; /* for pipes */
3430 int fd_fromshell[2];
3431 int pipe_error = FALSE;
3432# ifdef HAVE_SETENV
3433 char envbuf[50];
3434# else
3435 static char envbuf_Rows[20];
3436 static char envbuf_Columns[20];
3437# endif
3438# endif
3439 int did_settmode = FALSE; /* TRUE when settmode(TMODE_RAW) called */
3440
3441 out_flush();
3442 if (options & SHELL_COOKED)
3443 settmode(TMODE_COOK); /* set to normal mode */
3444
3445 /*
3446 * 1: find number of arguments
3447 * 2: separate them and built argv[]
3448 */
3449 newcmd = vim_strsave(p_sh);
3450 if (newcmd == NULL) /* out of memory */
3451 goto error;
3452 for (i = 0; i < 2; ++i)
3453 {
3454 p = newcmd;
3455 inquote = FALSE;
3456 argc = 0;
3457 for (;;)
3458 {
3459 if (i == 1)
3460 argv[argc] = (char *)p;
3461 ++argc;
3462 while (*p && (inquote || (*p != ' ' && *p != TAB)))
3463 {
3464 if (*p == '"')
3465 inquote = !inquote;
3466 ++p;
3467 }
3468 if (*p == NUL)
3469 break;
3470 if (i == 1)
3471 *p++ = NUL;
3472 p = skipwhite(p);
3473 }
3474 if (i == 0)
3475 {
3476 argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *)));
3477 if (argv == NULL) /* out of memory */
3478 goto error;
3479 }
3480 }
3481 if (cmd != NULL)
3482 {
3483 if (extra_shell_arg != NULL)
3484 argv[argc++] = (char *)extra_shell_arg;
3485 argv[argc++] = (char *)p_shcf;
3486 argv[argc++] = (char *)cmd;
3487 }
3488 argv[argc] = NULL;
3489
3490# ifdef FEAT_GUI
3491 /*
3492 * For the GUI: Try using a pseudo-tty to get the stdin/stdout of the
3493 * executed command into the Vim window. Or use a pipe.
3494 */
3495 if (gui.in_use && show_shell_mess)
3496 {
3497 /*
3498 * Try to open a master pty.
3499 * If this works, open the slave pty.
3500 * If the slave can't be opened, close the master pty.
3501 */
3502 if (p_guipty)
3503 {
3504 pty_master_fd = OpenPTY(&tty_name); /* open pty */
3505 if (pty_master_fd >= 0 && ((pty_slave_fd =
3506 open(tty_name, O_RDWR | O_EXTRA, 0)) < 0))
3507 {
3508 close(pty_master_fd);
3509 pty_master_fd = -1;
3510 }
3511 }
3512 /*
3513 * If not opening a pty or it didn't work, try using pipes.
3514 */
3515 if (pty_master_fd < 0)
3516 {
3517 pipe_error = (pipe(fd_toshell) < 0);
3518 if (!pipe_error) /* pipe create OK */
3519 {
3520 pipe_error = (pipe(fd_fromshell) < 0);
3521 if (pipe_error) /* pipe create failed */
3522 {
3523 close(fd_toshell[0]);
3524 close(fd_toshell[1]);
3525 }
3526 }
3527 if (pipe_error)
3528 {
3529 MSG_PUTS(_("\nCannot create pipes\n"));
3530 out_flush();
3531 }
3532 }
3533 }
3534
3535 if (!pipe_error) /* pty or pipe opened or not used */
3536# endif
3537
3538 {
3539# ifdef __BEOS__
3540 beos_cleanup_read_thread();
3541# endif
3542 if ((pid = fork()) == -1) /* maybe we should use vfork() */
3543 {
3544 MSG_PUTS(_("\nCannot fork\n"));
3545# ifdef FEAT_GUI
3546 if (gui.in_use && show_shell_mess)
3547 {
3548 if (pty_master_fd >= 0) /* close the pseudo tty */
3549 {
3550 close(pty_master_fd);
3551 close(pty_slave_fd);
3552 }
3553 else /* close the pipes */
3554 {
3555 close(fd_toshell[0]);
3556 close(fd_toshell[1]);
3557 close(fd_fromshell[0]);
3558 close(fd_fromshell[1]);
3559 }
3560 }
3561# endif
3562 }
3563 else if (pid == 0) /* child */
3564 {
3565 reset_signals(); /* handle signals normally */
3566
3567 if (!show_shell_mess || (options & SHELL_EXPAND))
3568 {
3569 int fd;
3570
3571 /*
3572 * Don't want to show any message from the shell. Can't just
3573 * close stdout and stderr though, because some systems will
3574 * break if you try to write to them after that, so we must
3575 * use dup() to replace them with something else -- webb
3576 * Connect stdin to /dev/null too, so ":n `cat`" doesn't hang,
3577 * waiting for input.
3578 */
3579 fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
3580 fclose(stdin);
3581 fclose(stdout);
3582 fclose(stderr);
3583
3584 /*
3585 * If any of these open()'s and dup()'s fail, we just continue
3586 * anyway. It's not fatal, and on most systems it will make
3587 * no difference at all. On a few it will cause the execvp()
3588 * to exit with a non-zero status even when the completion
3589 * could be done, which is nothing too serious. If the open()
3590 * or dup() failed we'd just do the same thing ourselves
3591 * anyway -- webb
3592 */
3593 if (fd >= 0)
3594 {
3595 dup(fd); /* To replace stdin (file descriptor 0) */
3596 dup(fd); /* To replace stdout (file descriptor 1) */
3597 dup(fd); /* To replace stderr (file descriptor 2) */
3598
3599 /* Don't need this now that we've duplicated it */
3600 close(fd);
3601 }
3602 }
3603# ifdef FEAT_GUI
3604 else if (gui.in_use)
3605 {
3606
3607# ifdef HAVE_SETSID
3608 (void)setsid();
3609# endif
3610 /* push stream discipline modules */
3611 if (options & SHELL_COOKED)
3612 SetupSlavePTY(pty_slave_fd);
3613# ifdef TIOCSCTTY
3614 /* try to become controlling tty (probably doesn't work,
3615 * unless run by root) */
3616 ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
3617# endif
3618 /* Simulate to have a dumb terminal (for now) */
3619# ifdef HAVE_SETENV
3620 setenv("TERM", "dumb", 1);
3621 sprintf((char *)envbuf, "%ld", Rows);
3622 setenv("ROWS", (char *)envbuf, 1);
3623 sprintf((char *)envbuf, "%ld", Rows);
3624 setenv("LINES", (char *)envbuf, 1);
3625 sprintf((char *)envbuf, "%ld", Columns);
3626 setenv("COLUMNS", (char *)envbuf, 1);
3627# else
3628 /*
3629 * Putenv does not copy the string, it has to remain valid.
3630 * Use a static array to avoid loosing allocated memory.
3631 */
3632 putenv("TERM=dumb");
3633 sprintf(envbuf_Rows, "ROWS=%ld", Rows);
3634 putenv(envbuf_Rows);
3635 sprintf(envbuf_Rows, "LINES=%ld", Rows);
3636 putenv(envbuf_Rows);
3637 sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
3638 putenv(envbuf_Columns);
3639# endif
3640
3641 if (pty_master_fd >= 0)
3642 {
3643 close(pty_master_fd); /* close master side of pty */
3644
3645 /* set up stdin/stdout/stderr for the child */
3646 close(0);
3647 dup(pty_slave_fd);
3648 close(1);
3649 dup(pty_slave_fd);
3650 close(2);
3651 dup(pty_slave_fd);
3652
3653 close(pty_slave_fd); /* has been dupped, close it now */
3654 }
3655 else
3656 {
3657 /* set up stdin for the child */
3658 close(fd_toshell[1]);
3659 close(0);
3660 dup(fd_toshell[0]);
3661 close(fd_toshell[0]);
3662
3663 /* set up stdout for the child */
3664 close(fd_fromshell[0]);
3665 close(1);
3666 dup(fd_fromshell[1]);
3667 close(fd_fromshell[1]);
3668
3669 /* set up stderr for the child */
3670 close(2);
3671 dup(1);
3672 }
3673 }
3674# endif /* FEAT_GUI */
3675 /*
3676 * There is no type cast for the argv, because the type may be
3677 * different on different machines. This may cause a warning
3678 * message with strict compilers, don't worry about it.
3679 * Call _exit() instead of exit() to avoid closing the connection
3680 * to the X server (esp. with GTK, which uses atexit()).
3681 */
3682 execvp(argv[0], argv);
3683 _exit(EXEC_FAILED); /* exec failed, return failure code */
3684 }
3685 else /* parent */
3686 {
3687 /*
3688 * While child is running, ignore terminating signals.
3689 */
3690 catch_signals(SIG_IGN, SIG_ERR);
3691
3692# ifdef FEAT_GUI
3693
3694 /*
3695 * For the GUI we redirect stdin, stdout and stderr to our window.
3696 */
3697 if (gui.in_use && show_shell_mess)
3698 {
3699# define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
3700 char_u buffer[BUFLEN + 1];
3701# ifdef FEAT_MBYTE
3702 int buffer_off = 0; /* valid bytes in buffer[] */
3703# endif
3704 char_u ta_buf[BUFLEN + 1]; /* TypeAHead */
3705 int ta_len = 0; /* valid bytes in ta_buf[] */
3706 int len;
3707 int p_more_save;
3708 int old_State;
3709 int c;
3710 int toshell_fd;
3711 int fromshell_fd;
3712
3713 if (pty_master_fd >= 0)
3714 {
3715 close(pty_slave_fd); /* close slave side of pty */
3716 fromshell_fd = pty_master_fd;
3717 toshell_fd = dup(pty_master_fd);
3718 }
3719 else
3720 {
3721 close(fd_toshell[0]);
3722 close(fd_fromshell[1]);
3723 toshell_fd = fd_toshell[1];
3724 fromshell_fd = fd_fromshell[0];
3725 }
3726
3727 /*
3728 * Write to the child if there are typed characters.
3729 * Read from the child if there are characters available.
3730 * Repeat the reading a few times if more characters are
3731 * available. Need to check for typed keys now and then, but
3732 * not too often (delays when no chars are available).
3733 * This loop is quit if no characters can be read from the pty
3734 * (WaitForChar detected special condition), or there are no
3735 * characters available and the child has exited.
3736 * Only check if the child has exited when there is no more
3737 * output. The child may exit before all the output has
3738 * been printed.
3739 *
3740 * Currently this busy loops!
3741 * This can probably dead-lock when the write blocks!
3742 */
3743 p_more_save = p_more;
3744 p_more = FALSE;
3745 old_State = State;
3746 State = EXTERNCMD; /* don't redraw at window resize */
3747
3748 for (;;)
3749 {
3750 /*
3751 * Check if keys have been typed, write them to the child
3752 * if there are any. Don't do this if we are expanding
3753 * wild cards (would eat typeahead). Don't get extra
3754 * characters when we already have one.
3755 */
3756 len = 0;
3757 if (!(options & SHELL_EXPAND)
3758 && (ta_len > 0
3759 || (len = ui_inchar(ta_buf, BUFLEN, 10L,
3760 0)) > 0))
3761 {
3762 /*
3763 * For pipes:
3764 * Check for CTRL-C: send interrupt signal to child.
3765 * Check for CTRL-D: EOF, close pipe to child.
3766 */
3767 if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
3768 {
3769# ifdef SIGINT
3770 /*
3771 * Send SIGINT to the child's group or all
3772 * processes in our group.
3773 */
3774 if (ta_buf[ta_len] == Ctrl_C
3775 || ta_buf[ta_len] == intr_char)
3776# ifdef HAVE_SETSID
3777 kill(-pid, SIGINT);
3778# else
3779 kill(0, SIGINT);
3780# endif
3781# endif
3782 if (pty_master_fd < 0 && toshell_fd >= 0
3783 && ta_buf[ta_len] == Ctrl_D)
3784 {
3785 close(toshell_fd);
3786 toshell_fd = -1;
3787 }
3788 }
3789
3790 /* replace K_BS by <BS> and K_DEL by <DEL> */
3791 for (i = ta_len; i < ta_len + len; ++i)
3792 {
3793 if (ta_buf[i] == CSI && len - i > 2)
3794 {
3795 c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]);
3796 if (c == K_DEL || c == K_KDEL || c == K_BS)
3797 {
3798 mch_memmove(ta_buf + i + 1, ta_buf + i + 3,
3799 (size_t)(len - i - 2));
3800 if (c == K_DEL || c == K_KDEL)
3801 ta_buf[i] = DEL;
3802 else
3803 ta_buf[i] = Ctrl_H;
3804 len -= 2;
3805 }
3806 }
3807 else if (ta_buf[i] == '\r')
3808 ta_buf[i] = '\n';
3809# ifdef FEAT_MBYTE
3810 if (has_mbyte)
3811 i += (*mb_ptr2len_check)(ta_buf + i) - 1;
3812# endif
3813 }
3814
3815 /*
3816 * For pipes: echo the typed characters.
3817 * For a pty this does not seem to work.
3818 */
3819 if (pty_master_fd < 0)
3820 {
3821 for (i = ta_len; i < ta_len + len; ++i)
3822 {
3823 if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
3824 msg_putchar(ta_buf[i]);
3825# ifdef FEAT_MBYTE
3826 else if (has_mbyte)
3827 {
3828 int l = (*mb_ptr2len_check)(ta_buf + i);
3829
3830 msg_outtrans_len(ta_buf + i, l);
3831 i += l - 1;
3832 }
3833# endif
3834 else
3835 msg_outtrans_len(ta_buf + i, 1);
3836 }
3837 windgoto(msg_row, msg_col);
3838 out_flush();
3839 }
3840
3841 ta_len += len;
3842
3843 /*
3844 * Write the characters to the child, unless EOF has
3845 * been typed for pipes. Write one character at a
3846 * time, to avoid loosing too much typeahead.
3847 */
3848 if (toshell_fd >= 0)
3849 {
3850 len = write(toshell_fd, (char *)ta_buf, (size_t)1);
3851 if (len > 0)
3852 {
3853 ta_len -= len;
3854 mch_memmove(ta_buf, ta_buf + len, ta_len);
3855 }
3856 }
3857 }
3858
3859 /*
3860 * Check if the child has any characters to be printed.
3861 * Read them and write them to our window. Repeat this as
3862 * long as there is something to do, avoid the 10ms wait
3863 * for mch_inchar(), or sending typeahead characters to
3864 * the external process.
3865 * TODO: This should handle escape sequences, compatible
3866 * to some terminal (vt52?).
3867 */
3868 while (RealWaitForChar(fromshell_fd, 10L, NULL))
3869 {
3870 len = read(fromshell_fd, (char *)buffer
3871# ifdef FEAT_MBYTE
3872 + buffer_off, (size_t)(BUFLEN - buffer_off)
3873# else
3874 , (size_t)BUFLEN
3875# endif
3876 );
3877 if (len <= 0) /* end of file or error */
3878 goto finished;
3879# ifdef FEAT_MBYTE
3880 len += buffer_off;
3881 buffer[len] = NUL;
3882 if (has_mbyte)
3883 {
3884 int l;
3885
3886 /* Check if the last character in buffer[] is
3887 * incomplete, keep these bytes for the next
3888 * round. */
3889 for (p = buffer; p < buffer + len; p += l)
3890 {
3891 if (enc_utf8) /* exclude composing chars */
3892 l = utf_ptr2len_check(p);
3893 else
3894 l = (*mb_ptr2len_check)(p);
3895 if (l == 0)
3896 l = 1; /* NUL byte? */
3897 else if (MB_BYTE2LEN(*p) != l)
3898 break;
3899 }
3900 if (p == buffer) /* no complete character */
3901 {
3902 /* avoid getting stuck at an illegal byte */
3903 if (len >= 12)
3904 ++p;
3905 else
3906 {
3907 buffer_off = len;
3908 continue;
3909 }
3910 }
3911 c = *p;
3912 *p = NUL;
3913 msg_puts(buffer);
3914 if (p < buffer + len)
3915 {
3916 *p = c;
3917 buffer_off = (buffer + len) - p;
3918 mch_memmove(buffer, p, buffer_off);
3919 continue;
3920 }
3921 buffer_off = 0;
3922 }
3923 else
3924# endif /* FEAT_MBYTE */
3925 {
3926 buffer[len] = NUL;
3927 msg_puts(buffer);
3928 }
3929
3930 windgoto(msg_row, msg_col);
3931 cursor_on();
3932 out_flush();
3933 if (got_int)
3934 break;
3935 }
3936
3937 /*
3938 * Check if the child still exists, before checking for
3939 * typed characters (otherwise we would loose typeahead).
3940 */
3941# ifdef __NeXT__
3942 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *) 0);
3943# else
3944 wait_pid = waitpid(pid, &status, WNOHANG);
3945# endif
3946 if ((wait_pid == (pid_t)-1 && errno == ECHILD)
3947 || (wait_pid == pid && WIFEXITED(status)))
3948 {
3949 wait_pid = pid;
3950 break;
3951 }
3952 wait_pid = 0;
3953 }
3954finished:
3955 p_more = p_more_save;
3956
3957# ifndef MACOS_X_UNIX /* TODO: Is it needed for MACOS_X ? */
3958 /*
3959 * Give all typeahead that wasn't used back to ui_inchar().
3960 */
3961 if (ta_len)
3962 ui_inchar_undo(ta_buf, ta_len);
3963# endif
3964 State = old_State;
3965 if (toshell_fd >= 0)
3966 close(toshell_fd);
3967 close(fromshell_fd);
3968 }
3969# endif /* FEAT_GUI */
3970
3971 /*
3972 * Wait until our child has exited.
3973 * Ignore wait() returning pids of other children and returning
3974 * because of some signal like SIGWINCH.
3975 * Don't wait if wait_pid was already set above, indicating the
3976 * child already exited.
3977 */
3978 while (wait_pid != pid)
3979 {
3980#ifdef _THREAD_SAFE
3981 /* Ugly hack: when compiled with Python threads are probably
3982 * used, in which case wait() sometimes hangs for no obvious
3983 * reason. Use waitpid() instead and loop (like the GUI). */
3984# ifdef __NeXT__
3985 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0);
3986# else
3987 wait_pid = waitpid(pid, &status, WNOHANG);
3988# endif
3989 if (wait_pid == 0)
3990 {
3991 /* Wait for 1/100 sec before trying again. */
3992 mch_delay(10L, TRUE);
3993 continue;
3994 }
3995#else
3996 wait_pid = wait(&status);
3997#endif
3998 if (wait_pid <= 0
3999# ifdef ECHILD
4000 && errno == ECHILD
4001# endif
4002 )
4003 break;
4004 }
4005
4006 /*
4007 * Set to raw mode right now, otherwise a CTRL-C after
4008 * catch_signals() will kill Vim.
4009 */
4010 if (tmode == TMODE_RAW)
4011 settmode(TMODE_RAW);
4012 did_settmode = TRUE;
4013 set_signals();
4014
4015 if (WIFEXITED(status))
4016 {
4017 retval = WEXITSTATUS(status);
4018 if (retval && !emsg_silent)
4019 {
4020 if (retval == EXEC_FAILED)
4021 {
4022 MSG_PUTS(_("\nCannot execute shell "));
4023 msg_outtrans(p_sh);
4024 msg_putchar('\n');
4025 }
4026 else if (!(options & SHELL_SILENT))
4027 {
4028 MSG_PUTS(_("\nshell returned "));
4029 msg_outnum((long)retval);
4030 msg_putchar('\n');
4031 }
4032 }
4033 }
4034 else
4035 MSG_PUTS(_("\nCommand terminated\n"));
4036 }
4037 }
4038 vim_free(argv);
4039
4040error:
4041 if (!did_settmode)
4042 if (tmode == TMODE_RAW)
4043 settmode(TMODE_RAW); /* set to raw mode */
4044# ifdef FEAT_TITLE
4045 resettitle();
4046# endif
4047 vim_free(newcmd);
4048
4049 return retval;
4050
4051#endif /* USE_SYSTEM */
4052}
4053
4054/*
4055 * Check for CTRL-C typed by reading all available characters.
4056 * In cooked mode we should get SIGINT, no need to check.
4057 */
4058 void
4059mch_breakcheck()
4060{
4061 if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL))
4062 fill_input_buf(FALSE);
4063}
4064
4065/*
4066 * Wait "msec" msec until a character is available from the keyboard or from
4067 * inbuf[]. msec == -1 will block forever.
4068 * When a GUI is being used, this will never get called -- webb
4069 */
4070 static int
4071WaitForChar(msec)
4072 long msec;
4073{
4074#ifdef FEAT_MOUSE_GPM
4075 int gpm_process_wanted;
4076#endif
4077#ifdef FEAT_XCLIPBOARD
4078 int rest;
4079#endif
4080 int avail;
4081
4082 if (input_available()) /* something in inbuf[] */
4083 return 1;
4084
4085#if defined(FEAT_MOUSE_DEC)
4086 /* May need to query the mouse position. */
4087 if (WantQueryMouse)
4088 {
4089 WantQueryMouse = 0;
4090 mch_write((char_u *)IF_EB("\033[1'|", ESC_STR "[1'|"), 5);
4091 }
4092#endif
4093
4094 /*
4095 * For FEAT_MOUSE_GPM and FEAT_XCLIPBOARD we loop here to process mouse
4096 * events. This is a bit complicated, because they might both be defined.
4097 */
4098#if defined(FEAT_MOUSE_GPM) || defined(FEAT_XCLIPBOARD)
4099# ifdef FEAT_XCLIPBOARD
4100 rest = 0;
4101 if (do_xterm_trace())
4102 rest = msec;
4103# endif
4104 do
4105 {
4106# ifdef FEAT_XCLIPBOARD
4107 if (rest != 0)
4108 {
4109 msec = XT_TRACE_DELAY;
4110 if (rest >= 0 && rest < XT_TRACE_DELAY)
4111 msec = rest;
4112 if (rest >= 0)
4113 rest -= msec;
4114 }
4115# endif
4116# ifdef FEAT_MOUSE_GPM
4117 gpm_process_wanted = 0;
4118 avail = RealWaitForChar(read_cmd_fd, msec, &gpm_process_wanted);
4119# else
4120 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4121# endif
4122 if (!avail)
4123 {
4124 if (input_available())
4125 return 1;
4126# ifdef FEAT_XCLIPBOARD
4127 if (rest == 0 || !do_xterm_trace())
4128# endif
4129 break;
4130 }
4131 }
4132 while (FALSE
4133# ifdef FEAT_MOUSE_GPM
4134 || (gpm_process_wanted && mch_gpm_process() == 0)
4135# endif
4136# ifdef FEAT_XCLIPBOARD
4137 || (!avail && rest != 0)
4138# endif
4139 );
4140
4141#else
4142 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4143#endif
4144 return avail;
4145}
4146
4147/*
4148 * Wait "msec" msec until a character is available from file descriptor "fd".
4149 * Time == -1 will block forever.
4150 * When a GUI is being used, this will not be used for input -- webb
4151 * Returns also, when a request from Sniff is waiting -- toni.
4152 * Or when a Linux GPM mouse event is waiting.
4153 */
4154/* ARGSUSED */
4155#if defined(__BEOS__)
4156 int
4157#else
4158 static int
4159#endif
4160RealWaitForChar(fd, msec, check_for_gpm)
4161 int fd;
4162 long msec;
4163 int *check_for_gpm;
4164{
4165 int ret;
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004166#if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004167 static int busy = FALSE;
4168
4169 /* May retry getting characters after an event was handled. */
4170# define MAY_LOOP
4171
4172# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4173 /* Remember at what time we started, so that we know how much longer we
4174 * should wait after being interrupted. */
4175# define USE_START_TV
4176 struct timeval start_tv;
4177
4178 if (msec > 0 && (
4179# ifdef FEAT_XCLIPBOARD
4180 xterm_Shell != (Widget)0
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004181# if defined(USE_XSMP) || defined(FEAT_MZSCHEME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004182 ||
4183# endif
4184# endif
4185# ifdef USE_XSMP
4186 xsmp_icefd != -1
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004187# ifdef FEAT_MZSCHEME
4188 ||
4189# endif
4190# endif
4191# ifdef FEAT_MZSCHEME
4192 (mzthreads_allowed() && p_mzq > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004193# endif
4194 ))
4195 gettimeofday(&start_tv, NULL);
4196# endif
4197
4198 /* Handle being called recursively. This may happen for the session
4199 * manager stuff, it may save the file, which does a breakcheck. */
4200 if (busy)
4201 return 0;
4202#endif
4203
4204#ifdef MAY_LOOP
4205 while (1)
4206#endif
4207 {
4208#ifdef MAY_LOOP
4209 int finished = TRUE; /* default is to 'loop' just once */
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004210# ifdef FEAT_MZSCHEME
4211 int mzquantum_used = FALSE;
4212# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004213#endif
4214#ifndef HAVE_SELECT
4215 struct pollfd fds[5];
4216 int nfd;
4217# ifdef FEAT_XCLIPBOARD
4218 int xterm_idx = -1;
4219# endif
4220# ifdef FEAT_MOUSE_GPM
4221 int gpm_idx = -1;
4222# endif
4223# ifdef USE_XSMP
4224 int xsmp_idx = -1;
4225# endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004226 int towait = (int)msec;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004227
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004228# ifdef FEAT_MZSCHEME
4229 mzvim_check_threads();
4230 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4231 {
4232 towait = (int)p_mzq; /* don't wait longer than 'mzquantum' */
4233 mzquantum_used = TRUE;
4234 }
4235# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004236 fds[0].fd = fd;
4237 fds[0].events = POLLIN;
4238 nfd = 1;
4239
4240# ifdef FEAT_SNIFF
4241# define SNIFF_IDX 1
4242 if (want_sniff_request)
4243 {
4244 fds[SNIFF_IDX].fd = fd_from_sniff;
4245 fds[SNIFF_IDX].events = POLLIN;
4246 nfd++;
4247 }
4248# endif
4249# ifdef FEAT_XCLIPBOARD
4250 if (xterm_Shell != (Widget)0)
4251 {
4252 xterm_idx = nfd;
4253 fds[nfd].fd = ConnectionNumber(xterm_dpy);
4254 fds[nfd].events = POLLIN;
4255 nfd++;
4256 }
4257# endif
4258# ifdef FEAT_MOUSE_GPM
4259 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4260 {
4261 gpm_idx = nfd;
4262 fds[nfd].fd = gpm_fd;
4263 fds[nfd].events = POLLIN;
4264 nfd++;
4265 }
4266# endif
4267# ifdef USE_XSMP
4268 if (xsmp_icefd != -1)
4269 {
4270 xsmp_idx = nfd;
4271 fds[nfd].fd = xsmp_icefd;
4272 fds[nfd].events = POLLIN;
4273 nfd++;
4274 }
4275# endif
4276
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004277 ret = poll(fds, nfd, towait);
4278# ifdef FEAT_MZSCHEME
4279 if (ret == 0 && mzquantum_used)
4280 /* MzThreads scheduling is required and timeout occured */
4281 finished = FALSE;
4282# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004283
4284# ifdef FEAT_SNIFF
4285 if (ret < 0)
4286 sniff_disconnect(1);
4287 else if (want_sniff_request)
4288 {
4289 if (fds[SNIFF_IDX].revents & POLLHUP)
4290 sniff_disconnect(1);
4291 if (fds[SNIFF_IDX].revents & POLLIN)
4292 sniff_request_waiting = 1;
4293 }
4294# endif
4295# ifdef FEAT_XCLIPBOARD
4296 if (xterm_Shell != (Widget)0 && (fds[xterm_idx].revents & POLLIN))
4297 {
4298 xterm_update(); /* Maybe we should hand out clipboard */
4299 if (--ret == 0 && !input_available())
4300 /* Try again */
4301 finished = FALSE;
4302 }
4303# endif
4304# ifdef FEAT_MOUSE_GPM
4305 if (gpm_idx >= 0 && (fds[gpm_idx].revents & POLLIN))
4306 {
4307 *check_for_gpm = 1;
4308 }
4309# endif
4310# ifdef USE_XSMP
4311 if (xsmp_idx >= 0 && (fds[xsmp_idx].revents & (POLLIN | POLLHUP)))
4312 {
4313 if (fds[xsmp_idx].revents & POLLIN)
4314 {
4315 busy = TRUE;
4316 xsmp_handle_requests();
4317 busy = FALSE;
4318 }
4319 else if (fds[xsmp_idx].revents & POLLHUP)
4320 {
4321 if (p_verbose > 0)
4322 MSG(_("XSMP lost ICE connection"));
4323 xsmp_close();
4324 }
4325 if (--ret == 0)
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004326 finished = FALSE; /* Try again */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004327 }
4328# endif
4329
4330
4331#else /* HAVE_SELECT */
4332
4333 struct timeval tv;
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004334 struct timeval *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004335 fd_set rfds, efds;
4336 int maxfd;
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004337 long towait = msec;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004338
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004339# ifdef FEAT_MZSCHEME
4340 mzvim_check_threads();
4341 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4342 {
4343 towait = p_mzq; /* don't wait longer than 'mzquantum' */
4344 mzquantum_used = TRUE;
4345 }
4346# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004347# ifdef __EMX__
4348 /* don't check for incoming chars if not in raw mode, because select()
4349 * always returns TRUE then (in some version of emx.dll) */
4350 if (curr_tmode != TMODE_RAW)
4351 return 0;
4352# endif
4353
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004354 if (towait >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004355 {
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004356 tv.tv_sec = towait / 1000;
4357 tv.tv_usec = (towait % 1000) * (1000000/1000);
4358 tvp = &tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004359 }
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004360 else
4361 tvp = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004362
4363 /*
4364 * Select on ready for reading and exceptional condition (end of file).
4365 */
4366 FD_ZERO(&rfds); /* calls bzero() on a sun */
4367 FD_ZERO(&efds);
4368 FD_SET(fd, &rfds);
4369# if !defined(__QNX__) && !defined(__CYGWIN32__)
4370 /* For QNX select() always returns 1 if this is set. Why? */
4371 FD_SET(fd, &efds);
4372# endif
4373 maxfd = fd;
4374
4375# ifdef FEAT_SNIFF
4376 if (want_sniff_request)
4377 {
4378 FD_SET(fd_from_sniff, &rfds);
4379 FD_SET(fd_from_sniff, &efds);
4380 if (maxfd < fd_from_sniff)
4381 maxfd = fd_from_sniff;
4382 }
4383# endif
4384# ifdef FEAT_XCLIPBOARD
4385 if (xterm_Shell != (Widget)0)
4386 {
4387 FD_SET(ConnectionNumber(xterm_dpy), &rfds);
4388 if (maxfd < ConnectionNumber(xterm_dpy))
4389 maxfd = ConnectionNumber(xterm_dpy);
4390 }
4391# endif
4392# ifdef FEAT_MOUSE_GPM
4393 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4394 {
4395 FD_SET(gpm_fd, &rfds);
4396 FD_SET(gpm_fd, &efds);
4397 if (maxfd < gpm_fd)
4398 maxfd = gpm_fd;
4399 }
4400# endif
4401# ifdef USE_XSMP
4402 if (xsmp_icefd != -1)
4403 {
4404 FD_SET(xsmp_icefd, &rfds);
4405 FD_SET(xsmp_icefd, &efds);
4406 if (maxfd < xsmp_icefd)
4407 maxfd = xsmp_icefd;
4408 }
4409# endif
4410
4411# ifdef OLD_VMS
4412 /* Old VMS as v6.2 and older have broken select(). It waits more than
4413 * required. Should not be used */
4414 ret = 0;
4415# else
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004416 ret = select(maxfd + 1, &rfds, NULL, &efds, tvp);
4417# endif
4418# ifdef FEAT_MZSCHEME
4419 if (ret == 0 && mzquantum_used)
4420 /* loop if MzThreads must be scheduled and timeout occured */
4421 finished = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004422# endif
4423
4424# ifdef FEAT_SNIFF
4425 if (ret < 0 )
4426 sniff_disconnect(1);
4427 else if (ret > 0 && want_sniff_request)
4428 {
4429 if (FD_ISSET(fd_from_sniff, &efds))
4430 sniff_disconnect(1);
4431 if (FD_ISSET(fd_from_sniff, &rfds))
4432 sniff_request_waiting = 1;
4433 }
4434# endif
4435# ifdef FEAT_XCLIPBOARD
4436 if (ret > 0 && xterm_Shell != (Widget)0
4437 && FD_ISSET(ConnectionNumber(xterm_dpy), &rfds))
4438 {
4439 xterm_update(); /* Maybe we should hand out clipboard */
4440 /* continue looping when we only got the X event and the input
4441 * buffer is empty */
4442 if (--ret == 0 && !input_available())
4443 {
4444 /* Try again */
4445 finished = FALSE;
4446 }
4447 }
4448# endif
4449# ifdef FEAT_MOUSE_GPM
4450 if (ret > 0 && gpm_flag && check_for_gpm != NULL && gpm_fd >= 0)
4451 {
4452 if (FD_ISSET(gpm_fd, &efds))
4453 gpm_close();
4454 else if (FD_ISSET(gpm_fd, &rfds))
4455 *check_for_gpm = 1;
4456 }
4457# endif
4458# ifdef USE_XSMP
4459 if (ret > 0 && xsmp_icefd != -1)
4460 {
4461 if (FD_ISSET(xsmp_icefd, &efds))
4462 {
4463 if (p_verbose > 0)
4464 MSG(_("XSMP lost ICE connection"));
4465 xsmp_close();
4466 if (--ret == 0)
4467 finished = FALSE; /* keep going if event was only one */
4468 }
4469 else if (FD_ISSET(xsmp_icefd, &rfds))
4470 {
4471 busy = TRUE;
4472 xsmp_handle_requests();
4473 busy = FALSE;
4474 if (--ret == 0)
4475 finished = FALSE; /* keep going if event was only one */
4476 }
4477 }
4478# endif
4479
4480#endif /* HAVE_SELECT */
4481
4482#ifdef MAY_LOOP
4483 if (finished || msec == 0)
4484 break;
4485
4486 /* We're going to loop around again, find out for how long */
4487 if (msec > 0)
4488 {
4489# ifdef USE_START_TV
4490 struct timeval mtv;
4491
4492 /* Compute remaining wait time. */
4493 gettimeofday(&mtv, NULL);
4494 msec -= (mtv.tv_sec - start_tv.tv_sec) * 1000L
4495 + (mtv.tv_usec - start_tv.tv_usec) / 1000L;
4496# else
4497 /* Guess we got interrupted halfway. */
4498 msec = msec / 2;
4499# endif
4500 if (msec <= 0)
4501 break; /* waited long enough */
4502 }
4503#endif
4504 }
4505
4506 return (ret > 0);
4507}
4508
4509#ifndef VMS
4510
4511#ifndef NO_EXPANDPATH
4512 static int
4513pstrcmp(a, b)
4514 const void *a, *b;
4515{
4516 return (pathcmp(*(char **)a, *(char **)b));
4517}
4518
4519/*
4520 * Recursively expand one path component into all matching files and/or
4521 * directories.
4522 * "path" has backslashes before chars that are not to be expanded, starting
4523 * at "path + wildoff".
4524 * Return the number of matches found.
4525 */
4526 int
4527mch_expandpath(gap, path, flags)
4528 garray_T *gap;
4529 char_u *path;
4530 int flags; /* EW_* flags */
4531{
4532 return unix_expandpath(gap, path, 0, flags);
4533}
4534
4535 static int
4536unix_expandpath(gap, path, wildoff, flags)
4537 garray_T *gap;
4538 char_u *path;
4539 int wildoff;
4540 int flags; /* EW_* flags */
4541{
4542 char_u *buf;
4543 char_u *path_end;
4544 char_u *p, *s, *e;
4545 int start_len, c;
4546 char_u *pat;
4547 DIR *dirp;
4548 regmatch_T regmatch;
4549 struct dirent *dp;
4550 int starts_with_dot;
4551 int matches;
4552 int len;
4553
4554 start_len = gap->ga_len;
4555 buf = alloc(STRLEN(path) + BASENAMELEN + 5);/* make room for file name */
4556 if (buf == NULL)
4557 return 0;
4558
4559/*
4560 * Find the first part in the path name that contains a wildcard.
4561 * Copy it into buf, including the preceding characters.
4562 */
4563 p = buf;
4564 s = buf;
4565 e = NULL;
4566 path_end = path;
4567 while (*path_end != NUL)
4568 {
4569 /* May ignore a wildcard that has a backslash before it; it will
4570 * be removed by rem_backslash() or file_pat_to_reg_pat() below. */
4571 if (path_end >= path + wildoff && rem_backslash(path_end))
4572 *p++ = *path_end++;
4573 else if (*path_end == '/')
4574 {
4575 if (e != NULL)
4576 break;
4577 s = p + 1;
4578 }
4579 else if (path_end >= path + wildoff
4580 && vim_strchr((char_u *)"*?[{~$", *path_end) != NULL)
4581 e = p;
4582#ifdef FEAT_MBYTE
4583 if (has_mbyte)
4584 {
4585 len = (*mb_ptr2len_check)(path_end);
4586 STRNCPY(p, path_end, len);
4587 p += len;
4588 path_end += len;
4589 }
4590 else
4591#endif
4592 *p++ = *path_end++;
4593 }
4594 e = p;
4595 *e = NUL;
4596
4597 /* now we have one wildcard component between s and e */
4598 /* Remove backslashes between "wildoff" and the start of the wildcard
4599 * component. */
4600 for (p = buf + wildoff; p < s; ++p)
4601 if (rem_backslash(p))
4602 {
4603 STRCPY(p, p + 1);
4604 --e;
4605 --s;
4606 }
4607
4608 /* convert the file pattern to a regexp pattern */
4609 starts_with_dot = (*s == '.');
4610 pat = file_pat_to_reg_pat(s, e, NULL, FALSE);
4611 if (pat == NULL)
4612 {
4613 vim_free(buf);
4614 return 0;
4615 }
4616
4617 /* compile the regexp into a program */
4618#ifdef MACOS_X /* Can/Should we use CASE_INSENSITIVE_FILENAME instead ?*/
4619 regmatch.rm_ic = TRUE; /* Behave like Terminal.app */
4620#else
4621 regmatch.rm_ic = FALSE; /* Don't ever ignore case */
4622#endif
4623 regmatch.regprog = vim_regcomp(pat, RE_MAGIC);
4624 vim_free(pat);
4625
4626 if (regmatch.regprog == NULL)
4627 {
4628 vim_free(buf);
4629 return 0;
4630 }
4631
4632 /* open the directory for scanning */
4633 c = *s;
4634 *s = NUL;
4635 dirp = opendir(*buf == NUL ? "." : (char *)buf);
4636 *s = c;
4637
4638 /* Find all matching entries */
4639 if (dirp != NULL)
4640 {
4641 for (;;)
4642 {
4643 dp = readdir(dirp);
4644 if (dp == NULL)
4645 break;
4646 if ((dp->d_name[0] != '.' || starts_with_dot)
4647 && vim_regexec(&regmatch, (char_u *)dp->d_name, (colnr_T)0))
4648 {
4649 STRCPY(s, dp->d_name);
4650 len = STRLEN(buf);
4651 STRCPY(buf + len, path_end);
4652 if (mch_has_exp_wildcard(path_end)) /* handle more wildcards */
4653 {
4654 /* need to expand another component of the path */
4655 /* remove backslashes for the remaining components only */
4656 (void)unix_expandpath(gap, buf, len + 1, flags);
4657 }
4658 else
4659 {
4660 /* no more wildcards, check if there is a match */
4661 /* remove backslashes for the remaining components only */
4662 if (*path_end != NUL)
4663 backslash_halve(buf + len + 1);
4664 if (mch_getperm(buf) >= 0) /* add existing file */
4665 addfile(gap, buf, flags);
4666 }
4667 }
4668 }
4669
4670 closedir(dirp);
4671 }
4672
4673 vim_free(buf);
4674 vim_free(regmatch.regprog);
4675
4676 matches = gap->ga_len - start_len;
4677 if (matches > 0)
4678 qsort(((char_u **)gap->ga_data) + start_len, matches,
4679 sizeof(char_u *), pstrcmp);
4680 return matches;
4681}
4682#endif
4683
4684/*
4685 * mch_expand_wildcards() - this code does wild-card pattern matching using
4686 * the shell
4687 *
4688 * return OK for success, FAIL for error (you may lose some memory) and put
4689 * an error message in *file.
4690 *
4691 * num_pat is number of input patterns
4692 * pat is array of pointers to input patterns
4693 * num_file is pointer to number of matched file names
4694 * file is pointer to array of pointers to matched file names
4695 */
4696
4697#ifndef SEEK_SET
4698# define SEEK_SET 0
4699#endif
4700#ifndef SEEK_END
4701# define SEEK_END 2
4702#endif
4703
4704/* ARGSUSED */
4705 int
4706mch_expand_wildcards(num_pat, pat, num_file, file, flags)
4707 int num_pat;
4708 char_u **pat;
4709 int *num_file;
4710 char_u ***file;
4711 int flags; /* EW_* flags */
4712{
4713 int i;
4714 size_t len;
4715 char_u *p;
4716 int dir;
4717#ifdef __EMX__
4718# define EXPL_ALLOC_INC 16
4719 char_u **expl_files;
4720 size_t files_alloced, files_free;
4721 char_u *buf;
4722 int has_wildcard;
4723
4724 *num_file = 0; /* default: no files found */
4725 files_alloced = EXPL_ALLOC_INC; /* how much space is allocated */
4726 files_free = EXPL_ALLOC_INC; /* how much space is not used */
4727 *file = (char_u **)alloc(sizeof(char_u **) * files_alloced);
4728 if (*file == NULL)
4729 return FAIL;
4730
4731 for (; num_pat > 0; num_pat--, pat++)
4732 {
4733 expl_files = NULL;
4734 if (vim_strchr(*pat, '$') || vim_strchr(*pat, '~'))
4735 /* expand environment var or home dir */
4736 buf = expand_env_save(*pat);
4737 else
4738 buf = vim_strsave(*pat);
4739 expl_files = NULL;
4740 has_wildcard = mch_has_exp_wildcard(buf); /* (still) wildcards in there? */
4741 if (has_wildcard) /* yes, so expand them */
4742 expl_files = (char_u **)_fnexplode(buf);
4743
4744 /*
4745 * return value of buf if no wildcards left,
4746 * OR if no match AND EW_NOTFOUND is set.
4747 */
4748 if ((!has_wildcard && ((flags & EW_NOTFOUND) || mch_getperm(buf) >= 0))
4749 || (expl_files == NULL && (flags & EW_NOTFOUND)))
4750 { /* simply save the current contents of *buf */
4751 expl_files = (char_u **)alloc(sizeof(char_u **) * 2);
4752 if (expl_files != NULL)
4753 {
4754 expl_files[0] = vim_strsave(buf);
4755 expl_files[1] = NULL;
4756 }
4757 }
4758 vim_free(buf);
4759
4760 /*
4761 * Count number of names resulting from expansion,
4762 * At the same time add a backslash to the end of names that happen to
4763 * be directories, and replace slashes with backslashes.
4764 */
4765 if (expl_files)
4766 {
4767 for (i = 0; (p = expl_files[i]) != NULL; i++)
4768 {
4769 dir = mch_isdir(p);
4770 /* If we don't want dirs and this is one, skip it */
4771 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
4772 continue;
4773
4774 if (--files_free == 0)
4775 {
4776 /* need more room in table of pointers */
4777 files_alloced += EXPL_ALLOC_INC;
4778 *file = (char_u **)vim_realloc(*file,
4779 sizeof(char_u **) * files_alloced);
4780 if (*file == NULL)
4781 {
4782 EMSG(_(e_outofmem));
4783 *num_file = 0;
4784 return FAIL;
4785 }
4786 files_free = EXPL_ALLOC_INC;
4787 }
4788 slash_adjust(p);
4789 if (dir)
4790 {
4791 /* For a directory we add a '/', unless it's already
4792 * there. */
4793 len = STRLEN(p);
4794 if (((*file)[*num_file] = alloc(len + 2)) != NULL)
4795 {
4796 STRCPY((*file)[*num_file], p);
4797 if (!vim_ispathsep((*file)[*num_file][len - 1]))
4798 {
4799 (*file)[*num_file][len] = psepc;
4800 (*file)[*num_file][len + 1] = 0;
4801 }
4802 }
4803 }
4804 else
4805 {
4806 (*file)[*num_file] = vim_strsave(p);
4807 }
4808
4809 /*
4810 * Error message already given by either alloc or vim_strsave.
4811 * Should return FAIL, but returning OK works also.
4812 */
4813 if ((*file)[*num_file] == NULL)
4814 break;
4815 (*num_file)++;
4816 }
4817 _fnexplodefree((char **)expl_files);
4818 }
4819 }
4820 return OK;
4821
4822#else /* __EMX__ */
4823
4824 int j;
4825 char_u *tempname;
4826 char_u *command;
4827 FILE *fd;
4828 char_u *buffer;
4829#define STYLE_ECHO 0 /* use "echo" to expand */
4830#define STYLE_GLOB 1 /* use "glob" to expand, for csh */
4831#define STYLE_PRINT 2 /* use "print -N" to expand, for zsh */
4832#define STYLE_BT 3 /* `cmd` expansion, execute the pattern directly */
4833 int shell_style = STYLE_ECHO;
4834 int check_spaces;
4835 static int did_find_nul = FALSE;
4836 int ampersent = FALSE;
4837
4838 *num_file = 0; /* default: no files found */
4839 *file = NULL;
4840
4841 /*
4842 * If there are no wildcards, just copy the names to allocated memory.
4843 * Saves a lot of time, because we don't have to start a new shell.
4844 */
4845 if (!have_wildcard(num_pat, pat))
4846 return save_patterns(num_pat, pat, num_file, file);
4847
4848 /*
4849 * Don't allow the use of backticks in secure and restricted mode.
4850 */
4851 if (secure || restricted)
4852 for (i = 0; i < num_pat; ++i)
4853 if (vim_strchr(pat[i], '`') != NULL
4854 && (check_restricted() || check_secure()))
4855 return FAIL;
4856
4857 /*
4858 * get a name for the temp file
4859 */
4860 if ((tempname = vim_tempname('o')) == NULL)
4861 {
4862 EMSG(_(e_notmp));
4863 return FAIL;
4864 }
4865
4866 /*
4867 * Let the shell expand the patterns and write the result into the temp
4868 * file. if expanding `cmd` execute it directly.
4869 * If we use csh, glob will work better than echo.
4870 * If we use zsh, print -N will work better than glob.
4871 */
4872 if (num_pat == 1 && *pat[0] == '`'
4873 && (len = STRLEN(pat[0])) > 2
4874 && *(pat[0] + len - 1) == '`')
4875 shell_style = STYLE_BT;
4876 else if ((len = STRLEN(p_sh)) >= 3)
4877 {
4878 if (STRCMP(p_sh + len - 3, "csh") == 0)
4879 shell_style = STYLE_GLOB;
4880 else if (STRCMP(p_sh + len - 3, "zsh") == 0)
4881 shell_style = STYLE_PRINT;
4882 }
4883
4884 /* "unset nonomatch; print -N >" plus two is 29 */
4885 len = STRLEN(tempname) + 29;
4886 for (i = 0; i < num_pat; ++i) /* count the length of the patterns */
4887 len += STRLEN(pat[i]) + 3; /* add space and two quotes */
4888 command = alloc(len);
4889 if (command == NULL)
4890 {
4891 /* out of memory */
4892 vim_free(tempname);
4893 return FAIL;
4894 }
4895
4896 /*
4897 * Build the shell command:
4898 * - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell
4899 * recognizes this).
4900 * - Add the shell command to print the expanded names.
4901 * - Add the temp file name.
4902 * - Add the file name patterns.
4903 */
4904 if (shell_style == STYLE_BT)
4905 {
4906 STRCPY(command, pat[0] + 1); /* exclude first backtick */
4907 p = command + STRLEN(command) - 1;
4908 *p = ' '; /* remove last backtick */
4909 while (p > command && vim_iswhite(*p))
4910 --p;
4911 if (*p == '&') /* remove trailing '&' */
4912 {
4913 ampersent = TRUE;
4914 *p = ' ';
4915 }
4916 STRCAT(command, ">");
4917 }
4918 else
4919 {
4920 if (flags & EW_NOTFOUND)
4921 STRCPY(command, "set nonomatch; ");
4922 else
4923 STRCPY(command, "unset nonomatch; ");
4924 if (shell_style == STYLE_GLOB)
4925 STRCAT(command, "glob >");
4926 else if (shell_style == STYLE_PRINT)
4927 STRCAT(command, "print -N >");
4928 else
4929 STRCAT(command, "echo >");
4930 }
4931 STRCAT(command, tempname);
4932 if (shell_style != STYLE_BT)
4933 for (i = 0; i < num_pat; ++i)
4934 {
4935 /* When using system() always add extra quotes, because the shell
4936 * is started twice. Otherwise only put quotes around spaces and
4937 * single quotes. */
4938#ifdef USE_SYSTEM
4939 STRCAT(command, " \"");
4940 STRCAT(command, pat[i]);
4941 STRCAT(command, "\"");
4942#else
4943 p = command + STRLEN(command);
4944 *p++ = ' ';
4945 for (j = 0; pat[i][j] != NUL; )
4946 if (vim_strchr((char_u *)" '", pat[i][j]) != NULL)
4947 {
4948 *p++ = '"';
4949 while (pat[i][j] != NUL
4950 && vim_strchr((char_u *)" '", pat[i][j]) != NULL)
4951 *p++ = pat[i][j++];
4952 *p++ = '"';
4953 }
4954 else
4955 *p++ = pat[i][j++];
4956 *p = NUL;
4957#endif
4958 }
4959 if (flags & EW_SILENT)
4960 show_shell_mess = FALSE;
4961 if (ampersent)
4962 STRCAT(command, "&"); /* put the '&' back after the
4963 redirection */
4964
4965 /*
4966 * Using zsh -G: If a pattern has no matches, it is just deleted from
4967 * the argument list, otherwise zsh gives an error message and doesn't
4968 * expand any other pattern.
4969 */
4970 if (shell_style == STYLE_PRINT)
4971 extra_shell_arg = (char_u *)"-G"; /* Use zsh NULL_GLOB option */
4972
4973 /*
4974 * If we use -f then shell variables set in .cshrc won't get expanded.
4975 * vi can do it, so we will too, but it is only necessary if there is a "$"
4976 * in one of the patterns, otherwise we can still use the fast option.
4977 */
4978 else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat))
4979 extra_shell_arg = (char_u *)"-f"; /* Use csh fast option */
4980
4981 /*
4982 * execute the shell command
4983 */
4984 i = call_shell(command, SHELL_EXPAND | SHELL_SILENT);
4985
4986 /* When running in the background, give it some time to create the temp
4987 * file, but don't wait for it to finish. */
4988 if (ampersent)
4989 mch_delay(10L, TRUE);
4990
4991 extra_shell_arg = NULL; /* cleanup */
4992 show_shell_mess = TRUE;
4993 vim_free(command);
4994
4995 if (i) /* mch_call_shell() failed */
4996 {
4997 mch_remove(tempname);
4998 vim_free(tempname);
4999 /*
5000 * With interactive completion, the error message is not printed.
5001 * However with USE_SYSTEM, I don't know how to turn off error messages
5002 * from the shell, so screen may still get messed up -- webb.
5003 */
5004#ifndef USE_SYSTEM
5005 if (!(flags & EW_SILENT))
5006#endif
5007 {
5008 redraw_later_clear(); /* probably messed up screen */
5009 msg_putchar('\n'); /* clear bottom line quickly */
5010 cmdline_row = Rows - 1; /* continue on last line */
5011#ifdef USE_SYSTEM
5012 if (!(flags & EW_SILENT))
5013#endif
5014 {
5015 MSG(_(e_wildexpand));
5016 msg_start(); /* don't overwrite this message */
5017 }
5018 }
5019 /* If a `cmd` expansion failed, don't list `cmd` as a match, even when
5020 * EW_NOTFOUND is given */
5021 if (shell_style == STYLE_BT)
5022 return FAIL;
5023 goto notfound;
5024 }
5025
5026 /*
5027 * read the names from the file into memory
5028 */
5029 fd = fopen((char *)tempname, READBIN);
5030 if (fd == NULL)
5031 {
5032 /* Something went wrong, perhaps a file name with a special char. */
5033 if (!(flags & EW_SILENT))
5034 {
5035 MSG(_(e_wildexpand));
5036 msg_start(); /* don't overwrite this message */
5037 }
5038 vim_free(tempname);
5039 goto notfound;
5040 }
5041 fseek(fd, 0L, SEEK_END);
5042 len = ftell(fd); /* get size of temp file */
5043 fseek(fd, 0L, SEEK_SET);
5044 buffer = alloc(len + 1);
5045 if (buffer == NULL)
5046 {
5047 /* out of memory */
5048 mch_remove(tempname);
5049 vim_free(tempname);
5050 fclose(fd);
5051 return FAIL;
5052 }
5053 i = fread((char *)buffer, 1, len, fd);
5054 fclose(fd);
5055 mch_remove(tempname);
5056 if (i != len)
5057 {
5058 /* unexpected read error */
5059 EMSG2(_(e_notread), tempname);
5060 vim_free(tempname);
5061 vim_free(buffer);
5062 return FAIL;
5063 }
5064 vim_free(tempname);
5065
5066#if defined(__CYGWIN__) || defined(__CYGWIN32__)
5067 /* Translate <CR><NL> into <NL>. Caution, buffer may contain NUL. */
5068 p = buffer;
5069 for (i = 0; i < len; ++i)
5070 if (!(buffer[i] == CAR && buffer[i + 1] == NL))
5071 *p++ = buffer[i];
5072 len = p - buffer;
5073# endif
5074
5075
5076 /* file names are separated with Space */
5077 if (shell_style == STYLE_ECHO)
5078 {
5079 buffer[len] = '\n'; /* make sure the buffer ends in NL */
5080 p = buffer;
5081 for (i = 0; *p != '\n'; ++i) /* count number of entries */
5082 {
5083 while (*p != ' ' && *p != '\n')
5084 ++p;
5085 p = skipwhite(p); /* skip to next entry */
5086 }
5087 }
5088 /* file names are separated with NL */
5089 else if (shell_style == STYLE_BT)
5090 {
5091 buffer[len] = NUL; /* make sure the buffer ends in NUL */
5092 p = buffer;
5093 for (i = 0; *p != NUL; ++i) /* count number of entries */
5094 {
5095 while (*p != '\n' && *p != NUL)
5096 ++p;
5097 if (*p != NUL)
5098 ++p;
5099 p = skipwhite(p); /* skip leading white space */
5100 }
5101 }
5102 /* file names are separated with NUL */
5103 else
5104 {
5105 /*
5106 * Some versions of zsh use spaces instead of NULs to separate
5107 * results. Only do this when there is no NUL before the end of the
5108 * buffer, otherwise we would never be able to use file names with
5109 * embedded spaces when zsh does use NULs.
5110 * When we found a NUL once, we know zsh is OK, set did_find_nul and
5111 * don't check for spaces again.
5112 */
5113 check_spaces = FALSE;
5114 if (shell_style == STYLE_PRINT && !did_find_nul)
5115 {
5116 /* If there is a NUL, set did_find_nul, else set check_spaces */
5117 if (len && (int)STRLEN(buffer) < len - 1)
5118 did_find_nul = TRUE;
5119 else
5120 check_spaces = TRUE;
5121 }
5122
5123 /*
5124 * Make sure the buffer ends with a NUL. For STYLE_PRINT there
5125 * already is one, for STYLE_GLOB it needs to be added.
5126 */
5127 if (len && buffer[len - 1] == NUL)
5128 --len;
5129 else
5130 buffer[len] = NUL;
5131 i = 0;
5132 for (p = buffer; p < buffer + len; ++p)
5133 if (*p == NUL || (*p == ' ' && check_spaces)) /* count entry */
5134 {
5135 ++i;
5136 *p = NUL;
5137 }
5138 if (len)
5139 ++i; /* count last entry */
5140 }
5141 if (i == 0)
5142 {
5143 /*
5144 * Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I".
5145 * /bin/sh will happily expand it to nothing rather than returning an
5146 * error; and hey, it's good to check anyway -- webb.
5147 */
5148 vim_free(buffer);
5149 goto notfound;
5150 }
5151 *num_file = i;
5152 *file = (char_u **)alloc(sizeof(char_u *) * i);
5153 if (*file == NULL)
5154 {
5155 /* out of memory */
5156 vim_free(buffer);
5157 return FAIL;
5158 }
5159
5160 /*
5161 * Isolate the individual file names.
5162 */
5163 p = buffer;
5164 for (i = 0; i < *num_file; ++i)
5165 {
5166 (*file)[i] = p;
5167 /* Space or NL separates */
5168 if (shell_style == STYLE_ECHO || shell_style == STYLE_BT)
5169 {
5170 while (!(shell_style == STYLE_ECHO && *p == ' ') && *p != '\n')
5171 ++p;
5172 if (p == buffer + len) /* last entry */
5173 *p = NUL;
5174 else
5175 {
5176 *p++ = NUL;
5177 p = skipwhite(p); /* skip to next entry */
5178 }
5179 }
5180 else /* NUL separates */
5181 {
5182 while (*p && p < buffer + len) /* skip entry */
5183 ++p;
5184 ++p; /* skip NUL */
5185 }
5186 }
5187
5188 /*
5189 * Move the file names to allocated memory.
5190 */
5191 for (j = 0, i = 0; i < *num_file; ++i)
5192 {
5193 /* Require the files to exist. Helps when using /bin/sh */
5194 if (!(flags & EW_NOTFOUND) && mch_getperm((*file)[i]) < 0)
5195 continue;
5196
5197 /* check if this entry should be included */
5198 dir = (mch_isdir((*file)[i]));
5199 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5200 continue;
5201
5202 p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir));
5203 if (p)
5204 {
5205 STRCPY(p, (*file)[i]);
5206 if (dir)
5207 STRCAT(p, "/"); /* add '/' to a directory name */
5208 (*file)[j++] = p;
5209 }
5210 }
5211 vim_free(buffer);
5212 *num_file = j;
5213
5214 if (*num_file == 0) /* rejected all entries */
5215 {
5216 vim_free(*file);
5217 *file = NULL;
5218 goto notfound;
5219 }
5220
5221 return OK;
5222
5223notfound:
5224 if (flags & EW_NOTFOUND)
5225 return save_patterns(num_pat, pat, num_file, file);
5226 return FAIL;
5227
5228#endif /* __EMX__ */
5229}
5230
5231#endif /* VMS */
5232
5233#ifndef __EMX__
5234 static int
5235save_patterns(num_pat, pat, num_file, file)
5236 int num_pat;
5237 char_u **pat;
5238 int *num_file;
5239 char_u ***file;
5240{
5241 int i;
5242
5243 *file = (char_u **)alloc(num_pat * sizeof(char_u *));
5244 if (*file == NULL)
5245 return FAIL;
5246 for (i = 0; i < num_pat; i++)
5247 (*file)[i] = vim_strsave(pat[i]);
5248 *num_file = num_pat;
5249 return OK;
5250}
5251#endif
5252
5253
5254/*
5255 * Return TRUE if the string "p" contains a wildcard that mch_expandpath() can
5256 * expand.
5257 */
5258 int
5259mch_has_exp_wildcard(p)
5260 char_u *p;
5261{
5262 for ( ; *p; ++p)
5263 {
5264#ifndef OS2
5265 if (*p == '\\' && p[1] != NUL)
5266 ++p;
5267 else
5268#endif
5269 if (vim_strchr((char_u *)
5270#ifdef VMS
5271 "*?%"
5272#else
5273# ifdef OS2
5274 "*?"
5275# else
5276 "*?[{'"
5277# endif
5278#endif
5279 , *p) != NULL)
5280 return TRUE;
5281#ifdef FEAT_MBYTE
5282 if (has_mbyte)
5283 p += (*mb_ptr2len_check)(p) - 1;
5284#endif
5285 }
5286 return FALSE;
5287}
5288
5289/*
5290 * Return TRUE if the string "p" contains a wildcard.
5291 * Don't recognize '~' at the end as a wildcard.
5292 */
5293 int
5294mch_has_wildcard(p)
5295 char_u *p;
5296{
5297 for ( ; *p; ++p)
5298 {
5299#ifndef OS2
5300 if (*p == '\\' && p[1] != NUL)
5301 ++p;
5302 else
5303#endif
5304 if (vim_strchr((char_u *)
5305#ifdef VMS
5306 "*?%$"
5307#else
5308# ifdef OS2
5309# ifdef VIM_BACKTICK
5310 "*?$`"
5311# else
5312 "*?$"
5313# endif
5314# else
5315 "*?[{`'$"
5316# endif
5317#endif
5318 , *p) != NULL
5319 || (*p == '~' && p[1] != NUL))
5320 return TRUE;
5321#ifdef FEAT_MBYTE
5322 if (has_mbyte)
5323 p += (*mb_ptr2len_check)(p) - 1;
5324#endif
5325 }
5326 return FALSE;
5327}
5328
5329#ifndef __EMX__
5330 static int
5331have_wildcard(num, file)
5332 int num;
5333 char_u **file;
5334{
5335 int i;
5336
5337 for (i = 0; i < num; i++)
5338 if (mch_has_wildcard(file[i]))
5339 return 1;
5340 return 0;
5341}
5342
5343 static int
5344have_dollars(num, file)
5345 int num;
5346 char_u **file;
5347{
5348 int i;
5349
5350 for (i = 0; i < num; i++)
5351 if (vim_strchr(file[i], '$') != NULL)
5352 return TRUE;
5353 return FALSE;
5354}
5355#endif /* ifndef __EMX__ */
5356
5357#ifndef HAVE_RENAME
5358/*
5359 * Scaled-down version of rename(), which is missing in Xenix.
5360 * This version can only move regular files and will fail if the
5361 * destination exists.
5362 */
5363 int
5364mch_rename(src, dest)
5365 const char *src, *dest;
5366{
5367 struct stat st;
5368
5369 if (stat(dest, &st) >= 0) /* fail if destination exists */
5370 return -1;
5371 if (link(src, dest) != 0) /* link file to new name */
5372 return -1;
5373 if (mch_remove(src) == 0) /* delete link to old name */
5374 return 0;
5375 return -1;
5376}
5377#endif /* !HAVE_RENAME */
5378
5379#ifdef FEAT_MOUSE_GPM
5380/*
5381 * Initializes connection with gpm (if it isn't already opened)
5382 * Return 1 if succeeded (or connection already opened), 0 if failed
5383 */
5384 static int
5385gpm_open()
5386{
5387 static Gpm_Connect gpm_connect; /* Must it be kept till closing ? */
5388
5389 if (!gpm_flag)
5390 {
5391 gpm_connect.eventMask = (GPM_UP | GPM_DRAG | GPM_DOWN);
5392 gpm_connect.defaultMask = ~GPM_HARD;
5393 /* Default handling for mouse move*/
5394 gpm_connect.minMod = 0; /* Handle any modifier keys */
5395 gpm_connect.maxMod = 0xffff;
5396 if (Gpm_Open(&gpm_connect, 0) > 0)
5397 {
5398 /* gpm library tries to handling TSTP causes
5399 * problems. Anyways, we close connection to Gpm whenever
5400 * we are going to suspend or starting an external process
5401 * so we should'nt have problem with this
5402 */
5403 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
5404 return 1; /* succeed */
5405 }
5406 if (gpm_fd == -2)
5407 Gpm_Close(); /* We don't want to talk to xterm via gpm */
5408 return 0;
5409 }
5410 return 1; /* already open */
5411}
5412
5413/*
5414 * Closes connection to gpm
5415 * returns non-zero if connection succesfully closed
5416 */
5417 static void
5418gpm_close()
5419{
5420 if (gpm_flag && gpm_fd >= 0) /* if Open */
5421 Gpm_Close();
5422}
5423
5424/* Reads gpm event and adds special keys to input buf. Returns length of
5425 * generated key sequence.
5426 * This function is made after gui_send_mouse_event
5427 */
5428 static int
5429mch_gpm_process()
5430{
5431 int button;
5432 static Gpm_Event gpm_event;
5433 char_u string[6];
5434 int_u vim_modifiers;
5435 int row,col;
5436 unsigned char buttons_mask;
5437 unsigned char gpm_modifiers;
5438 static unsigned char old_buttons = 0;
5439
5440 Gpm_GetEvent(&gpm_event);
5441
5442#ifdef FEAT_GUI
5443 /* Don't put events in the input queue now. */
5444 if (hold_gui_events)
5445 return 0;
5446#endif
5447
5448 row = gpm_event.y - 1;
5449 col = gpm_event.x - 1;
5450
5451 string[0] = ESC; /* Our termcode */
5452 string[1] = 'M';
5453 string[2] = 'G';
5454 switch (GPM_BARE_EVENTS(gpm_event.type))
5455 {
5456 case GPM_DRAG:
5457 string[3] = MOUSE_DRAG;
5458 break;
5459 case GPM_DOWN:
5460 buttons_mask = gpm_event.buttons & ~old_buttons;
5461 old_buttons = gpm_event.buttons;
5462 switch (buttons_mask)
5463 {
5464 case GPM_B_LEFT:
5465 button = MOUSE_LEFT;
5466 break;
5467 case GPM_B_MIDDLE:
5468 button = MOUSE_MIDDLE;
5469 break;
5470 case GPM_B_RIGHT:
5471 button = MOUSE_RIGHT;
5472 break;
5473 default:
5474 return 0;
5475 /*Don't know what to do. Can more than one button be
5476 * reported in one event? */
5477 }
5478 string[3] = (char_u)(button | 0x20);
5479 SET_NUM_MOUSE_CLICKS(string[3], gpm_event.clicks + 1);
5480 break;
5481 case GPM_UP:
5482 string[3] = MOUSE_RELEASE;
5483 old_buttons &= ~gpm_event.buttons;
5484 break;
5485 default:
5486 return 0;
5487 }
5488 /*This code is based on gui_x11_mouse_cb in gui_x11.c */
5489 gpm_modifiers = gpm_event.modifiers;
5490 vim_modifiers = 0x0;
5491 /* I ignore capslock stats. Aren't we all just hate capslock mixing with
5492 * Vim commands ? Besides, gpm_event.modifiers is unsigned char, and
5493 * K_CAPSSHIFT is defined 8, so it probably isn't even reported
5494 */
5495 if (gpm_modifiers & ((1 << KG_SHIFT) | (1 << KG_SHIFTR) | (1 << KG_SHIFTL)))
5496 vim_modifiers |= MOUSE_SHIFT;
5497
5498 if (gpm_modifiers & ((1 << KG_CTRL) | (1 << KG_CTRLR) | (1 << KG_CTRLL)))
5499 vim_modifiers |= MOUSE_CTRL;
5500 if (gpm_modifiers & ((1 << KG_ALT) | (1 << KG_ALTGR)))
5501 vim_modifiers |= MOUSE_ALT;
5502 string[3] |= vim_modifiers;
5503 string[4] = (char_u)(col + ' ' + 1);
5504 string[5] = (char_u)(row + ' ' + 1);
5505 add_to_input_buf(string, 6);
5506 return 6;
5507}
5508#endif /* FEAT_MOUSE_GPM */
5509
5510#if defined(FEAT_LIBCALL) || defined(PROTO)
5511typedef char_u * (*STRPROCSTR)__ARGS((char_u *));
5512typedef char_u * (*INTPROCSTR)__ARGS((int));
5513typedef int (*STRPROCINT)__ARGS((char_u *));
5514typedef int (*INTPROCINT)__ARGS((int));
5515
5516/*
5517 * Call a DLL routine which takes either a string or int param
5518 * and returns an allocated string.
5519 */
5520 int
5521mch_libcall(libname, funcname, argstring, argint, string_result, number_result)
5522 char_u *libname;
5523 char_u *funcname;
5524 char_u *argstring; /* NULL when using a argint */
5525 int argint;
5526 char_u **string_result;/* NULL when using number_result */
5527 int *number_result;
5528{
5529# if defined(USE_DLOPEN)
5530 void *hinstLib;
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005531 char *dlerr = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005532# else
5533 shl_t hinstLib;
5534# endif
5535 STRPROCSTR ProcAdd;
5536 INTPROCSTR ProcAddI;
5537 char_u *retval_str = NULL;
5538 int retval_int = 0;
5539 int success = FALSE;
5540
5541 /* Get a handle to the DLL module. */
5542# if defined(USE_DLOPEN)
5543 hinstLib = dlopen((char *)libname, RTLD_LAZY
5544# ifdef RTLD_LOCAL
5545 | RTLD_LOCAL
5546# endif
5547 );
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005548 if (hinstLib == NULL)
5549 {
5550 /* "dlerr" must be used before dlclose() */
5551 dlerr = (char *)dlerror();
5552 if (dlerr != NULL)
5553 EMSG2(_("dlerror = \"%s\""), dlerr);
5554 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005555# else
5556 hinstLib = shl_load((const char*)libname, BIND_IMMEDIATE|BIND_VERBOSE, 0L);
5557# endif
5558
5559 /* If the handle is valid, try to get the function address. */
5560 if (hinstLib != NULL)
5561 {
5562# ifdef HAVE_SETJMP_H
5563 /*
5564 * Catch a crash when calling the library function. For example when
5565 * using a number where a string pointer is expected.
5566 */
5567 mch_startjmp();
5568 if (SETJMP(lc_jump_env) != 0)
5569 {
5570 success = FALSE;
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005571 dlerr = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005572 mch_didjmp();
5573 }
5574 else
5575# endif
5576 {
5577 retval_str = NULL;
5578 retval_int = 0;
5579
5580 if (argstring != NULL)
5581 {
5582# if defined(USE_DLOPEN)
5583 ProcAdd = (STRPROCSTR)dlsym(hinstLib, (const char *)funcname);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005584 dlerr = (char *)dlerror();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005585# else
5586 if (shl_findsym(&hinstLib, (const char *)funcname,
5587 TYPE_PROCEDURE, (void *)&ProcAdd) < 0)
5588 ProcAdd = NULL;
5589# endif
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005590 if ((success = (ProcAdd != NULL
5591# if defined(USE_DLOPEN)
5592 && dlerr == NULL
5593# endif
5594 )))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005595 {
5596 if (string_result == NULL)
5597 retval_int = ((STRPROCINT)ProcAdd)(argstring);
5598 else
5599 retval_str = (ProcAdd)(argstring);
5600 }
5601 }
5602 else
5603 {
5604# if defined(USE_DLOPEN)
5605 ProcAddI = (INTPROCSTR)dlsym(hinstLib, (const char *)funcname);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005606 dlerr = (char *)dlerror();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005607# else
5608 if (shl_findsym(&hinstLib, (const char *)funcname,
5609 TYPE_PROCEDURE, (void *)&ProcAddI) < 0)
5610 ProcAddI = NULL;
5611# endif
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005612 if ((success = (ProcAddI != NULL
5613# if defined(USE_DLOPEN)
5614 && dlerr == NULL
5615# endif
5616 )))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005617 {
5618 if (string_result == NULL)
5619 retval_int = ((INTPROCINT)ProcAddI)(argint);
5620 else
5621 retval_str = (ProcAddI)(argint);
5622 }
5623 }
5624
5625 /* Save the string before we free the library. */
5626 /* Assume that a "1" or "-1" result is an illegal pointer. */
5627 if (string_result == NULL)
5628 *number_result = retval_int;
5629 else if (retval_str != NULL
5630 && retval_str != (char_u *)1
5631 && retval_str != (char_u *)-1)
5632 *string_result = vim_strsave(retval_str);
5633 }
5634
5635# ifdef HAVE_SETJMP_H
5636 mch_endjmp();
5637# ifdef SIGHASARG
5638 if (lc_signal != 0)
5639 {
5640 int i;
5641
5642 /* try to find the name of this signal */
5643 for (i = 0; signal_info[i].sig != -1; i++)
5644 if (lc_signal == signal_info[i].sig)
5645 break;
5646 EMSG2("E368: got SIG%s in libcall()", signal_info[i].name);
5647 }
5648# endif
5649# endif
5650
Bram Moolenaar071d4272004-06-13 20:20:40 +00005651# if defined(USE_DLOPEN)
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005652 /* "dlerr" must be used before dlclose() */
5653 if (dlerr != NULL)
5654 EMSG2(_("dlerror = \"%s\""), dlerr);
5655
5656 /* Free the DLL module. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005657 (void)dlclose(hinstLib);
5658# else
5659 (void)shl_unload(hinstLib);
5660# endif
5661 }
5662
5663 if (!success)
5664 {
5665 EMSG2(_(e_libcall), funcname);
5666 return FAIL;
5667 }
5668
5669 return OK;
5670}
5671#endif
5672
5673#if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
5674static int xterm_trace = -1; /* default: disabled */
5675static int xterm_button;
5676
5677/*
5678 * Setup a dummy window for X selections in a terminal.
5679 */
5680 void
5681setup_term_clip()
5682{
5683 int z = 0;
5684 char *strp = "";
5685 Widget AppShell;
5686
5687 if (!x_connect_to_server())
5688 return;
5689
5690 open_app_context();
5691 if (app_context != NULL && xterm_Shell == (Widget)0)
5692 {
5693 int (*oldhandler)();
5694#if defined(HAVE_SETJMP_H)
5695 int (*oldIOhandler)();
5696#endif
5697# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
5698 struct timeval start_tv;
5699
5700 if (p_verbose > 0)
5701 gettimeofday(&start_tv, NULL);
5702# endif
5703
5704 /* Ignore X errors while opening the display */
5705 oldhandler = XSetErrorHandler(x_error_check);
5706
5707#if defined(HAVE_SETJMP_H)
5708 /* Ignore X IO errors while opening the display */
5709 oldIOhandler = XSetIOErrorHandler(x_IOerror_check);
5710 mch_startjmp();
5711 if (SETJMP(lc_jump_env) != 0)
5712 {
5713 mch_didjmp();
5714 xterm_dpy = NULL;
5715 }
5716 else
5717#endif
5718 {
5719 xterm_dpy = XtOpenDisplay(app_context, xterm_display,
5720 "vim_xterm", "Vim_xterm", NULL, 0, &z, &strp);
5721#if defined(HAVE_SETJMP_H)
5722 mch_endjmp();
5723#endif
5724 }
5725
5726#if defined(HAVE_SETJMP_H)
5727 /* Now handle X IO errors normally. */
5728 (void)XSetIOErrorHandler(oldIOhandler);
5729#endif
5730 /* Now handle X errors normally. */
5731 (void)XSetErrorHandler(oldhandler);
5732
5733 if (xterm_dpy == NULL)
5734 {
5735 if (p_verbose > 0)
5736 MSG(_("Opening the X display failed"));
5737 return;
5738 }
5739
5740 /* Catch terminating error of the X server connection. */
5741 (void)XSetIOErrorHandler(x_IOerror_handler);
5742
5743# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
5744 if (p_verbose > 0)
5745 xopen_message(&start_tv);
5746# endif
5747
5748 /* Create a Shell to make converters work. */
5749 AppShell = XtVaAppCreateShell("vim_xterm", "Vim_xterm",
5750 applicationShellWidgetClass, xterm_dpy,
5751 NULL);
5752 if (AppShell == (Widget)0)
5753 return;
5754 xterm_Shell = XtVaCreatePopupShell("VIM",
5755 topLevelShellWidgetClass, AppShell,
5756 XtNmappedWhenManaged, 0,
5757 XtNwidth, 1,
5758 XtNheight, 1,
5759 NULL);
5760 if (xterm_Shell == (Widget)0)
5761 return;
5762
5763 x11_setup_atoms(xterm_dpy);
5764 if (x11_display == NULL)
5765 x11_display = xterm_dpy;
5766
5767 XtRealizeWidget(xterm_Shell);
5768 XSync(xterm_dpy, False);
5769 xterm_update();
5770 }
5771 if (xterm_Shell != (Widget)0)
5772 {
5773 clip_init(TRUE);
5774 if (x11_window == 0 && (strp = getenv("WINDOWID")) != NULL)
5775 x11_window = (Window)atol(strp);
5776 /* Check if $WINDOWID is valid. */
5777 if (test_x11_window(xterm_dpy) == FAIL)
5778 x11_window = 0;
5779 if (x11_window != 0)
5780 xterm_trace = 0;
5781 }
5782}
5783
5784 void
5785start_xterm_trace(button)
5786 int button;
5787{
5788 if (x11_window == 0 || xterm_trace < 0 || xterm_Shell == (Widget)0)
5789 return;
5790 xterm_trace = 1;
5791 xterm_button = button;
5792 do_xterm_trace();
5793}
5794
5795
5796 void
5797stop_xterm_trace()
5798{
5799 if (xterm_trace < 0)
5800 return;
5801 xterm_trace = 0;
5802}
5803
5804/*
5805 * Query the xterm pointer and generate mouse termcodes if necessary
5806 * return TRUE if dragging is active, else FALSE
5807 */
5808 static int
5809do_xterm_trace()
5810{
5811 Window root, child;
5812 int root_x, root_y;
5813 int win_x, win_y;
5814 int row, col;
5815 int_u mask_return;
5816 char_u buf[50];
5817 char_u *strp;
5818 long got_hints;
5819 static char_u *mouse_code;
5820 static char_u mouse_name[2] = {KS_MOUSE, KE_FILLER};
5821 static int prev_row = 0, prev_col = 0;
5822 static XSizeHints xterm_hints;
5823
5824 if (xterm_trace <= 0)
5825 return FALSE;
5826
5827 if (xterm_trace == 1)
5828 {
5829 /* Get the hints just before tracking starts. The font size might
5830 * have changed recently */
5831 XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints);
5832 if (!(got_hints & PResizeInc)
5833 || xterm_hints.width_inc <= 1
5834 || xterm_hints.height_inc <= 1)
5835 {
5836 xterm_trace = -1; /* Not enough data -- disable tracing */
5837 return FALSE;
5838 }
5839
5840 /* Rely on the same mouse code for the duration of this */
5841 mouse_code = find_termcode(mouse_name);
5842 prev_row = mouse_row;
5843 prev_row = mouse_col;
5844 xterm_trace = 2;
5845
5846 /* Find the offset of the chars, there might be a scrollbar on the
5847 * left of the window and/or a menu on the top (eterm etc.) */
5848 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
5849 &win_x, &win_y, &mask_return);
5850 xterm_hints.y = win_y - (xterm_hints.height_inc * mouse_row)
5851 - (xterm_hints.height_inc / 2);
5852 if (xterm_hints.y <= xterm_hints.height_inc / 2)
5853 xterm_hints.y = 2;
5854 xterm_hints.x = win_x - (xterm_hints.width_inc * mouse_col)
5855 - (xterm_hints.width_inc / 2);
5856 if (xterm_hints.x <= xterm_hints.width_inc / 2)
5857 xterm_hints.x = 2;
5858 return TRUE;
5859 }
5860 if (mouse_code == NULL)
5861 {
5862 xterm_trace = 0;
5863 return FALSE;
5864 }
5865
5866 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
5867 &win_x, &win_y, &mask_return);
5868
5869 row = check_row((win_y - xterm_hints.y) / xterm_hints.height_inc);
5870 col = check_col((win_x - xterm_hints.x) / xterm_hints.width_inc);
5871 if (row == prev_row && col == prev_col)
5872 return TRUE;
5873
5874 STRCPY(buf, mouse_code);
5875 strp = buf + STRLEN(buf);
5876 *strp++ = (xterm_button | MOUSE_DRAG) & ~0x20;
5877 *strp++ = (char_u)(col + ' ' + 1);
5878 *strp++ = (char_u)(row + ' ' + 1);
5879 *strp = 0;
5880 add_to_input_buf(buf, STRLEN(buf));
5881
5882 prev_row = row;
5883 prev_col = col;
5884 return TRUE;
5885}
5886
5887# if defined(FEAT_GUI) || defined(PROTO)
5888/*
5889 * Destroy the display, window and app_context. Required for GTK.
5890 */
5891 void
5892clear_xterm_clip()
5893{
5894 if (xterm_Shell != (Widget)0)
5895 {
5896 XtDestroyWidget(xterm_Shell);
5897 xterm_Shell = (Widget)0;
5898 }
5899 if (xterm_dpy != NULL)
5900 {
5901#if 0
5902 /* Lesstif and Solaris crash here, lose some memory */
5903 XtCloseDisplay(xterm_dpy);
5904#endif
5905 if (x11_display == xterm_dpy)
5906 x11_display = NULL;
5907 xterm_dpy = NULL;
5908 }
5909#if 0
5910 if (app_context != (XtAppContext)NULL)
5911 {
5912 /* Lesstif and Solaris crash here, lose some memory */
5913 XtDestroyApplicationContext(app_context);
5914 app_context = (XtAppContext)NULL;
5915 }
5916#endif
5917}
5918# endif
5919
5920/*
5921 * Catch up with any queued X events. This may put keyboard input into the
5922 * input buffer, call resize call-backs, trigger timers etc. If there is
5923 * nothing in the X event queue (& no timers pending), then we return
5924 * immediately.
5925 */
5926 static void
5927xterm_update()
5928{
5929 XEvent event;
5930
5931 while (XtAppPending(app_context) && !vim_is_input_buf_full())
5932 {
5933 XtAppNextEvent(app_context, &event);
5934#ifdef FEAT_CLIENTSERVER
5935 {
5936 XPropertyEvent *e = (XPropertyEvent *)&event;
5937
5938 if (e->type == PropertyNotify && e->window == commWindow
5939 && e->atom == commProperty && e->state == PropertyNewValue)
5940 serverEventProc(xterm_dpy, &event);
5941 }
5942#endif
5943 XtDispatchEvent(&event);
5944 }
5945}
5946
5947 int
5948clip_xterm_own_selection(cbd)
5949 VimClipboard *cbd;
5950{
5951 if (xterm_Shell != (Widget)0)
5952 return clip_x11_own_selection(xterm_Shell, cbd);
5953 return FAIL;
5954}
5955
5956 void
5957clip_xterm_lose_selection(cbd)
5958 VimClipboard *cbd;
5959{
5960 if (xterm_Shell != (Widget)0)
5961 clip_x11_lose_selection(xterm_Shell, cbd);
5962}
5963
5964 void
5965clip_xterm_request_selection(cbd)
5966 VimClipboard *cbd;
5967{
5968 if (xterm_Shell != (Widget)0)
5969 clip_x11_request_selection(xterm_Shell, xterm_dpy, cbd);
5970}
5971
5972 void
5973clip_xterm_set_selection(cbd)
5974 VimClipboard *cbd;
5975{
5976 clip_x11_set_selection(cbd);
5977}
5978#endif
5979
5980
5981#if defined(USE_XSMP) || defined(PROTO)
5982/*
5983 * Code for X Session Management Protocol.
5984 */
5985static void xsmp_handle_save_yourself __ARGS((SmcConn smc_conn, SmPointer client_data, int save_type, Bool shutdown, int interact_style, Bool fast));
5986static void xsmp_die __ARGS((SmcConn smc_conn, SmPointer client_data));
5987static void xsmp_save_complete __ARGS((SmcConn smc_conn, SmPointer client_data));
5988static void xsmp_shutdown_cancelled __ARGS((SmcConn smc_conn, SmPointer client_data));
5989static void xsmp_ice_connection __ARGS((IceConn iceConn, IcePointer clientData, Bool opening, IcePointer *watchData));
5990
5991
5992# if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
5993static void xsmp_handle_interaction __ARGS((SmcConn smc_conn, SmPointer client_data));
5994
5995/*
5996 * This is our chance to ask the user if they want to save,
5997 * or abort the logout
5998 */
5999/*ARGSUSED*/
6000 static void
6001xsmp_handle_interaction(smc_conn, client_data)
6002 SmcConn smc_conn;
6003 SmPointer client_data;
6004{
6005 cmdmod_T save_cmdmod;
6006 int cancel_shutdown = False;
6007
6008 save_cmdmod = cmdmod;
6009 cmdmod.confirm = TRUE;
6010 if (check_changed_any(FALSE))
6011 /* Mustn't logout */
6012 cancel_shutdown = True;
6013 cmdmod = save_cmdmod;
6014 setcursor(); /* position cursor */
6015 out_flush();
6016
6017 /* Done interaction */
6018 SmcInteractDone(smc_conn, cancel_shutdown);
6019
6020 /* Finish off
6021 * Only end save-yourself here if we're not cancelling shutdown;
6022 * we'll get a cancelled callback later in which we'll end it.
6023 * Hopefully get around glitchy SMs (like GNOME-1)
6024 */
6025 if (!cancel_shutdown)
6026 {
6027 xsmp.save_yourself = False;
6028 SmcSaveYourselfDone(smc_conn, True);
6029 }
6030}
6031# endif
6032
6033/*
6034 * Callback that starts save-yourself.
6035 */
6036/*ARGSUSED*/
6037 static void
6038xsmp_handle_save_yourself(smc_conn, client_data, save_type,
6039 shutdown, interact_style, fast)
6040 SmcConn smc_conn;
6041 SmPointer client_data;
6042 int save_type;
6043 Bool shutdown;
6044 int interact_style;
6045 Bool fast;
6046{
6047 /* Handle already being in saveyourself */
6048 if (xsmp.save_yourself)
6049 SmcSaveYourselfDone(smc_conn, True);
6050 xsmp.save_yourself = True;
6051 xsmp.shutdown = shutdown;
6052
6053 /* First up, preserve all files */
6054 out_flush();
6055 ml_sync_all(FALSE, FALSE); /* preserve all swap files */
6056
6057 if (p_verbose > 0)
6058 MSG(_("XSMP handling save-yourself request"));
6059
6060# if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6061 /* Now see if we can ask about unsaved files */
6062 if (shutdown && !fast && gui.in_use)
6063 /* Need to interact with user, but need SM's permission */
6064 SmcInteractRequest(smc_conn, SmDialogError,
6065 xsmp_handle_interaction, client_data);
6066 else
6067# endif
6068 {
6069 /* Can stop the cycle here */
6070 SmcSaveYourselfDone(smc_conn, True);
6071 xsmp.save_yourself = False;
6072 }
6073}
6074
6075
6076/*
6077 * Callback to warn us of imminent death.
6078 */
6079/*ARGSUSED*/
6080 static void
6081xsmp_die(smc_conn, client_data)
6082 SmcConn smc_conn;
6083 SmPointer client_data;
6084{
6085 xsmp_close();
6086
6087 /* quit quickly leaving swapfiles for modified buffers behind */
6088 getout_preserve_modified(0);
6089}
6090
6091
6092/*
6093 * Callback to tell us that save-yourself has completed.
6094 */
6095/*ARGSUSED*/
6096 static void
6097xsmp_save_complete(smc_conn, client_data)
6098 SmcConn smc_conn;
6099 SmPointer client_data;
6100{
6101 xsmp.save_yourself = False;
6102}
6103
6104
6105/*
6106 * Callback to tell us that an instigated shutdown was cancelled
6107 * (maybe even by us)
6108 */
6109/*ARGSUSED*/
6110 static void
6111xsmp_shutdown_cancelled(smc_conn, client_data)
6112 SmcConn smc_conn;
6113 SmPointer client_data;
6114{
6115 if (xsmp.save_yourself)
6116 SmcSaveYourselfDone(smc_conn, True);
6117 xsmp.save_yourself = False;
6118 xsmp.shutdown = False;
6119}
6120
6121
6122/*
6123 * Callback to tell us that a new ICE connection has been established.
6124 */
6125/*ARGSUSED*/
6126 static void
6127xsmp_ice_connection(iceConn, clientData, opening, watchData)
6128 IceConn iceConn;
6129 IcePointer clientData;
6130 Bool opening;
6131 IcePointer *watchData;
6132{
6133 /* Intercept creation of ICE connection fd */
6134 if (opening)
6135 {
6136 xsmp_icefd = IceConnectionNumber(iceConn);
6137 IceRemoveConnectionWatch(xsmp_ice_connection, NULL);
6138 }
6139}
6140
6141
6142/* Handle any ICE processing that's required; return FAIL if SM lost */
6143 int
6144xsmp_handle_requests()
6145{
6146 Bool rep;
6147
6148 if (IceProcessMessages(xsmp.iceconn, NULL, &rep)
6149 == IceProcessMessagesIOError)
6150 {
6151 /* Lost ICE */
6152 if (p_verbose > 0)
6153 MSG(_("XSMP lost ICE connection"));
6154 xsmp_close();
6155 return FAIL;
6156 }
6157 else
6158 return OK;
6159}
6160
6161static int dummy;
6162
6163/* Set up X Session Management Protocol */
6164 void
6165xsmp_init(void)
6166{
6167 char errorstring[80];
6168 char *clientid;
6169 SmcCallbacks smcallbacks;
6170#if 0
6171 SmPropValue smname;
6172 SmProp smnameprop;
6173 SmProp *smprops[1];
6174#endif
6175
6176 if (p_verbose > 0)
6177 MSG(_("XSMP opening connection"));
6178
6179 xsmp.save_yourself = xsmp.shutdown = False;
6180
6181 /* Set up SM callbacks - must have all, even if they're not used */
6182 smcallbacks.save_yourself.callback = xsmp_handle_save_yourself;
6183 smcallbacks.save_yourself.client_data = NULL;
6184 smcallbacks.die.callback = xsmp_die;
6185 smcallbacks.die.client_data = NULL;
6186 smcallbacks.save_complete.callback = xsmp_save_complete;
6187 smcallbacks.save_complete.client_data = NULL;
6188 smcallbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
6189 smcallbacks.shutdown_cancelled.client_data = NULL;
6190
6191 /* Set up a watch on ICE connection creations. The "dummy" argument is
6192 * apparently required for FreeBSD (we get a BUS error when using NULL). */
6193 if (IceAddConnectionWatch(xsmp_ice_connection, &dummy) == 0)
6194 {
6195 if (p_verbose > 0)
6196 MSG(_("XSMP ICE connection watch failed"));
6197 return;
6198 }
6199
6200 /* Create an SM connection */
6201 xsmp.smcconn = SmcOpenConnection(
6202 NULL,
6203 NULL,
6204 SmProtoMajor,
6205 SmProtoMinor,
6206 SmcSaveYourselfProcMask | SmcDieProcMask
6207 | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
6208 &smcallbacks,
6209 NULL,
6210 &clientid,
6211 sizeof(errorstring),
6212 errorstring);
6213 if (xsmp.smcconn == NULL)
6214 {
6215 char errorreport[132];
6216 sprintf(errorreport, _("XSMP SmcOpenConnection failed: %s"),
6217 errorstring);
6218 if (p_verbose > 0)
6219 MSG(errorreport);
6220 return;
6221 }
6222 xsmp.iceconn = SmcGetIceConnection(xsmp.smcconn);
6223
6224#if 0
6225 /* ID ourselves */
6226 smname.value = "vim";
6227 smname.length = 3;
6228 smnameprop.name = "SmProgram";
6229 smnameprop.type = "SmARRAY8";
6230 smnameprop.num_vals = 1;
6231 smnameprop.vals = &smname;
6232
6233 smprops[0] = &smnameprop;
6234 SmcSetProperties(xsmp.smcconn, 1, smprops);
6235#endif
6236}
6237
6238
6239/* Shut down XSMP comms. */
6240 void
6241xsmp_close()
6242{
6243 if (xsmp_icefd != -1)
6244 {
6245 SmcCloseConnection(xsmp.smcconn, 0, NULL);
6246 xsmp_icefd = -1;
6247 }
6248}
6249#endif /* USE_XSMP */
6250
6251
6252#ifdef EBCDIC
6253/* Translate character to its CTRL- value */
6254char CtrlTable[] =
6255{
6256/* 00 - 5E */
6257 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6258 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6259 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6260 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6261 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6262 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6263/* ^ */ 0x1E,
6264/* - */ 0x1F,
6265/* 61 - 6C */
6266 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6267/* _ */ 0x1F,
6268/* 6E - 80 */
6269 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6270/* a */ 0x01,
6271/* b */ 0x02,
6272/* c */ 0x03,
6273/* d */ 0x37,
6274/* e */ 0x2D,
6275/* f */ 0x2E,
6276/* g */ 0x2F,
6277/* h */ 0x16,
6278/* i */ 0x05,
6279/* 8A - 90 */
6280 0, 0, 0, 0, 0, 0, 0,
6281/* j */ 0x15,
6282/* k */ 0x0B,
6283/* l */ 0x0C,
6284/* m */ 0x0D,
6285/* n */ 0x0E,
6286/* o */ 0x0F,
6287/* p */ 0x10,
6288/* q */ 0x11,
6289/* r */ 0x12,
6290/* 9A - A1 */
6291 0, 0, 0, 0, 0, 0, 0, 0,
6292/* s */ 0x13,
6293/* t */ 0x3C,
6294/* u */ 0x3D,
6295/* v */ 0x32,
6296/* w */ 0x26,
6297/* x */ 0x18,
6298/* y */ 0x19,
6299/* z */ 0x3F,
6300/* AA - AC */
6301 0, 0, 0,
6302/* [ */ 0x27,
6303/* AE - BC */
6304 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6305/* ] */ 0x1D,
6306/* BE - C0 */ 0, 0, 0,
6307/* A */ 0x01,
6308/* B */ 0x02,
6309/* C */ 0x03,
6310/* D */ 0x37,
6311/* E */ 0x2D,
6312/* F */ 0x2E,
6313/* G */ 0x2F,
6314/* H */ 0x16,
6315/* I */ 0x05,
6316/* CA - D0 */ 0, 0, 0, 0, 0, 0, 0,
6317/* J */ 0x15,
6318/* K */ 0x0B,
6319/* L */ 0x0C,
6320/* M */ 0x0D,
6321/* N */ 0x0E,
6322/* O */ 0x0F,
6323/* P */ 0x10,
6324/* Q */ 0x11,
6325/* R */ 0x12,
6326/* DA - DF */ 0, 0, 0, 0, 0, 0,
6327/* \ */ 0x1C,
6328/* E1 */ 0,
6329/* S */ 0x13,
6330/* T */ 0x3C,
6331/* U */ 0x3D,
6332/* V */ 0x32,
6333/* W */ 0x26,
6334/* X */ 0x18,
6335/* Y */ 0x19,
6336/* Z */ 0x3F,
6337/* EA - FF*/ 0, 0, 0, 0, 0, 0,
6338 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6339};
6340
6341char MetaCharTable[]=
6342{/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6343 0, 0, 0, 0,'\\', 0,'F', 0,'W','M','N', 0, 0, 0, 0, 0,
6344 0, 0, 0, 0,']', 0, 0,'G', 0, 0,'R','O', 0, 0, 0, 0,
6345 '@','A','B','C','D','E', 0, 0,'H','I','J','K','L', 0, 0, 0,
6346 'P','Q', 0,'S','T','U','V', 0,'X','Y','Z','[', 0, 0,'^', 0
6347};
6348
6349
6350/* TODO: Use characters NOT numbers!!! */
6351char CtrlCharTable[]=
6352{/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6353 124,193,194,195, 0,201, 0, 0, 0, 0, 0,210,211,212,213,214,
6354 215,216,217,226, 0,209,200, 0,231,232, 0, 0,224,189, 95,109,
6355 0, 0, 0, 0, 0, 0,230,173, 0, 0, 0, 0, 0,197,198,199,
6356 0, 0,229, 0, 0, 0, 0,196, 0, 0, 0, 0,227,228, 0,233,
6357};
6358
6359
6360#endif