Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /ports/branches/tendra/editors/vim/files/os_unix.c – Rev 89

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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