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