blob: fce731b9a07fc2681e3c20a86d7fc317bc5f72fa [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 XGetErrorText(dpy, error_event->error_code, (char *)IObuff, IOSIZE);
Bram Moolenaar81695252004-12-29 20:58:21 +00001324#if defined(FEAT_GUI_KDE)
1325 /* KDE sometimes produces X error that we want to ignore */
1326 STRCAT(IObuff, _("\nVim: Got X error but we continue...\n"));
1327 mch_errmsg((char *)IObuff);
Bram Moolenaar843ee412004-06-30 16:16:41 +00001328 return 0;
1329#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00001330 STRCAT(IObuff, _("\nVim: Got X error\n"));
1331
1332 /* We cannot print a message and continue, because no X calls are allowed
1333 * here (causes my system to hang). Silently continuing might be an
1334 * alternative... */
1335 preserve_exit(); /* preserve files and exit */
1336
1337 return 0; /* NOTREACHED */
Bram Moolenaar843ee412004-06-30 16:16:41 +00001338#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001339}
1340
1341/*
1342 * Another X Error handler, just used to check for errors.
1343 */
1344/* ARGSUSED */
1345 static int
1346x_error_check(dpy, error_event)
1347 Display *dpy;
1348 XErrorEvent *error_event;
1349{
1350 got_x_error = TRUE;
1351 return 0;
1352}
1353
1354#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
1355# if defined(HAVE_SETJMP_H)
1356/*
1357 * An X IO Error handler, used to catch error while opening the display.
1358 */
1359static int x_IOerror_check __ARGS((Display *dpy));
1360
1361/* ARGSUSED */
1362 static int
1363x_IOerror_check(dpy)
1364 Display *dpy;
1365{
1366 /* This function should not return, it causes exit(). Longjump instead. */
1367 LONGJMP(lc_jump_env, 1);
1368 /*NOTREACHED*/
1369 return 0;
1370}
1371# endif
1372
1373/*
1374 * An X IO Error handler, used to catch terminal errors.
1375 */
1376static int x_IOerror_handler __ARGS((Display *dpy));
1377
1378/* ARGSUSED */
1379 static int
1380x_IOerror_handler(dpy)
1381 Display *dpy;
1382{
1383 xterm_dpy = NULL;
1384 x11_window = 0;
1385 x11_display = NULL;
1386 xterm_Shell = (Widget)0;
1387
1388 /* This function should not return, it causes exit(). Longjump instead. */
1389 LONGJMP(x_jump_env, 1);
1390 /*NOTREACHED*/
1391 return 0;
1392}
1393#endif
1394
1395/*
1396 * Return TRUE when connection to the X server is desired.
1397 */
1398 static int
1399x_connect_to_server()
1400{
1401 regmatch_T regmatch;
1402
1403#if defined(FEAT_CLIENTSERVER)
1404 if (x_force_connect)
1405 return TRUE;
1406#endif
1407 if (x_no_connect)
1408 return FALSE;
1409
1410 /* Check for a match with "exclude:" from 'clipboard'. */
1411 if (clip_exclude_prog != NULL)
1412 {
1413 regmatch.rm_ic = FALSE; /* Don't ignore case */
1414 regmatch.regprog = clip_exclude_prog;
1415 if (vim_regexec(&regmatch, T_NAME, (colnr_T)0))
1416 return FALSE;
1417 }
1418 return TRUE;
1419}
1420
1421/*
1422 * Test if "dpy" and x11_window are valid by getting the window title.
1423 * I don't actually want it yet, so there may be a simpler call to use, but
1424 * this will cause the error handler x_error_check() to be called if anything
1425 * is wrong, such as the window pointer being invalid (as can happen when the
1426 * user changes his DISPLAY, but not his WINDOWID) -- webb
1427 */
1428 static int
1429test_x11_window(dpy)
1430 Display *dpy;
1431{
1432 int (*old_handler)();
1433 XTextProperty text_prop;
1434
1435 old_handler = XSetErrorHandler(x_error_check);
1436 got_x_error = FALSE;
1437 if (XGetWMName(dpy, x11_window, &text_prop))
1438 XFree((void *)text_prop.value);
1439 XSync(dpy, False);
1440 (void)XSetErrorHandler(old_handler);
1441
1442 if (p_verbose > 0 && got_x_error)
1443 MSG(_("Testing the X display failed"));
1444
1445 return (got_x_error ? FAIL : OK);
1446}
1447#endif
1448
1449#ifdef FEAT_TITLE
1450
1451#ifdef FEAT_X11
1452
1453static int get_x11_thing __ARGS((int get_title, int test_only));
1454
1455/*
1456 * try to get x11 window and display
1457 *
1458 * return FAIL for failure, OK otherwise
1459 */
1460 static int
1461get_x11_windis()
1462{
1463 char *winid;
1464 static int result = -1;
1465#define XD_NONE 0 /* x11_display not set here */
1466#define XD_HERE 1 /* x11_display opened here */
1467#define XD_GUI 2 /* x11_display used from gui.dpy */
1468#define XD_XTERM 3 /* x11_display used from xterm_dpy */
1469 static int x11_display_from = XD_NONE;
1470 static int did_set_error_handler = FALSE;
1471
1472 if (!did_set_error_handler)
1473 {
1474 /* X just exits if it finds an error otherwise! */
1475 (void)XSetErrorHandler(x_error_handler);
1476 did_set_error_handler = TRUE;
1477 }
1478
Bram Moolenaar843ee412004-06-30 16:16:41 +00001479#if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_KDE)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001480 if (gui.in_use)
1481 {
1482 /*
1483 * If the X11 display was opened here before, for the window where Vim
1484 * was started, close that one now to avoid a memory leak.
1485 */
1486 if (x11_display_from == XD_HERE && x11_display != NULL)
1487 {
1488 XCloseDisplay(x11_display);
1489 x11_display_from = XD_NONE;
1490 }
1491 if (gui_get_x11_windis(&x11_window, &x11_display) == OK)
1492 {
1493 x11_display_from = XD_GUI;
1494 return OK;
1495 }
1496 x11_display = NULL;
1497 return FAIL;
1498 }
1499 else if (x11_display_from == XD_GUI)
1500 {
1501 /* GUI must have stopped somehow, clear x11_display */
1502 x11_window = 0;
1503 x11_display = NULL;
1504 x11_display_from = XD_NONE;
1505 }
1506#endif
1507
1508 /* When started with the "-X" argument, don't try connecting. */
1509 if (!x_connect_to_server())
1510 return FAIL;
1511
1512 /*
1513 * If WINDOWID not set, should try another method to find out
1514 * what the current window number is. The only code I know for
1515 * this is very complicated.
1516 * We assume that zero is invalid for WINDOWID.
1517 */
1518 if (x11_window == 0 && (winid = getenv("WINDOWID")) != NULL)
1519 x11_window = (Window)atol(winid);
1520
1521#ifdef FEAT_XCLIPBOARD
1522 if (xterm_dpy != NULL && x11_window != 0)
1523 {
1524 /* Checked it already. */
1525 if (x11_display_from == XD_XTERM)
1526 return OK;
1527
1528 /*
1529 * If the X11 display was opened here before, for the window where Vim
1530 * was started, close that one now to avoid a memory leak.
1531 */
1532 if (x11_display_from == XD_HERE && x11_display != NULL)
1533 XCloseDisplay(x11_display);
1534 x11_display = xterm_dpy;
1535 x11_display_from = XD_XTERM;
1536 if (test_x11_window(x11_display) == FAIL)
1537 {
1538 /* probably bad $WINDOWID */
1539 x11_window = 0;
1540 x11_display = NULL;
1541 x11_display_from = XD_NONE;
1542 return FAIL;
1543 }
1544 return OK;
1545 }
1546#endif
1547
1548 if (x11_window == 0 || x11_display == NULL)
1549 result = -1;
1550
1551 if (result != -1) /* Have already been here and set this */
1552 return result; /* Don't do all these X calls again */
1553
1554 if (x11_window != 0 && x11_display == NULL)
1555 {
1556#ifdef SET_SIG_ALARM
1557 RETSIGTYPE (*sig_save)();
1558#endif
1559#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1560 struct timeval start_tv;
1561
1562 if (p_verbose > 0)
1563 gettimeofday(&start_tv, NULL);
1564#endif
1565
1566#ifdef SET_SIG_ALARM
1567 /*
1568 * Opening the Display may hang if the DISPLAY setting is wrong, or
1569 * the network connection is bad. Set an alarm timer to get out.
1570 */
1571 sig_alarm_called = FALSE;
1572 sig_save = (RETSIGTYPE (*)())signal(SIGALRM,
1573 (RETSIGTYPE (*)())sig_alarm);
1574 alarm(2);
1575#endif
1576 x11_display = XOpenDisplay(NULL);
1577
1578#ifdef SET_SIG_ALARM
1579 alarm(0);
1580 signal(SIGALRM, (RETSIGTYPE (*)())sig_save);
1581 if (p_verbose > 0 && sig_alarm_called)
1582 MSG(_("Opening the X display timed out"));
1583#endif
1584 if (x11_display != NULL)
1585 {
1586# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1587 if (p_verbose > 0)
1588 xopen_message(&start_tv);
1589# endif
1590 if (test_x11_window(x11_display) == FAIL)
1591 {
1592 /* Maybe window id is bad */
1593 x11_window = 0;
1594 XCloseDisplay(x11_display);
1595 x11_display = NULL;
1596 }
1597 else
1598 x11_display_from = XD_HERE;
1599 }
1600 }
1601 if (x11_window == 0 || x11_display == NULL)
1602 return (result = FAIL);
1603 return (result = OK);
1604}
1605
1606/*
1607 * Determine original x11 Window Title
1608 */
1609 static int
1610get_x11_title(test_only)
1611 int test_only;
1612{
Bram Moolenaar47136d72004-10-12 20:02:24 +00001613 return get_x11_thing(TRUE, test_only);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001614}
1615
1616/*
1617 * Determine original x11 Window icon
1618 */
1619 static int
1620get_x11_icon(test_only)
1621 int test_only;
1622{
1623 int retval = FALSE;
1624
1625 retval = get_x11_thing(FALSE, test_only);
1626
1627 /* could not get old icon, use terminal name */
1628 if (oldicon == NULL && !test_only)
1629 {
1630 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1631 oldicon = T_NAME + 8;
1632 else
1633 oldicon = T_NAME;
1634 }
1635
1636 return retval;
1637}
1638
1639 static int
1640get_x11_thing(get_title, test_only)
1641 int get_title; /* get title string */
1642 int test_only;
1643{
1644 XTextProperty text_prop;
1645 int retval = FALSE;
1646 Status status;
1647
1648 if (get_x11_windis() == OK)
1649 {
1650 /* Get window/icon name if any */
1651 if (get_title)
1652 status = XGetWMName(x11_display, x11_window, &text_prop);
1653 else
1654 status = XGetWMIconName(x11_display, x11_window, &text_prop);
1655
1656 /*
1657 * If terminal is xterm, then x11_window may be a child window of the
1658 * outer xterm window that actually contains the window/icon name, so
1659 * keep traversing up the tree until a window with a title/icon is
1660 * found.
1661 */
1662 /* Previously this was only done for xterm and alikes. I don't see a
1663 * reason why it would fail for other terminal emulators.
1664 * if (term_is_xterm) */
1665 {
1666 Window root;
1667 Window parent;
1668 Window win = x11_window;
1669 Window *children;
1670 unsigned int num_children;
1671
1672 while (!status || text_prop.value == NULL)
1673 {
1674 if (!XQueryTree(x11_display, win, &root, &parent, &children,
1675 &num_children))
1676 break;
1677 if (children)
1678 XFree((void *)children);
1679 if (parent == root || parent == 0)
1680 break;
1681
1682 win = parent;
1683 if (get_title)
1684 status = XGetWMName(x11_display, win, &text_prop);
1685 else
1686 status = XGetWMIconName(x11_display, win, &text_prop);
1687 }
1688 }
1689 if (status && text_prop.value != NULL)
1690 {
1691 retval = TRUE;
1692 if (!test_only)
1693 {
1694#ifdef FEAT_XFONTSET
1695 if (text_prop.encoding == XA_STRING)
1696 {
1697#endif
1698 if (get_title)
1699 oldtitle = vim_strsave((char_u *)text_prop.value);
1700 else
1701 oldicon = vim_strsave((char_u *)text_prop.value);
1702#ifdef FEAT_XFONTSET
1703 }
1704 else
1705 {
1706 char **cl;
1707 Status transform_status;
1708 int n = 0;
1709
1710 transform_status = XmbTextPropertyToTextList(x11_display,
1711 &text_prop,
1712 &cl, &n);
1713 if (transform_status >= Success && n > 0 && cl[0])
1714 {
1715 if (get_title)
1716 oldtitle = vim_strsave((char_u *) cl[0]);
1717 else
1718 oldicon = vim_strsave((char_u *) cl[0]);
1719 XFreeStringList(cl);
1720 }
1721 else
1722 {
1723 if (get_title)
1724 oldtitle = vim_strsave((char_u *)text_prop.value);
1725 else
1726 oldicon = vim_strsave((char_u *)text_prop.value);
1727 }
1728 }
1729#endif
1730 }
1731 XFree((void *)text_prop.value);
1732 }
1733 }
1734 return retval;
1735}
1736
1737/* Are Xutf8 functions available? Avoid error from old compilers. */
1738#if defined(X_HAVE_UTF8_STRING) && defined(FEAT_MBYTE)
1739# if X_HAVE_UTF8_STRING
1740# define USE_UTF8_STRING
1741# endif
1742#endif
1743
1744/*
1745 * Set x11 Window Title
1746 *
1747 * get_x11_windis() must be called before this and have returned OK
1748 */
1749 static void
1750set_x11_title(title)
1751 char_u *title;
1752{
1753 /* XmbSetWMProperties() and Xutf8SetWMProperties() should use a STRING
1754 * when possible, COMPOUND_TEXT otherwise. COMPOUND_TEXT isn't
1755 * supported everywhere and STRING doesn't work for multi-byte titles.
1756 */
1757#ifdef USE_UTF8_STRING
1758 if (enc_utf8)
1759 Xutf8SetWMProperties(x11_display, x11_window, (const char *)title,
1760 NULL, NULL, 0, NULL, NULL, NULL);
1761 else
1762#endif
1763 {
1764#if XtSpecificationRelease >= 4
1765# ifdef FEAT_XFONTSET
1766 XmbSetWMProperties(x11_display, x11_window, (const char *)title,
1767 NULL, NULL, 0, NULL, NULL, NULL);
1768# else
1769 XTextProperty text_prop;
1770
1771 /* directly from example 3-18 "basicwin" of Xlib Programming Manual */
1772 (void)XStringListToTextProperty((char **)&title, 1, &text_prop);
1773 XSetWMProperties(x11_display, x11_window, &text_prop,
1774 NULL, NULL, 0, NULL, NULL, NULL);
1775# endif
1776#else
1777 XStoreName(x11_display, x11_window, (char *)title);
1778#endif
1779 }
1780 XFlush(x11_display);
1781}
1782
1783/*
1784 * Set x11 Window icon
1785 *
1786 * get_x11_windis() must be called before this and have returned OK
1787 */
1788 static void
1789set_x11_icon(icon)
1790 char_u *icon;
1791{
1792 /* See above for comments about using X*SetWMProperties(). */
1793#ifdef USE_UTF8_STRING
1794 if (enc_utf8)
1795 Xutf8SetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
1796 NULL, 0, NULL, NULL, NULL);
1797 else
1798#endif
1799 {
1800#if XtSpecificationRelease >= 4
1801# ifdef FEAT_XFONTSET
1802 XmbSetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
1803 NULL, 0, NULL, NULL, NULL);
1804# else
1805 XTextProperty text_prop;
1806
1807 (void)XStringListToTextProperty((char **)&icon, 1, &text_prop);
1808 XSetWMProperties(x11_display, x11_window, NULL, &text_prop,
1809 NULL, 0, NULL, NULL, NULL);
1810# endif
1811#else
1812 XSetIconName(x11_display, x11_window, (char *)icon);
1813#endif
1814 }
1815 XFlush(x11_display);
1816}
1817
1818#else /* FEAT_X11 */
1819
1820/*ARGSUSED*/
1821 static int
1822get_x11_title(test_only)
1823 int test_only;
1824{
1825 return FALSE;
1826}
1827
1828 static int
1829get_x11_icon(test_only)
1830 int test_only;
1831{
1832 if (!test_only)
1833 {
1834 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1835 oldicon = T_NAME + 8;
1836 else
1837 oldicon = T_NAME;
1838 }
1839 return FALSE;
1840}
1841
1842#endif /* FEAT_X11 */
1843
1844 int
1845mch_can_restore_title()
1846{
1847 return get_x11_title(TRUE);
1848}
1849
1850 int
1851mch_can_restore_icon()
1852{
1853 return get_x11_icon(TRUE);
1854}
1855
1856/*
1857 * Set the window title and icon.
1858 */
1859 void
1860mch_settitle(title, icon)
1861 char_u *title;
1862 char_u *icon;
1863{
1864 int type = 0;
1865 static int recursive = 0;
1866
1867 if (T_NAME == NULL) /* no terminal name (yet) */
1868 return;
1869 if (title == NULL && icon == NULL) /* nothing to do */
1870 return;
1871
1872 /* When one of the X11 functions causes a deadly signal, we get here again
1873 * recursively. Avoid hanging then (something is probably locked). */
1874 if (recursive)
1875 return;
1876 ++recursive;
1877
1878 /*
1879 * if the window ID and the display is known, we may use X11 calls
1880 */
1881#ifdef FEAT_X11
1882 if (get_x11_windis() == OK)
1883 type = 1;
1884#else
1885# if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_GTK)
1886 if (gui.in_use)
1887 type = 1;
1888# endif
1889# ifdef FEAT_GUI_BEOS
1890 /* TODO: If this means (gui.in_use) why not merge with above? (Dany) */
1891 /* we always have a 'window' */
1892 type = 1;
1893# endif
1894#endif
1895
1896 /*
1897 * Note: if "t_TS" is set, title is set with escape sequence rather
1898 * than x11 calls, because the x11 calls don't always work
1899 */
Bram Moolenaar843ee412004-06-30 16:16:41 +00001900#ifdef FEAT_GUI_KDE
Bram Moolenaar47136d72004-10-12 20:02:24 +00001901 /* dont know why but KDE needs this one as we don't go through the next
1902 * function... */
Bram Moolenaar843ee412004-06-30 16:16:41 +00001903 gui_mch_settitle(title, icon);
1904#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001905 if ((type || *T_TS != NUL) && title != NULL)
1906 {
1907 if (oldtitle == NULL
1908#ifdef FEAT_GUI
1909 && !gui.in_use
1910#endif
1911 ) /* first call but not in GUI, save title */
1912 (void)get_x11_title(FALSE);
1913
1914 if (*T_TS != NUL) /* it's OK if t_fs is empty */
1915 term_settitle(title);
1916#ifdef FEAT_X11
1917 else
1918# ifdef FEAT_GUI_GTK
1919 if (!gui.in_use) /* don't do this if GTK+ is running */
1920# endif
1921 set_x11_title(title); /* x11 */
1922#endif
1923#if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_BEOS) \
1924 || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
1925 else
1926 gui_mch_settitle(title, icon);
1927#endif
1928 did_set_title = TRUE;
1929 }
1930
1931 if ((type || *T_CIS != NUL) && icon != NULL)
1932 {
1933 if (oldicon == NULL
1934#ifdef FEAT_GUI
1935 && !gui.in_use
1936#endif
1937 ) /* first call, save icon */
1938 get_x11_icon(FALSE);
1939
1940 if (*T_CIS != NUL)
1941 {
1942 out_str(T_CIS); /* set icon start */
1943 out_str_nf(icon);
1944 out_str(T_CIE); /* set icon end */
1945 out_flush();
1946 }
1947#ifdef FEAT_X11
1948 else
1949# ifdef FEAT_GUI_GTK
1950 if (!gui.in_use) /* don't do this if GTK+ is running */
1951# endif
1952 set_x11_icon(icon); /* x11 */
1953#endif
1954 did_set_icon = TRUE;
1955 }
1956 --recursive;
1957}
1958
1959/*
1960 * Restore the window/icon title.
1961 * "which" is one of:
1962 * 1 only restore title
1963 * 2 only restore icon
1964 * 3 restore title and icon
1965 */
1966 void
1967mch_restore_title(which)
1968 int which;
1969{
1970 /* only restore the title or icon when it has been set */
1971 mch_settitle(((which & 1) && did_set_title) ?
1972 (oldtitle ? oldtitle : p_titleold) : NULL,
1973 ((which & 2) && did_set_icon) ? oldicon : NULL);
1974}
1975
1976#endif /* FEAT_TITLE */
1977
1978/*
1979 * Return TRUE if "name" looks like some xterm name.
1980 */
1981 int
1982vim_is_xterm(name)
1983 char_u *name;
1984{
1985 if (name == NULL)
1986 return FALSE;
1987 return (STRNICMP(name, "xterm", 5) == 0
1988 || STRNICMP(name, "nxterm", 6) == 0
1989 || STRNICMP(name, "kterm", 5) == 0
1990 || STRNICMP(name, "rxvt", 4) == 0
1991 || STRCMP(name, "builtin_xterm") == 0);
1992}
1993
1994#if defined(FEAT_MOUSE_TTY) || defined(PROTO)
1995/*
1996 * Return non-zero when using an xterm mouse, according to 'ttymouse'.
1997 * Return 1 for "xterm".
1998 * Return 2 for "xterm2".
1999 */
2000 int
2001use_xterm_mouse()
2002{
2003 if (ttym_flags == TTYM_XTERM2)
2004 return 2;
2005 if (ttym_flags == TTYM_XTERM)
2006 return 1;
2007 return 0;
2008}
2009#endif
2010
2011 int
2012vim_is_iris(name)
2013 char_u *name;
2014{
2015 if (name == NULL)
2016 return FALSE;
2017 return (STRNICMP(name, "iris-ansi", 9) == 0
2018 || STRCMP(name, "builtin_iris-ansi") == 0);
2019}
2020
2021 int
2022vim_is_vt300(name)
2023 char_u *name;
2024{
2025 if (name == NULL)
2026 return FALSE; /* actually all ANSI comp. terminals should be here */
Bram Moolenaard4755bb2004-09-02 19:12:26 +00002027 /* catch VT100 - VT5xx */
2028 return ((STRNICMP(name, "vt", 2) == 0
2029 && vim_strchr((char_u *)"12345", name[2]) != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002030 || STRCMP(name, "builtin_vt320") == 0);
2031}
2032
2033/*
2034 * Return TRUE if "name" is a terminal for which 'ttyfast' should be set.
2035 * This should include all windowed terminal emulators.
2036 */
2037 int
2038vim_is_fastterm(name)
2039 char_u *name;
2040{
2041 if (name == NULL)
2042 return FALSE;
2043 if (vim_is_xterm(name) || vim_is_vt300(name) || vim_is_iris(name))
2044 return TRUE;
2045 return ( STRNICMP(name, "hpterm", 6) == 0
2046 || STRNICMP(name, "sun-cmd", 7) == 0
2047 || STRNICMP(name, "screen", 6) == 0
2048 || STRNICMP(name, "dtterm", 6) == 0);
2049}
2050
2051/*
2052 * Insert user name in s[len].
2053 * Return OK if a name found.
2054 */
2055 int
2056mch_get_user_name(s, len)
2057 char_u *s;
2058 int len;
2059{
2060#ifdef VMS
2061 STRNCPY((char *)s, cuserid(NULL), len);
2062 return OK;
2063#else
2064 return mch_get_uname(getuid(), s, len);
2065#endif
2066}
2067
2068/*
2069 * Insert user name for "uid" in s[len].
2070 * Return OK if a name found.
2071 */
2072 int
2073mch_get_uname(uid, s, len)
2074 uid_t uid;
2075 char_u *s;
2076 int len;
2077{
2078#if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
2079 struct passwd *pw;
2080
2081 if ((pw = getpwuid(uid)) != NULL
2082 && pw->pw_name != NULL && *(pw->pw_name) != NUL)
2083 {
2084 STRNCPY(s, pw->pw_name, len);
2085 return OK;
2086 }
2087#endif
2088 sprintf((char *)s, "%d", (int)uid); /* assumes s is long enough */
2089 return FAIL; /* a number is not a name */
2090}
2091
2092/*
2093 * Insert host name is s[len].
2094 */
2095
2096#ifdef HAVE_SYS_UTSNAME_H
2097 void
2098mch_get_host_name(s, len)
2099 char_u *s;
2100 int len;
2101{
2102 struct utsname vutsname;
2103
2104 if (uname(&vutsname) < 0)
2105 *s = NUL;
2106 else
2107 STRNCPY(s, vutsname.nodename, len);
2108 s[len - 1] = NUL; /* make sure it's terminated */
2109}
2110#else /* HAVE_SYS_UTSNAME_H */
2111
2112# ifdef HAVE_SYS_SYSTEMINFO_H
2113# define gethostname(nam, len) sysinfo(SI_HOSTNAME, nam, len)
2114# endif
2115
2116 void
2117mch_get_host_name(s, len)
2118 char_u *s;
2119 int len;
2120{
2121# ifdef VAXC
2122 vaxc$gethostname((char *)s, len);
2123# else
2124 gethostname((char *)s, len);
2125# endif
2126 s[len - 1] = NUL; /* make sure it's terminated */
2127}
2128#endif /* HAVE_SYS_UTSNAME_H */
2129
2130/*
2131 * return process ID
2132 */
2133 long
2134mch_get_pid()
2135{
2136 return (long)getpid();
2137}
2138
2139#if !defined(HAVE_STRERROR) && defined(USE_GETCWD)
2140static char *strerror __ARGS((int));
2141
2142 static char *
2143strerror(err)
2144 int err;
2145{
2146 extern int sys_nerr;
2147 extern char *sys_errlist[];
2148 static char er[20];
2149
2150 if (err > 0 && err < sys_nerr)
2151 return (sys_errlist[err]);
2152 sprintf(er, "Error %d", err);
2153 return er;
2154}
2155#endif
2156
2157/*
2158 * Get name of current directory into buffer 'buf' of length 'len' bytes.
2159 * Return OK for success, FAIL for failure.
2160 */
2161 int
2162mch_dirname(buf, len)
2163 char_u *buf;
2164 int len;
2165{
2166#if defined(USE_GETCWD)
2167 if (getcwd((char *)buf, len) == NULL)
2168 {
2169 STRCPY(buf, strerror(errno));
2170 return FAIL;
2171 }
2172 return OK;
2173#else
2174 return (getwd((char *)buf) != NULL ? OK : FAIL);
2175#endif
2176}
2177
2178#if defined(OS2) || defined(PROTO)
2179/*
2180 * Replace all slashes by backslashes.
2181 * When 'shellslash' set do it the other way around.
2182 */
2183 void
2184slash_adjust(p)
2185 char_u *p;
2186{
2187 while (*p)
2188 {
2189 if (*p == psepcN)
2190 *p = psepc;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00002191 mb_ptr_adv(p);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002192 }
2193}
2194#endif
2195
2196/*
2197 * Get absolute file name into buffer 'buf' of length 'len' bytes.
2198 *
2199 * return FAIL for failure, OK for success
2200 */
2201 int
2202mch_FullName(fname, buf, len, force)
2203 char_u *fname, *buf;
2204 int len;
2205 int force; /* also expand when already absolute path */
2206{
2207 int l;
2208#ifdef OS2
2209 int only_drive; /* file name is only a drive letter */
2210#endif
2211#ifdef HAVE_FCHDIR
2212 int fd = -1;
2213 static int dont_fchdir = FALSE; /* TRUE when fchdir() doesn't work */
2214#endif
2215 char_u olddir[MAXPATHL];
2216 char_u *p;
2217 int retval = OK;
2218
2219#ifdef VMS
2220 fname = vms_fixfilename(fname);
2221#endif
2222
2223 /* expand it if forced or not an absolute path */
2224 if (force || !mch_isFullName(fname))
2225 {
2226 /*
2227 * If the file name has a path, change to that directory for a moment,
2228 * and then do the getwd() (and get back to where we were).
2229 * This will get the correct path name with "../" things.
2230 */
2231#ifdef OS2
2232 only_drive = 0;
2233 if (((p = vim_strrchr(fname, '/')) != NULL)
2234 || ((p = vim_strrchr(fname, '\\')) != NULL)
2235 || (((p = vim_strchr(fname, ':')) != NULL) && ++only_drive))
2236#else
2237 if ((p = vim_strrchr(fname, '/')) != NULL)
2238#endif
2239 {
2240#ifdef HAVE_FCHDIR
2241 /*
2242 * Use fchdir() if possible, it's said to be faster and more
2243 * reliable. But on SunOS 4 it might not work. Check this by
2244 * doing a fchdir() right now.
2245 */
2246 if (!dont_fchdir)
2247 {
2248 fd = open(".", O_RDONLY | O_EXTRA, 0);
2249 if (fd >= 0 && fchdir(fd) < 0)
2250 {
2251 close(fd);
2252 fd = -1;
2253 dont_fchdir = TRUE; /* don't try again */
2254 }
2255 }
2256#endif
2257
2258 /* Only change directory when we are sure we can return to where
2259 * we are now. After doing "su" chdir(".") might not work. */
2260 if (
2261#ifdef HAVE_FCHDIR
2262 fd < 0 &&
2263#endif
2264 (mch_dirname(olddir, MAXPATHL) == FAIL
2265 || mch_chdir((char *)olddir) != 0))
2266 {
2267 p = NULL; /* can't get current dir: don't chdir */
2268 retval = FAIL;
2269 }
2270 else
2271 {
2272#ifdef OS2
2273 /*
2274 * compensate for case where ':' from "D:" was the only
2275 * path separator detected in the file name; the _next_
2276 * character has to be removed, and then restored later.
2277 */
2278 if (only_drive)
2279 p++;
2280#endif
2281 /* The directory is copied into buf[], to be able to remove
2282 * the file name without changing it (could be a string in
2283 * read-only memory) */
2284 if (p - fname >= len)
2285 retval = FAIL;
2286 else
2287 {
2288 STRNCPY(buf, fname, p - fname);
2289 buf[p - fname] = NUL;
2290 if (mch_chdir((char *)buf))
2291 retval = FAIL;
2292 else
2293 fname = p + 1;
2294 *buf = NUL;
2295 }
2296#ifdef OS2
2297 if (only_drive)
2298 {
2299 p--;
2300 if (retval != FAIL)
2301 fname--;
2302 }
2303#endif
2304 }
2305 }
2306 if (mch_dirname(buf, len) == FAIL)
2307 {
2308 retval = FAIL;
2309 *buf = NUL;
2310 }
2311 if (p != NULL)
2312 {
2313#ifdef HAVE_FCHDIR
2314 if (fd >= 0)
2315 {
2316 l = fchdir(fd);
2317 close(fd);
2318 }
2319 else
2320#endif
2321 l = mch_chdir((char *)olddir);
2322 if (l != 0)
2323 EMSG(_(e_prev_dir));
2324 }
2325
2326 l = STRLEN(buf);
2327 if (l >= len)
2328 retval = FAIL;
2329#ifndef VMS
2330 else
2331 {
2332 if (l > 0 && buf[l - 1] != '/' && *fname != NUL
2333 && STRCMP(fname, ".") != 0)
2334 STRCAT(buf, "/");
2335 }
2336#endif
2337 }
2338 /* Catch file names which are too long. */
2339 if (retval == FAIL || STRLEN(buf) + STRLEN(fname) >= len)
2340 return FAIL;
2341
2342 /* Do not append ".", "/dir/." is equal to "/dir". */
2343 if (STRCMP(fname, ".") != 0)
2344 STRCAT(buf, fname);
2345
2346 return OK;
2347}
2348
2349/*
2350 * Return TRUE if "fname" does not depend on the current directory.
2351 */
2352 int
2353mch_isFullName(fname)
2354 char_u *fname;
2355{
2356#ifdef __EMX__
2357 return _fnisabs(fname);
2358#else
2359# ifdef VMS
2360 return ( fname[0] == '/' || fname[0] == '.' ||
2361 strchr((char *)fname,':') || strchr((char *)fname,'"') ||
2362 (strchr((char *)fname,'[') && strchr((char *)fname,']'))||
2363 (strchr((char *)fname,'<') && strchr((char *)fname,'>')) );
2364# else
2365 return (*fname == '/' || *fname == '~');
2366# endif
2367#endif
2368}
2369
2370/*
2371 * Get file permissions for 'name'.
2372 * Returns -1 when it doesn't exist.
2373 */
2374 long
2375mch_getperm(name)
2376 char_u *name;
2377{
2378 struct stat statb;
2379
2380 /* Keep the #ifdef outside of stat(), it may be a macro. */
2381#ifdef VMS
2382 if (stat((char *)vms_fixfilename(name), &statb))
2383#else
2384 if (stat((char *)name, &statb))
2385#endif
2386 return -1;
2387 return statb.st_mode;
2388}
2389
2390/*
2391 * set file permission for 'name' to 'perm'
2392 *
2393 * return FAIL for failure, OK otherwise
2394 */
2395 int
2396mch_setperm(name, perm)
2397 char_u *name;
2398 long perm;
2399{
2400 return (chmod((char *)
2401#ifdef VMS
2402 vms_fixfilename(name),
2403#else
2404 name,
2405#endif
2406 (mode_t)perm) == 0 ? OK : FAIL);
2407}
2408
2409#if defined(HAVE_ACL) || defined(PROTO)
2410# ifdef HAVE_SYS_ACL_H
2411# include <sys/acl.h>
2412# endif
2413# ifdef HAVE_SYS_ACCESS_H
2414# include <sys/access.h>
2415# endif
2416
2417# ifdef HAVE_SOLARIS_ACL
2418typedef struct vim_acl_solaris_T {
2419 int acl_cnt;
2420 aclent_t *acl_entry;
2421} vim_acl_solaris_T;
2422# endif
2423
2424/*
2425 * Return a pointer to the ACL of file "fname" in allocated memory.
2426 * Return NULL if the ACL is not available for whatever reason.
2427 */
2428 vim_acl_T
2429mch_get_acl(fname)
2430 char_u *fname;
2431{
2432 vim_acl_T ret = NULL;
2433#ifdef HAVE_POSIX_ACL
2434 ret = (vim_acl_T)acl_get_file((char *)fname, ACL_TYPE_ACCESS);
2435#else
2436#ifdef HAVE_SOLARIS_ACL
2437 vim_acl_solaris_T *aclent;
2438
2439 aclent = malloc(sizeof(vim_acl_solaris_T));
2440 if ((aclent->acl_cnt = acl((char *)fname, GETACLCNT, 0, NULL)) < 0)
2441 {
2442 free(aclent);
2443 return NULL;
2444 }
2445 aclent->acl_entry = malloc(aclent->acl_cnt * sizeof(aclent_t));
2446 if (acl((char *)fname, GETACL, aclent->acl_cnt, aclent->acl_entry) < 0)
2447 {
2448 free(aclent->acl_entry);
2449 free(aclent);
2450 return NULL;
2451 }
2452 ret = (vim_acl_T)aclent;
2453#else
2454#if defined(HAVE_AIX_ACL)
2455 int aclsize;
2456 struct acl *aclent;
2457
2458 aclsize = sizeof(struct acl);
2459 aclent = malloc(aclsize);
2460 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2461 {
2462 if (errno == ENOSPC)
2463 {
2464 aclsize = aclent->acl_len;
2465 aclent = realloc(aclent, aclsize);
2466 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2467 {
2468 free(aclent);
2469 return NULL;
2470 }
2471 }
2472 else
2473 {
2474 free(aclent);
2475 return NULL;
2476 }
2477 }
2478 ret = (vim_acl_T)aclent;
2479#endif /* HAVE_AIX_ACL */
2480#endif /* HAVE_SOLARIS_ACL */
2481#endif /* HAVE_POSIX_ACL */
2482 return ret;
2483}
2484
2485/*
2486 * Set the ACL of file "fname" to "acl" (unless it's NULL).
2487 */
2488 void
2489mch_set_acl(fname, aclent)
2490 char_u *fname;
2491 vim_acl_T aclent;
2492{
2493 if (aclent == NULL)
2494 return;
2495#ifdef HAVE_POSIX_ACL
2496 acl_set_file((char *)fname, ACL_TYPE_ACCESS, (acl_t)aclent);
2497#else
2498#ifdef HAVE_SOLARIS_ACL
2499 acl((char *)fname, SETACL, ((vim_acl_solaris_T *)aclent)->acl_cnt,
2500 ((vim_acl_solaris_T *)aclent)->acl_entry);
2501#else
2502#ifdef HAVE_AIX_ACL
2503 chacl((char *)fname, aclent, ((struct acl *)aclent)->acl_len);
2504#endif /* HAVE_AIX_ACL */
2505#endif /* HAVE_SOLARIS_ACL */
2506#endif /* HAVE_POSIX_ACL */
2507}
2508
2509 void
2510mch_free_acl(aclent)
2511 vim_acl_T aclent;
2512{
2513 if (aclent == NULL)
2514 return;
2515#ifdef HAVE_POSIX_ACL
2516 acl_free((acl_t)aclent);
2517#else
2518#ifdef HAVE_SOLARIS_ACL
2519 free(((vim_acl_solaris_T *)aclent)->acl_entry);
2520 free(aclent);
2521#else
2522#ifdef HAVE_AIX_ACL
2523 free(aclent);
2524#endif /* HAVE_AIX_ACL */
2525#endif /* HAVE_SOLARIS_ACL */
2526#endif /* HAVE_POSIX_ACL */
2527}
2528#endif
2529
2530/*
2531 * Set hidden flag for "name".
2532 */
2533/* ARGSUSED */
2534 void
2535mch_hide(name)
2536 char_u *name;
2537{
2538 /* can't hide a file */
2539}
2540
2541/*
2542 * return TRUE if "name" is a directory
2543 * return FALSE if "name" is not a directory
2544 * return FALSE for error
2545 */
2546 int
2547mch_isdir(name)
2548 char_u *name;
2549{
2550 struct stat statb;
2551
2552 if (*name == NUL) /* Some stat()s don't flag "" as an error. */
2553 return FALSE;
2554 if (stat((char *)name, &statb))
2555 return FALSE;
2556#ifdef _POSIX_SOURCE
2557 return (S_ISDIR(statb.st_mode) ? TRUE : FALSE);
2558#else
2559 return ((statb.st_mode & S_IFMT) == S_IFDIR ? TRUE : FALSE);
2560#endif
2561}
2562
2563#if defined(FEAT_EVAL) || defined(PROTO)
2564
2565static int executable_file __ARGS((char_u *name));
2566
2567/*
2568 * Return 1 if "name" is an executable file, 0 if not or it doesn't exist.
2569 */
2570 static int
2571executable_file(name)
2572 char_u *name;
2573{
2574 struct stat st;
2575
2576 if (stat((char *)name, &st))
2577 return 0;
2578 return S_ISREG(st.st_mode) && mch_access((char *)name, X_OK) == 0;
2579}
2580
2581/*
2582 * Return 1 if "name" can be found in $PATH and executed, 0 if not.
2583 * Return -1 if unknown.
2584 */
2585 int
2586mch_can_exe(name)
2587 char_u *name;
2588{
2589 char_u *buf;
2590 char_u *p, *e;
2591 int retval;
2592
2593 /* If it's an absolute or relative path don't need to use $PATH. */
2594 if (mch_isFullName(name) || (name[0] == '.' && (name[1] == '/'
2595 || (name[1] == '.' && name[2] == '/'))))
2596 return executable_file(name);
2597
2598 p = (char_u *)getenv("PATH");
2599 if (p == NULL || *p == NUL)
2600 return -1;
2601 buf = alloc((unsigned)(STRLEN(name) + STRLEN(p) + 2));
2602 if (buf == NULL)
2603 return -1;
2604
2605 /*
2606 * Walk through all entries in $PATH to check if "name" exists there and
2607 * is an executable file.
2608 */
2609 for (;;)
2610 {
2611 e = (char_u *)strchr((char *)p, ':');
2612 if (e == NULL)
2613 e = p + STRLEN(p);
2614 if (e - p <= 1) /* empty entry means current dir */
2615 STRCPY(buf, "./");
2616 else
2617 {
2618 STRNCPY(buf, p, e - p);
2619 buf[e - p] = NUL;
2620 add_pathsep(buf);
2621 }
2622 STRCAT(buf, name);
2623 retval = executable_file(buf);
2624 if (retval == 1)
2625 break;
2626
2627 if (*e != ':')
2628 break;
2629 p = e + 1;
2630 }
2631
2632 vim_free(buf);
2633 return retval;
2634}
2635#endif
2636
2637/*
2638 * Check what "name" is:
2639 * NODE_NORMAL: file or directory (or doesn't exist)
2640 * NODE_WRITABLE: writable device, socket, fifo, etc.
2641 * NODE_OTHER: non-writable things
2642 */
2643 int
2644mch_nodetype(name)
2645 char_u *name;
2646{
2647 struct stat st;
2648
2649 if (stat((char *)name, &st))
2650 return NODE_NORMAL;
2651 if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
2652 return NODE_NORMAL;
2653#ifndef OS2
2654 if (S_ISBLK(st.st_mode)) /* block device isn't writable */
2655 return NODE_OTHER;
2656#endif
2657 /* Everything else is writable? */
2658 return NODE_WRITABLE;
2659}
2660
2661 void
2662mch_early_init()
2663{
2664#ifdef HAVE_CHECK_STACK_GROWTH
2665 int i;
2666#endif
2667
2668#ifdef HAVE_CHECK_STACK_GROWTH
2669 check_stack_growth((char *)&i);
2670
2671# ifdef HAVE_GETRLIMIT
2672 get_stack_limit();
2673# endif
2674
2675#endif
2676
2677 /*
2678 * Setup an alternative stack for signals. Helps to catch signals when
2679 * running out of stack space.
2680 * Use of sigaltstack() is preferred, it's more portable.
2681 * Ignore any errors.
2682 */
2683#if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2684 signal_stack = malloc(SIGSTKSZ);
2685 init_signal_stack();
2686#endif
2687}
2688
2689static void exit_scroll __ARGS((void));
2690
2691/*
2692 * Output a newline when exiting.
2693 * Make sure the newline goes to the same stream as the text.
2694 */
2695 static void
2696exit_scroll()
2697{
2698 if (newline_on_exit || msg_didout)
2699 {
2700 if (msg_use_printf())
2701 {
2702 if (info_message)
2703 mch_msg("\n");
2704 else
2705 mch_errmsg("\r\n");
2706 }
2707 else
2708 out_char('\n');
2709 }
2710 else
2711 {
2712 restore_cterm_colors(); /* get original colors back */
2713 msg_clr_eos_force(); /* clear the rest of the display */
2714 windgoto((int)Rows - 1, 0); /* may have moved the cursor */
2715 }
2716}
2717
2718 void
2719mch_exit(r)
2720 int r;
2721{
2722 exiting = TRUE;
2723
2724#if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
2725 x11_export_final_selection();
2726#endif
2727
2728#ifdef FEAT_GUI
2729 if (!gui.in_use)
2730#endif
2731 {
2732 settmode(TMODE_COOK);
2733#ifdef FEAT_TITLE
2734 mch_restore_title(3); /* restore xterm title and icon name */
2735#endif
2736 /*
2737 * When t_ti is not empty but it doesn't cause swapping terminal
2738 * pages, need to output a newline when msg_didout is set. But when
2739 * t_ti does swap pages it should not go to the shell page. Do this
2740 * before stoptermcap().
2741 */
2742 if (swapping_screen() && !newline_on_exit)
2743 exit_scroll();
2744
2745 /* Stop termcap: May need to check for T_CRV response, which
2746 * requires RAW mode. */
2747 stoptermcap();
2748
2749 /*
2750 * A newline is only required after a message in the alternate screen.
2751 * This is set to TRUE by wait_return().
2752 */
2753 if (!swapping_screen() || newline_on_exit)
2754 exit_scroll();
2755
2756 /* Cursor may have been switched off without calling starttermcap()
2757 * when doing "vim -u vimrc" and vimrc contains ":q". */
2758 if (full_screen)
2759 cursor_on();
2760 }
2761 out_flush();
2762 ml_close_all(TRUE); /* remove all memfiles */
2763 may_core_dump();
2764#ifdef FEAT_GUI
2765# ifndef FEAT_GUI_BEOS /* BeOS always has GUI */
2766 if (gui.in_use)
2767# endif
2768 gui_exit(r);
2769#endif
2770#ifdef __QNX__
2771 /* A core dump won't be created if the signal handler
2772 * doesn't return, so we can't call exit() */
2773 if (deadly_signal != 0)
2774 return;
2775#endif
2776
Bram Moolenaar009b2592004-10-24 19:18:58 +00002777#ifdef FEAT_NETBEANS_INTG
2778 if (usingNetbeans)
2779 netbeans_send_disconnect();
2780#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002781 exit(r);
2782}
2783
2784 static void
2785may_core_dump()
2786{
2787 if (deadly_signal != 0)
2788 {
2789 signal(deadly_signal, SIG_DFL);
2790 kill(getpid(), deadly_signal); /* Die using the signal we caught */
2791 }
2792}
2793
2794#ifndef VMS
2795
2796 void
2797mch_settmode(tmode)
2798 int tmode;
2799{
2800 static int first = TRUE;
2801
2802 /* Why is NeXT excluded here (and not in os_unixx.h)? */
2803#if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
2804 /*
2805 * for "new" tty systems
2806 */
2807# ifdef HAVE_TERMIOS_H
2808 static struct termios told;
2809 struct termios tnew;
2810# else
2811 static struct termio told;
2812 struct termio tnew;
2813# endif
2814
2815 if (first)
2816 {
2817 first = FALSE;
2818# if defined(HAVE_TERMIOS_H)
2819 tcgetattr(read_cmd_fd, &told);
2820# else
2821 ioctl(read_cmd_fd, TCGETA, &told);
2822# endif
2823 }
2824
2825 tnew = told;
2826 if (tmode == TMODE_RAW)
2827 {
2828 /*
2829 * ~ICRNL enables typing ^V^M
2830 */
2831 tnew.c_iflag &= ~ICRNL;
2832 tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE
2833# if defined(IEXTEN) && !defined(__MINT__)
2834 | IEXTEN /* IEXTEN enables typing ^V on SOLARIS */
2835 /* but it breaks function keys on MINT */
2836# endif
2837 );
2838# ifdef ONLCR /* don't map NL -> CR NL, we do it ourselves */
2839 tnew.c_oflag &= ~ONLCR;
2840# endif
2841 tnew.c_cc[VMIN] = 1; /* return after 1 char */
2842 tnew.c_cc[VTIME] = 0; /* don't wait */
2843 }
2844 else if (tmode == TMODE_SLEEP)
2845 tnew.c_lflag &= ~(ECHO);
2846
2847# if defined(HAVE_TERMIOS_H)
2848 {
2849 int n = 10;
2850
2851 /* A signal may cause tcsetattr() to fail (e.g., SIGCONT). Retry a
2852 * few times. */
2853 while (tcsetattr(read_cmd_fd, TCSANOW, &tnew) == -1
2854 && errno == EINTR && n > 0)
2855 --n;
2856 }
2857# else
2858 ioctl(read_cmd_fd, TCSETA, &tnew);
2859# endif
2860
2861#else
2862
2863 /*
2864 * for "old" tty systems
2865 */
2866# ifndef TIOCSETN
2867# define TIOCSETN TIOCSETP /* for hpux 9.0 */
2868# endif
2869 static struct sgttyb ttybold;
2870 struct sgttyb ttybnew;
2871
2872 if (first)
2873 {
2874 first = FALSE;
2875 ioctl(read_cmd_fd, TIOCGETP, &ttybold);
2876 }
2877
2878 ttybnew = ttybold;
2879 if (tmode == TMODE_RAW)
2880 {
2881 ttybnew.sg_flags &= ~(CRMOD | ECHO);
2882 ttybnew.sg_flags |= RAW;
2883 }
2884 else if (tmode == TMODE_SLEEP)
2885 ttybnew.sg_flags &= ~(ECHO);
2886 ioctl(read_cmd_fd, TIOCSETN, &ttybnew);
2887#endif
2888 curr_tmode = tmode;
2889}
2890
2891/*
2892 * Try to get the code for "t_kb" from the stty setting
2893 *
2894 * Even if termcap claims a backspace key, the user's setting *should*
2895 * prevail. stty knows more about reality than termcap does, and if
2896 * somebody's usual erase key is DEL (which, for most BSD users, it will
2897 * be), they're going to get really annoyed if their erase key starts
2898 * doing forward deletes for no reason. (Eric Fischer)
2899 */
2900 void
2901get_stty()
2902{
2903 char_u buf[2];
2904 char_u *p;
2905
2906 /* Why is NeXT excluded here (and not in os_unixx.h)? */
2907#if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
2908 /* for "new" tty systems */
2909# ifdef HAVE_TERMIOS_H
2910 struct termios keys;
2911# else
2912 struct termio keys;
2913# endif
2914
2915# if defined(HAVE_TERMIOS_H)
2916 if (tcgetattr(read_cmd_fd, &keys) != -1)
2917# else
2918 if (ioctl(read_cmd_fd, TCGETA, &keys) != -1)
2919# endif
2920 {
2921 buf[0] = keys.c_cc[VERASE];
2922 intr_char = keys.c_cc[VINTR];
2923#else
2924 /* for "old" tty systems */
2925 struct sgttyb keys;
2926
2927 if (ioctl(read_cmd_fd, TIOCGETP, &keys) != -1)
2928 {
2929 buf[0] = keys.sg_erase;
2930 intr_char = keys.sg_kill;
2931#endif
2932 buf[1] = NUL;
2933 add_termcode((char_u *)"kb", buf, FALSE);
2934
2935 /*
2936 * If <BS> and <DEL> are now the same, redefine <DEL>.
2937 */
2938 p = find_termcode((char_u *)"kD");
2939 if (p != NULL && p[0] == buf[0] && p[1] == buf[1])
2940 do_fixdel(NULL);
2941 }
2942#if 0
2943 } /* to keep cindent happy */
2944#endif
2945}
2946
2947#endif /* VMS */
2948
2949#if defined(FEAT_MOUSE_TTY) || defined(PROTO)
2950/*
2951 * Set mouse clicks on or off.
2952 */
2953 void
2954mch_setmouse(on)
2955 int on;
2956{
2957 static int ison = FALSE;
2958 int xterm_mouse_vers;
2959
2960 if (on == ison) /* return quickly if nothing to do */
2961 return;
2962
2963 xterm_mouse_vers = use_xterm_mouse();
2964 if (xterm_mouse_vers > 0)
2965 {
2966 if (on) /* enable mouse events, use mouse tracking if available */
2967 out_str_nf((char_u *)
2968 (xterm_mouse_vers > 1
2969 ? IF_EB("\033[?1002h", ESC_STR "[?1002h")
2970 : IF_EB("\033[?1000h", ESC_STR "[?1000h")));
2971 else /* disable mouse events, could probably always send the same */
2972 out_str_nf((char_u *)
2973 (xterm_mouse_vers > 1
2974 ? IF_EB("\033[?1002l", ESC_STR "[?1002l")
2975 : IF_EB("\033[?1000l", ESC_STR "[?1000l")));
2976 ison = on;
2977 }
2978
2979# ifdef FEAT_MOUSE_DEC
2980 else if (ttym_flags == TTYM_DEC)
2981 {
2982 if (on) /* enable mouse events */
2983 out_str_nf((char_u *)"\033[1;2'z\033[1;3'{");
2984 else /* disable mouse events */
2985 out_str_nf((char_u *)"\033['z");
2986 ison = on;
2987 }
2988# endif
2989
2990# ifdef FEAT_MOUSE_GPM
2991 else
2992 {
2993 if (on)
2994 {
2995 if (gpm_open())
2996 ison = TRUE;
2997 }
2998 else
2999 {
3000 gpm_close();
3001 ison = FALSE;
3002 }
3003 }
3004# endif
3005
3006# ifdef FEAT_MOUSE_JSB
3007 else
3008 {
3009 if (on)
3010 {
3011 /* D - Enable Mouse up/down messages
3012 * L - Enable Left Button Reporting
3013 * M - Enable Middle Button Reporting
3014 * R - Enable Right Button Reporting
3015 * K - Enable SHIFT and CTRL key Reporting
3016 * + - Enable Advanced messaging of mouse moves and up/down messages
3017 * Q - Quiet No Ack
3018 * # - Numeric value of mouse pointer required
3019 * 0 = Multiview 2000 cursor, used as standard
3020 * 1 = Windows Arrow
3021 * 2 = Windows I Beam
3022 * 3 = Windows Hour Glass
3023 * 4 = Windows Cross Hair
3024 * 5 = Windows UP Arrow
3025 */
3026#ifdef JSBTERM_MOUSE_NONADVANCED /* Disables full feedback of pointer movements */
3027 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK1Q\033\\",
3028 ESC_STR "[0~ZwLMRK1Q" ESC_STR "\\"));
3029#else
3030 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK+1Q\033\\",
3031 ESC_STR "[0~ZwLMRK+1Q" ESC_STR "\\"));
3032#endif
3033 ison = TRUE;
3034 }
3035 else
3036 {
3037 out_str_nf((char_u *)IF_EB("\033[0~ZwQ\033\\",
3038 ESC_STR "[0~ZwQ" ESC_STR "\\"));
3039 ison = FALSE;
3040 }
3041 }
3042# endif
3043# ifdef FEAT_MOUSE_PTERM
3044 else
3045 {
3046 /* 1 = button press, 6 = release, 7 = drag, 1h...9l = right button */
3047 if (on)
3048 out_str_nf("\033[>1h\033[>6h\033[>7h\033[>1h\033[>9l");
3049 else
3050 out_str_nf("\033[>1l\033[>6l\033[>7l\033[>1l\033[>9h");
3051 ison = on;
3052 }
3053# endif
3054}
3055
3056/*
3057 * Set the mouse termcode, depending on the 'term' and 'ttymouse' options.
3058 */
3059 void
3060check_mouse_termcode()
3061{
3062# ifdef FEAT_MOUSE_XTERM
3063 if (use_xterm_mouse()
3064# ifdef FEAT_GUI
3065 && !gui.in_use
3066# endif
3067 )
3068 {
3069 set_mouse_termcode(KS_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3070 ? IF_EB("\233M", CSI_STR "M") : IF_EB("\033[M", ESC_STR "[M")));
3071 if (*p_mouse != NUL)
3072 {
3073 /* force mouse off and maybe on to send possibly new mouse
3074 * activation sequence to the xterm, with(out) drag tracing. */
3075 mch_setmouse(FALSE);
3076 setmouse();
3077 }
3078 }
3079 else
3080 del_mouse_termcode(KS_MOUSE);
3081# endif
3082
3083# ifdef FEAT_MOUSE_GPM
3084 if (!use_xterm_mouse()
3085# ifdef FEAT_GUI
3086 && !gui.in_use
3087# endif
3088 )
3089 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MG", ESC_STR "MG"));
3090# endif
3091
3092# ifdef FEAT_MOUSE_JSB
3093 /* conflicts with xterm mouse: "\033[" and "\033[M" ??? */
3094 if (!use_xterm_mouse()
3095# ifdef FEAT_GUI
3096 && !gui.in_use
3097# endif
3098 )
3099 set_mouse_termcode(KS_JSBTERM_MOUSE,
3100 (char_u *)IF_EB("\033[0~zw", ESC_STR "[0~zw"));
3101 else
3102 del_mouse_termcode(KS_JSBTERM_MOUSE);
3103# endif
3104
3105# ifdef FEAT_MOUSE_NET
3106 /* There is no conflict, but one may type ESC } from Insert mode. Don't
3107 * define it in the GUI or when using an xterm. */
3108 if (!use_xterm_mouse()
3109# ifdef FEAT_GUI
3110 && !gui.in_use
3111# endif
3112 )
3113 set_mouse_termcode(KS_NETTERM_MOUSE,
3114 (char_u *)IF_EB("\033}", ESC_STR "}"));
3115 else
3116 del_mouse_termcode(KS_NETTERM_MOUSE);
3117# endif
3118
3119# ifdef FEAT_MOUSE_DEC
3120 /* conflicts with xterm mouse: "\033[" and "\033[M" */
3121 if (!use_xterm_mouse()
3122# ifdef FEAT_GUI
3123 && !gui.in_use
3124# endif
3125 )
3126 set_mouse_termcode(KS_DEC_MOUSE,
3127 (char_u *)IF_EB("\033[", ESC_STR "["));
3128 else
3129 del_mouse_termcode(KS_DEC_MOUSE);
3130# endif
3131# ifdef FEAT_MOUSE_PTERM
3132 /* same as the dec mouse */
3133 if (!use_xterm_mouse()
3134# ifdef FEAT_GUI
3135 && !gui.in_use
3136# endif
3137 )
3138 set_mouse_termcode(KS_PTERM_MOUSE,
3139 (char_u *) IF_EB("\033[", ESC_STR "["));
3140 else
3141 del_mouse_termcode(KS_PTERM_MOUSE);
3142# endif
3143}
3144#endif
3145
3146/*
3147 * set screen mode, always fails.
3148 */
3149/* ARGSUSED */
3150 int
3151mch_screenmode(arg)
3152 char_u *arg;
3153{
3154 EMSG(_(e_screenmode));
3155 return FAIL;
3156}
3157
3158#ifndef VMS
3159
3160/*
3161 * Try to get the current window size:
3162 * 1. with an ioctl(), most accurate method
3163 * 2. from the environment variables LINES and COLUMNS
3164 * 3. from the termcap
3165 * 4. keep using the old values
3166 * Return OK when size could be determined, FAIL otherwise.
3167 */
3168 int
3169mch_get_shellsize()
3170{
3171 long rows = 0;
3172 long columns = 0;
3173 char_u *p;
3174
3175 /*
3176 * For OS/2 use _scrsize().
3177 */
3178# ifdef __EMX__
3179 {
3180 int s[2];
3181
3182 _scrsize(s);
3183 columns = s[0];
3184 rows = s[1];
3185 }
3186# endif
3187
3188 /*
3189 * 1. try using an ioctl. It is the most accurate method.
3190 *
3191 * Try using TIOCGWINSZ first, some systems that have it also define
3192 * TIOCGSIZE but don't have a struct ttysize.
3193 */
3194# ifdef TIOCGWINSZ
3195 {
3196 struct winsize ws;
3197 int fd = 1;
3198
3199 /* When stdout is not a tty, use stdin for the ioctl(). */
3200 if (!isatty(fd) && isatty(read_cmd_fd))
3201 fd = read_cmd_fd;
3202 if (ioctl(fd, TIOCGWINSZ, &ws) == 0)
3203 {
3204 columns = ws.ws_col;
3205 rows = ws.ws_row;
3206 }
3207 }
3208# else /* TIOCGWINSZ */
3209# ifdef TIOCGSIZE
3210 {
3211 struct ttysize ts;
3212 int fd = 1;
3213
3214 /* When stdout is not a tty, use stdin for the ioctl(). */
3215 if (!isatty(fd) && isatty(read_cmd_fd))
3216 fd = read_cmd_fd;
3217 if (ioctl(fd, TIOCGSIZE, &ts) == 0)
3218 {
3219 columns = ts.ts_cols;
3220 rows = ts.ts_lines;
3221 }
3222 }
3223# endif /* TIOCGSIZE */
3224# endif /* TIOCGWINSZ */
3225
3226 /*
3227 * 2. get size from environment
3228 */
3229 if (columns == 0 || rows == 0)
3230 {
3231 if ((p = (char_u *)getenv("LINES")))
3232 rows = atoi((char *)p);
3233 if ((p = (char_u *)getenv("COLUMNS")))
3234 columns = atoi((char *)p);
3235 }
3236
3237#ifdef HAVE_TGETENT
3238 /*
3239 * 3. try reading "co" and "li" entries from termcap
3240 */
3241 if (columns == 0 || rows == 0)
3242 getlinecol(&columns, &rows);
3243#endif
3244
3245 /*
3246 * 4. If everything fails, use the old values
3247 */
3248 if (columns <= 0 || rows <= 0)
3249 return FAIL;
3250
3251 Rows = rows;
3252 Columns = columns;
3253 return OK;
3254}
3255
3256/*
3257 * Try to set the window size to Rows and Columns.
3258 */
3259 void
3260mch_set_shellsize()
3261{
3262 if (*T_CWS)
3263 {
3264 /*
3265 * NOTE: if you get an error here that term_set_winsize() is
3266 * undefined, check the output of configure. It could probably not
3267 * find a ncurses, termcap or termlib library.
3268 */
3269 term_set_winsize((int)Rows, (int)Columns);
3270 out_flush();
3271 screen_start(); /* don't know where cursor is now */
3272 }
3273}
3274
3275#endif /* VMS */
3276
3277/*
3278 * Rows and/or Columns has changed.
3279 */
3280 void
3281mch_new_shellsize()
3282{
3283 /* Nothing to do. */
3284}
3285
3286 int
3287mch_call_shell(cmd, options)
3288 char_u *cmd;
3289 int options; /* SHELL_*, see vim.h */
3290{
3291#ifdef VMS
3292 char *ifn = NULL;
3293 char *ofn = NULL;
3294#endif
3295 int tmode = cur_tmode;
3296#ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
3297 int x;
3298# ifndef __EMX__
3299 char_u *newcmd; /* only needed for unix */
3300# else
3301 /*
3302 * Set the preferred shell in the EMXSHELL environment variable (but
3303 * only if it is different from what is already in the environment).
3304 * Emx then takes care of whether to use "/c" or "-c" in an
3305 * intelligent way. Simply pass the whole thing to emx's system() call.
3306 * Emx also starts an interactive shell if system() is passed an empty
3307 * string.
3308 */
3309 char_u *p, *old;
3310
3311 if (((old = (char_u *)getenv("EMXSHELL")) == NULL) || STRCMP(old, p_sh))
3312 {
3313 /* should check HAVE_SETENV, but I know we don't have it. */
3314 p = alloc(10 + strlen(p_sh));
3315 if (p)
3316 {
3317 sprintf((char *)p, "EMXSHELL=%s", p_sh);
3318 putenv((char *)p); /* don't free the pointer! */
3319 }
3320 }
3321# endif
3322
3323 out_flush();
3324
3325 if (options & SHELL_COOKED)
3326 settmode(TMODE_COOK); /* set to normal mode */
3327
3328# ifdef __EMX__
3329 if (cmd == NULL)
3330 x = system(""); /* this starts an interactive shell in emx */
3331 else
3332 x = system((char *)cmd);
3333 /* system() returns -1 when error occurs in starting shell */
3334 if (x == -1 && !emsg_silent)
3335 {
3336 MSG_PUTS(_("\nCannot execute shell "));
3337 msg_outtrans(p_sh);
3338 msg_putchar('\n');
3339 }
3340# else /* not __EMX__ */
3341 if (cmd == NULL)
3342 x = system((char *)p_sh);
3343 else
3344 {
3345# ifdef VMS
3346 if (ofn = strchr((char *)cmd, '>'))
3347 *ofn++ = '\0';
3348 if (ifn = strchr((char *)cmd, '<'))
3349 {
3350 char *p;
3351
3352 *ifn++ = '\0';
3353 p = strchr(ifn,' '); /* chop off any trailing spaces */
3354 if (p)
3355 *p = '\0';
3356 }
3357 if (ofn)
3358 x = vms_sys((char *)cmd, ofn, ifn);
3359 else
3360 x = system((char *)cmd);
3361# else
3362 newcmd = lalloc(STRLEN(p_sh)
3363 + (extra_shell_arg == NULL ? 0 : STRLEN(extra_shell_arg))
3364 + STRLEN(p_shcf) + STRLEN(cmd) + 4, TRUE);
3365 if (newcmd == NULL)
3366 x = 0;
3367 else
3368 {
3369 sprintf((char *)newcmd, "%s %s %s %s", p_sh,
3370 extra_shell_arg == NULL ? "" : (char *)extra_shell_arg,
3371 (char *)p_shcf,
3372 (char *)cmd);
3373 x = system((char *)newcmd);
3374 vim_free(newcmd);
3375 }
3376# endif
3377 }
3378# ifdef VMS
3379 x = vms_sys_status(x);
3380# endif
3381 if (emsg_silent)
3382 ;
3383 else if (x == 127)
3384 MSG_PUTS(_("\nCannot execute shell sh\n"));
3385# endif /* __EMX__ */
3386 else if (x && !(options & SHELL_SILENT))
3387 {
3388 MSG_PUTS(_("\nshell returned "));
3389 msg_outnum((long)x);
3390 msg_putchar('\n');
3391 }
3392
3393 if (tmode == TMODE_RAW)
3394 settmode(TMODE_RAW); /* set to raw mode */
3395# ifdef FEAT_TITLE
3396 resettitle();
3397# endif
3398 return x;
3399
3400#else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
3401
3402#define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
3403 127, some shell use that already */
3404
3405 char_u *newcmd = NULL;
3406 pid_t pid;
3407 pid_t wait_pid = 0;
3408# ifdef HAVE_UNION_WAIT
3409 union wait status;
3410# else
3411 int status = -1;
3412# endif
3413 int retval = -1;
3414 char **argv = NULL;
3415 int argc;
3416 int i;
3417 char_u *p;
3418 int inquote;
3419# ifdef FEAT_GUI
3420 int pty_master_fd = -1; /* for pty's */
3421 int pty_slave_fd = -1;
3422 char *tty_name;
3423 int fd_toshell[2]; /* for pipes */
3424 int fd_fromshell[2];
3425 int pipe_error = FALSE;
3426# ifdef HAVE_SETENV
3427 char envbuf[50];
3428# else
3429 static char envbuf_Rows[20];
3430 static char envbuf_Columns[20];
3431# endif
3432# endif
3433 int did_settmode = FALSE; /* TRUE when settmode(TMODE_RAW) called */
3434
3435 out_flush();
3436 if (options & SHELL_COOKED)
3437 settmode(TMODE_COOK); /* set to normal mode */
3438
3439 /*
3440 * 1: find number of arguments
3441 * 2: separate them and built argv[]
3442 */
3443 newcmd = vim_strsave(p_sh);
3444 if (newcmd == NULL) /* out of memory */
3445 goto error;
3446 for (i = 0; i < 2; ++i)
3447 {
3448 p = newcmd;
3449 inquote = FALSE;
3450 argc = 0;
3451 for (;;)
3452 {
3453 if (i == 1)
3454 argv[argc] = (char *)p;
3455 ++argc;
3456 while (*p && (inquote || (*p != ' ' && *p != TAB)))
3457 {
3458 if (*p == '"')
3459 inquote = !inquote;
3460 ++p;
3461 }
3462 if (*p == NUL)
3463 break;
3464 if (i == 1)
3465 *p++ = NUL;
3466 p = skipwhite(p);
3467 }
3468 if (i == 0)
3469 {
3470 argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *)));
3471 if (argv == NULL) /* out of memory */
3472 goto error;
3473 }
3474 }
3475 if (cmd != NULL)
3476 {
3477 if (extra_shell_arg != NULL)
3478 argv[argc++] = (char *)extra_shell_arg;
3479 argv[argc++] = (char *)p_shcf;
3480 argv[argc++] = (char *)cmd;
3481 }
3482 argv[argc] = NULL;
3483
3484# ifdef FEAT_GUI
3485 /*
3486 * For the GUI: Try using a pseudo-tty to get the stdin/stdout of the
3487 * executed command into the Vim window. Or use a pipe.
3488 */
3489 if (gui.in_use && show_shell_mess)
3490 {
3491 /*
3492 * Try to open a master pty.
3493 * If this works, open the slave pty.
3494 * If the slave can't be opened, close the master pty.
3495 */
3496 if (p_guipty)
3497 {
3498 pty_master_fd = OpenPTY(&tty_name); /* open pty */
3499 if (pty_master_fd >= 0 && ((pty_slave_fd =
3500 open(tty_name, O_RDWR | O_EXTRA, 0)) < 0))
3501 {
3502 close(pty_master_fd);
3503 pty_master_fd = -1;
3504 }
3505 }
3506 /*
3507 * If not opening a pty or it didn't work, try using pipes.
3508 */
3509 if (pty_master_fd < 0)
3510 {
3511 pipe_error = (pipe(fd_toshell) < 0);
3512 if (!pipe_error) /* pipe create OK */
3513 {
3514 pipe_error = (pipe(fd_fromshell) < 0);
3515 if (pipe_error) /* pipe create failed */
3516 {
3517 close(fd_toshell[0]);
3518 close(fd_toshell[1]);
3519 }
3520 }
3521 if (pipe_error)
3522 {
3523 MSG_PUTS(_("\nCannot create pipes\n"));
3524 out_flush();
3525 }
3526 }
3527 }
3528
3529 if (!pipe_error) /* pty or pipe opened or not used */
3530# endif
3531
3532 {
3533# ifdef __BEOS__
3534 beos_cleanup_read_thread();
3535# endif
3536 if ((pid = fork()) == -1) /* maybe we should use vfork() */
3537 {
3538 MSG_PUTS(_("\nCannot fork\n"));
3539# ifdef FEAT_GUI
3540 if (gui.in_use && show_shell_mess)
3541 {
3542 if (pty_master_fd >= 0) /* close the pseudo tty */
3543 {
3544 close(pty_master_fd);
3545 close(pty_slave_fd);
3546 }
3547 else /* close the pipes */
3548 {
3549 close(fd_toshell[0]);
3550 close(fd_toshell[1]);
3551 close(fd_fromshell[0]);
3552 close(fd_fromshell[1]);
3553 }
3554 }
3555# endif
3556 }
3557 else if (pid == 0) /* child */
3558 {
3559 reset_signals(); /* handle signals normally */
3560
3561 if (!show_shell_mess || (options & SHELL_EXPAND))
3562 {
3563 int fd;
3564
3565 /*
3566 * Don't want to show any message from the shell. Can't just
3567 * close stdout and stderr though, because some systems will
3568 * break if you try to write to them after that, so we must
3569 * use dup() to replace them with something else -- webb
3570 * Connect stdin to /dev/null too, so ":n `cat`" doesn't hang,
3571 * waiting for input.
3572 */
3573 fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
3574 fclose(stdin);
3575 fclose(stdout);
3576 fclose(stderr);
3577
3578 /*
3579 * If any of these open()'s and dup()'s fail, we just continue
3580 * anyway. It's not fatal, and on most systems it will make
3581 * no difference at all. On a few it will cause the execvp()
3582 * to exit with a non-zero status even when the completion
3583 * could be done, which is nothing too serious. If the open()
3584 * or dup() failed we'd just do the same thing ourselves
3585 * anyway -- webb
3586 */
3587 if (fd >= 0)
3588 {
3589 dup(fd); /* To replace stdin (file descriptor 0) */
3590 dup(fd); /* To replace stdout (file descriptor 1) */
3591 dup(fd); /* To replace stderr (file descriptor 2) */
3592
3593 /* Don't need this now that we've duplicated it */
3594 close(fd);
3595 }
3596 }
3597# ifdef FEAT_GUI
3598 else if (gui.in_use)
3599 {
3600
3601# ifdef HAVE_SETSID
3602 (void)setsid();
3603# endif
3604 /* push stream discipline modules */
3605 if (options & SHELL_COOKED)
3606 SetupSlavePTY(pty_slave_fd);
3607# ifdef TIOCSCTTY
3608 /* try to become controlling tty (probably doesn't work,
3609 * unless run by root) */
3610 ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
3611# endif
3612 /* Simulate to have a dumb terminal (for now) */
3613# ifdef HAVE_SETENV
3614 setenv("TERM", "dumb", 1);
3615 sprintf((char *)envbuf, "%ld", Rows);
3616 setenv("ROWS", (char *)envbuf, 1);
3617 sprintf((char *)envbuf, "%ld", Rows);
3618 setenv("LINES", (char *)envbuf, 1);
3619 sprintf((char *)envbuf, "%ld", Columns);
3620 setenv("COLUMNS", (char *)envbuf, 1);
3621# else
3622 /*
3623 * Putenv does not copy the string, it has to remain valid.
3624 * Use a static array to avoid loosing allocated memory.
3625 */
3626 putenv("TERM=dumb");
3627 sprintf(envbuf_Rows, "ROWS=%ld", Rows);
3628 putenv(envbuf_Rows);
3629 sprintf(envbuf_Rows, "LINES=%ld", Rows);
3630 putenv(envbuf_Rows);
3631 sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
3632 putenv(envbuf_Columns);
3633# endif
3634
3635 if (pty_master_fd >= 0)
3636 {
3637 close(pty_master_fd); /* close master side of pty */
3638
3639 /* set up stdin/stdout/stderr for the child */
3640 close(0);
3641 dup(pty_slave_fd);
3642 close(1);
3643 dup(pty_slave_fd);
3644 close(2);
3645 dup(pty_slave_fd);
3646
3647 close(pty_slave_fd); /* has been dupped, close it now */
3648 }
3649 else
3650 {
3651 /* set up stdin for the child */
3652 close(fd_toshell[1]);
3653 close(0);
3654 dup(fd_toshell[0]);
3655 close(fd_toshell[0]);
3656
3657 /* set up stdout for the child */
3658 close(fd_fromshell[0]);
3659 close(1);
3660 dup(fd_fromshell[1]);
3661 close(fd_fromshell[1]);
3662
3663 /* set up stderr for the child */
3664 close(2);
3665 dup(1);
3666 }
3667 }
3668# endif /* FEAT_GUI */
3669 /*
3670 * There is no type cast for the argv, because the type may be
3671 * different on different machines. This may cause a warning
3672 * message with strict compilers, don't worry about it.
3673 * Call _exit() instead of exit() to avoid closing the connection
3674 * to the X server (esp. with GTK, which uses atexit()).
3675 */
3676 execvp(argv[0], argv);
3677 _exit(EXEC_FAILED); /* exec failed, return failure code */
3678 }
3679 else /* parent */
3680 {
3681 /*
3682 * While child is running, ignore terminating signals.
3683 */
3684 catch_signals(SIG_IGN, SIG_ERR);
3685
3686# ifdef FEAT_GUI
3687
3688 /*
3689 * For the GUI we redirect stdin, stdout and stderr to our window.
3690 */
3691 if (gui.in_use && show_shell_mess)
3692 {
3693# define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
3694 char_u buffer[BUFLEN + 1];
3695# ifdef FEAT_MBYTE
3696 int buffer_off = 0; /* valid bytes in buffer[] */
3697# endif
3698 char_u ta_buf[BUFLEN + 1]; /* TypeAHead */
3699 int ta_len = 0; /* valid bytes in ta_buf[] */
3700 int len;
3701 int p_more_save;
3702 int old_State;
3703 int c;
3704 int toshell_fd;
3705 int fromshell_fd;
3706
3707 if (pty_master_fd >= 0)
3708 {
3709 close(pty_slave_fd); /* close slave side of pty */
3710 fromshell_fd = pty_master_fd;
3711 toshell_fd = dup(pty_master_fd);
3712 }
3713 else
3714 {
3715 close(fd_toshell[0]);
3716 close(fd_fromshell[1]);
3717 toshell_fd = fd_toshell[1];
3718 fromshell_fd = fd_fromshell[0];
3719 }
3720
3721 /*
3722 * Write to the child if there are typed characters.
3723 * Read from the child if there are characters available.
3724 * Repeat the reading a few times if more characters are
3725 * available. Need to check for typed keys now and then, but
3726 * not too often (delays when no chars are available).
3727 * This loop is quit if no characters can be read from the pty
3728 * (WaitForChar detected special condition), or there are no
3729 * characters available and the child has exited.
3730 * Only check if the child has exited when there is no more
3731 * output. The child may exit before all the output has
3732 * been printed.
3733 *
3734 * Currently this busy loops!
3735 * This can probably dead-lock when the write blocks!
3736 */
3737 p_more_save = p_more;
3738 p_more = FALSE;
3739 old_State = State;
3740 State = EXTERNCMD; /* don't redraw at window resize */
3741
3742 for (;;)
3743 {
3744 /*
3745 * Check if keys have been typed, write them to the child
3746 * if there are any. Don't do this if we are expanding
3747 * wild cards (would eat typeahead). Don't get extra
3748 * characters when we already have one.
3749 */
3750 len = 0;
3751 if (!(options & SHELL_EXPAND)
3752 && (ta_len > 0
3753 || (len = ui_inchar(ta_buf, BUFLEN, 10L,
3754 0)) > 0))
3755 {
3756 /*
3757 * For pipes:
3758 * Check for CTRL-C: send interrupt signal to child.
3759 * Check for CTRL-D: EOF, close pipe to child.
3760 */
3761 if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
3762 {
3763# ifdef SIGINT
3764 /*
3765 * Send SIGINT to the child's group or all
3766 * processes in our group.
3767 */
3768 if (ta_buf[ta_len] == Ctrl_C
3769 || ta_buf[ta_len] == intr_char)
3770# ifdef HAVE_SETSID
3771 kill(-pid, SIGINT);
3772# else
3773 kill(0, SIGINT);
3774# endif
3775# endif
3776 if (pty_master_fd < 0 && toshell_fd >= 0
3777 && ta_buf[ta_len] == Ctrl_D)
3778 {
3779 close(toshell_fd);
3780 toshell_fd = -1;
3781 }
3782 }
3783
3784 /* replace K_BS by <BS> and K_DEL by <DEL> */
3785 for (i = ta_len; i < ta_len + len; ++i)
3786 {
3787 if (ta_buf[i] == CSI && len - i > 2)
3788 {
3789 c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]);
3790 if (c == K_DEL || c == K_KDEL || c == K_BS)
3791 {
3792 mch_memmove(ta_buf + i + 1, ta_buf + i + 3,
3793 (size_t)(len - i - 2));
3794 if (c == K_DEL || c == K_KDEL)
3795 ta_buf[i] = DEL;
3796 else
3797 ta_buf[i] = Ctrl_H;
3798 len -= 2;
3799 }
3800 }
3801 else if (ta_buf[i] == '\r')
3802 ta_buf[i] = '\n';
3803# ifdef FEAT_MBYTE
3804 if (has_mbyte)
3805 i += (*mb_ptr2len_check)(ta_buf + i) - 1;
3806# endif
3807 }
3808
3809 /*
3810 * For pipes: echo the typed characters.
3811 * For a pty this does not seem to work.
3812 */
3813 if (pty_master_fd < 0)
3814 {
3815 for (i = ta_len; i < ta_len + len; ++i)
3816 {
3817 if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
3818 msg_putchar(ta_buf[i]);
3819# ifdef FEAT_MBYTE
3820 else if (has_mbyte)
3821 {
3822 int l = (*mb_ptr2len_check)(ta_buf + i);
3823
3824 msg_outtrans_len(ta_buf + i, l);
3825 i += l - 1;
3826 }
3827# endif
3828 else
3829 msg_outtrans_len(ta_buf + i, 1);
3830 }
3831 windgoto(msg_row, msg_col);
3832 out_flush();
3833 }
3834
3835 ta_len += len;
3836
3837 /*
3838 * Write the characters to the child, unless EOF has
3839 * been typed for pipes. Write one character at a
3840 * time, to avoid loosing too much typeahead.
3841 */
3842 if (toshell_fd >= 0)
3843 {
3844 len = write(toshell_fd, (char *)ta_buf, (size_t)1);
3845 if (len > 0)
3846 {
3847 ta_len -= len;
3848 mch_memmove(ta_buf, ta_buf + len, ta_len);
3849 }
3850 }
3851 }
3852
3853 /*
3854 * Check if the child has any characters to be printed.
3855 * Read them and write them to our window. Repeat this as
3856 * long as there is something to do, avoid the 10ms wait
3857 * for mch_inchar(), or sending typeahead characters to
3858 * the external process.
3859 * TODO: This should handle escape sequences, compatible
3860 * to some terminal (vt52?).
3861 */
3862 while (RealWaitForChar(fromshell_fd, 10L, NULL))
3863 {
3864 len = read(fromshell_fd, (char *)buffer
3865# ifdef FEAT_MBYTE
3866 + buffer_off, (size_t)(BUFLEN - buffer_off)
3867# else
3868 , (size_t)BUFLEN
3869# endif
3870 );
3871 if (len <= 0) /* end of file or error */
3872 goto finished;
3873# ifdef FEAT_MBYTE
3874 len += buffer_off;
3875 buffer[len] = NUL;
3876 if (has_mbyte)
3877 {
3878 int l;
3879
3880 /* Check if the last character in buffer[] is
3881 * incomplete, keep these bytes for the next
3882 * round. */
3883 for (p = buffer; p < buffer + len; p += l)
3884 {
3885 if (enc_utf8) /* exclude composing chars */
3886 l = utf_ptr2len_check(p);
3887 else
3888 l = (*mb_ptr2len_check)(p);
3889 if (l == 0)
3890 l = 1; /* NUL byte? */
3891 else if (MB_BYTE2LEN(*p) != l)
3892 break;
3893 }
3894 if (p == buffer) /* no complete character */
3895 {
3896 /* avoid getting stuck at an illegal byte */
3897 if (len >= 12)
3898 ++p;
3899 else
3900 {
3901 buffer_off = len;
3902 continue;
3903 }
3904 }
3905 c = *p;
3906 *p = NUL;
3907 msg_puts(buffer);
3908 if (p < buffer + len)
3909 {
3910 *p = c;
3911 buffer_off = (buffer + len) - p;
3912 mch_memmove(buffer, p, buffer_off);
3913 continue;
3914 }
3915 buffer_off = 0;
3916 }
3917 else
3918# endif /* FEAT_MBYTE */
3919 {
3920 buffer[len] = NUL;
3921 msg_puts(buffer);
3922 }
3923
3924 windgoto(msg_row, msg_col);
3925 cursor_on();
3926 out_flush();
3927 if (got_int)
3928 break;
3929 }
3930
3931 /*
3932 * Check if the child still exists, before checking for
3933 * typed characters (otherwise we would loose typeahead).
3934 */
3935# ifdef __NeXT__
3936 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *) 0);
3937# else
3938 wait_pid = waitpid(pid, &status, WNOHANG);
3939# endif
3940 if ((wait_pid == (pid_t)-1 && errno == ECHILD)
3941 || (wait_pid == pid && WIFEXITED(status)))
3942 {
3943 wait_pid = pid;
3944 break;
3945 }
3946 wait_pid = 0;
3947 }
3948finished:
3949 p_more = p_more_save;
3950
3951# ifndef MACOS_X_UNIX /* TODO: Is it needed for MACOS_X ? */
3952 /*
3953 * Give all typeahead that wasn't used back to ui_inchar().
3954 */
3955 if (ta_len)
3956 ui_inchar_undo(ta_buf, ta_len);
3957# endif
3958 State = old_State;
3959 if (toshell_fd >= 0)
3960 close(toshell_fd);
3961 close(fromshell_fd);
3962 }
3963# endif /* FEAT_GUI */
3964
3965 /*
3966 * Wait until our child has exited.
3967 * Ignore wait() returning pids of other children and returning
3968 * because of some signal like SIGWINCH.
3969 * Don't wait if wait_pid was already set above, indicating the
3970 * child already exited.
3971 */
3972 while (wait_pid != pid)
3973 {
3974#ifdef _THREAD_SAFE
3975 /* Ugly hack: when compiled with Python threads are probably
3976 * used, in which case wait() sometimes hangs for no obvious
3977 * reason. Use waitpid() instead and loop (like the GUI). */
3978# ifdef __NeXT__
3979 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0);
3980# else
3981 wait_pid = waitpid(pid, &status, WNOHANG);
3982# endif
3983 if (wait_pid == 0)
3984 {
3985 /* Wait for 1/100 sec before trying again. */
3986 mch_delay(10L, TRUE);
3987 continue;
3988 }
3989#else
3990 wait_pid = wait(&status);
3991#endif
3992 if (wait_pid <= 0
3993# ifdef ECHILD
3994 && errno == ECHILD
3995# endif
3996 )
3997 break;
3998 }
3999
4000 /*
4001 * Set to raw mode right now, otherwise a CTRL-C after
4002 * catch_signals() will kill Vim.
4003 */
4004 if (tmode == TMODE_RAW)
4005 settmode(TMODE_RAW);
4006 did_settmode = TRUE;
4007 set_signals();
4008
4009 if (WIFEXITED(status))
4010 {
4011 retval = WEXITSTATUS(status);
4012 if (retval && !emsg_silent)
4013 {
4014 if (retval == EXEC_FAILED)
4015 {
4016 MSG_PUTS(_("\nCannot execute shell "));
4017 msg_outtrans(p_sh);
4018 msg_putchar('\n');
4019 }
4020 else if (!(options & SHELL_SILENT))
4021 {
4022 MSG_PUTS(_("\nshell returned "));
4023 msg_outnum((long)retval);
4024 msg_putchar('\n');
4025 }
4026 }
4027 }
4028 else
4029 MSG_PUTS(_("\nCommand terminated\n"));
4030 }
4031 }
4032 vim_free(argv);
4033
4034error:
4035 if (!did_settmode)
4036 if (tmode == TMODE_RAW)
4037 settmode(TMODE_RAW); /* set to raw mode */
4038# ifdef FEAT_TITLE
4039 resettitle();
4040# endif
4041 vim_free(newcmd);
4042
4043 return retval;
4044
4045#endif /* USE_SYSTEM */
4046}
4047
4048/*
4049 * Check for CTRL-C typed by reading all available characters.
4050 * In cooked mode we should get SIGINT, no need to check.
4051 */
4052 void
4053mch_breakcheck()
4054{
4055 if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL))
4056 fill_input_buf(FALSE);
4057}
4058
4059/*
4060 * Wait "msec" msec until a character is available from the keyboard or from
4061 * inbuf[]. msec == -1 will block forever.
4062 * When a GUI is being used, this will never get called -- webb
4063 */
4064 static int
4065WaitForChar(msec)
4066 long msec;
4067{
4068#ifdef FEAT_MOUSE_GPM
4069 int gpm_process_wanted;
4070#endif
4071#ifdef FEAT_XCLIPBOARD
4072 int rest;
4073#endif
4074 int avail;
4075
4076 if (input_available()) /* something in inbuf[] */
4077 return 1;
4078
4079#if defined(FEAT_MOUSE_DEC)
4080 /* May need to query the mouse position. */
4081 if (WantQueryMouse)
4082 {
4083 WantQueryMouse = 0;
4084 mch_write((char_u *)IF_EB("\033[1'|", ESC_STR "[1'|"), 5);
4085 }
4086#endif
4087
4088 /*
4089 * For FEAT_MOUSE_GPM and FEAT_XCLIPBOARD we loop here to process mouse
4090 * events. This is a bit complicated, because they might both be defined.
4091 */
4092#if defined(FEAT_MOUSE_GPM) || defined(FEAT_XCLIPBOARD)
4093# ifdef FEAT_XCLIPBOARD
4094 rest = 0;
4095 if (do_xterm_trace())
4096 rest = msec;
4097# endif
4098 do
4099 {
4100# ifdef FEAT_XCLIPBOARD
4101 if (rest != 0)
4102 {
4103 msec = XT_TRACE_DELAY;
4104 if (rest >= 0 && rest < XT_TRACE_DELAY)
4105 msec = rest;
4106 if (rest >= 0)
4107 rest -= msec;
4108 }
4109# endif
4110# ifdef FEAT_MOUSE_GPM
4111 gpm_process_wanted = 0;
4112 avail = RealWaitForChar(read_cmd_fd, msec, &gpm_process_wanted);
4113# else
4114 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4115# endif
4116 if (!avail)
4117 {
4118 if (input_available())
4119 return 1;
4120# ifdef FEAT_XCLIPBOARD
4121 if (rest == 0 || !do_xterm_trace())
4122# endif
4123 break;
4124 }
4125 }
4126 while (FALSE
4127# ifdef FEAT_MOUSE_GPM
4128 || (gpm_process_wanted && mch_gpm_process() == 0)
4129# endif
4130# ifdef FEAT_XCLIPBOARD
4131 || (!avail && rest != 0)
4132# endif
4133 );
4134
4135#else
4136 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4137#endif
4138 return avail;
4139}
4140
4141/*
4142 * Wait "msec" msec until a character is available from file descriptor "fd".
4143 * Time == -1 will block forever.
4144 * When a GUI is being used, this will not be used for input -- webb
4145 * Returns also, when a request from Sniff is waiting -- toni.
4146 * Or when a Linux GPM mouse event is waiting.
4147 */
4148/* ARGSUSED */
4149#if defined(__BEOS__)
4150 int
4151#else
4152 static int
4153#endif
4154RealWaitForChar(fd, msec, check_for_gpm)
4155 int fd;
4156 long msec;
4157 int *check_for_gpm;
4158{
4159 int ret;
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004160#if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004161 static int busy = FALSE;
4162
4163 /* May retry getting characters after an event was handled. */
4164# define MAY_LOOP
4165
4166# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4167 /* Remember at what time we started, so that we know how much longer we
4168 * should wait after being interrupted. */
4169# define USE_START_TV
4170 struct timeval start_tv;
4171
4172 if (msec > 0 && (
4173# ifdef FEAT_XCLIPBOARD
4174 xterm_Shell != (Widget)0
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004175# if defined(USE_XSMP) || defined(FEAT_MZSCHEME)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004176 ||
4177# endif
4178# endif
4179# ifdef USE_XSMP
4180 xsmp_icefd != -1
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004181# ifdef FEAT_MZSCHEME
4182 ||
4183# endif
4184# endif
4185# ifdef FEAT_MZSCHEME
4186 (mzthreads_allowed() && p_mzq > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004187# endif
4188 ))
4189 gettimeofday(&start_tv, NULL);
4190# endif
4191
4192 /* Handle being called recursively. This may happen for the session
4193 * manager stuff, it may save the file, which does a breakcheck. */
4194 if (busy)
4195 return 0;
4196#endif
4197
4198#ifdef MAY_LOOP
4199 while (1)
4200#endif
4201 {
4202#ifdef MAY_LOOP
4203 int finished = TRUE; /* default is to 'loop' just once */
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004204# ifdef FEAT_MZSCHEME
4205 int mzquantum_used = FALSE;
4206# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004207#endif
4208#ifndef HAVE_SELECT
4209 struct pollfd fds[5];
4210 int nfd;
4211# ifdef FEAT_XCLIPBOARD
4212 int xterm_idx = -1;
4213# endif
4214# ifdef FEAT_MOUSE_GPM
4215 int gpm_idx = -1;
4216# endif
4217# ifdef USE_XSMP
4218 int xsmp_idx = -1;
4219# endif
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004220 int towait = (int)msec;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004221
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004222# ifdef FEAT_MZSCHEME
4223 mzvim_check_threads();
4224 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4225 {
4226 towait = (int)p_mzq; /* don't wait longer than 'mzquantum' */
4227 mzquantum_used = TRUE;
4228 }
4229# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004230 fds[0].fd = fd;
4231 fds[0].events = POLLIN;
4232 nfd = 1;
4233
4234# ifdef FEAT_SNIFF
4235# define SNIFF_IDX 1
4236 if (want_sniff_request)
4237 {
4238 fds[SNIFF_IDX].fd = fd_from_sniff;
4239 fds[SNIFF_IDX].events = POLLIN;
4240 nfd++;
4241 }
4242# endif
4243# ifdef FEAT_XCLIPBOARD
4244 if (xterm_Shell != (Widget)0)
4245 {
4246 xterm_idx = nfd;
4247 fds[nfd].fd = ConnectionNumber(xterm_dpy);
4248 fds[nfd].events = POLLIN;
4249 nfd++;
4250 }
4251# endif
4252# ifdef FEAT_MOUSE_GPM
4253 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4254 {
4255 gpm_idx = nfd;
4256 fds[nfd].fd = gpm_fd;
4257 fds[nfd].events = POLLIN;
4258 nfd++;
4259 }
4260# endif
4261# ifdef USE_XSMP
4262 if (xsmp_icefd != -1)
4263 {
4264 xsmp_idx = nfd;
4265 fds[nfd].fd = xsmp_icefd;
4266 fds[nfd].events = POLLIN;
4267 nfd++;
4268 }
4269# endif
4270
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004271 ret = poll(fds, nfd, towait);
4272# ifdef FEAT_MZSCHEME
4273 if (ret == 0 && mzquantum_used)
4274 /* MzThreads scheduling is required and timeout occured */
4275 finished = FALSE;
4276# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004277
4278# ifdef FEAT_SNIFF
4279 if (ret < 0)
4280 sniff_disconnect(1);
4281 else if (want_sniff_request)
4282 {
4283 if (fds[SNIFF_IDX].revents & POLLHUP)
4284 sniff_disconnect(1);
4285 if (fds[SNIFF_IDX].revents & POLLIN)
4286 sniff_request_waiting = 1;
4287 }
4288# endif
4289# ifdef FEAT_XCLIPBOARD
4290 if (xterm_Shell != (Widget)0 && (fds[xterm_idx].revents & POLLIN))
4291 {
4292 xterm_update(); /* Maybe we should hand out clipboard */
4293 if (--ret == 0 && !input_available())
4294 /* Try again */
4295 finished = FALSE;
4296 }
4297# endif
4298# ifdef FEAT_MOUSE_GPM
4299 if (gpm_idx >= 0 && (fds[gpm_idx].revents & POLLIN))
4300 {
4301 *check_for_gpm = 1;
4302 }
4303# endif
4304# ifdef USE_XSMP
4305 if (xsmp_idx >= 0 && (fds[xsmp_idx].revents & (POLLIN | POLLHUP)))
4306 {
4307 if (fds[xsmp_idx].revents & POLLIN)
4308 {
4309 busy = TRUE;
4310 xsmp_handle_requests();
4311 busy = FALSE;
4312 }
4313 else if (fds[xsmp_idx].revents & POLLHUP)
4314 {
4315 if (p_verbose > 0)
4316 MSG(_("XSMP lost ICE connection"));
4317 xsmp_close();
4318 }
4319 if (--ret == 0)
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004320 finished = FALSE; /* Try again */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004321 }
4322# endif
4323
4324
4325#else /* HAVE_SELECT */
4326
4327 struct timeval tv;
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004328 struct timeval *tvp;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004329 fd_set rfds, efds;
4330 int maxfd;
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004331 long towait = msec;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004332
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004333# ifdef FEAT_MZSCHEME
4334 mzvim_check_threads();
4335 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4336 {
4337 towait = p_mzq; /* don't wait longer than 'mzquantum' */
4338 mzquantum_used = TRUE;
4339 }
4340# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004341# ifdef __EMX__
4342 /* don't check for incoming chars if not in raw mode, because select()
4343 * always returns TRUE then (in some version of emx.dll) */
4344 if (curr_tmode != TMODE_RAW)
4345 return 0;
4346# endif
4347
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004348 if (towait >= 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004349 {
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004350 tv.tv_sec = towait / 1000;
4351 tv.tv_usec = (towait % 1000) * (1000000/1000);
4352 tvp = &tv;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004353 }
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004354 else
4355 tvp = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004356
4357 /*
4358 * Select on ready for reading and exceptional condition (end of file).
4359 */
4360 FD_ZERO(&rfds); /* calls bzero() on a sun */
4361 FD_ZERO(&efds);
4362 FD_SET(fd, &rfds);
4363# if !defined(__QNX__) && !defined(__CYGWIN32__)
4364 /* For QNX select() always returns 1 if this is set. Why? */
4365 FD_SET(fd, &efds);
4366# endif
4367 maxfd = fd;
4368
4369# ifdef FEAT_SNIFF
4370 if (want_sniff_request)
4371 {
4372 FD_SET(fd_from_sniff, &rfds);
4373 FD_SET(fd_from_sniff, &efds);
4374 if (maxfd < fd_from_sniff)
4375 maxfd = fd_from_sniff;
4376 }
4377# endif
4378# ifdef FEAT_XCLIPBOARD
4379 if (xterm_Shell != (Widget)0)
4380 {
4381 FD_SET(ConnectionNumber(xterm_dpy), &rfds);
4382 if (maxfd < ConnectionNumber(xterm_dpy))
4383 maxfd = ConnectionNumber(xterm_dpy);
4384 }
4385# endif
4386# ifdef FEAT_MOUSE_GPM
4387 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4388 {
4389 FD_SET(gpm_fd, &rfds);
4390 FD_SET(gpm_fd, &efds);
4391 if (maxfd < gpm_fd)
4392 maxfd = gpm_fd;
4393 }
4394# endif
4395# ifdef USE_XSMP
4396 if (xsmp_icefd != -1)
4397 {
4398 FD_SET(xsmp_icefd, &rfds);
4399 FD_SET(xsmp_icefd, &efds);
4400 if (maxfd < xsmp_icefd)
4401 maxfd = xsmp_icefd;
4402 }
4403# endif
4404
4405# ifdef OLD_VMS
4406 /* Old VMS as v6.2 and older have broken select(). It waits more than
4407 * required. Should not be used */
4408 ret = 0;
4409# else
Bram Moolenaar325b7a22004-07-05 15:58:32 +00004410 ret = select(maxfd + 1, &rfds, NULL, &efds, tvp);
4411# endif
4412# ifdef FEAT_MZSCHEME
4413 if (ret == 0 && mzquantum_used)
4414 /* loop if MzThreads must be scheduled and timeout occured */
4415 finished = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004416# endif
4417
4418# ifdef FEAT_SNIFF
4419 if (ret < 0 )
4420 sniff_disconnect(1);
4421 else if (ret > 0 && want_sniff_request)
4422 {
4423 if (FD_ISSET(fd_from_sniff, &efds))
4424 sniff_disconnect(1);
4425 if (FD_ISSET(fd_from_sniff, &rfds))
4426 sniff_request_waiting = 1;
4427 }
4428# endif
4429# ifdef FEAT_XCLIPBOARD
4430 if (ret > 0 && xterm_Shell != (Widget)0
4431 && FD_ISSET(ConnectionNumber(xterm_dpy), &rfds))
4432 {
4433 xterm_update(); /* Maybe we should hand out clipboard */
4434 /* continue looping when we only got the X event and the input
4435 * buffer is empty */
4436 if (--ret == 0 && !input_available())
4437 {
4438 /* Try again */
4439 finished = FALSE;
4440 }
4441 }
4442# endif
4443# ifdef FEAT_MOUSE_GPM
4444 if (ret > 0 && gpm_flag && check_for_gpm != NULL && gpm_fd >= 0)
4445 {
4446 if (FD_ISSET(gpm_fd, &efds))
4447 gpm_close();
4448 else if (FD_ISSET(gpm_fd, &rfds))
4449 *check_for_gpm = 1;
4450 }
4451# endif
4452# ifdef USE_XSMP
4453 if (ret > 0 && xsmp_icefd != -1)
4454 {
4455 if (FD_ISSET(xsmp_icefd, &efds))
4456 {
4457 if (p_verbose > 0)
4458 MSG(_("XSMP lost ICE connection"));
4459 xsmp_close();
4460 if (--ret == 0)
4461 finished = FALSE; /* keep going if event was only one */
4462 }
4463 else if (FD_ISSET(xsmp_icefd, &rfds))
4464 {
4465 busy = TRUE;
4466 xsmp_handle_requests();
4467 busy = FALSE;
4468 if (--ret == 0)
4469 finished = FALSE; /* keep going if event was only one */
4470 }
4471 }
4472# endif
4473
4474#endif /* HAVE_SELECT */
4475
4476#ifdef MAY_LOOP
4477 if (finished || msec == 0)
4478 break;
4479
4480 /* We're going to loop around again, find out for how long */
4481 if (msec > 0)
4482 {
4483# ifdef USE_START_TV
4484 struct timeval mtv;
4485
4486 /* Compute remaining wait time. */
4487 gettimeofday(&mtv, NULL);
4488 msec -= (mtv.tv_sec - start_tv.tv_sec) * 1000L
4489 + (mtv.tv_usec - start_tv.tv_usec) / 1000L;
4490# else
4491 /* Guess we got interrupted halfway. */
4492 msec = msec / 2;
4493# endif
4494 if (msec <= 0)
4495 break; /* waited long enough */
4496 }
4497#endif
4498 }
4499
4500 return (ret > 0);
4501}
4502
4503#ifndef VMS
4504
4505#ifndef NO_EXPANDPATH
4506 static int
4507pstrcmp(a, b)
4508 const void *a, *b;
4509{
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004510 return (pathcmp(*(char **)a, *(char **)b, -1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004511}
4512
4513/*
4514 * Recursively expand one path component into all matching files and/or
4515 * directories.
4516 * "path" has backslashes before chars that are not to be expanded, starting
4517 * at "path + wildoff".
4518 * Return the number of matches found.
4519 */
4520 int
4521mch_expandpath(gap, path, flags)
4522 garray_T *gap;
4523 char_u *path;
4524 int flags; /* EW_* flags */
4525{
4526 return unix_expandpath(gap, path, 0, flags);
4527}
4528
4529 static int
4530unix_expandpath(gap, path, wildoff, flags)
4531 garray_T *gap;
4532 char_u *path;
4533 int wildoff;
4534 int flags; /* EW_* flags */
4535{
4536 char_u *buf;
4537 char_u *path_end;
4538 char_u *p, *s, *e;
4539 int start_len, c;
4540 char_u *pat;
4541 DIR *dirp;
4542 regmatch_T regmatch;
4543 struct dirent *dp;
4544 int starts_with_dot;
4545 int matches;
4546 int len;
4547
4548 start_len = gap->ga_len;
4549 buf = alloc(STRLEN(path) + BASENAMELEN + 5);/* make room for file name */
4550 if (buf == NULL)
4551 return 0;
4552
4553/*
4554 * Find the first part in the path name that contains a wildcard.
4555 * Copy it into buf, including the preceding characters.
4556 */
4557 p = buf;
4558 s = buf;
4559 e = NULL;
4560 path_end = path;
4561 while (*path_end != NUL)
4562 {
4563 /* May ignore a wildcard that has a backslash before it; it will
4564 * be removed by rem_backslash() or file_pat_to_reg_pat() below. */
4565 if (path_end >= path + wildoff && rem_backslash(path_end))
4566 *p++ = *path_end++;
4567 else if (*path_end == '/')
4568 {
4569 if (e != NULL)
4570 break;
4571 s = p + 1;
4572 }
4573 else if (path_end >= path + wildoff
4574 && vim_strchr((char_u *)"*?[{~$", *path_end) != NULL)
4575 e = p;
4576#ifdef FEAT_MBYTE
4577 if (has_mbyte)
4578 {
4579 len = (*mb_ptr2len_check)(path_end);
4580 STRNCPY(p, path_end, len);
4581 p += len;
4582 path_end += len;
4583 }
4584 else
4585#endif
4586 *p++ = *path_end++;
4587 }
4588 e = p;
4589 *e = NUL;
4590
4591 /* now we have one wildcard component between s and e */
4592 /* Remove backslashes between "wildoff" and the start of the wildcard
4593 * component. */
4594 for (p = buf + wildoff; p < s; ++p)
4595 if (rem_backslash(p))
4596 {
4597 STRCPY(p, p + 1);
4598 --e;
4599 --s;
4600 }
4601
4602 /* convert the file pattern to a regexp pattern */
4603 starts_with_dot = (*s == '.');
4604 pat = file_pat_to_reg_pat(s, e, NULL, FALSE);
4605 if (pat == NULL)
4606 {
4607 vim_free(buf);
4608 return 0;
4609 }
4610
4611 /* compile the regexp into a program */
4612#ifdef MACOS_X /* Can/Should we use CASE_INSENSITIVE_FILENAME instead ?*/
4613 regmatch.rm_ic = TRUE; /* Behave like Terminal.app */
4614#else
4615 regmatch.rm_ic = FALSE; /* Don't ever ignore case */
4616#endif
4617 regmatch.regprog = vim_regcomp(pat, RE_MAGIC);
4618 vim_free(pat);
4619
4620 if (regmatch.regprog == NULL)
4621 {
4622 vim_free(buf);
4623 return 0;
4624 }
4625
4626 /* open the directory for scanning */
4627 c = *s;
4628 *s = NUL;
4629 dirp = opendir(*buf == NUL ? "." : (char *)buf);
4630 *s = c;
4631
4632 /* Find all matching entries */
4633 if (dirp != NULL)
4634 {
4635 for (;;)
4636 {
4637 dp = readdir(dirp);
4638 if (dp == NULL)
4639 break;
4640 if ((dp->d_name[0] != '.' || starts_with_dot)
4641 && vim_regexec(&regmatch, (char_u *)dp->d_name, (colnr_T)0))
4642 {
4643 STRCPY(s, dp->d_name);
4644 len = STRLEN(buf);
4645 STRCPY(buf + len, path_end);
4646 if (mch_has_exp_wildcard(path_end)) /* handle more wildcards */
4647 {
4648 /* need to expand another component of the path */
4649 /* remove backslashes for the remaining components only */
4650 (void)unix_expandpath(gap, buf, len + 1, flags);
4651 }
4652 else
4653 {
4654 /* no more wildcards, check if there is a match */
4655 /* remove backslashes for the remaining components only */
4656 if (*path_end != NUL)
4657 backslash_halve(buf + len + 1);
4658 if (mch_getperm(buf) >= 0) /* add existing file */
4659 addfile(gap, buf, flags);
4660 }
4661 }
4662 }
4663
4664 closedir(dirp);
4665 }
4666
4667 vim_free(buf);
4668 vim_free(regmatch.regprog);
4669
4670 matches = gap->ga_len - start_len;
4671 if (matches > 0)
4672 qsort(((char_u **)gap->ga_data) + start_len, matches,
4673 sizeof(char_u *), pstrcmp);
4674 return matches;
4675}
4676#endif
4677
4678/*
4679 * mch_expand_wildcards() - this code does wild-card pattern matching using
4680 * the shell
4681 *
4682 * return OK for success, FAIL for error (you may lose some memory) and put
4683 * an error message in *file.
4684 *
4685 * num_pat is number of input patterns
4686 * pat is array of pointers to input patterns
4687 * num_file is pointer to number of matched file names
4688 * file is pointer to array of pointers to matched file names
4689 */
4690
4691#ifndef SEEK_SET
4692# define SEEK_SET 0
4693#endif
4694#ifndef SEEK_END
4695# define SEEK_END 2
4696#endif
4697
4698/* ARGSUSED */
4699 int
4700mch_expand_wildcards(num_pat, pat, num_file, file, flags)
4701 int num_pat;
4702 char_u **pat;
4703 int *num_file;
4704 char_u ***file;
4705 int flags; /* EW_* flags */
4706{
4707 int i;
4708 size_t len;
4709 char_u *p;
4710 int dir;
4711#ifdef __EMX__
4712# define EXPL_ALLOC_INC 16
4713 char_u **expl_files;
4714 size_t files_alloced, files_free;
4715 char_u *buf;
4716 int has_wildcard;
4717
4718 *num_file = 0; /* default: no files found */
4719 files_alloced = EXPL_ALLOC_INC; /* how much space is allocated */
4720 files_free = EXPL_ALLOC_INC; /* how much space is not used */
4721 *file = (char_u **)alloc(sizeof(char_u **) * files_alloced);
4722 if (*file == NULL)
4723 return FAIL;
4724
4725 for (; num_pat > 0; num_pat--, pat++)
4726 {
4727 expl_files = NULL;
4728 if (vim_strchr(*pat, '$') || vim_strchr(*pat, '~'))
4729 /* expand environment var or home dir */
4730 buf = expand_env_save(*pat);
4731 else
4732 buf = vim_strsave(*pat);
4733 expl_files = NULL;
4734 has_wildcard = mch_has_exp_wildcard(buf); /* (still) wildcards in there? */
4735 if (has_wildcard) /* yes, so expand them */
4736 expl_files = (char_u **)_fnexplode(buf);
4737
4738 /*
4739 * return value of buf if no wildcards left,
4740 * OR if no match AND EW_NOTFOUND is set.
4741 */
4742 if ((!has_wildcard && ((flags & EW_NOTFOUND) || mch_getperm(buf) >= 0))
4743 || (expl_files == NULL && (flags & EW_NOTFOUND)))
4744 { /* simply save the current contents of *buf */
4745 expl_files = (char_u **)alloc(sizeof(char_u **) * 2);
4746 if (expl_files != NULL)
4747 {
4748 expl_files[0] = vim_strsave(buf);
4749 expl_files[1] = NULL;
4750 }
4751 }
4752 vim_free(buf);
4753
4754 /*
4755 * Count number of names resulting from expansion,
4756 * At the same time add a backslash to the end of names that happen to
4757 * be directories, and replace slashes with backslashes.
4758 */
4759 if (expl_files)
4760 {
4761 for (i = 0; (p = expl_files[i]) != NULL; i++)
4762 {
4763 dir = mch_isdir(p);
4764 /* If we don't want dirs and this is one, skip it */
4765 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
4766 continue;
4767
4768 if (--files_free == 0)
4769 {
4770 /* need more room in table of pointers */
4771 files_alloced += EXPL_ALLOC_INC;
4772 *file = (char_u **)vim_realloc(*file,
4773 sizeof(char_u **) * files_alloced);
4774 if (*file == NULL)
4775 {
4776 EMSG(_(e_outofmem));
4777 *num_file = 0;
4778 return FAIL;
4779 }
4780 files_free = EXPL_ALLOC_INC;
4781 }
4782 slash_adjust(p);
4783 if (dir)
4784 {
4785 /* For a directory we add a '/', unless it's already
4786 * there. */
4787 len = STRLEN(p);
4788 if (((*file)[*num_file] = alloc(len + 2)) != NULL)
4789 {
4790 STRCPY((*file)[*num_file], p);
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004791 if (!after_pathsep((*file)[*num_file] + len))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004792 {
4793 (*file)[*num_file][len] = psepc;
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00004794 (*file)[*num_file][len + 1] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004795 }
4796 }
4797 }
4798 else
4799 {
4800 (*file)[*num_file] = vim_strsave(p);
4801 }
4802
4803 /*
4804 * Error message already given by either alloc or vim_strsave.
4805 * Should return FAIL, but returning OK works also.
4806 */
4807 if ((*file)[*num_file] == NULL)
4808 break;
4809 (*num_file)++;
4810 }
4811 _fnexplodefree((char **)expl_files);
4812 }
4813 }
4814 return OK;
4815
4816#else /* __EMX__ */
4817
4818 int j;
4819 char_u *tempname;
4820 char_u *command;
4821 FILE *fd;
4822 char_u *buffer;
4823#define STYLE_ECHO 0 /* use "echo" to expand */
4824#define STYLE_GLOB 1 /* use "glob" to expand, for csh */
4825#define STYLE_PRINT 2 /* use "print -N" to expand, for zsh */
4826#define STYLE_BT 3 /* `cmd` expansion, execute the pattern directly */
4827 int shell_style = STYLE_ECHO;
4828 int check_spaces;
4829 static int did_find_nul = FALSE;
4830 int ampersent = FALSE;
4831
4832 *num_file = 0; /* default: no files found */
4833 *file = NULL;
4834
4835 /*
4836 * If there are no wildcards, just copy the names to allocated memory.
4837 * Saves a lot of time, because we don't have to start a new shell.
4838 */
4839 if (!have_wildcard(num_pat, pat))
4840 return save_patterns(num_pat, pat, num_file, file);
4841
4842 /*
4843 * Don't allow the use of backticks in secure and restricted mode.
4844 */
4845 if (secure || restricted)
4846 for (i = 0; i < num_pat; ++i)
4847 if (vim_strchr(pat[i], '`') != NULL
4848 && (check_restricted() || check_secure()))
4849 return FAIL;
4850
4851 /*
4852 * get a name for the temp file
4853 */
4854 if ((tempname = vim_tempname('o')) == NULL)
4855 {
4856 EMSG(_(e_notmp));
4857 return FAIL;
4858 }
4859
4860 /*
4861 * Let the shell expand the patterns and write the result into the temp
4862 * file. if expanding `cmd` execute it directly.
4863 * If we use csh, glob will work better than echo.
4864 * If we use zsh, print -N will work better than glob.
4865 */
4866 if (num_pat == 1 && *pat[0] == '`'
4867 && (len = STRLEN(pat[0])) > 2
4868 && *(pat[0] + len - 1) == '`')
4869 shell_style = STYLE_BT;
4870 else if ((len = STRLEN(p_sh)) >= 3)
4871 {
4872 if (STRCMP(p_sh + len - 3, "csh") == 0)
4873 shell_style = STYLE_GLOB;
4874 else if (STRCMP(p_sh + len - 3, "zsh") == 0)
4875 shell_style = STYLE_PRINT;
4876 }
4877
4878 /* "unset nonomatch; print -N >" plus two is 29 */
4879 len = STRLEN(tempname) + 29;
4880 for (i = 0; i < num_pat; ++i) /* count the length of the patterns */
4881 len += STRLEN(pat[i]) + 3; /* add space and two quotes */
4882 command = alloc(len);
4883 if (command == NULL)
4884 {
4885 /* out of memory */
4886 vim_free(tempname);
4887 return FAIL;
4888 }
4889
4890 /*
4891 * Build the shell command:
4892 * - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell
4893 * recognizes this).
4894 * - Add the shell command to print the expanded names.
4895 * - Add the temp file name.
4896 * - Add the file name patterns.
4897 */
4898 if (shell_style == STYLE_BT)
4899 {
4900 STRCPY(command, pat[0] + 1); /* exclude first backtick */
4901 p = command + STRLEN(command) - 1;
4902 *p = ' '; /* remove last backtick */
4903 while (p > command && vim_iswhite(*p))
4904 --p;
4905 if (*p == '&') /* remove trailing '&' */
4906 {
4907 ampersent = TRUE;
4908 *p = ' ';
4909 }
4910 STRCAT(command, ">");
4911 }
4912 else
4913 {
4914 if (flags & EW_NOTFOUND)
4915 STRCPY(command, "set nonomatch; ");
4916 else
4917 STRCPY(command, "unset nonomatch; ");
4918 if (shell_style == STYLE_GLOB)
4919 STRCAT(command, "glob >");
4920 else if (shell_style == STYLE_PRINT)
4921 STRCAT(command, "print -N >");
4922 else
4923 STRCAT(command, "echo >");
4924 }
4925 STRCAT(command, tempname);
4926 if (shell_style != STYLE_BT)
4927 for (i = 0; i < num_pat; ++i)
4928 {
4929 /* When using system() always add extra quotes, because the shell
4930 * is started twice. Otherwise only put quotes around spaces and
4931 * single quotes. */
4932#ifdef USE_SYSTEM
4933 STRCAT(command, " \"");
4934 STRCAT(command, pat[i]);
4935 STRCAT(command, "\"");
4936#else
4937 p = command + STRLEN(command);
4938 *p++ = ' ';
4939 for (j = 0; pat[i][j] != NUL; )
4940 if (vim_strchr((char_u *)" '", pat[i][j]) != NULL)
4941 {
4942 *p++ = '"';
4943 while (pat[i][j] != NUL
4944 && vim_strchr((char_u *)" '", pat[i][j]) != NULL)
4945 *p++ = pat[i][j++];
4946 *p++ = '"';
4947 }
4948 else
4949 *p++ = pat[i][j++];
4950 *p = NUL;
4951#endif
4952 }
4953 if (flags & EW_SILENT)
4954 show_shell_mess = FALSE;
4955 if (ampersent)
4956 STRCAT(command, "&"); /* put the '&' back after the
4957 redirection */
4958
4959 /*
4960 * Using zsh -G: If a pattern has no matches, it is just deleted from
4961 * the argument list, otherwise zsh gives an error message and doesn't
4962 * expand any other pattern.
4963 */
4964 if (shell_style == STYLE_PRINT)
4965 extra_shell_arg = (char_u *)"-G"; /* Use zsh NULL_GLOB option */
4966
4967 /*
4968 * If we use -f then shell variables set in .cshrc won't get expanded.
4969 * vi can do it, so we will too, but it is only necessary if there is a "$"
4970 * in one of the patterns, otherwise we can still use the fast option.
4971 */
4972 else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat))
4973 extra_shell_arg = (char_u *)"-f"; /* Use csh fast option */
4974
4975 /*
4976 * execute the shell command
4977 */
4978 i = call_shell(command, SHELL_EXPAND | SHELL_SILENT);
4979
4980 /* When running in the background, give it some time to create the temp
4981 * file, but don't wait for it to finish. */
4982 if (ampersent)
4983 mch_delay(10L, TRUE);
4984
4985 extra_shell_arg = NULL; /* cleanup */
4986 show_shell_mess = TRUE;
4987 vim_free(command);
4988
4989 if (i) /* mch_call_shell() failed */
4990 {
4991 mch_remove(tempname);
4992 vim_free(tempname);
4993 /*
4994 * With interactive completion, the error message is not printed.
4995 * However with USE_SYSTEM, I don't know how to turn off error messages
4996 * from the shell, so screen may still get messed up -- webb.
4997 */
4998#ifndef USE_SYSTEM
4999 if (!(flags & EW_SILENT))
5000#endif
5001 {
5002 redraw_later_clear(); /* probably messed up screen */
5003 msg_putchar('\n'); /* clear bottom line quickly */
5004 cmdline_row = Rows - 1; /* continue on last line */
5005#ifdef USE_SYSTEM
5006 if (!(flags & EW_SILENT))
5007#endif
5008 {
5009 MSG(_(e_wildexpand));
5010 msg_start(); /* don't overwrite this message */
5011 }
5012 }
5013 /* If a `cmd` expansion failed, don't list `cmd` as a match, even when
5014 * EW_NOTFOUND is given */
5015 if (shell_style == STYLE_BT)
5016 return FAIL;
5017 goto notfound;
5018 }
5019
5020 /*
5021 * read the names from the file into memory
5022 */
5023 fd = fopen((char *)tempname, READBIN);
5024 if (fd == NULL)
5025 {
5026 /* Something went wrong, perhaps a file name with a special char. */
5027 if (!(flags & EW_SILENT))
5028 {
5029 MSG(_(e_wildexpand));
5030 msg_start(); /* don't overwrite this message */
5031 }
5032 vim_free(tempname);
5033 goto notfound;
5034 }
5035 fseek(fd, 0L, SEEK_END);
5036 len = ftell(fd); /* get size of temp file */
5037 fseek(fd, 0L, SEEK_SET);
5038 buffer = alloc(len + 1);
5039 if (buffer == NULL)
5040 {
5041 /* out of memory */
5042 mch_remove(tempname);
5043 vim_free(tempname);
5044 fclose(fd);
5045 return FAIL;
5046 }
5047 i = fread((char *)buffer, 1, len, fd);
5048 fclose(fd);
5049 mch_remove(tempname);
5050 if (i != len)
5051 {
5052 /* unexpected read error */
5053 EMSG2(_(e_notread), tempname);
5054 vim_free(tempname);
5055 vim_free(buffer);
5056 return FAIL;
5057 }
5058 vim_free(tempname);
5059
5060#if defined(__CYGWIN__) || defined(__CYGWIN32__)
5061 /* Translate <CR><NL> into <NL>. Caution, buffer may contain NUL. */
5062 p = buffer;
5063 for (i = 0; i < len; ++i)
5064 if (!(buffer[i] == CAR && buffer[i + 1] == NL))
5065 *p++ = buffer[i];
5066 len = p - buffer;
5067# endif
5068
5069
5070 /* file names are separated with Space */
5071 if (shell_style == STYLE_ECHO)
5072 {
5073 buffer[len] = '\n'; /* make sure the buffer ends in NL */
5074 p = buffer;
5075 for (i = 0; *p != '\n'; ++i) /* count number of entries */
5076 {
5077 while (*p != ' ' && *p != '\n')
5078 ++p;
5079 p = skipwhite(p); /* skip to next entry */
5080 }
5081 }
5082 /* file names are separated with NL */
5083 else if (shell_style == STYLE_BT)
5084 {
5085 buffer[len] = NUL; /* make sure the buffer ends in NUL */
5086 p = buffer;
5087 for (i = 0; *p != NUL; ++i) /* count number of entries */
5088 {
5089 while (*p != '\n' && *p != NUL)
5090 ++p;
5091 if (*p != NUL)
5092 ++p;
5093 p = skipwhite(p); /* skip leading white space */
5094 }
5095 }
5096 /* file names are separated with NUL */
5097 else
5098 {
5099 /*
5100 * Some versions of zsh use spaces instead of NULs to separate
5101 * results. Only do this when there is no NUL before the end of the
5102 * buffer, otherwise we would never be able to use file names with
5103 * embedded spaces when zsh does use NULs.
5104 * When we found a NUL once, we know zsh is OK, set did_find_nul and
5105 * don't check for spaces again.
5106 */
5107 check_spaces = FALSE;
5108 if (shell_style == STYLE_PRINT && !did_find_nul)
5109 {
5110 /* If there is a NUL, set did_find_nul, else set check_spaces */
5111 if (len && (int)STRLEN(buffer) < len - 1)
5112 did_find_nul = TRUE;
5113 else
5114 check_spaces = TRUE;
5115 }
5116
5117 /*
5118 * Make sure the buffer ends with a NUL. For STYLE_PRINT there
5119 * already is one, for STYLE_GLOB it needs to be added.
5120 */
5121 if (len && buffer[len - 1] == NUL)
5122 --len;
5123 else
5124 buffer[len] = NUL;
5125 i = 0;
5126 for (p = buffer; p < buffer + len; ++p)
5127 if (*p == NUL || (*p == ' ' && check_spaces)) /* count entry */
5128 {
5129 ++i;
5130 *p = NUL;
5131 }
5132 if (len)
5133 ++i; /* count last entry */
5134 }
5135 if (i == 0)
5136 {
5137 /*
5138 * Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I".
5139 * /bin/sh will happily expand it to nothing rather than returning an
5140 * error; and hey, it's good to check anyway -- webb.
5141 */
5142 vim_free(buffer);
5143 goto notfound;
5144 }
5145 *num_file = i;
5146 *file = (char_u **)alloc(sizeof(char_u *) * i);
5147 if (*file == NULL)
5148 {
5149 /* out of memory */
5150 vim_free(buffer);
5151 return FAIL;
5152 }
5153
5154 /*
5155 * Isolate the individual file names.
5156 */
5157 p = buffer;
5158 for (i = 0; i < *num_file; ++i)
5159 {
5160 (*file)[i] = p;
5161 /* Space or NL separates */
5162 if (shell_style == STYLE_ECHO || shell_style == STYLE_BT)
5163 {
5164 while (!(shell_style == STYLE_ECHO && *p == ' ') && *p != '\n')
5165 ++p;
5166 if (p == buffer + len) /* last entry */
5167 *p = NUL;
5168 else
5169 {
5170 *p++ = NUL;
5171 p = skipwhite(p); /* skip to next entry */
5172 }
5173 }
5174 else /* NUL separates */
5175 {
5176 while (*p && p < buffer + len) /* skip entry */
5177 ++p;
5178 ++p; /* skip NUL */
5179 }
5180 }
5181
5182 /*
5183 * Move the file names to allocated memory.
5184 */
5185 for (j = 0, i = 0; i < *num_file; ++i)
5186 {
5187 /* Require the files to exist. Helps when using /bin/sh */
5188 if (!(flags & EW_NOTFOUND) && mch_getperm((*file)[i]) < 0)
5189 continue;
5190
5191 /* check if this entry should be included */
5192 dir = (mch_isdir((*file)[i]));
5193 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5194 continue;
5195
5196 p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir));
5197 if (p)
5198 {
5199 STRCPY(p, (*file)[i]);
5200 if (dir)
5201 STRCAT(p, "/"); /* add '/' to a directory name */
5202 (*file)[j++] = p;
5203 }
5204 }
5205 vim_free(buffer);
5206 *num_file = j;
5207
5208 if (*num_file == 0) /* rejected all entries */
5209 {
5210 vim_free(*file);
5211 *file = NULL;
5212 goto notfound;
5213 }
5214
5215 return OK;
5216
5217notfound:
5218 if (flags & EW_NOTFOUND)
5219 return save_patterns(num_pat, pat, num_file, file);
5220 return FAIL;
5221
5222#endif /* __EMX__ */
5223}
5224
5225#endif /* VMS */
5226
5227#ifndef __EMX__
5228 static int
5229save_patterns(num_pat, pat, num_file, file)
5230 int num_pat;
5231 char_u **pat;
5232 int *num_file;
5233 char_u ***file;
5234{
5235 int i;
5236
5237 *file = (char_u **)alloc(num_pat * sizeof(char_u *));
5238 if (*file == NULL)
5239 return FAIL;
5240 for (i = 0; i < num_pat; i++)
5241 (*file)[i] = vim_strsave(pat[i]);
5242 *num_file = num_pat;
5243 return OK;
5244}
5245#endif
5246
5247
5248/*
5249 * Return TRUE if the string "p" contains a wildcard that mch_expandpath() can
5250 * expand.
5251 */
5252 int
5253mch_has_exp_wildcard(p)
5254 char_u *p;
5255{
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00005256 for ( ; *p; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005257 {
5258#ifndef OS2
5259 if (*p == '\\' && p[1] != NUL)
5260 ++p;
5261 else
5262#endif
5263 if (vim_strchr((char_u *)
5264#ifdef VMS
5265 "*?%"
5266#else
5267# ifdef OS2
5268 "*?"
5269# else
5270 "*?[{'"
5271# endif
5272#endif
5273 , *p) != NULL)
5274 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005275 }
5276 return FALSE;
5277}
5278
5279/*
5280 * Return TRUE if the string "p" contains a wildcard.
5281 * Don't recognize '~' at the end as a wildcard.
5282 */
5283 int
5284mch_has_wildcard(p)
5285 char_u *p;
5286{
Bram Moolenaar1cd871b2004-12-19 22:46:22 +00005287 for ( ; *p; mb_ptr_adv(p))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005288 {
5289#ifndef OS2
5290 if (*p == '\\' && p[1] != NUL)
5291 ++p;
5292 else
5293#endif
5294 if (vim_strchr((char_u *)
5295#ifdef VMS
5296 "*?%$"
5297#else
5298# ifdef OS2
5299# ifdef VIM_BACKTICK
5300 "*?$`"
5301# else
5302 "*?$"
5303# endif
5304# else
5305 "*?[{`'$"
5306# endif
5307#endif
5308 , *p) != NULL
5309 || (*p == '~' && p[1] != NUL))
5310 return TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005311 }
5312 return FALSE;
5313}
5314
5315#ifndef __EMX__
5316 static int
5317have_wildcard(num, file)
5318 int num;
5319 char_u **file;
5320{
5321 int i;
5322
5323 for (i = 0; i < num; i++)
5324 if (mch_has_wildcard(file[i]))
5325 return 1;
5326 return 0;
5327}
5328
5329 static int
5330have_dollars(num, file)
5331 int num;
5332 char_u **file;
5333{
5334 int i;
5335
5336 for (i = 0; i < num; i++)
5337 if (vim_strchr(file[i], '$') != NULL)
5338 return TRUE;
5339 return FALSE;
5340}
5341#endif /* ifndef __EMX__ */
5342
5343#ifndef HAVE_RENAME
5344/*
5345 * Scaled-down version of rename(), which is missing in Xenix.
5346 * This version can only move regular files and will fail if the
5347 * destination exists.
5348 */
5349 int
5350mch_rename(src, dest)
5351 const char *src, *dest;
5352{
5353 struct stat st;
5354
5355 if (stat(dest, &st) >= 0) /* fail if destination exists */
5356 return -1;
5357 if (link(src, dest) != 0) /* link file to new name */
5358 return -1;
5359 if (mch_remove(src) == 0) /* delete link to old name */
5360 return 0;
5361 return -1;
5362}
5363#endif /* !HAVE_RENAME */
5364
5365#ifdef FEAT_MOUSE_GPM
5366/*
5367 * Initializes connection with gpm (if it isn't already opened)
5368 * Return 1 if succeeded (or connection already opened), 0 if failed
5369 */
5370 static int
5371gpm_open()
5372{
5373 static Gpm_Connect gpm_connect; /* Must it be kept till closing ? */
5374
5375 if (!gpm_flag)
5376 {
5377 gpm_connect.eventMask = (GPM_UP | GPM_DRAG | GPM_DOWN);
5378 gpm_connect.defaultMask = ~GPM_HARD;
5379 /* Default handling for mouse move*/
5380 gpm_connect.minMod = 0; /* Handle any modifier keys */
5381 gpm_connect.maxMod = 0xffff;
5382 if (Gpm_Open(&gpm_connect, 0) > 0)
5383 {
5384 /* gpm library tries to handling TSTP causes
5385 * problems. Anyways, we close connection to Gpm whenever
5386 * we are going to suspend or starting an external process
5387 * so we should'nt have problem with this
5388 */
5389 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
5390 return 1; /* succeed */
5391 }
5392 if (gpm_fd == -2)
5393 Gpm_Close(); /* We don't want to talk to xterm via gpm */
5394 return 0;
5395 }
5396 return 1; /* already open */
5397}
5398
5399/*
5400 * Closes connection to gpm
5401 * returns non-zero if connection succesfully closed
5402 */
5403 static void
5404gpm_close()
5405{
5406 if (gpm_flag && gpm_fd >= 0) /* if Open */
5407 Gpm_Close();
5408}
5409
5410/* Reads gpm event and adds special keys to input buf. Returns length of
5411 * generated key sequence.
5412 * This function is made after gui_send_mouse_event
5413 */
5414 static int
5415mch_gpm_process()
5416{
5417 int button;
5418 static Gpm_Event gpm_event;
5419 char_u string[6];
5420 int_u vim_modifiers;
5421 int row,col;
5422 unsigned char buttons_mask;
5423 unsigned char gpm_modifiers;
5424 static unsigned char old_buttons = 0;
5425
5426 Gpm_GetEvent(&gpm_event);
5427
5428#ifdef FEAT_GUI
5429 /* Don't put events in the input queue now. */
5430 if (hold_gui_events)
5431 return 0;
5432#endif
5433
5434 row = gpm_event.y - 1;
5435 col = gpm_event.x - 1;
5436
5437 string[0] = ESC; /* Our termcode */
5438 string[1] = 'M';
5439 string[2] = 'G';
5440 switch (GPM_BARE_EVENTS(gpm_event.type))
5441 {
5442 case GPM_DRAG:
5443 string[3] = MOUSE_DRAG;
5444 break;
5445 case GPM_DOWN:
5446 buttons_mask = gpm_event.buttons & ~old_buttons;
5447 old_buttons = gpm_event.buttons;
5448 switch (buttons_mask)
5449 {
5450 case GPM_B_LEFT:
5451 button = MOUSE_LEFT;
5452 break;
5453 case GPM_B_MIDDLE:
5454 button = MOUSE_MIDDLE;
5455 break;
5456 case GPM_B_RIGHT:
5457 button = MOUSE_RIGHT;
5458 break;
5459 default:
5460 return 0;
5461 /*Don't know what to do. Can more than one button be
5462 * reported in one event? */
5463 }
5464 string[3] = (char_u)(button | 0x20);
5465 SET_NUM_MOUSE_CLICKS(string[3], gpm_event.clicks + 1);
5466 break;
5467 case GPM_UP:
5468 string[3] = MOUSE_RELEASE;
5469 old_buttons &= ~gpm_event.buttons;
5470 break;
5471 default:
5472 return 0;
5473 }
5474 /*This code is based on gui_x11_mouse_cb in gui_x11.c */
5475 gpm_modifiers = gpm_event.modifiers;
5476 vim_modifiers = 0x0;
5477 /* I ignore capslock stats. Aren't we all just hate capslock mixing with
5478 * Vim commands ? Besides, gpm_event.modifiers is unsigned char, and
5479 * K_CAPSSHIFT is defined 8, so it probably isn't even reported
5480 */
5481 if (gpm_modifiers & ((1 << KG_SHIFT) | (1 << KG_SHIFTR) | (1 << KG_SHIFTL)))
5482 vim_modifiers |= MOUSE_SHIFT;
5483
5484 if (gpm_modifiers & ((1 << KG_CTRL) | (1 << KG_CTRLR) | (1 << KG_CTRLL)))
5485 vim_modifiers |= MOUSE_CTRL;
5486 if (gpm_modifiers & ((1 << KG_ALT) | (1 << KG_ALTGR)))
5487 vim_modifiers |= MOUSE_ALT;
5488 string[3] |= vim_modifiers;
5489 string[4] = (char_u)(col + ' ' + 1);
5490 string[5] = (char_u)(row + ' ' + 1);
5491 add_to_input_buf(string, 6);
5492 return 6;
5493}
5494#endif /* FEAT_MOUSE_GPM */
5495
5496#if defined(FEAT_LIBCALL) || defined(PROTO)
5497typedef char_u * (*STRPROCSTR)__ARGS((char_u *));
5498typedef char_u * (*INTPROCSTR)__ARGS((int));
5499typedef int (*STRPROCINT)__ARGS((char_u *));
5500typedef int (*INTPROCINT)__ARGS((int));
5501
5502/*
5503 * Call a DLL routine which takes either a string or int param
5504 * and returns an allocated string.
5505 */
5506 int
5507mch_libcall(libname, funcname, argstring, argint, string_result, number_result)
5508 char_u *libname;
5509 char_u *funcname;
5510 char_u *argstring; /* NULL when using a argint */
5511 int argint;
5512 char_u **string_result;/* NULL when using number_result */
5513 int *number_result;
5514{
5515# if defined(USE_DLOPEN)
5516 void *hinstLib;
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005517 char *dlerr = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005518# else
5519 shl_t hinstLib;
5520# endif
5521 STRPROCSTR ProcAdd;
5522 INTPROCSTR ProcAddI;
5523 char_u *retval_str = NULL;
5524 int retval_int = 0;
5525 int success = FALSE;
5526
5527 /* Get a handle to the DLL module. */
5528# if defined(USE_DLOPEN)
5529 hinstLib = dlopen((char *)libname, RTLD_LAZY
5530# ifdef RTLD_LOCAL
5531 | RTLD_LOCAL
5532# endif
5533 );
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005534 if (hinstLib == NULL)
5535 {
5536 /* "dlerr" must be used before dlclose() */
5537 dlerr = (char *)dlerror();
5538 if (dlerr != NULL)
5539 EMSG2(_("dlerror = \"%s\""), dlerr);
5540 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005541# else
5542 hinstLib = shl_load((const char*)libname, BIND_IMMEDIATE|BIND_VERBOSE, 0L);
5543# endif
5544
5545 /* If the handle is valid, try to get the function address. */
5546 if (hinstLib != NULL)
5547 {
5548# ifdef HAVE_SETJMP_H
5549 /*
5550 * Catch a crash when calling the library function. For example when
5551 * using a number where a string pointer is expected.
5552 */
5553 mch_startjmp();
5554 if (SETJMP(lc_jump_env) != 0)
5555 {
5556 success = FALSE;
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005557 dlerr = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005558 mch_didjmp();
5559 }
5560 else
5561# endif
5562 {
5563 retval_str = NULL;
5564 retval_int = 0;
5565
5566 if (argstring != NULL)
5567 {
5568# if defined(USE_DLOPEN)
5569 ProcAdd = (STRPROCSTR)dlsym(hinstLib, (const char *)funcname);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005570 dlerr = (char *)dlerror();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005571# else
5572 if (shl_findsym(&hinstLib, (const char *)funcname,
5573 TYPE_PROCEDURE, (void *)&ProcAdd) < 0)
5574 ProcAdd = NULL;
5575# endif
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005576 if ((success = (ProcAdd != NULL
5577# if defined(USE_DLOPEN)
5578 && dlerr == NULL
5579# endif
5580 )))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005581 {
5582 if (string_result == NULL)
5583 retval_int = ((STRPROCINT)ProcAdd)(argstring);
5584 else
5585 retval_str = (ProcAdd)(argstring);
5586 }
5587 }
5588 else
5589 {
5590# if defined(USE_DLOPEN)
5591 ProcAddI = (INTPROCSTR)dlsym(hinstLib, (const char *)funcname);
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005592 dlerr = (char *)dlerror();
Bram Moolenaar071d4272004-06-13 20:20:40 +00005593# else
5594 if (shl_findsym(&hinstLib, (const char *)funcname,
5595 TYPE_PROCEDURE, (void *)&ProcAddI) < 0)
5596 ProcAddI = NULL;
5597# endif
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005598 if ((success = (ProcAddI != NULL
5599# if defined(USE_DLOPEN)
5600 && dlerr == NULL
5601# endif
5602 )))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005603 {
5604 if (string_result == NULL)
5605 retval_int = ((INTPROCINT)ProcAddI)(argint);
5606 else
5607 retval_str = (ProcAddI)(argint);
5608 }
5609 }
5610
5611 /* Save the string before we free the library. */
5612 /* Assume that a "1" or "-1" result is an illegal pointer. */
5613 if (string_result == NULL)
5614 *number_result = retval_int;
5615 else if (retval_str != NULL
5616 && retval_str != (char_u *)1
5617 && retval_str != (char_u *)-1)
5618 *string_result = vim_strsave(retval_str);
5619 }
5620
5621# ifdef HAVE_SETJMP_H
5622 mch_endjmp();
5623# ifdef SIGHASARG
5624 if (lc_signal != 0)
5625 {
5626 int i;
5627
5628 /* try to find the name of this signal */
5629 for (i = 0; signal_info[i].sig != -1; i++)
5630 if (lc_signal == signal_info[i].sig)
5631 break;
5632 EMSG2("E368: got SIG%s in libcall()", signal_info[i].name);
5633 }
5634# endif
5635# endif
5636
Bram Moolenaar071d4272004-06-13 20:20:40 +00005637# if defined(USE_DLOPEN)
Bram Moolenaarcfbc5ee2004-07-02 15:38:35 +00005638 /* "dlerr" must be used before dlclose() */
5639 if (dlerr != NULL)
5640 EMSG2(_("dlerror = \"%s\""), dlerr);
5641
5642 /* Free the DLL module. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005643 (void)dlclose(hinstLib);
5644# else
5645 (void)shl_unload(hinstLib);
5646# endif
5647 }
5648
5649 if (!success)
5650 {
5651 EMSG2(_(e_libcall), funcname);
5652 return FAIL;
5653 }
5654
5655 return OK;
5656}
5657#endif
5658
5659#if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
5660static int xterm_trace = -1; /* default: disabled */
5661static int xterm_button;
5662
5663/*
5664 * Setup a dummy window for X selections in a terminal.
5665 */
5666 void
5667setup_term_clip()
5668{
5669 int z = 0;
5670 char *strp = "";
5671 Widget AppShell;
5672
5673 if (!x_connect_to_server())
5674 return;
5675
5676 open_app_context();
5677 if (app_context != NULL && xterm_Shell == (Widget)0)
5678 {
5679 int (*oldhandler)();
5680#if defined(HAVE_SETJMP_H)
5681 int (*oldIOhandler)();
5682#endif
5683# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
5684 struct timeval start_tv;
5685
5686 if (p_verbose > 0)
5687 gettimeofday(&start_tv, NULL);
5688# endif
5689
5690 /* Ignore X errors while opening the display */
5691 oldhandler = XSetErrorHandler(x_error_check);
5692
5693#if defined(HAVE_SETJMP_H)
5694 /* Ignore X IO errors while opening the display */
5695 oldIOhandler = XSetIOErrorHandler(x_IOerror_check);
5696 mch_startjmp();
5697 if (SETJMP(lc_jump_env) != 0)
5698 {
5699 mch_didjmp();
5700 xterm_dpy = NULL;
5701 }
5702 else
5703#endif
5704 {
5705 xterm_dpy = XtOpenDisplay(app_context, xterm_display,
5706 "vim_xterm", "Vim_xterm", NULL, 0, &z, &strp);
5707#if defined(HAVE_SETJMP_H)
5708 mch_endjmp();
5709#endif
5710 }
5711
5712#if defined(HAVE_SETJMP_H)
5713 /* Now handle X IO errors normally. */
5714 (void)XSetIOErrorHandler(oldIOhandler);
5715#endif
5716 /* Now handle X errors normally. */
5717 (void)XSetErrorHandler(oldhandler);
5718
5719 if (xterm_dpy == NULL)
5720 {
5721 if (p_verbose > 0)
5722 MSG(_("Opening the X display failed"));
5723 return;
5724 }
5725
5726 /* Catch terminating error of the X server connection. */
5727 (void)XSetIOErrorHandler(x_IOerror_handler);
5728
5729# if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
5730 if (p_verbose > 0)
5731 xopen_message(&start_tv);
5732# endif
5733
5734 /* Create a Shell to make converters work. */
5735 AppShell = XtVaAppCreateShell("vim_xterm", "Vim_xterm",
5736 applicationShellWidgetClass, xterm_dpy,
5737 NULL);
5738 if (AppShell == (Widget)0)
5739 return;
5740 xterm_Shell = XtVaCreatePopupShell("VIM",
5741 topLevelShellWidgetClass, AppShell,
5742 XtNmappedWhenManaged, 0,
5743 XtNwidth, 1,
5744 XtNheight, 1,
5745 NULL);
5746 if (xterm_Shell == (Widget)0)
5747 return;
5748
5749 x11_setup_atoms(xterm_dpy);
5750 if (x11_display == NULL)
5751 x11_display = xterm_dpy;
5752
5753 XtRealizeWidget(xterm_Shell);
5754 XSync(xterm_dpy, False);
5755 xterm_update();
5756 }
5757 if (xterm_Shell != (Widget)0)
5758 {
5759 clip_init(TRUE);
5760 if (x11_window == 0 && (strp = getenv("WINDOWID")) != NULL)
5761 x11_window = (Window)atol(strp);
5762 /* Check if $WINDOWID is valid. */
5763 if (test_x11_window(xterm_dpy) == FAIL)
5764 x11_window = 0;
5765 if (x11_window != 0)
5766 xterm_trace = 0;
5767 }
5768}
5769
5770 void
5771start_xterm_trace(button)
5772 int button;
5773{
5774 if (x11_window == 0 || xterm_trace < 0 || xterm_Shell == (Widget)0)
5775 return;
5776 xterm_trace = 1;
5777 xterm_button = button;
5778 do_xterm_trace();
5779}
5780
5781
5782 void
5783stop_xterm_trace()
5784{
5785 if (xterm_trace < 0)
5786 return;
5787 xterm_trace = 0;
5788}
5789
5790/*
5791 * Query the xterm pointer and generate mouse termcodes if necessary
5792 * return TRUE if dragging is active, else FALSE
5793 */
5794 static int
5795do_xterm_trace()
5796{
5797 Window root, child;
5798 int root_x, root_y;
5799 int win_x, win_y;
5800 int row, col;
5801 int_u mask_return;
5802 char_u buf[50];
5803 char_u *strp;
5804 long got_hints;
5805 static char_u *mouse_code;
5806 static char_u mouse_name[2] = {KS_MOUSE, KE_FILLER};
5807 static int prev_row = 0, prev_col = 0;
5808 static XSizeHints xterm_hints;
5809
5810 if (xterm_trace <= 0)
5811 return FALSE;
5812
5813 if (xterm_trace == 1)
5814 {
5815 /* Get the hints just before tracking starts. The font size might
5816 * have changed recently */
5817 XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints);
5818 if (!(got_hints & PResizeInc)
5819 || xterm_hints.width_inc <= 1
5820 || xterm_hints.height_inc <= 1)
5821 {
5822 xterm_trace = -1; /* Not enough data -- disable tracing */
5823 return FALSE;
5824 }
5825
5826 /* Rely on the same mouse code for the duration of this */
5827 mouse_code = find_termcode(mouse_name);
5828 prev_row = mouse_row;
5829 prev_row = mouse_col;
5830 xterm_trace = 2;
5831
5832 /* Find the offset of the chars, there might be a scrollbar on the
5833 * left of the window and/or a menu on the top (eterm etc.) */
5834 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
5835 &win_x, &win_y, &mask_return);
5836 xterm_hints.y = win_y - (xterm_hints.height_inc * mouse_row)
5837 - (xterm_hints.height_inc / 2);
5838 if (xterm_hints.y <= xterm_hints.height_inc / 2)
5839 xterm_hints.y = 2;
5840 xterm_hints.x = win_x - (xterm_hints.width_inc * mouse_col)
5841 - (xterm_hints.width_inc / 2);
5842 if (xterm_hints.x <= xterm_hints.width_inc / 2)
5843 xterm_hints.x = 2;
5844 return TRUE;
5845 }
5846 if (mouse_code == NULL)
5847 {
5848 xterm_trace = 0;
5849 return FALSE;
5850 }
5851
5852 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
5853 &win_x, &win_y, &mask_return);
5854
5855 row = check_row((win_y - xterm_hints.y) / xterm_hints.height_inc);
5856 col = check_col((win_x - xterm_hints.x) / xterm_hints.width_inc);
5857 if (row == prev_row && col == prev_col)
5858 return TRUE;
5859
5860 STRCPY(buf, mouse_code);
5861 strp = buf + STRLEN(buf);
5862 *strp++ = (xterm_button | MOUSE_DRAG) & ~0x20;
5863 *strp++ = (char_u)(col + ' ' + 1);
5864 *strp++ = (char_u)(row + ' ' + 1);
5865 *strp = 0;
5866 add_to_input_buf(buf, STRLEN(buf));
5867
5868 prev_row = row;
5869 prev_col = col;
5870 return TRUE;
5871}
5872
5873# if defined(FEAT_GUI) || defined(PROTO)
5874/*
5875 * Destroy the display, window and app_context. Required for GTK.
5876 */
5877 void
5878clear_xterm_clip()
5879{
5880 if (xterm_Shell != (Widget)0)
5881 {
5882 XtDestroyWidget(xterm_Shell);
5883 xterm_Shell = (Widget)0;
5884 }
5885 if (xterm_dpy != NULL)
5886 {
5887#if 0
5888 /* Lesstif and Solaris crash here, lose some memory */
5889 XtCloseDisplay(xterm_dpy);
5890#endif
5891 if (x11_display == xterm_dpy)
5892 x11_display = NULL;
5893 xterm_dpy = NULL;
5894 }
5895#if 0
5896 if (app_context != (XtAppContext)NULL)
5897 {
5898 /* Lesstif and Solaris crash here, lose some memory */
5899 XtDestroyApplicationContext(app_context);
5900 app_context = (XtAppContext)NULL;
5901 }
5902#endif
5903}
5904# endif
5905
5906/*
5907 * Catch up with any queued X events. This may put keyboard input into the
5908 * input buffer, call resize call-backs, trigger timers etc. If there is
5909 * nothing in the X event queue (& no timers pending), then we return
5910 * immediately.
5911 */
5912 static void
5913xterm_update()
5914{
5915 XEvent event;
5916
5917 while (XtAppPending(app_context) && !vim_is_input_buf_full())
5918 {
5919 XtAppNextEvent(app_context, &event);
5920#ifdef FEAT_CLIENTSERVER
5921 {
5922 XPropertyEvent *e = (XPropertyEvent *)&event;
5923
5924 if (e->type == PropertyNotify && e->window == commWindow
5925 && e->atom == commProperty && e->state == PropertyNewValue)
5926 serverEventProc(xterm_dpy, &event);
5927 }
5928#endif
5929 XtDispatchEvent(&event);
5930 }
5931}
5932
5933 int
5934clip_xterm_own_selection(cbd)
5935 VimClipboard *cbd;
5936{
5937 if (xterm_Shell != (Widget)0)
5938 return clip_x11_own_selection(xterm_Shell, cbd);
5939 return FAIL;
5940}
5941
5942 void
5943clip_xterm_lose_selection(cbd)
5944 VimClipboard *cbd;
5945{
5946 if (xterm_Shell != (Widget)0)
5947 clip_x11_lose_selection(xterm_Shell, cbd);
5948}
5949
5950 void
5951clip_xterm_request_selection(cbd)
5952 VimClipboard *cbd;
5953{
5954 if (xterm_Shell != (Widget)0)
5955 clip_x11_request_selection(xterm_Shell, xterm_dpy, cbd);
5956}
5957
5958 void
5959clip_xterm_set_selection(cbd)
5960 VimClipboard *cbd;
5961{
5962 clip_x11_set_selection(cbd);
5963}
5964#endif
5965
5966
5967#if defined(USE_XSMP) || defined(PROTO)
5968/*
5969 * Code for X Session Management Protocol.
5970 */
5971static void xsmp_handle_save_yourself __ARGS((SmcConn smc_conn, SmPointer client_data, int save_type, Bool shutdown, int interact_style, Bool fast));
5972static void xsmp_die __ARGS((SmcConn smc_conn, SmPointer client_data));
5973static void xsmp_save_complete __ARGS((SmcConn smc_conn, SmPointer client_data));
5974static void xsmp_shutdown_cancelled __ARGS((SmcConn smc_conn, SmPointer client_data));
5975static void xsmp_ice_connection __ARGS((IceConn iceConn, IcePointer clientData, Bool opening, IcePointer *watchData));
5976
5977
5978# if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
5979static void xsmp_handle_interaction __ARGS((SmcConn smc_conn, SmPointer client_data));
5980
5981/*
5982 * This is our chance to ask the user if they want to save,
5983 * or abort the logout
5984 */
5985/*ARGSUSED*/
5986 static void
5987xsmp_handle_interaction(smc_conn, client_data)
5988 SmcConn smc_conn;
5989 SmPointer client_data;
5990{
5991 cmdmod_T save_cmdmod;
5992 int cancel_shutdown = False;
5993
5994 save_cmdmod = cmdmod;
5995 cmdmod.confirm = TRUE;
5996 if (check_changed_any(FALSE))
5997 /* Mustn't logout */
5998 cancel_shutdown = True;
5999 cmdmod = save_cmdmod;
6000 setcursor(); /* position cursor */
6001 out_flush();
6002
6003 /* Done interaction */
6004 SmcInteractDone(smc_conn, cancel_shutdown);
6005
6006 /* Finish off
6007 * Only end save-yourself here if we're not cancelling shutdown;
6008 * we'll get a cancelled callback later in which we'll end it.
6009 * Hopefully get around glitchy SMs (like GNOME-1)
6010 */
6011 if (!cancel_shutdown)
6012 {
6013 xsmp.save_yourself = False;
6014 SmcSaveYourselfDone(smc_conn, True);
6015 }
6016}
6017# endif
6018
6019/*
6020 * Callback that starts save-yourself.
6021 */
6022/*ARGSUSED*/
6023 static void
6024xsmp_handle_save_yourself(smc_conn, client_data, save_type,
6025 shutdown, interact_style, fast)
6026 SmcConn smc_conn;
6027 SmPointer client_data;
6028 int save_type;
6029 Bool shutdown;
6030 int interact_style;
6031 Bool fast;
6032{
6033 /* Handle already being in saveyourself */
6034 if (xsmp.save_yourself)
6035 SmcSaveYourselfDone(smc_conn, True);
6036 xsmp.save_yourself = True;
6037 xsmp.shutdown = shutdown;
6038
6039 /* First up, preserve all files */
6040 out_flush();
6041 ml_sync_all(FALSE, FALSE); /* preserve all swap files */
6042
6043 if (p_verbose > 0)
6044 MSG(_("XSMP handling save-yourself request"));
6045
6046# if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6047 /* Now see if we can ask about unsaved files */
6048 if (shutdown && !fast && gui.in_use)
6049 /* Need to interact with user, but need SM's permission */
6050 SmcInteractRequest(smc_conn, SmDialogError,
6051 xsmp_handle_interaction, client_data);
6052 else
6053# endif
6054 {
6055 /* Can stop the cycle here */
6056 SmcSaveYourselfDone(smc_conn, True);
6057 xsmp.save_yourself = False;
6058 }
6059}
6060
6061
6062/*
6063 * Callback to warn us of imminent death.
6064 */
6065/*ARGSUSED*/
6066 static void
6067xsmp_die(smc_conn, client_data)
6068 SmcConn smc_conn;
6069 SmPointer client_data;
6070{
6071 xsmp_close();
6072
6073 /* quit quickly leaving swapfiles for modified buffers behind */
6074 getout_preserve_modified(0);
6075}
6076
6077
6078/*
6079 * Callback to tell us that save-yourself has completed.
6080 */
6081/*ARGSUSED*/
6082 static void
6083xsmp_save_complete(smc_conn, client_data)
6084 SmcConn smc_conn;
6085 SmPointer client_data;
6086{
6087 xsmp.save_yourself = False;
6088}
6089
6090
6091/*
6092 * Callback to tell us that an instigated shutdown was cancelled
6093 * (maybe even by us)
6094 */
6095/*ARGSUSED*/
6096 static void
6097xsmp_shutdown_cancelled(smc_conn, client_data)
6098 SmcConn smc_conn;
6099 SmPointer client_data;
6100{
6101 if (xsmp.save_yourself)
6102 SmcSaveYourselfDone(smc_conn, True);
6103 xsmp.save_yourself = False;
6104 xsmp.shutdown = False;
6105}
6106
6107
6108/*
6109 * Callback to tell us that a new ICE connection has been established.
6110 */
6111/*ARGSUSED*/
6112 static void
6113xsmp_ice_connection(iceConn, clientData, opening, watchData)
6114 IceConn iceConn;
6115 IcePointer clientData;
6116 Bool opening;
6117 IcePointer *watchData;
6118{
6119 /* Intercept creation of ICE connection fd */
6120 if (opening)
6121 {
6122 xsmp_icefd = IceConnectionNumber(iceConn);
6123 IceRemoveConnectionWatch(xsmp_ice_connection, NULL);
6124 }
6125}
6126
6127
6128/* Handle any ICE processing that's required; return FAIL if SM lost */
6129 int
6130xsmp_handle_requests()
6131{
6132 Bool rep;
6133
6134 if (IceProcessMessages(xsmp.iceconn, NULL, &rep)
6135 == IceProcessMessagesIOError)
6136 {
6137 /* Lost ICE */
6138 if (p_verbose > 0)
6139 MSG(_("XSMP lost ICE connection"));
6140 xsmp_close();
6141 return FAIL;
6142 }
6143 else
6144 return OK;
6145}
6146
6147static int dummy;
6148
6149/* Set up X Session Management Protocol */
6150 void
6151xsmp_init(void)
6152{
6153 char errorstring[80];
6154 char *clientid;
6155 SmcCallbacks smcallbacks;
6156#if 0
6157 SmPropValue smname;
6158 SmProp smnameprop;
6159 SmProp *smprops[1];
6160#endif
6161
6162 if (p_verbose > 0)
6163 MSG(_("XSMP opening connection"));
6164
6165 xsmp.save_yourself = xsmp.shutdown = False;
6166
6167 /* Set up SM callbacks - must have all, even if they're not used */
6168 smcallbacks.save_yourself.callback = xsmp_handle_save_yourself;
6169 smcallbacks.save_yourself.client_data = NULL;
6170 smcallbacks.die.callback = xsmp_die;
6171 smcallbacks.die.client_data = NULL;
6172 smcallbacks.save_complete.callback = xsmp_save_complete;
6173 smcallbacks.save_complete.client_data = NULL;
6174 smcallbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
6175 smcallbacks.shutdown_cancelled.client_data = NULL;
6176
6177 /* Set up a watch on ICE connection creations. The "dummy" argument is
6178 * apparently required for FreeBSD (we get a BUS error when using NULL). */
6179 if (IceAddConnectionWatch(xsmp_ice_connection, &dummy) == 0)
6180 {
6181 if (p_verbose > 0)
6182 MSG(_("XSMP ICE connection watch failed"));
6183 return;
6184 }
6185
6186 /* Create an SM connection */
6187 xsmp.smcconn = SmcOpenConnection(
6188 NULL,
6189 NULL,
6190 SmProtoMajor,
6191 SmProtoMinor,
6192 SmcSaveYourselfProcMask | SmcDieProcMask
6193 | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
6194 &smcallbacks,
6195 NULL,
6196 &clientid,
6197 sizeof(errorstring),
6198 errorstring);
6199 if (xsmp.smcconn == NULL)
6200 {
6201 char errorreport[132];
6202 sprintf(errorreport, _("XSMP SmcOpenConnection failed: %s"),
6203 errorstring);
6204 if (p_verbose > 0)
6205 MSG(errorreport);
6206 return;
6207 }
6208 xsmp.iceconn = SmcGetIceConnection(xsmp.smcconn);
6209
6210#if 0
6211 /* ID ourselves */
6212 smname.value = "vim";
6213 smname.length = 3;
6214 smnameprop.name = "SmProgram";
6215 smnameprop.type = "SmARRAY8";
6216 smnameprop.num_vals = 1;
6217 smnameprop.vals = &smname;
6218
6219 smprops[0] = &smnameprop;
6220 SmcSetProperties(xsmp.smcconn, 1, smprops);
6221#endif
6222}
6223
6224
6225/* Shut down XSMP comms. */
6226 void
6227xsmp_close()
6228{
6229 if (xsmp_icefd != -1)
6230 {
6231 SmcCloseConnection(xsmp.smcconn, 0, NULL);
6232 xsmp_icefd = -1;
6233 }
6234}
6235#endif /* USE_XSMP */
6236
6237
6238#ifdef EBCDIC
6239/* Translate character to its CTRL- value */
6240char CtrlTable[] =
6241{
6242/* 00 - 5E */
6243 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6244 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6245 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6246 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6247 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6248 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6249/* ^ */ 0x1E,
6250/* - */ 0x1F,
6251/* 61 - 6C */
6252 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6253/* _ */ 0x1F,
6254/* 6E - 80 */
6255 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6256/* a */ 0x01,
6257/* b */ 0x02,
6258/* c */ 0x03,
6259/* d */ 0x37,
6260/* e */ 0x2D,
6261/* f */ 0x2E,
6262/* g */ 0x2F,
6263/* h */ 0x16,
6264/* i */ 0x05,
6265/* 8A - 90 */
6266 0, 0, 0, 0, 0, 0, 0,
6267/* j */ 0x15,
6268/* k */ 0x0B,
6269/* l */ 0x0C,
6270/* m */ 0x0D,
6271/* n */ 0x0E,
6272/* o */ 0x0F,
6273/* p */ 0x10,
6274/* q */ 0x11,
6275/* r */ 0x12,
6276/* 9A - A1 */
6277 0, 0, 0, 0, 0, 0, 0, 0,
6278/* s */ 0x13,
6279/* t */ 0x3C,
6280/* u */ 0x3D,
6281/* v */ 0x32,
6282/* w */ 0x26,
6283/* x */ 0x18,
6284/* y */ 0x19,
6285/* z */ 0x3F,
6286/* AA - AC */
6287 0, 0, 0,
6288/* [ */ 0x27,
6289/* AE - BC */
6290 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6291/* ] */ 0x1D,
6292/* BE - C0 */ 0, 0, 0,
6293/* A */ 0x01,
6294/* B */ 0x02,
6295/* C */ 0x03,
6296/* D */ 0x37,
6297/* E */ 0x2D,
6298/* F */ 0x2E,
6299/* G */ 0x2F,
6300/* H */ 0x16,
6301/* I */ 0x05,
6302/* CA - D0 */ 0, 0, 0, 0, 0, 0, 0,
6303/* J */ 0x15,
6304/* K */ 0x0B,
6305/* L */ 0x0C,
6306/* M */ 0x0D,
6307/* N */ 0x0E,
6308/* O */ 0x0F,
6309/* P */ 0x10,
6310/* Q */ 0x11,
6311/* R */ 0x12,
6312/* DA - DF */ 0, 0, 0, 0, 0, 0,
6313/* \ */ 0x1C,
6314/* E1 */ 0,
6315/* S */ 0x13,
6316/* T */ 0x3C,
6317/* U */ 0x3D,
6318/* V */ 0x32,
6319/* W */ 0x26,
6320/* X */ 0x18,
6321/* Y */ 0x19,
6322/* Z */ 0x3F,
6323/* EA - FF*/ 0, 0, 0, 0, 0, 0,
6324 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6325};
6326
6327char MetaCharTable[]=
6328{/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6329 0, 0, 0, 0,'\\', 0,'F', 0,'W','M','N', 0, 0, 0, 0, 0,
6330 0, 0, 0, 0,']', 0, 0,'G', 0, 0,'R','O', 0, 0, 0, 0,
6331 '@','A','B','C','D','E', 0, 0,'H','I','J','K','L', 0, 0, 0,
6332 'P','Q', 0,'S','T','U','V', 0,'X','Y','Z','[', 0, 0,'^', 0
6333};
6334
6335
6336/* TODO: Use characters NOT numbers!!! */
6337char CtrlCharTable[]=
6338{/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6339 124,193,194,195, 0,201, 0, 0, 0, 0, 0,210,211,212,213,214,
6340 215,216,217,226, 0,209,200, 0,231,232, 0, 0,224,189, 95,109,
6341 0, 0, 0, 0, 0, 0,230,173, 0, 0, 0, 0, 0,197,198,199,
6342 0, 0,229, 0, 0, 0, 0,196, 0, 0, 0, 0,227,228, 0,233,
6343};
6344
6345
6346#endif