Merged from the latest developing branch.
[MacVim.git] / src / os_unix.c
blob2d512b730f8077d3dc2497ee2d6c72fe5688551e
1 /* vi:set ts=8 sts=4 sw=4:
3 * VIM - Vi IMproved by Bram Moolenaar
4 * OS/2 port by Paul Slootman
5 * VMS merge by Zoltan Arpadffy
7 * Do ":help uganda" in Vim to read copying and usage conditions.
8 * Do ":help credits" in Vim to see a list of people who contributed.
9 * See README.txt for an overview of the Vim source code.
13 * os_unix.c -- code for all flavors of Unix (BSD, SYSV, SVR4, POSIX, ...)
14 * Also for OS/2, using the excellent EMX package!!!
15 * Also for BeOS and Atari MiNT.
17 * A lot of this file was originally written by Juergen Weigert and later
18 * changed beyond recognition.
22 * Some systems have a prototype for select() that has (int *) instead of
23 * (fd_set *), which is wrong. This define removes that prototype. We define
24 * our own prototype below.
25 * Don't use it for the Mac, it causes a warning for precompiled headers.
26 * TODO: use a configure check for precompiled headers?
28 #if !defined(__APPLE__) && !defined(__TANDEM)
29 # define select select_declared_wrong
30 #endif
32 #include "vim.h"
34 #ifdef FEAT_MZSCHEME
35 # include "if_mzsch.h"
36 #endif
38 #ifdef HAVE_FCNTL_H
39 # include <fcntl.h>
40 #endif
42 #include "os_unixx.h" /* unix includes for os_unix.c only */
44 #ifdef USE_XSMP
45 # include <X11/SM/SMlib.h>
46 #endif
49 * Use this prototype for select, some include files have a wrong prototype
51 #ifndef __TANDEM
52 # undef select
53 # ifdef __BEOS__
54 # define select beos_select
55 # endif
56 #endif
58 #ifdef __CYGWIN__
59 # ifndef WIN32
60 # include <sys/cygwin.h> /* for cygwin_conv_to_posix_path() */
61 # endif
62 #endif
64 #if defined(HAVE_SELECT)
65 extern int select __ARGS((int, fd_set *, fd_set *, fd_set *, struct timeval *));
66 #endif
68 #ifdef FEAT_MOUSE_GPM
69 # include <gpm.h>
70 /* <linux/keyboard.h> contains defines conflicting with "keymap.h",
71 * I just copied relevant defines here. A cleaner solution would be to put gpm
72 * code into separate file and include there linux/keyboard.h
74 /* #include <linux/keyboard.h> */
75 # define KG_SHIFT 0
76 # define KG_CTRL 2
77 # define KG_ALT 3
78 # define KG_ALTGR 1
79 # define KG_SHIFTL 4
80 # define KG_SHIFTR 5
81 # define KG_CTRLL 6
82 # define KG_CTRLR 7
83 # define KG_CAPSSHIFT 8
85 static void gpm_close __ARGS((void));
86 static int gpm_open __ARGS((void));
87 static int mch_gpm_process __ARGS((void));
88 #endif
91 * end of autoconf section. To be extended...
94 /* Are the following #ifdefs still required? And why? Is that for X11? */
96 #if defined(ESIX) || defined(M_UNIX) && !defined(SCO)
97 # ifdef SIGWINCH
98 # undef SIGWINCH
99 # endif
100 # ifdef TIOCGWINSZ
101 # undef TIOCGWINSZ
102 # endif
103 #endif
105 #if defined(SIGWINDOW) && !defined(SIGWINCH) /* hpux 9.01 has it */
106 # define SIGWINCH SIGWINDOW
107 #endif
109 #ifdef FEAT_X11
110 # include <X11/Xlib.h>
111 # include <X11/Xutil.h>
112 # include <X11/Xatom.h>
113 # ifdef FEAT_XCLIPBOARD
114 # include <X11/Intrinsic.h>
115 # include <X11/Shell.h>
116 # include <X11/StringDefs.h>
117 static Widget xterm_Shell = (Widget)0;
118 static void xterm_update __ARGS((void));
119 # endif
121 # if defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE)
122 Window x11_window = 0;
123 # endif
124 Display *x11_display = NULL;
126 # ifdef FEAT_TITLE
127 static int get_x11_windis __ARGS((void));
128 static void set_x11_title __ARGS((char_u *));
129 static void set_x11_icon __ARGS((char_u *));
130 # endif
131 #endif
133 #ifdef FEAT_TITLE
134 static int get_x11_title __ARGS((int));
135 static int get_x11_icon __ARGS((int));
137 static char_u *oldtitle = NULL;
138 static int did_set_title = FALSE;
139 static char_u *oldicon = NULL;
140 static int did_set_icon = FALSE;
141 #endif
143 static void may_core_dump __ARGS((void));
145 static int WaitForChar __ARGS((long));
146 #if defined(__BEOS__)
147 int RealWaitForChar __ARGS((int, long, int *));
148 #else
149 static int RealWaitForChar __ARGS((int, long, int *));
150 #endif
152 #ifdef FEAT_XCLIPBOARD
153 static int do_xterm_trace __ARGS((void));
154 # define XT_TRACE_DELAY 50 /* delay for xterm tracing */
155 #endif
157 static void handle_resize __ARGS((void));
159 #if defined(SIGWINCH)
160 static RETSIGTYPE sig_winch __ARGS(SIGPROTOARG);
161 #endif
162 #if defined(SIGINT)
163 static RETSIGTYPE catch_sigint __ARGS(SIGPROTOARG);
164 #endif
165 #if defined(SIGPWR)
166 static RETSIGTYPE catch_sigpwr __ARGS(SIGPROTOARG);
167 #endif
168 #if defined(SIGALRM) && defined(FEAT_X11) \
169 && defined(FEAT_TITLE) && !defined(FEAT_GUI_GTK)
170 # define SET_SIG_ALARM
171 static RETSIGTYPE sig_alarm __ARGS(SIGPROTOARG);
172 static int sig_alarm_called;
173 #endif
174 static RETSIGTYPE deathtrap __ARGS(SIGPROTOARG);
176 static void catch_int_signal __ARGS((void));
177 static void set_signals __ARGS((void));
178 static void catch_signals __ARGS((RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)()));
179 #ifndef __EMX__
180 static int have_wildcard __ARGS((int, char_u **));
181 static int have_dollars __ARGS((int, char_u **));
182 #endif
184 #ifndef __EMX__
185 static int save_patterns __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file));
186 #endif
188 #ifndef SIG_ERR
189 # define SIG_ERR ((RETSIGTYPE (*)())-1)
190 #endif
192 static int do_resize = FALSE;
193 #ifndef __EMX__
194 static char_u *extra_shell_arg = NULL;
195 static int show_shell_mess = TRUE;
196 #endif
197 static int deadly_signal = 0; /* The signal we caught */
199 static int curr_tmode = TMODE_COOK; /* contains current terminal mode */
201 #ifdef USE_XSMP
202 typedef struct
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;
210 static xsmp_config_T xsmp;
211 #endif
213 #ifdef SYS_SIGLIST_DECLARED
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
223 #endif
225 static struct signalinfo
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[] =
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}
302 void
303 mch_write(s, len)
304 char_u *s;
305 int len;
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);
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.
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;
327 int len;
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();
334 if (wtime >= 0)
336 while (WaitForChar(wtime) == 0) /* no character available */
338 if (!do_resize) /* return if not interrupted by resize */
339 return 0;
340 handle_resize();
343 else /* wtime == -1 */
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.
350 if (WaitForChar(p_ut) == 0)
352 #ifdef FEAT_AUTOCMD
353 if (trigger_cursorhold() && maxlen >= 3
354 && !typebuf_changed(tb_change_cnt))
356 buf[0] = K_SPECIAL;
357 buf[1] = KS_EXTRA;
358 buf[2] = (int)KE_CURSORHOLD;
359 return 3;
361 #endif
362 before_blocking();
366 for (;;) /* repeat until we got a character */
368 while (do_resize) /* window changed size */
369 handle_resize();
371 * we want to be interrupted by the winch signal
373 WaitForChar(-1L);
374 if (do_resize) /* interrupted by SIGWINCH signal */
375 continue;
377 /* If input was put directly in typeahead buffer bail out here. */
378 if (typebuf_changed(tb_change_cnt))
379 return 0;
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.
388 len = read_from_input_buf(buf, (long)maxlen);
389 if (len > 0)
391 #ifdef OS2
392 int i;
394 for (i = 0; i < len; i++)
395 if (buf[i] == 0)
396 buf[i] = K_NUL;
397 #endif
398 return len;
403 static void
404 handle_resize()
406 do_resize = FALSE;
407 shell_resized();
411 * return non-zero if a character is available
414 mch_char_avail()
416 return WaitForChar(0L);
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
431 * Return total amount of memory available in Kbyte.
432 * Doesn't change when memory has been allocated.
434 /* ARGSUSED */
435 long_u
436 mch_total_mem(special)
437 int special;
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 */
445 # ifdef HAVE_SYSCTL
446 int mib[2], physmem;
447 size_t len;
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
457 # if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
458 if (mem == 0)
460 struct sysinfo sinfo;
462 /* Linux way of getting amount of RAM available */
463 if (sysinfo(&sinfo) == 0)
465 # ifdef HAVE_SYSINFO_MEM_UNIT
466 /* avoid overflow as much as possible */
467 while (shiftright > 0 && (sinfo.mem_unit & 1) == 0)
469 sinfo.mem_unit = sinfo.mem_unit >> 1;
470 --shiftright;
472 mem = sinfo.totalram * sinfo.mem_unit;
473 # else
474 mem = sinfo.totalram;
475 # endif
478 # endif
480 # ifdef HAVE_SYSCONF
481 if (mem == 0)
483 long pagesize, pagecount;
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)
490 /* avoid overflow as much as possible */
491 while (shiftright > 0 && (pagesize & 1) == 0)
493 pagesize = (long_u)pagesize >> 1;
494 --shiftright;
496 mem = (long_u)pagesize * pagecount;
499 # endif
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)
505 struct rlimit rlp;
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)
515 mem = (long_u)rlp.rlim_cur;
516 shiftright = 10;
519 # endif
521 if (mem > 0)
522 return mem >> shiftright;
523 return (long_u)0x1fffff;
524 # endif
526 #endif
528 void
529 mch_delay(msec, ignoreinput)
530 long msec;
531 int ignoreinput;
533 int old_tmode;
534 #ifdef FEAT_MZSCHEME
535 long total = msec; /* remember original value */
536 #endif
538 if (ignoreinput)
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);
547 * Everybody sleeps in a different way...
548 * Prefer nanosleep(), some versions of usleep() can only sleep up to
549 * one second.
551 #ifdef FEAT_MZSCHEME
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
563 struct timespec ts;
565 ts.tv_sec = msec / 1000;
566 ts.tv_nsec = (msec % 1000) * 1000000;
567 (void)nanosleep(&ts, NULL);
569 #else
570 # ifdef HAVE_USLEEP
571 while (msec >= 1000)
573 usleep((unsigned int)(999 * 1000));
574 msec -= 999;
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
585 struct timeval tv;
587 tv.tv_sec = msec / 1000;
588 tv.tv_usec = (msec % 1000) * 1000;
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.
593 select(0, NULL, NULL, NULL, &tv);
595 # endif /* __EMX__ */
596 # endif /* HAVE_SELECT */
597 # endif /* HAVE_NANOSLEEP */
598 #endif /* HAVE_USLEEP */
599 #ifdef FEAT_MZSCHEME
601 while (total > 0);
602 #endif
604 settmode(old_tmode);
606 else
607 WaitForChar(msec);
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
616 #if defined(HAVE_STACK_LIMIT) \
617 || (!defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGSTACK))
618 # define HAVE_CHECK_STACK_GROWTH
620 * Support for checking for an almost-out-of-stack-space situation.
624 * Return a pointer to an item on the stack. Used to find out if the stack
625 * grows up or down.
627 static void check_stack_growth __ARGS((char *p));
628 static int stack_grows_downwards;
631 * Find out if the stack grows upwards or downwards.
632 * "p" points to a variable on the stack of the caller.
634 static void
635 check_stack_growth(p)
636 char *p;
638 int i;
640 stack_grows_downwards = (p > (char *)&i);
642 #endif
644 #if defined(HAVE_STACK_LIMIT) || defined(PROTO)
645 static char *stack_limit = NULL;
647 #if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
648 # include <pthread.h>
649 # include <pthread_np.h>
650 #endif
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().
657 static void
658 get_stack_limit()
660 struct rlimit rlp;
661 int i;
662 long lim;
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
673 lim = (long)rlp.rlim_cur;
674 #if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
676 pthread_attr_t attr;
677 size_t size;
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)
684 pthread_attr_getstacksize(&attr, &size);
685 if (lim > (long)size)
686 lim = (long)size;
688 pthread_attr_destroy(&attr);
690 #endif
691 if (stack_grows_downwards)
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);
698 else
700 stack_limit = (char *)((long)&i + (lim / 16L * 15L));
701 if (stack_limit <= (char *)&i)
702 stack_limit = NULL; /* overflow */
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.
712 mch_stackcheck(p)
713 char *p;
715 if (stack_limit != NULL)
717 if (stack_grows_downwards)
719 if (p < stack_limit)
720 return FAIL;
722 else if (p > stack_limit)
723 return FAIL;
725 return OK;
727 #endif
729 #if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
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.
737 #ifndef SIGSTKSZ
738 # define SIGSTKSZ 8000 /* just a guess of how much stack is needed... */
739 #endif
741 # ifdef HAVE_SIGALTSTACK
742 static stack_t sigstk; /* for sigaltstack() */
743 # else
744 static struct sigstack sigstk; /* for sigstack() */
745 # endif
747 static void init_signal_stack __ARGS((void));
748 static char *signal_stack;
750 static void
751 init_signal_stack()
753 if (signal_stack != NULL)
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
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
779 #endif
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).
786 #if defined(SIGWINCH)
787 /* ARGSUSED */
788 static RETSIGTYPE
789 sig_winch SIGDEFARG(sigarg)
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;
796 #endif
798 #if defined(SIGINT)
799 /* ARGSUSED */
800 static RETSIGTYPE
801 catch_sigint SIGDEFARG(sigarg)
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;
808 #endif
810 #if defined(SIGPWR)
811 /* ARGSUSED */
812 static RETSIGTYPE
813 catch_sigpwr SIGDEFARG(sigarg)
815 /* this is not required on all systems, but it doesn't hurt anybody */
816 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
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.
822 ml_sync_all(FALSE, FALSE);
823 SIGRETURN;
825 #endif
827 #ifdef SET_SIG_ALARM
829 * signal function for alarm().
831 /* ARGSUSED */
832 static RETSIGTYPE
833 sig_alarm SIGDEFARG(sigarg)
835 /* doesn't do anything, just to break a system call */
836 sig_alarm_called = TRUE;
837 SIGRETURN;
839 #endif
841 #if (defined(HAVE_SETJMP_H) \
842 && ((defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) \
843 || defined(FEAT_LIBCALL))) \
844 || defined(PROTO)
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)
852 * mch_didjmp();
853 * EMSG("crash!");
855 * else
857 * do_the_work;
858 * mch_endjmp();
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.
865 void
866 mch_startjmp()
868 #ifdef SIGHASARG
869 lc_signal = 0;
870 #endif
871 lc_active = TRUE;
874 void
875 mch_endjmp()
877 lc_active = FALSE;
880 void
881 mch_didjmp()
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
889 #endif
892 * This function handles deadly signals.
893 * It tries to preserve any swap file and exit properly.
894 * (partly from Elvis).
896 static RETSIGTYPE
897 deathtrap SIGDEFARG(sigarg)
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
906 #if defined(HAVE_SETJMP_H)
908 * Catch a crash in protected code.
909 * Restores the environment saved in lc_jump_env, which looks like
910 * SETJMP() returns 1.
912 if (lc_active)
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 */
921 #endif
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
948 && !vim_handle_signal(sigarg))
949 SIGRETURN;
950 #endif
952 /* Remember how often we have been called. */
953 ++entered;
955 #ifdef FEAT_EVAL
956 /* Set the v:dying variable. */
957 set_vim_var_nr(VV_DYING, (long)entered);
958 #endif
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
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. */
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)
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);
987 #endif
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
997 full_screen = FALSE; /* don't write message to the GUI, it might be
998 * part of the problem... */
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.
1008 if (entered >= 3)
1010 reset_signals(); /* don't catch any signals anymore */
1011 may_core_dump();
1012 if (entered >= 4)
1013 _exit(8);
1014 exit(7);
1016 if (entered == 2)
1018 OUT_STR(_("Vim: Double signal, exiting\n"));
1019 out_flush();
1020 getout(1);
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 */
1031 #ifdef NBDEBUG
1032 reset_signals();
1033 may_core_dump();
1034 abort();
1035 #endif
1037 SIGRETURN;
1040 #ifdef _REENTRANT
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.
1046 static int sigcont_received;
1047 static RETSIGTYPE sigcont_handler __ARGS(SIGPROTOARG);
1050 * signal handler for SIGCONT
1052 /* ARGSUSED */
1053 static RETSIGTYPE
1054 sigcont_handler SIGDEFARG(sigarg)
1056 sigcont_received = TRUE;
1057 SIGRETURN;
1059 #endif
1062 * If the machine has job control, use it to suspend the program,
1063 * otherwise fake it by starting a new shell.
1065 void
1066 mch_suspend()
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 */
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)
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);
1088 # endif
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
1101 # ifdef FEAT_TITLE
1103 * Set oldtitle to NULL, so the current title is obtained again.
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
1116 void
1117 mch_init()
1119 Columns = 80;
1120 Rows = 24;
1122 out_flush();
1123 set_signals();
1125 #ifdef MACOS_CONVERT
1126 mac_conv_init();
1127 #endif
1130 static void
1131 set_signals()
1133 #if defined(SIGWINCH)
1135 * WINDOW CHANGE signal is handled with sig_winch().
1137 signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
1138 #endif
1141 * We want the STOP signal to work, to make mch_suspend() work.
1142 * For "rvim" the STOP signal is ignored.
1144 #ifdef SIGTSTP
1145 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
1146 #endif
1147 #ifdef _REENTRANT
1148 signal(SIGCONT, sigcont_handler);
1149 #endif
1152 * We want to ignore breaking of PIPEs.
1154 #ifdef SIGPIPE
1155 signal(SIGPIPE, SIG_IGN);
1156 #endif
1158 #ifdef SIGINT
1159 catch_int_signal();
1160 #endif
1163 * Ignore alarm signals (Perl's alarm() generates it).
1165 #ifdef SIGALRM
1166 signal(SIGALRM, SIG_IGN);
1167 #endif
1170 * Catch SIGPWR (power failure?) to preserve the swap files, so that no
1171 * work will be lost.
1173 #ifdef SIGPWR
1174 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
1175 #endif
1178 * Arrange for other signals to gracefully shutdown Vim.
1180 catch_signals(deathtrap, SIG_ERR);
1182 #if defined(FEAT_GUI) && defined(SIGHUP)
1184 * When the GUI is running, ignore the hangup signal.
1186 if (gui.in_use)
1187 signal(SIGHUP, SIG_IGN);
1188 #endif
1191 #if defined(SIGINT) || defined(PROTO)
1193 * Catch CTRL-C (only works while in Cooked mode).
1195 static void
1196 catch_int_signal()
1198 signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
1200 #endif
1202 void
1203 reset_signals()
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
1212 static void
1213 catch_signals(func_deadly, func_other)
1214 RETSIGTYPE (*func_deadly)();
1215 RETSIGTYPE (*func_other)();
1217 int i;
1219 for (i = 0; signal_info[i].sig != -1; i++)
1220 if (signal_info[i].deadly)
1222 #if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
1223 struct sigaction sa;
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;
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
1253 else if (func_other != SIG_ERR)
1254 signal(signal_info[i].sig, func_other);
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.
1267 vim_handle_signal(sig)
1268 int sig;
1270 static int got_signal = 0;
1271 static int blocked = TRUE;
1273 switch (sig)
1275 case SIGNAL_BLOCK: blocked = TRUE;
1276 break;
1278 case SIGNAL_UNBLOCK: blocked = FALSE;
1279 if (got_signal != 0)
1281 kill(getpid(), got_signal);
1282 got_signal = 0;
1284 break;
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;
1295 return FALSE;
1299 * Check_win checks whether we have an interactive stdout.
1301 /* ARGSUSED */
1303 mch_check_win(argc, argv)
1304 int argc;
1305 char **argv;
1307 #ifdef OS2
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.
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;
1321 * Return TRUE if the input comes from a terminal, FALSE otherwise.
1324 mch_input_isatty()
1326 if (isatty(read_cmd_fd))
1327 return TRUE;
1328 return FALSE;
1331 #ifdef FEAT_X11
1333 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) \
1334 && (defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE))
1336 static void xopen_message __ARGS((struct timeval *tvp));
1339 * Give a message about the elapsed time for opening the X window.
1341 static void
1342 xopen_message(tvp)
1343 struct timeval *tvp; /* must contain start time */
1345 struct timeval end_tv;
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);
1353 # endif
1354 #endif
1356 #if defined(FEAT_X11) && (defined(FEAT_TITLE) || defined(FEAT_XCLIPBOARD))
1358 * A few functions shared by X11 title and clipboard code.
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));
1365 static int got_x_error = FALSE;
1368 * X Error handler, otherwise X just exits! (very rude) -- webb
1370 static int
1371 x_error_handler(dpy, error_event)
1372 Display *dpy;
1373 XErrorEvent *error_event;
1375 XGetErrorText(dpy, error_event->error_code, (char *)IObuff, IOSIZE);
1376 STRCAT(IObuff, _("\nVim: Got X error\n"));
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 */
1383 return 0; /* NOTREACHED */
1387 * Another X Error handler, just used to check for errors.
1389 /* ARGSUSED */
1390 static int
1391 x_error_check(dpy, error_event)
1392 Display *dpy;
1393 XErrorEvent *error_event;
1395 got_x_error = TRUE;
1396 return 0;
1399 #if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
1400 # if defined(HAVE_SETJMP_H)
1402 * An X IO Error handler, used to catch error while opening the display.
1404 static int x_IOerror_check __ARGS((Display *dpy));
1406 /* ARGSUSED */
1407 static int
1408 x_IOerror_check(dpy)
1409 Display *dpy;
1411 /* This function should not return, it causes exit(). Longjump instead. */
1412 LONGJMP(lc_jump_env, 1);
1413 /*NOTREACHED*/
1414 return 0;
1416 # endif
1419 * An X IO Error handler, used to catch terminal errors.
1421 static int x_IOerror_handler __ARGS((Display *dpy));
1423 /* ARGSUSED */
1424 static int
1425 x_IOerror_handler(dpy)
1426 Display *dpy;
1428 xterm_dpy = NULL;
1429 x11_window = 0;
1430 x11_display = NULL;
1431 xterm_Shell = (Widget)0;
1433 /* This function should not return, it causes exit(). Longjump instead. */
1434 LONGJMP(x_jump_env, 1);
1435 /*NOTREACHED*/
1436 return 0;
1438 #endif
1441 * Return TRUE when connection to the X server is desired.
1443 static int
1444 x_connect_to_server()
1446 regmatch_T regmatch;
1448 #if defined(FEAT_CLIENTSERVER)
1449 if (x_force_connect)
1450 return TRUE;
1451 #endif
1452 if (x_no_connect)
1453 return FALSE;
1455 /* Check for a match with "exclude:" from 'clipboard'. */
1456 if (clip_exclude_prog != NULL)
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;
1463 return TRUE;
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
1473 static int
1474 test_x11_window(dpy)
1475 Display *dpy;
1477 int (*old_handler)();
1478 XTextProperty text_prop;
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);
1487 if (p_verbose > 0 && got_x_error)
1488 verb_msg((char_u *)_("Testing the X display failed"));
1490 return (got_x_error ? FAIL : OK);
1492 #endif
1494 #ifdef FEAT_TITLE
1496 #ifdef FEAT_X11
1498 static int get_x11_thing __ARGS((int get_title, int test_only));
1501 * try to get x11 window and display
1503 * return FAIL for failure, OK otherwise
1505 static int
1506 get_x11_windis()
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;
1517 if (!did_set_error_handler)
1519 /* X just exits if it finds an error otherwise! */
1520 (void)XSetErrorHandler(x_error_handler);
1521 did_set_error_handler = TRUE;
1524 #if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
1525 if (gui.in_use)
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.
1531 if (x11_display_from == XD_HERE && x11_display != NULL)
1533 XCloseDisplay(x11_display);
1534 x11_display_from = XD_NONE;
1536 if (gui_get_x11_windis(&x11_window, &x11_display) == OK)
1538 x11_display_from = XD_GUI;
1539 return OK;
1541 x11_display = NULL;
1542 return FAIL;
1544 else if (x11_display_from == XD_GUI)
1546 /* GUI must have stopped somehow, clear x11_display */
1547 x11_window = 0;
1548 x11_display = NULL;
1549 x11_display_from = XD_NONE;
1551 #endif
1553 /* When started with the "-X" argument, don't try connecting. */
1554 if (!x_connect_to_server())
1555 return FAIL;
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.
1563 if (x11_window == 0 && (winid = getenv("WINDOWID")) != NULL)
1564 x11_window = (Window)atol(winid);
1566 #ifdef FEAT_XCLIPBOARD
1567 if (xterm_dpy != NULL && x11_window != 0)
1569 /* Checked it already. */
1570 if (x11_display_from == XD_XTERM)
1571 return OK;
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.
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)
1583 /* probably bad $WINDOWID */
1584 x11_window = 0;
1585 x11_display = NULL;
1586 x11_display_from = XD_NONE;
1587 return FAIL;
1589 return OK;
1591 #endif
1593 if (x11_window == 0 || x11_display == NULL)
1594 result = -1;
1596 if (result != -1) /* Have already been here and set this */
1597 return result; /* Don't do all these X calls again */
1599 if (x11_window != 0 && x11_display == NULL)
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;
1607 if (p_verbose > 0)
1608 gettimeofday(&start_tv, NULL);
1609 #endif
1611 #ifdef SET_SIG_ALARM
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.
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);
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)
1631 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1632 if (p_verbose > 0)
1634 verbose_enter();
1635 xopen_message(&start_tv);
1636 verbose_leave();
1638 # endif
1639 if (test_x11_window(x11_display) == FAIL)
1641 /* Maybe window id is bad */
1642 x11_window = 0;
1643 XCloseDisplay(x11_display);
1644 x11_display = NULL;
1646 else
1647 x11_display_from = XD_HERE;
1650 if (x11_window == 0 || x11_display == NULL)
1651 return (result = FAIL);
1652 return (result = OK);
1656 * Determine original x11 Window Title
1658 static int
1659 get_x11_title(test_only)
1660 int test_only;
1662 return get_x11_thing(TRUE, test_only);
1666 * Determine original x11 Window icon
1668 static int
1669 get_x11_icon(test_only)
1670 int test_only;
1672 int retval = FALSE;
1674 retval = get_x11_thing(FALSE, test_only);
1676 /* could not get old icon, use terminal name */
1677 if (oldicon == NULL && !test_only)
1679 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1680 oldicon = T_NAME + 8;
1681 else
1682 oldicon = T_NAME;
1685 return retval;
1688 static int
1689 get_x11_thing(get_title, test_only)
1690 int get_title; /* get title string */
1691 int test_only;
1693 XTextProperty text_prop;
1694 int retval = FALSE;
1695 Status status;
1697 if (get_x11_windis() == OK)
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);
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.
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) */
1715 Window root;
1716 Window parent;
1717 Window win = x11_window;
1718 Window *children;
1719 unsigned int num_children;
1721 while (!status || text_prop.value == NULL)
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;
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);
1738 if (status && text_prop.value != NULL)
1740 retval = TRUE;
1741 if (!test_only)
1743 #ifdef FEAT_XFONTSET
1744 if (text_prop.encoding == XA_STRING)
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
1753 else
1755 char **cl;
1756 Status transform_status;
1757 int n = 0;
1759 transform_status = XmbTextPropertyToTextList(x11_display,
1760 &text_prop,
1761 &cl, &n);
1762 if (transform_status >= Success && n > 0 && cl[0])
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);
1770 else
1772 if (get_title)
1773 oldtitle = vim_strsave((char_u *)text_prop.value);
1774 else
1775 oldicon = vim_strsave((char_u *)text_prop.value);
1778 #endif
1780 XFree((void *)text_prop.value);
1783 return retval;
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
1794 * Set x11 Window Title
1796 * get_x11_windis() must be called before this and have returned OK
1798 static void
1799 set_x11_title(title)
1800 char_u *title;
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.
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
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;
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
1830 XFlush(x11_display);
1834 * Set x11 Window icon
1836 * get_x11_windis() must be called before this and have returned OK
1838 static void
1839 set_x11_icon(icon)
1840 char_u *icon;
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
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;
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
1866 XFlush(x11_display);
1869 #else /* FEAT_X11 */
1871 /*ARGSUSED*/
1872 static int
1873 get_x11_title(test_only)
1874 int test_only;
1876 return FALSE;
1879 static int
1880 get_x11_icon(test_only)
1881 int test_only;
1883 if (!test_only)
1885 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1886 oldicon = T_NAME + 8;
1887 else
1888 oldicon = T_NAME;
1890 return FALSE;
1893 #endif /* FEAT_X11 */
1896 mch_can_restore_title()
1898 return get_x11_title(TRUE);
1902 mch_can_restore_icon()
1904 return get_x11_icon(TRUE);
1908 * Set the window title and icon.
1910 void
1911 mch_settitle(title, icon)
1912 char_u *title;
1913 char_u *icon;
1915 int type = 0;
1916 static int recursive = 0;
1918 if (T_NAME == NULL) /* no terminal name (yet) */
1919 return;
1920 if (title == NULL && icon == NULL) /* nothing to do */
1921 return;
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;
1930 * if the window ID and the display is known, we may use X11 calls
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
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
1946 if ((type || *T_TS != NUL) && title != NULL)
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);
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;
1972 if ((type || *T_CIS != NUL) && icon != NULL)
1974 if (oldicon == NULL
1975 #ifdef FEAT_GUI
1976 && !gui.in_use
1977 #endif
1978 ) /* first call, save icon */
1979 get_x11_icon(FALSE);
1981 if (*T_CIS != NUL)
1983 out_str(T_CIS); /* set icon start */
1984 out_str_nf(icon);
1985 out_str(T_CIE); /* set icon end */
1986 out_flush();
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;
1997 --recursive;
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
2007 void
2008 mch_restore_title(which)
2009 int which;
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);
2017 #endif /* FEAT_TITLE */
2020 * Return TRUE if "name" looks like some xterm name.
2021 * Seiichi Sato mentioned that "mlterm" works like xterm.
2024 vim_is_xterm(name)
2025 char_u *name;
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);
2037 #if defined(FEAT_MOUSE_TTY) || defined(PROTO)
2039 * Return non-zero when using an xterm mouse, according to 'ttymouse'.
2040 * Return 1 for "xterm".
2041 * Return 2 for "xterm2".
2044 use_xterm_mouse()
2046 if (ttym_flags == TTYM_XTERM2)
2047 return 2;
2048 if (ttym_flags == TTYM_XTERM)
2049 return 1;
2050 return 0;
2052 #endif
2055 vim_is_iris(name)
2056 char_u *name;
2058 if (name == NULL)
2059 return FALSE;
2060 return (STRNICMP(name, "iris-ansi", 9) == 0
2061 || STRCMP(name, "builtin_iris-ansi") == 0);
2065 vim_is_vt300(name)
2066 char_u *name;
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);
2077 * Return TRUE if "name" is a terminal for which 'ttyfast' should be set.
2078 * This should include all windowed terminal emulators.
2081 vim_is_fastterm(name)
2082 char_u *name;
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);
2095 * Insert user name in s[len].
2096 * Return OK if a name found.
2099 mch_get_user_name(s, len)
2100 char_u *s;
2101 int len;
2103 #ifdef VMS
2104 vim_strncpy(s, (char_u *)cuserid(NULL), len - 1);
2105 return OK;
2106 #else
2107 return mch_get_uname(getuid(), s, len);
2108 #endif
2112 * Insert user name for "uid" in s[len].
2113 * Return OK if a name found.
2116 mch_get_uname(uid, s, len)
2117 uid_t uid;
2118 char_u *s;
2119 int len;
2121 #if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
2122 struct passwd *pw;
2124 if ((pw = getpwuid(uid)) != NULL
2125 && pw->pw_name != NULL && *(pw->pw_name) != NUL)
2127 vim_strncpy(s, (char_u *)pw->pw_name, len - 1);
2128 return OK;
2130 #endif
2131 sprintf((char *)s, "%d", (int)uid); /* assumes s is long enough */
2132 return FAIL; /* a number is not a name */
2136 * Insert host name is s[len].
2139 #ifdef HAVE_SYS_UTSNAME_H
2140 void
2141 mch_get_host_name(s, len)
2142 char_u *s;
2143 int len;
2145 struct utsname vutsname;
2147 if (uname(&vutsname) < 0)
2148 *s = NUL;
2149 else
2150 vim_strncpy(s, (char_u *)vutsname.nodename, len - 1);
2152 #else /* HAVE_SYS_UTSNAME_H */
2154 # ifdef HAVE_SYS_SYSTEMINFO_H
2155 # define gethostname(nam, len) sysinfo(SI_HOSTNAME, nam, len)
2156 # endif
2158 void
2159 mch_get_host_name(s, len)
2160 char_u *s;
2161 int len;
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 */
2170 #endif /* HAVE_SYS_UTSNAME_H */
2173 * return process ID
2175 long
2176 mch_get_pid()
2178 return (long)getpid();
2181 #if !defined(HAVE_STRERROR) && defined(USE_GETCWD)
2182 static char *strerror __ARGS((int));
2184 static char *
2185 strerror(err)
2186 int err;
2188 extern int sys_nerr;
2189 extern char *sys_errlist[];
2190 static char er[20];
2192 if (err > 0 && err < sys_nerr)
2193 return (sys_errlist[err]);
2194 sprintf(er, "Error %d", err);
2195 return er;
2197 #endif
2200 * Get name of current directory into buffer 'buf' of length 'len' bytes.
2201 * Return OK for success, FAIL for failure.
2204 mch_dirname(buf, len)
2205 char_u *buf;
2206 int len;
2208 #if defined(USE_GETCWD)
2209 if (getcwd((char *)buf, len) == NULL)
2211 STRCPY(buf, strerror(errno));
2212 return FAIL;
2214 return OK;
2215 #else
2216 return (getwd((char *)buf) != NULL ? OK : FAIL);
2217 #endif
2220 #if defined(OS2) || defined(PROTO)
2222 * Replace all slashes by backslashes.
2223 * When 'shellslash' set do it the other way around.
2225 void
2226 slash_adjust(p)
2227 char_u *p;
2229 while (*p)
2231 if (*p == psepcN)
2232 *p = psepc;
2233 mb_ptr_adv(p);
2236 #endif
2239 * Get absolute file name into "buf[len]".
2241 * return FAIL for failure, OK for success
2244 mch_FullName(fname, buf, len, force)
2245 char_u *fname, *buf;
2246 int len;
2247 int force; /* also expand when already absolute path */
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;
2261 #ifdef VMS
2262 fname = vms_fixfilename(fname);
2263 #endif
2265 #ifdef __CYGWIN__
2267 * This helps for when "/etc/hosts" is a symlink to "c:/something/hosts".
2269 cygwin_conv_to_posix_path(fname, fname);
2270 #endif
2272 /* expand it if forced or not an absolute path */
2273 if (force || !mch_isFullName(fname))
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.
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
2289 #ifdef HAVE_FCHDIR
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.
2295 if (!dont_fchdir)
2297 fd = open(".", O_RDONLY | O_EXTRA, 0);
2298 if (fd >= 0 && fchdir(fd) < 0)
2300 close(fd);
2301 fd = -1;
2302 dont_fchdir = TRUE; /* don't try again */
2305 #endif
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))
2316 p = NULL; /* can't get current dir: don't chdir */
2317 retval = FAIL;
2319 else
2321 #ifdef OS2
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.
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
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;
2344 #ifdef OS2
2345 if (only_drive)
2347 p--;
2348 if (retval != FAIL)
2349 fname--;
2351 #endif
2354 if (mch_dirname(buf, len) == FAIL)
2356 retval = FAIL;
2357 *buf = NUL;
2359 if (p != NULL)
2361 #ifdef HAVE_FCHDIR
2362 if (fd >= 0)
2364 l = fchdir(fd);
2365 close(fd);
2367 else
2368 #endif
2369 l = mch_chdir((char *)olddir);
2370 if (l != 0)
2371 EMSG(_(e_prev_dir));
2374 l = STRLEN(buf);
2375 if (l >= len)
2376 retval = FAIL;
2377 #ifndef VMS
2378 else
2380 if (l > 0 && buf[l - 1] != '/' && *fname != NUL
2381 && STRCMP(fname, ".") != 0)
2382 STRCAT(buf, "/");
2384 #endif
2387 /* Catch file names which are too long. */
2388 if (retval == FAIL || STRLEN(buf) + STRLEN(fname) >= len)
2389 return FAIL;
2391 /* Do not append ".", "/dir/." is equal to "/dir". */
2392 if (STRCMP(fname, ".") != 0)
2393 STRCAT(buf, fname);
2395 return OK;
2399 * Return TRUE if "fname" does not depend on the current directory.
2402 mch_isFullName(fname)
2403 char_u *fname;
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
2419 #if defined(USE_FNAME_CASE) || defined(PROTO)
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.
2425 /*ARGSUSED*/
2426 void
2427 fname_case(name, len)
2428 char_u *name;
2429 int len; /* buffer size, only used when name gets longer */
2431 struct stat st;
2432 char_u *slash, *tail;
2433 DIR *dirp;
2434 struct dirent *dp;
2436 if (lstat((char *)name, &st) >= 0)
2438 /* Open the directory where the file is located. */
2439 slash = vim_strrchr(name, '/');
2440 if (slash == NULL)
2442 dirp = opendir(".");
2443 tail = name;
2445 else
2447 *slash = NUL;
2448 dirp = opendir((char *)name);
2449 *slash = '/';
2450 tail = slash + 1;
2453 if (dirp != NULL)
2455 while ((dp = readdir(dirp)) != NULL)
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))
2462 char_u newname[MAXPATHL + 1];
2463 struct stat st2;
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)
2473 STRCPY(tail, dp->d_name);
2474 break;
2479 closedir(dirp);
2483 #endif
2486 * Get file permissions for 'name'.
2487 * Returns -1 when it doesn't exist.
2489 long
2490 mch_getperm(name)
2491 char_u *name;
2493 struct stat statb;
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;
2506 * set file permission for 'name' to 'perm'
2508 * return FAIL for failure, OK otherwise
2511 mch_setperm(name, perm)
2512 char_u *name;
2513 long perm;
2515 return (chmod((char *)
2516 #ifdef VMS
2517 vms_fixfilename(name),
2518 #else
2519 name,
2520 #endif
2521 (mode_t)perm) == 0 ? OK : FAIL);
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
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
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.
2543 vim_acl_T
2544 mch_get_acl(fname)
2545 char_u *fname;
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;
2554 aclent = malloc(sizeof(vim_acl_solaris_T));
2555 if ((aclent->acl_cnt = acl((char *)fname, GETACLCNT, 0, NULL)) < 0)
2557 free(aclent);
2558 return NULL;
2560 aclent->acl_entry = malloc(aclent->acl_cnt * sizeof(aclent_t));
2561 if (acl((char *)fname, GETACL, aclent->acl_cnt, aclent->acl_entry) < 0)
2563 free(aclent->acl_entry);
2564 free(aclent);
2565 return NULL;
2567 ret = (vim_acl_T)aclent;
2568 #else
2569 #if defined(HAVE_AIX_ACL)
2570 int aclsize;
2571 struct acl *aclent;
2573 aclsize = sizeof(struct acl);
2574 aclent = malloc(aclsize);
2575 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2577 if (errno == ENOSPC)
2579 aclsize = aclent->acl_len;
2580 aclent = realloc(aclent, aclsize);
2581 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2583 free(aclent);
2584 return NULL;
2587 else
2589 free(aclent);
2590 return NULL;
2593 ret = (vim_acl_T)aclent;
2594 #endif /* HAVE_AIX_ACL */
2595 #endif /* HAVE_SOLARIS_ACL */
2596 #endif /* HAVE_POSIX_ACL */
2597 return ret;
2601 * Set the ACL of file "fname" to "acl" (unless it's NULL).
2603 void
2604 mch_set_acl(fname, aclent)
2605 char_u *fname;
2606 vim_acl_T aclent;
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 */
2624 void
2625 mch_free_acl(aclent)
2626 vim_acl_T aclent;
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 */
2643 #endif
2646 * Set hidden flag for "name".
2648 /* ARGSUSED */
2649 void
2650 mch_hide(name)
2651 char_u *name;
2653 /* can't hide a file */
2657 * return TRUE if "name" is a directory
2658 * return FALSE if "name" is not a directory
2659 * return FALSE for error
2662 mch_isdir(name)
2663 char_u *name;
2665 struct stat statb;
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
2678 static int executable_file __ARGS((char_u *name));
2681 * Return 1 if "name" is an executable file, 0 if not or it doesn't exist.
2683 static int
2684 executable_file(name)
2685 char_u *name;
2687 struct stat st;
2689 if (stat((char *)name, &st))
2690 return 0;
2691 return S_ISREG(st.st_mode) && mch_access((char *)name, X_OK) == 0;
2695 * Return 1 if "name" can be found in $PATH and executed, 0 if not.
2696 * Return -1 if unknown.
2699 mch_can_exe(name)
2700 char_u *name;
2702 char_u *buf;
2703 char_u *p, *e;
2704 int retval;
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);
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;
2719 * Walk through all entries in $PATH to check if "name" exists there and
2720 * is an executable file.
2722 for (;;)
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
2731 vim_strncpy(buf, p, e - p);
2732 add_pathsep(buf);
2734 STRCAT(buf, name);
2735 retval = executable_file(buf);
2736 if (retval == 1)
2737 break;
2739 if (*e != ':')
2740 break;
2741 p = e + 1;
2744 vim_free(buf);
2745 return retval;
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
2755 mch_nodetype(name)
2756 char_u *name;
2758 struct stat st;
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;
2772 void
2773 mch_early_init()
2775 #ifdef HAVE_CHECK_STACK_GROWTH
2776 int i;
2778 check_stack_growth((char *)&i);
2780 # ifdef HAVE_STACK_LIMIT
2781 get_stack_limit();
2782 # endif
2784 #endif
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.
2792 #if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2793 signal_stack = malloc(SIGSTKSZ);
2794 init_signal_stack();
2795 #endif
2798 #if defined(EXITFREE) || defined(PROTO)
2799 void
2800 mch_free_mem()
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
2829 #endif
2831 static void exit_scroll __ARGS((void));
2834 * Output a newline when exiting.
2835 * Make sure the newline goes to the same stream as the text.
2837 static void
2838 exit_scroll()
2840 if (silent_mode)
2841 return;
2842 if (newline_on_exit || msg_didout)
2844 if (msg_use_printf())
2846 if (info_message)
2847 mch_msg("\n");
2848 else
2849 mch_errmsg("\r\n");
2851 else
2852 out_char('\n');
2854 else
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 */
2862 void
2863 mch_exit(r)
2864 int r;
2866 exiting = TRUE;
2868 #if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
2869 x11_export_final_selection();
2870 #endif
2872 #ifdef FEAT_GUI
2873 if (!gui.in_use)
2874 #endif
2876 settmode(TMODE_COOK);
2877 #ifdef FEAT_TITLE
2878 mch_restore_title(3); /* restore xterm title and icon name */
2879 #endif
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().
2886 if (swapping_screen() && !newline_on_exit)
2887 exit_scroll();
2889 /* Stop termcap: May need to check for T_CRV response, which
2890 * requires RAW mode. */
2891 stoptermcap();
2894 * A newline is only required after a message in the alternate screen.
2895 * This is set to TRUE by wait_return().
2897 if (!swapping_screen() || newline_on_exit)
2898 exit_scroll();
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();
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
2913 #ifdef MACOS_CONVERT
2914 mac_conv_cleanup();
2915 #endif
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
2924 #ifdef FEAT_NETBEANS_INTG
2925 if (usingNetbeans)
2926 netbeans_send_disconnect();
2927 #endif
2929 #ifdef EXITFREE
2930 free_all_mem();
2931 #endif
2933 exit(r);
2936 static void
2937 may_core_dump()
2939 if (deadly_signal != 0)
2941 signal(deadly_signal, SIG_DFL);
2942 kill(getpid(), deadly_signal); /* Die using the signal we caught */
2946 #ifndef VMS
2948 void
2949 mch_settmode(tmode)
2950 int tmode;
2952 static int first = TRUE;
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__)
2957 * for "new" tty systems
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
2967 if (first)
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
2977 tnew = told;
2978 if (tmode == TMODE_RAW)
2981 * ~ICRNL enables typing ^V^M
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
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 */
2996 else if (tmode == TMODE_SLEEP)
2997 tnew.c_lflag &= ~(ECHO);
2999 # if defined(HAVE_TERMIOS_H)
3001 int n = 10;
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;
3009 # else
3010 ioctl(read_cmd_fd, TCSETA, &tnew);
3011 # endif
3013 #else
3016 * for "old" tty systems
3018 # ifndef TIOCSETN
3019 # define TIOCSETN TIOCSETP /* for hpux 9.0 */
3020 # endif
3021 static struct sgttyb ttybold;
3022 struct sgttyb ttybnew;
3024 if (first)
3026 first = FALSE;
3027 ioctl(read_cmd_fd, TIOCGETP, &ttybold);
3030 ttybnew = ttybold;
3031 if (tmode == TMODE_RAW)
3033 ttybnew.sg_flags &= ~(CRMOD | ECHO);
3034 ttybnew.sg_flags |= RAW;
3036 else if (tmode == TMODE_SLEEP)
3037 ttybnew.sg_flags &= ~(ECHO);
3038 ioctl(read_cmd_fd, TIOCSETN, &ttybnew);
3039 #endif
3040 curr_tmode = tmode;
3044 * Try to get the code for "t_kb" from the stty setting
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)
3052 void
3053 get_stty()
3055 char_u buf[2];
3056 char_u *p;
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
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
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;
3079 if (ioctl(read_cmd_fd, TIOCGETP, &keys) != -1)
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);
3088 * If <BS> and <DEL> are now the same, redefine <DEL>.
3090 p = find_termcode((char_u *)"kD");
3091 if (p != NULL && p[0] == buf[0] && p[1] == buf[1])
3092 do_fixdel(NULL);
3094 #if 0
3095 } /* to keep cindent happy */
3096 #endif
3099 #endif /* VMS */
3101 #if defined(FEAT_MOUSE_TTY) || defined(PROTO)
3103 * Set mouse clicks on or off.
3105 void
3106 mch_setmouse(on)
3107 int on;
3109 static int ison = FALSE;
3110 int xterm_mouse_vers;
3112 if (on == ison) /* return quickly if nothing to do */
3113 return;
3115 xterm_mouse_vers = use_xterm_mouse();
3116 if (xterm_mouse_vers > 0)
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;
3131 # ifdef FEAT_MOUSE_DEC
3132 else if (ttym_flags == TTYM_DEC)
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;
3140 # endif
3142 # ifdef FEAT_MOUSE_GPM
3143 else
3145 if (on)
3147 if (gpm_open())
3148 ison = TRUE;
3150 else
3152 gpm_close();
3153 ison = FALSE;
3156 # endif
3158 # ifdef FEAT_MOUSE_JSB
3159 else
3161 if (on)
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
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;
3187 else
3189 out_str_nf((char_u *)IF_EB("\033[0~ZwQ\033\\",
3190 ESC_STR "[0~ZwQ" ESC_STR "\\"));
3191 ison = FALSE;
3194 # endif
3195 # ifdef FEAT_MOUSE_PTERM
3196 else
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;
3205 # endif
3209 * Set the mouse termcode, depending on the 'term' and 'ttymouse' options.
3211 void
3212 check_mouse_termcode()
3214 # ifdef FEAT_MOUSE_XTERM
3215 if (use_xterm_mouse()
3216 # ifdef FEAT_GUI
3217 && !gui.in_use
3218 # endif
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)
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();
3232 else
3233 del_mouse_termcode(KS_MOUSE);
3234 # endif
3236 # ifdef FEAT_MOUSE_GPM
3237 if (!use_xterm_mouse()
3238 # ifdef FEAT_GUI
3239 && !gui.in_use
3240 # endif
3242 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MG", ESC_STR "MG"));
3243 # endif
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
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
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
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
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
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
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
3297 #endif
3300 * set screen mode, always fails.
3302 /* ARGSUSED */
3304 mch_screenmode(arg)
3305 char_u *arg;
3307 EMSG(_(e_screenmode));
3308 return FAIL;
3311 #ifndef VMS
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.
3322 mch_get_shellsize()
3324 long rows = 0;
3325 long columns = 0;
3326 char_u *p;
3329 * For OS/2 use _scrsize().
3331 # ifdef __EMX__
3333 int s[2];
3335 _scrsize(s);
3336 columns = s[0];
3337 rows = s[1];
3339 # endif
3342 * 1. try using an ioctl. It is the most accurate method.
3344 * Try using TIOCGWINSZ first, some systems that have it also define
3345 * TIOCGSIZE but don't have a struct ttysize.
3347 # ifdef TIOCGWINSZ
3349 struct winsize ws;
3350 int fd = 1;
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)
3357 columns = ws.ws_col;
3358 rows = ws.ws_row;
3361 # else /* TIOCGWINSZ */
3362 # ifdef TIOCGSIZE
3364 struct ttysize ts;
3365 int fd = 1;
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)
3372 columns = ts.ts_cols;
3373 rows = ts.ts_lines;
3376 # endif /* TIOCGSIZE */
3377 # endif /* TIOCGWINSZ */
3380 * 2. get size from environment
3381 * When being POSIX compliant ('|' flag in 'cpoptions') this overrules
3382 * the ioctl() values!
3384 if (columns == 0 || rows == 0 || vim_strchr(p_cpo, CPO_TSIZE) != NULL)
3386 if ((p = (char_u *)getenv("LINES")))
3387 rows = atoi((char *)p);
3388 if ((p = (char_u *)getenv("COLUMNS")))
3389 columns = atoi((char *)p);
3392 #ifdef HAVE_TGETENT
3394 * 3. try reading "co" and "li" entries from termcap
3396 if (columns == 0 || rows == 0)
3397 getlinecol(&columns, &rows);
3398 #endif
3401 * 4. If everything fails, use the old values
3403 if (columns <= 0 || rows <= 0)
3404 return FAIL;
3406 Rows = rows;
3407 Columns = columns;
3408 return OK;
3412 * Try to set the window size to Rows and Columns.
3414 void
3415 mch_set_shellsize()
3417 if (*T_CWS)
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.
3424 term_set_winsize((int)Rows, (int)Columns);
3425 out_flush();
3426 screen_start(); /* don't know where cursor is now */
3430 #endif /* VMS */
3433 * Rows and/or Columns has changed.
3435 void
3436 mch_new_shellsize()
3438 /* Nothing to do. */
3441 #ifndef USE_SYSTEM
3442 static void append_ga_line __ARGS((garray_T *gap));
3445 * Append the text in "gap" below the cursor line and clear "gap".
3447 static void
3448 append_ga_line(gap)
3449 garray_T *gap;
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;
3460 #endif
3463 mch_call_shell(cmd, options)
3464 char_u *cmd;
3465 int options; /* SHELL_*, see vim.h */
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
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.
3485 char_u *p, *old;
3487 if (((old = (char_u *)getenv("EMXSHELL")) == NULL) || STRCMP(old, p_sh))
3489 /* should check HAVE_SETENV, but I know we don't have it. */
3490 p = alloc(10 + strlen(p_sh));
3491 if (p)
3493 sprintf((char *)p, "EMXSHELL=%s", p_sh);
3494 putenv((char *)p); /* don't free the pointer! */
3497 # endif
3499 out_flush();
3501 if (options & SHELL_COOKED)
3502 settmode(TMODE_COOK); /* set to normal mode */
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)
3512 MSG_PUTS(_("\nCannot execute shell "));
3513 msg_outtrans(p_sh);
3514 msg_putchar('\n');
3516 # else /* not __EMX__ */
3517 if (cmd == NULL)
3518 x = system((char *)p_sh);
3519 else
3521 # ifdef VMS
3522 if (ofn = strchr((char *)cmd, '>'))
3523 *ofn++ = '\0';
3524 if (ifn = strchr((char *)cmd, '<'))
3526 char *p;
3528 *ifn++ = '\0';
3529 p = strchr(ifn,' '); /* chop off any trailing spaces */
3530 if (p)
3531 *p = '\0';
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
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);
3552 # endif
3554 # ifdef VMS
3555 x = vms_sys_status(x);
3556 # endif
3557 if (emsg_silent)
3559 else if (x == 127)
3560 MSG_PUTS(_("\nCannot execute shell sh\n"));
3561 # endif /* __EMX__ */
3562 else if (x && !(options & SHELL_SILENT))
3564 MSG_PUTS(_("\nshell returned "));
3565 msg_outnum((long)x);
3566 msg_putchar('\n');
3569 if (tmode == TMODE_RAW)
3570 settmode(TMODE_RAW); /* set to raw mode */
3571 # ifdef FEAT_TITLE
3572 resettitle();
3573 # endif
3574 return x;
3576 #else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
3578 # define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
3579 127, some shells use that already */
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 */
3612 out_flush();
3613 if (options & SHELL_COOKED)
3614 settmode(TMODE_COOK); /* set to normal mode */
3616 newcmd = vim_strsave(p_sh);
3617 if (newcmd == NULL) /* out of memory */
3618 goto error;
3621 * Do this loop twice:
3622 * 1: find number of arguments
3623 * 2: separate them and build argv[]
3625 for (i = 0; i < 2; ++i)
3627 p = newcmd;
3628 inquote = FALSE;
3629 argc = 0;
3630 for (;;)
3632 if (i == 1)
3633 argv[argc] = (char *)p;
3634 ++argc;
3635 while (*p && (inquote || (*p != ' ' && *p != TAB)))
3637 if (*p == '"')
3638 inquote = !inquote;
3639 ++p;
3641 if (*p == NUL)
3642 break;
3643 if (i == 1)
3644 *p++ = NUL;
3645 p = skipwhite(p);
3647 if (argv == NULL)
3649 argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *)));
3650 if (argv == NULL) /* out of memory */
3651 goto error;
3654 if (cmd != NULL)
3656 if (extra_shell_arg != NULL)
3657 argv[argc++] = (char *)extra_shell_arg;
3658 argv[argc++] = (char *)p_shcf;
3659 argv[argc++] = (char *)cmd;
3661 argv[argc] = NULL;
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.
3668 if ((options & (SHELL_READ|SHELL_WRITE))
3669 # ifdef FEAT_GUI
3670 || (gui.in_use && show_shell_mess)
3671 # endif
3674 # ifdef FEAT_GUI
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.
3680 if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
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))
3686 close(pty_master_fd);
3687 pty_master_fd = -1;
3691 * If not opening a pty or it didn't work, try using pipes.
3693 if (pty_master_fd < 0)
3694 # endif
3696 pipe_error = (pipe(fd_toshell) < 0);
3697 if (!pipe_error) /* pipe create OK */
3699 pipe_error = (pipe(fd_fromshell) < 0);
3700 if (pipe_error) /* pipe create failed */
3702 close(fd_toshell[0]);
3703 close(fd_toshell[1]);
3706 if (pipe_error)
3708 MSG_PUTS(_("\nCannot create pipes\n"));
3709 out_flush();
3714 if (!pipe_error) /* pty or pipe opened or not used */
3716 # ifdef __BEOS__
3717 beos_cleanup_read_thread();
3718 # endif
3720 if ((pid = fork()) == -1) /* maybe we should use vfork() */
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
3729 # ifdef FEAT_GUI
3730 if (pty_master_fd >= 0) /* close the pseudo tty */
3732 close(pty_master_fd);
3733 close(pty_slave_fd);
3735 else /* close the pipes */
3736 # endif
3738 close(fd_toshell[0]);
3739 close(fd_toshell[1]);
3740 close(fd_fromshell[0]);
3741 close(fd_fromshell[1]);
3745 else if (pid == 0) /* child */
3747 reset_signals(); /* handle signals normally */
3749 if (!show_shell_mess || (options & SHELL_EXPAND))
3751 int fd;
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.
3761 fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
3762 fclose(stdin);
3763 fclose(stdout);
3764 fclose(stderr);
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
3775 if (fd >= 0)
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) */
3781 /* Don't need this now that we've duplicated it */
3782 close(fd);
3785 else if ((options & (SHELL_READ|SHELL_WRITE))
3786 # ifdef FEAT_GUI
3787 || gui.in_use
3788 # endif
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)
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
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
3823 * Putenv does not copy the string, it has to remain valid.
3824 * Use a static array to avoid loosing allocated memory.
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
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.
3840 # ifdef FEAT_GUI
3841 if (pty_master_fd >= 0)
3843 close(pty_master_fd); /* close master side of pty */
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)
3852 close(2);
3853 dup(pty_slave_fd);
3856 close(pty_slave_fd); /* has been dupped, close it now */
3858 else
3859 # endif
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]);
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]);
3873 # ifdef FEAT_GUI
3874 if (gui.in_use)
3876 /* set up stderr for the child */
3877 close(2);
3878 dup(1);
3880 # endif
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()).
3891 execvp(argv[0], argv);
3892 _exit(EXEC_FAILED); /* exec failed, return failure code */
3894 else /* parent */
3897 * While child is running, ignore terminating signals.
3898 * Do catch CTRL-C, so that "got_int" is set.
3900 catch_signals(SIG_IGN, SIG_ERR);
3901 catch_int_signal();
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.
3908 if ((options & (SHELL_READ|SHELL_WRITE))
3909 # ifdef FEAT_GUI
3910 || (gui.in_use && show_shell_mess)
3911 # endif
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;
3930 # ifdef FEAT_GUI
3931 if (pty_master_fd >= 0)
3933 close(pty_slave_fd); /* close slave side of pty */
3934 fromshell_fd = pty_master_fd;
3935 toshell_fd = dup(pty_master_fd);
3937 else
3938 # endif
3940 close(fd_toshell[0]);
3941 close(fd_fromshell[1]);
3942 toshell_fd = fd_toshell[1];
3943 fromshell_fd = fd_fromshell[0];
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.
3959 * Currently this busy loops!
3960 * This can probably dead-lock when the write blocks!
3962 p_more_save = p_more;
3963 p_more = FALSE;
3964 old_State = State;
3965 State = EXTERNCMD; /* don't redraw at window resize */
3967 if ((options & SHELL_WRITE) && toshell_fd >= 0)
3969 /* Fork a process that will write the lines to the
3970 * external program. */
3971 if ((wpid = fork()) == -1)
3973 MSG_PUTS(_("\nCannot fork\n"));
3975 else if (wpid == 0)
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;
3983 /* child */
3984 close(fromshell_fd);
3985 for (;;)
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
3995 s = vim_strchr(lp + written, NL);
3996 len = write(toshell_fd, (char *)lp + written,
3997 s == NULL ? l : s - (lp + written));
3999 if (len == l)
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)
4013 /* finished all the lines, close pipe */
4014 close(toshell_fd);
4015 toshell_fd = -1;
4016 break;
4018 lp = ml_get(lnum);
4019 written = 0;
4021 else if (len > 0)
4022 written += len;
4024 _exit(0);
4026 else
4028 close(toshell_fd);
4029 toshell_fd = -1;
4033 if (options & SHELL_READ)
4034 ga_init2(&ga, 1, BUFLEN);
4036 noread_cnt = 0;
4038 for (;;)
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.
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
4063 && wait_pid == 0
4064 && (ta_len > 0
4065 || (noread_cnt > 4
4066 && (len = ui_inchar(ta_buf,
4067 BUFLEN, 10L, 0)) > 0)))
4070 * For pipes:
4071 * Check for CTRL-C: send interrupt signal to child.
4072 * Check for CTRL-D: EOF, close pipe to child.
4074 if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
4076 # ifdef SIGINT
4078 * Send SIGINT to the child's group or all
4079 * processes in our group.
4081 if (ta_buf[ta_len] == Ctrl_C
4082 || ta_buf[ta_len] == intr_char)
4084 # ifdef HAVE_SETSID
4085 kill(-pid, SIGINT);
4086 # else
4087 kill(0, SIGINT);
4088 # endif
4089 if (wpid > 0)
4090 kill(wpid, SIGINT);
4092 # endif
4093 if (pty_master_fd < 0 && toshell_fd >= 0
4094 && ta_buf[ta_len] == Ctrl_D)
4096 close(toshell_fd);
4097 toshell_fd = -1;
4101 /* replace K_BS by <BS> and K_DEL by <DEL> */
4102 for (i = ta_len; i < ta_len + len; ++i)
4104 if (ta_buf[i] == CSI && len - i > 2)
4106 c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]);
4107 if (c == K_DEL || c == K_KDEL || c == K_BS)
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;
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
4127 * For pipes: echo the typed characters.
4128 * For a pty this does not seem to work.
4130 if (pty_master_fd < 0)
4132 for (i = ta_len; i < ta_len + len; ++i)
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)
4139 int l = (*mb_ptr2len)(ta_buf + i);
4141 msg_outtrans_len(ta_buf + i, l);
4142 i += l - 1;
4144 # endif
4145 else
4146 msg_outtrans_len(ta_buf + i, 1);
4148 windgoto(msg_row, msg_col);
4149 out_flush();
4152 ta_len += len;
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).
4161 if (options & SHELL_WRITE)
4162 ta_len = 0;
4163 else if (toshell_fd >= 0)
4165 len = write(toshell_fd, (char *)ta_buf, (size_t)1);
4166 if (len > 0)
4168 ta_len -= len;
4169 mch_memmove(ta_buf, ta_buf + len, ta_len);
4170 noread_cnt = 0;
4175 if (got_int)
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;
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?).
4198 ++noread_cnt;
4199 while (RealWaitForChar(fromshell_fd, 10L, NULL))
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
4208 if (len <= 0) /* end of file or error */
4209 goto finished;
4211 noread_cnt = 0;
4212 if (options & SHELL_READ)
4214 /* Do NUL -> NL translation, append NL separated
4215 * lines to the current buffer. */
4216 for (i = 0; i < len; ++i)
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]);
4226 # ifdef FEAT_MBYTE
4227 else if (has_mbyte)
4229 int l;
4231 len += buffer_off;
4232 buffer[len] = NUL;
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)
4239 l = mb_cptr2len(p);
4240 if (l == 0)
4241 l = 1; /* NUL byte? */
4242 else if (MB_BYTE2LEN(*p) != l)
4243 break;
4245 if (p == buffer) /* no complete character */
4247 /* avoid getting stuck at an illegal byte */
4248 if (len >= 12)
4249 ++p;
4250 else
4252 buffer_off = len;
4253 continue;
4256 c = *p;
4257 *p = NUL;
4258 msg_puts(buffer);
4259 if (p < buffer + len)
4261 *p = c;
4262 buffer_off = (buffer + len) - p;
4263 mch_memmove(buffer, p, buffer_off);
4264 continue;
4266 buffer_off = 0;
4268 # endif /* FEAT_MBYTE */
4269 else
4271 buffer[len] = NUL;
4272 msg_puts(buffer);
4275 windgoto(msg_row, msg_col);
4276 cursor_on();
4277 out_flush();
4278 if (got_int)
4279 break;
4282 /* If we already detected the child has finished break the
4283 * loop now. */
4284 if (wait_pid == pid)
4285 break;
4288 * Check if the child still exists, before checking for
4289 * typed characters (otherwise we would loose typeahead).
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)))
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;
4305 else
4306 wait_pid = 0;
4308 finished:
4309 p_more = p_more_save;
4310 if (options & SHELL_READ)
4312 if (ga.ga_len > 0)
4314 append_ga_line(&ga);
4315 /* remember that the NL was missing */
4316 write_no_eol_lnum = curwin->w_cursor.lnum;
4318 else
4319 write_no_eol_lnum = 0;
4320 ga_clear(&ga);
4324 * Give all typeahead that wasn't used back to ui_inchar().
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);
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.
4341 while (wait_pid != pid)
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)
4354 /* Wait for 1/100 sec before trying again. */
4355 mch_delay(10L, TRUE);
4356 continue;
4358 # else
4359 wait_pid = wait(&status);
4360 # endif
4361 if (wait_pid <= 0
4362 # ifdef ECHILD
4363 && errno == ECHILD
4364 # endif
4366 break;
4369 /* Make sure the child that writes to the external program is
4370 * dead. */
4371 if (wpid > 0)
4372 kill(wpid, SIGKILL);
4375 * Set to raw mode right now, otherwise a CTRL-C after
4376 * catch_signals() will kill Vim.
4378 if (tmode == TMODE_RAW)
4379 settmode(TMODE_RAW);
4380 did_settmode = TRUE;
4381 set_signals();
4383 if (WIFEXITED(status))
4385 /* LINTED avoid "bitwise operation on signed value" */
4386 retval = WEXITSTATUS(status);
4387 if (retval && !emsg_silent)
4389 if (retval == EXEC_FAILED)
4391 MSG_PUTS(_("\nCannot execute shell "));
4392 msg_outtrans(p_sh);
4393 msg_putchar('\n');
4395 else if (!(options & SHELL_SILENT))
4397 MSG_PUTS(_("\nshell returned "));
4398 msg_outnum((long)retval);
4399 msg_putchar('\n');
4403 else
4404 MSG_PUTS(_("\nCommand terminated\n"));
4407 vim_free(argv);
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);
4418 return retval;
4420 #endif /* USE_SYSTEM */
4424 * Check for CTRL-C typed by reading all available characters.
4425 * In cooked mode we should get SIGINT, no need to check.
4427 void
4428 mch_breakcheck()
4430 if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL))
4431 fill_input_buf(FALSE);
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
4439 static int
4440 WaitForChar(msec)
4441 long msec;
4443 #ifdef FEAT_MOUSE_GPM
4444 int gpm_process_wanted;
4445 #endif
4446 #ifdef FEAT_XCLIPBOARD
4447 int rest;
4448 #endif
4449 int avail;
4451 if (input_available()) /* something in inbuf[] */
4452 return 1;
4454 #if defined(FEAT_MOUSE_DEC)
4455 /* May need to query the mouse position. */
4456 if (WantQueryMouse)
4458 WantQueryMouse = FALSE;
4459 mch_write((char_u *)IF_EB("\033[1'|", ESC_STR "[1'|"), 5);
4461 #endif
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.
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
4475 # ifdef FEAT_XCLIPBOARD
4476 if (rest != 0)
4478 msec = XT_TRACE_DELAY;
4479 if (rest >= 0 && rest < XT_TRACE_DELAY)
4480 msec = rest;
4481 if (rest >= 0)
4482 rest -= msec;
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)
4493 if (input_available())
4494 return 1;
4495 # ifdef FEAT_XCLIPBOARD
4496 if (rest == 0 || !do_xterm_trace())
4497 # endif
4498 break;
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
4510 #else
4511 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4512 #endif
4513 return avail;
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.
4523 /* ARGSUSED */
4524 #if defined(__BEOS__)
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;
4534 int ret;
4535 #if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4536 static int busy = FALSE;
4538 /* May retry getting characters after an event was handled. */
4539 # define MAY_LOOP
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;
4547 if (msec > 0 && (
4548 # ifdef FEAT_XCLIPBOARD
4549 xterm_Shell != (Widget)0
4550 # if defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4552 # endif
4553 # endif
4554 # ifdef USE_XSMP
4555 xsmp_icefd != -1
4556 # ifdef FEAT_MZSCHEME
4558 # endif
4559 # endif
4560 # ifdef FEAT_MZSCHEME
4561 (mzthreads_allowed() && p_mzq > 0)
4562 # endif
4564 gettimeofday(&start_tv, NULL);
4565 # endif
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
4573 #ifdef MAY_LOOP
4574 for (;;)
4575 #endif
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;
4597 # ifdef FEAT_MZSCHEME
4598 mzvim_check_threads();
4599 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4601 towait = (int)p_mzq; /* don't wait longer than 'mzquantum' */
4602 mzquantum_used = TRUE;
4604 # endif
4605 fds[0].fd = fd;
4606 fds[0].events = POLLIN;
4607 nfd = 1;
4609 # ifdef FEAT_SNIFF
4610 # define SNIFF_IDX 1
4611 if (want_sniff_request)
4613 fds[SNIFF_IDX].fd = fd_from_sniff;
4614 fds[SNIFF_IDX].events = POLLIN;
4615 nfd++;
4617 # endif
4618 # ifdef FEAT_XCLIPBOARD
4619 if (xterm_Shell != (Widget)0)
4621 xterm_idx = nfd;
4622 fds[nfd].fd = ConnectionNumber(xterm_dpy);
4623 fds[nfd].events = POLLIN;
4624 nfd++;
4626 # endif
4627 # ifdef FEAT_MOUSE_GPM
4628 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4630 gpm_idx = nfd;
4631 fds[nfd].fd = gpm_fd;
4632 fds[nfd].events = POLLIN;
4633 nfd++;
4635 # endif
4636 # ifdef USE_XSMP
4637 if (xsmp_icefd != -1)
4639 xsmp_idx = nfd;
4640 fds[nfd].fd = xsmp_icefd;
4641 fds[nfd].events = POLLIN;
4642 nfd++;
4644 # endif
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
4653 # ifdef FEAT_SNIFF
4654 if (ret < 0)
4655 sniff_disconnect(1);
4656 else if (want_sniff_request)
4658 if (fds[SNIFF_IDX].revents & POLLHUP)
4659 sniff_disconnect(1);
4660 if (fds[SNIFF_IDX].revents & POLLIN)
4661 sniff_request_waiting = 1;
4663 # endif
4664 # ifdef FEAT_XCLIPBOARD
4665 if (xterm_Shell != (Widget)0 && (fds[xterm_idx].revents & POLLIN))
4667 xterm_update(); /* Maybe we should hand out clipboard */
4668 if (--ret == 0 && !input_available())
4669 /* Try again */
4670 finished = FALSE;
4672 # endif
4673 # ifdef FEAT_MOUSE_GPM
4674 if (gpm_idx >= 0 && (fds[gpm_idx].revents & POLLIN))
4676 *check_for_gpm = 1;
4678 # endif
4679 # ifdef USE_XSMP
4680 if (xsmp_idx >= 0 && (fds[xsmp_idx].revents & (POLLIN | POLLHUP)))
4682 if (fds[xsmp_idx].revents & POLLIN)
4684 busy = TRUE;
4685 xsmp_handle_requests();
4686 busy = FALSE;
4688 else if (fds[xsmp_idx].revents & POLLHUP)
4690 if (p_verbose > 0)
4691 verb_msg((char_u *)_("XSMP lost ICE connection"));
4692 xsmp_close();
4694 if (--ret == 0)
4695 finished = FALSE; /* Try again */
4697 # endif
4700 #else /* HAVE_SELECT */
4702 struct timeval tv;
4703 struct timeval *tvp;
4704 fd_set rfds, efds;
4705 int maxfd;
4706 long towait = msec;
4708 # ifdef FEAT_MZSCHEME
4709 mzvim_check_threads();
4710 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4712 towait = p_mzq; /* don't wait longer than 'mzquantum' */
4713 mzquantum_used = TRUE;
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
4723 if (towait >= 0)
4725 tv.tv_sec = towait / 1000;
4726 tv.tv_usec = (towait % 1000) * (1000000/1000);
4727 tvp = &tv;
4729 else
4730 tvp = NULL;
4733 * Select on ready for reading and exceptional condition (end of file).
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;
4744 # ifdef FEAT_SNIFF
4745 if (want_sniff_request)
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;
4752 # endif
4753 # ifdef FEAT_XCLIPBOARD
4754 if (xterm_Shell != (Widget)0)
4756 FD_SET(ConnectionNumber(xterm_dpy), &rfds);
4757 if (maxfd < ConnectionNumber(xterm_dpy))
4758 maxfd = ConnectionNumber(xterm_dpy);
4760 # endif
4761 # ifdef FEAT_MOUSE_GPM
4762 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4764 FD_SET(gpm_fd, &rfds);
4765 FD_SET(gpm_fd, &efds);
4766 if (maxfd < gpm_fd)
4767 maxfd = gpm_fd;
4769 # endif
4770 # ifdef USE_XSMP
4771 if (xsmp_icefd != -1)
4773 FD_SET(xsmp_icefd, &rfds);
4774 FD_SET(xsmp_icefd, &efds);
4775 if (maxfd < xsmp_icefd)
4776 maxfd = xsmp_icefd;
4778 # endif
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)
4790 FD_ZERO(&rfds);
4791 FD_ZERO(&efds);
4792 ret = 0;
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
4801 # ifdef FEAT_SNIFF
4802 if (ret < 0 )
4803 sniff_disconnect(1);
4804 else if (ret > 0 && want_sniff_request)
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;
4811 # endif
4812 # ifdef FEAT_XCLIPBOARD
4813 if (ret > 0 && xterm_Shell != (Widget)0
4814 && FD_ISSET(ConnectionNumber(xterm_dpy), &rfds))
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())
4821 /* Try again */
4822 finished = FALSE;
4825 # endif
4826 # ifdef FEAT_MOUSE_GPM
4827 if (ret > 0 && gpm_flag && check_for_gpm != NULL && gpm_fd >= 0)
4829 if (FD_ISSET(gpm_fd, &efds))
4830 gpm_close();
4831 else if (FD_ISSET(gpm_fd, &rfds))
4832 *check_for_gpm = 1;
4834 # endif
4835 # ifdef USE_XSMP
4836 if (ret > 0 && xsmp_icefd != -1)
4838 if (FD_ISSET(xsmp_icefd, &efds))
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 */
4846 else if (FD_ISSET(xsmp_icefd, &rfds))
4848 busy = TRUE;
4849 xsmp_handle_requests();
4850 busy = FALSE;
4851 if (--ret == 0)
4852 finished = FALSE; /* keep going if event was only one */
4855 # endif
4857 #endif /* HAVE_SELECT */
4859 #ifdef MAY_LOOP
4860 if (finished || msec == 0)
4861 break;
4863 /* We're going to loop around again, find out for how long */
4864 if (msec > 0)
4866 # ifdef USE_START_TV
4867 struct timeval mtv;
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 */
4880 #endif
4883 return (ret > 0);
4886 #ifndef VMS
4888 #ifndef NO_EXPANDPATH
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.
4896 mch_expandpath(gap, path, flags)
4897 garray_T *gap;
4898 char_u *path;
4899 int flags; /* EW_* flags */
4901 return unix_expandpath(gap, path, 0, flags, FALSE);
4903 #endif
4906 * mch_expand_wildcards() - this code does wild-card pattern matching using
4907 * the shell
4909 * return OK for success, FAIL for error (you may lose some memory) and put
4910 * an error message in *file.
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
4918 #ifndef SEEK_SET
4919 # define SEEK_SET 0
4920 #endif
4921 #ifndef SEEK_END
4922 # define SEEK_END 2
4923 #endif
4925 #define SHELL_SPECIAL (char_u *)"\t \"&'$;<>()\\|"
4927 /* ARGSUSED */
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 */
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;
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;
4954 for (; num_pat > 0; num_pat--, pat++)
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);
4968 * return value of buf if no wildcards left,
4969 * OR if no match AND EW_NOTFOUND is set.
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)
4977 expl_files[0] = vim_strsave(buf);
4978 expl_files[1] = NULL;
4981 vim_free(buf);
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.
4988 if (expl_files)
4990 for (i = 0; (p = expl_files[i]) != NULL; i++)
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;
4997 /* Skip files that are not executable if we check for that. */
4998 if (!dir && (flags & EW_EXEC) && !mch_can_exe(p))
4999 continue;
5001 if (--files_free == 0)
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)
5009 EMSG(_(e_outofmem));
5010 *num_file = 0;
5011 return FAIL;
5013 files_free = EXPL_ALLOC_INC;
5015 slash_adjust(p);
5016 if (dir)
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)
5023 STRCPY((*file)[*num_file], p);
5024 if (!after_pathsep((*file)[*num_file],
5025 (*file)[*num_file] + len))
5027 (*file)[*num_file][len] = psepc;
5028 (*file)[*num_file][len + 1] = NUL;
5032 else
5034 (*file)[*num_file] = vim_strsave(p);
5038 * Error message already given by either alloc or vim_strsave.
5039 * Should return FAIL, but returning OK works also.
5041 if ((*file)[*num_file] == NULL)
5042 break;
5043 (*num_file)++;
5045 _fnexplodefree((char **)expl_files);
5048 return OK;
5050 #else /* __EMX__ */
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;
5066 *num_file = 0; /* default: no files found */
5067 *file = NULL;
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.
5073 if (!have_wildcard(num_pat, pat))
5074 return save_patterns(num_pat, pat, num_file, file);
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
5083 * Don't allow the use of backticks in secure and restricted mode.
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;
5092 * get a name for the temp file
5094 if ((tempname = vim_tempname('o')) == NULL)
5096 EMSG(_(e_notmp));
5097 return FAIL;
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.
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)
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;
5118 /* "unset nonomatch; print -N >" plus two is 29 */
5119 len = STRLEN(tempname) + 29;
5120 for (i = 0; i < num_pat; ++i)
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)
5130 if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL)
5131 ++len; /* may add a backslash */
5132 ++len;
5134 #endif
5136 command = alloc(len);
5137 if (command == NULL)
5139 /* out of memory */
5140 vim_free(tempname);
5141 return FAIL;
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.
5152 if (shell_style == STYLE_BT)
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 '&' */
5163 ampersent = TRUE;
5164 *p = ' ';
5166 STRCAT(command, ">");
5168 else
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 >");
5181 STRCAT(command, tempname);
5182 if (shell_style != STYLE_BT)
5183 for (i = 0; i < num_pat; ++i)
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;
5195 p = command + STRLEN(command);
5196 *p++ = ' ';
5197 for (j = 0; pat[i][j] != NUL; ++j)
5199 if (pat[i][j] == '`')
5200 intick = !intick;
5201 else if (pat[i][j] == '\\' && pat[i][j + 1] != NUL)
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;
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++ = '\\';
5218 /* Copy one character. */
5219 *p++ = pat[i][j];
5221 *p = NUL;
5222 #endif
5224 if (flags & EW_SILENT)
5225 show_shell_mess = FALSE;
5226 if (ampersent)
5227 STRCAT(command, "&"); /* put the '&' back after the
5228 redirection */
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.
5235 if (shell_style == STYLE_PRINT)
5236 extra_shell_arg = (char_u *)"-G"; /* Use zsh NULL_GLOB option */
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.
5243 else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat))
5244 extra_shell_arg = (char_u *)"-f"; /* Use csh fast option */
5247 * execute the shell command
5249 i = call_shell(command, SHELL_EXPAND | SHELL_SILENT);
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);
5256 extra_shell_arg = NULL; /* cleanup */
5257 show_shell_mess = TRUE;
5258 vim_free(command);
5260 if (i) /* mch_call_shell() failed */
5262 mch_remove(tempname);
5263 vim_free(tempname);
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.
5269 #ifndef USE_SYSTEM
5270 if (!(flags & EW_SILENT))
5271 #endif
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
5280 MSG(_(e_wildexpand));
5281 msg_start(); /* don't overwrite this message */
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;
5292 * read the names from the file into memory
5294 fd = fopen((char *)tempname, READBIN);
5295 if (fd == NULL)
5297 /* Something went wrong, perhaps a file name with a special char. */
5298 if (!(flags & EW_SILENT))
5300 MSG(_(e_wildexpand));
5301 msg_start(); /* don't overwrite this message */
5303 vim_free(tempname);
5304 goto notfound;
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)
5312 /* out of memory */
5313 mch_remove(tempname);
5314 vim_free(tempname);
5315 fclose(fd);
5316 return FAIL;
5318 i = fread((char *)buffer, 1, len, fd);
5319 fclose(fd);
5320 mch_remove(tempname);
5321 if (i != len)
5323 /* unexpected read error */
5324 EMSG2(_(e_notread), tempname);
5325 vim_free(tempname);
5326 vim_free(buffer);
5327 return FAIL;
5329 vim_free(tempname);
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
5341 /* file names are separated with Space */
5342 if (shell_style == STYLE_ECHO)
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 */
5348 while (*p != ' ' && *p != '\n')
5349 ++p;
5350 p = skipwhite(p); /* skip to next entry */
5353 /* file names are separated with NL */
5354 else if (shell_style == STYLE_BT)
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 */
5360 while (*p != '\n' && *p != NUL)
5361 ++p;
5362 if (*p != NUL)
5363 ++p;
5364 p = skipwhite(p); /* skip leading white space */
5367 /* file names are separated with NUL */
5368 else
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.
5378 check_spaces = FALSE;
5379 if (shell_style == STYLE_PRINT && !did_find_nul)
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;
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.
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 */
5400 ++i;
5401 *p = NUL;
5403 if (len)
5404 ++i; /* count last entry */
5406 if (i == 0)
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.
5413 vim_free(buffer);
5414 goto notfound;
5416 *num_file = i;
5417 *file = (char_u **)alloc(sizeof(char_u *) * i);
5418 if (*file == NULL)
5420 /* out of memory */
5421 vim_free(buffer);
5422 return FAIL;
5426 * Isolate the individual file names.
5428 p = buffer;
5429 for (i = 0; i < *num_file; ++i)
5431 (*file)[i] = p;
5432 /* Space or NL separates */
5433 if (shell_style == STYLE_ECHO || shell_style == STYLE_BT)
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
5442 *p++ = NUL;
5443 p = skipwhite(p); /* skip to next entry */
5446 else /* NUL separates */
5448 while (*p && p < buffer + len) /* skip entry */
5449 ++p;
5450 ++p; /* skip NUL */
5455 * Move the file names to allocated memory.
5457 for (j = 0, i = 0; i < *num_file; ++i)
5459 /* Require the files to exist. Helps when using /bin/sh */
5460 if (!(flags & EW_NOTFOUND) && mch_getperm((*file)[i]) < 0)
5461 continue;
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;
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;
5472 p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir));
5473 if (p)
5475 STRCPY(p, (*file)[i]);
5476 if (dir)
5477 STRCAT(p, "/"); /* add '/' to a directory name */
5478 (*file)[j++] = p;
5481 vim_free(buffer);
5482 *num_file = j;
5484 if (*num_file == 0) /* rejected all entries */
5486 vim_free(*file);
5487 *file = NULL;
5488 goto notfound;
5491 return OK;
5493 notfound:
5494 if (flags & EW_NOTFOUND)
5495 return save_patterns(num_pat, pat, num_file, file);
5496 return FAIL;
5498 #endif /* __EMX__ */
5501 #endif /* VMS */
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;
5511 int i;
5512 char_u *s;
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++)
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;
5526 *num_file = num_pat;
5527 return OK;
5529 #endif
5533 * Return TRUE if the string "p" contains a wildcard that mch_expandpath() can
5534 * expand.
5537 mch_has_exp_wildcard(p)
5538 char_u *p;
5540 for ( ; *p; mb_ptr_adv(p))
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;
5560 return FALSE;
5564 * Return TRUE if the string "p" contains a wildcard.
5565 * Don't recognize '~' at the end as a wildcard.
5568 mch_has_wildcard(p)
5569 char_u *p;
5571 for ( ; *p; mb_ptr_adv(p))
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;
5596 return FALSE;
5599 #ifndef __EMX__
5600 static int
5601 have_wildcard(num, file)
5602 int num;
5603 char_u **file;
5605 int i;
5607 for (i = 0; i < num; i++)
5608 if (mch_has_wildcard(file[i]))
5609 return 1;
5610 return 0;
5613 static int
5614 have_dollars(num, file)
5615 int num;
5616 char_u **file;
5618 int i;
5620 for (i = 0; i < num; i++)
5621 if (vim_strchr(file[i], '$') != NULL)
5622 return TRUE;
5623 return FALSE;
5625 #endif /* ifndef __EMX__ */
5627 #ifndef HAVE_RENAME
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.
5634 mch_rename(src, dest)
5635 const char *src, *dest;
5637 struct stat st;
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;
5647 #endif /* !HAVE_RENAME */
5649 #ifdef FEAT_MOUSE_GPM
5651 * Initializes connection with gpm (if it isn't already opened)
5652 * Return 1 if succeeded (or connection already opened), 0 if failed
5654 static int
5655 gpm_open()
5657 static Gpm_Connect gpm_connect; /* Must it be kept till closing ? */
5659 if (!gpm_flag)
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)
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
5673 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
5674 return 1; /* succeed */
5676 if (gpm_fd == -2)
5677 Gpm_Close(); /* We don't want to talk to xterm via gpm */
5678 return 0;
5680 return 1; /* already open */
5684 * Closes connection to gpm
5685 * returns non-zero if connection succesfully closed
5687 static void
5688 gpm_close()
5690 if (gpm_flag && gpm_fd >= 0) /* if Open */
5691 Gpm_Close();
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
5698 static int
5699 mch_gpm_process()
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;
5710 Gpm_GetEvent(&gpm_event);
5712 #ifdef FEAT_GUI
5713 /* Don't put events in the input queue now. */
5714 if (hold_gui_events)
5715 return 0;
5716 #endif
5718 row = gpm_event.y - 1;
5719 col = gpm_event.x - 1;
5721 string[0] = ESC; /* Our termcode */
5722 string[1] = 'M';
5723 string[2] = 'G';
5724 switch (GPM_BARE_EVENTS(gpm_event.type))
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)
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? */
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;
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
5765 if (gpm_modifiers & ((1 << KG_SHIFT) | (1 << KG_SHIFTR) | (1 << KG_SHIFTL)))
5766 vim_modifiers |= MOUSE_SHIFT;
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;
5778 #endif /* FEAT_MOUSE_GPM */
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));
5787 * Call a DLL routine which takes either a string or int param
5788 * and returns an allocated string.
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;
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;
5812 * Get a handle to the DLL module.
5814 # if defined(USE_DLOPEN)
5815 /* First clear any error, it's not cleared by the dlopen() call. */
5816 (void)dlerror();
5818 hinstLib = dlopen((char *)libname, RTLD_LAZY
5819 # ifdef RTLD_LOCAL
5820 | RTLD_LOCAL
5821 # endif
5823 if (hinstLib == NULL)
5825 /* "dlerr" must be used before dlclose() */
5826 dlerr = (char *)dlerror();
5827 if (dlerr != NULL)
5828 EMSG2(_("dlerror = \"%s\""), dlerr);
5830 # else
5831 hinstLib = shl_load((const char*)libname, BIND_IMMEDIATE|BIND_VERBOSE, 0L);
5832 # endif
5834 /* If the handle is valid, try to get the function address. */
5835 if (hinstLib != NULL)
5837 # ifdef HAVE_SETJMP_H
5839 * Catch a crash when calling the library function. For example when
5840 * using a number where a string pointer is expected.
5842 mch_startjmp();
5843 if (SETJMP(lc_jump_env) != 0)
5845 success = FALSE;
5846 # if defined(USE_DLOPEN)
5847 dlerr = NULL;
5848 # endif
5849 mch_didjmp();
5851 else
5852 # endif
5854 retval_str = NULL;
5855 retval_int = 0;
5857 if (argstring != NULL)
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
5873 if (string_result == NULL)
5874 retval_int = ((STRPROCINT)ProcAdd)(argstring);
5875 else
5876 retval_str = (ProcAdd)(argstring);
5879 else
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
5895 if (string_result == NULL)
5896 retval_int = ((INTPROCINT)ProcAddI)(argint);
5897 else
5898 retval_str = (ProcAddI)(argint);
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);
5912 # ifdef HAVE_SETJMP_H
5913 mch_endjmp();
5914 # ifdef SIGHASARG
5915 if (lc_signal != 0)
5917 int i;
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);
5925 # endif
5926 # endif
5928 # if defined(USE_DLOPEN)
5929 /* "dlerr" must be used before dlclose() */
5930 if (dlerr != NULL)
5931 EMSG2(_("dlerror = \"%s\""), dlerr);
5933 /* Free the DLL module. */
5934 (void)dlclose(hinstLib);
5935 # else
5936 (void)shl_unload(hinstLib);
5937 # endif
5940 if (!success)
5942 EMSG2(_(e_libcall), funcname);
5943 return FAIL;
5946 return OK;
5948 #endif
5950 #if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
5951 static int xterm_trace = -1; /* default: disabled */
5952 static int xterm_button;
5955 * Setup a dummy window for X selections in a terminal.
5957 void
5958 setup_term_clip()
5960 int z = 0;
5961 char *strp = "";
5962 Widget AppShell;
5964 if (!x_connect_to_server())
5965 return;
5967 open_app_context();
5968 if (app_context != NULL && xterm_Shell == (Widget)0)
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;
5977 if (p_verbose > 0)
5978 gettimeofday(&start_tv, NULL);
5979 # endif
5981 /* Ignore X errors while opening the display */
5982 oldhandler = XSetErrorHandler(x_error_check);
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)
5990 mch_didjmp();
5991 xterm_dpy = NULL;
5993 else
5994 #endif
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
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);
6010 if (xterm_dpy == NULL)
6012 if (p_verbose > 0)
6013 verb_msg((char_u *)_("Opening the X display failed"));
6014 return;
6017 /* Catch terminating error of the X server connection. */
6018 (void)XSetIOErrorHandler(x_IOerror_handler);
6020 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
6021 if (p_verbose > 0)
6023 verbose_enter();
6024 xopen_message(&start_tv);
6025 verbose_leave();
6027 # endif
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;
6044 x11_setup_atoms(xterm_dpy);
6045 if (x11_display == NULL)
6046 x11_display = xterm_dpy;
6048 XtRealizeWidget(xterm_Shell);
6049 XSync(xterm_dpy, False);
6050 xterm_update();
6052 if (xterm_Shell != (Widget)0)
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;
6065 void
6066 start_xterm_trace(button)
6067 int button;
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();
6077 void
6078 stop_xterm_trace()
6080 if (xterm_trace < 0)
6081 return;
6082 xterm_trace = 0;
6086 * Query the xterm pointer and generate mouse termcodes if necessary
6087 * return TRUE if dragging is active, else FALSE
6089 static int
6090 do_xterm_trace()
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;
6105 if (xterm_trace <= 0)
6106 return FALSE;
6108 if (xterm_trace == 1)
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)
6117 xterm_trace = -1; /* Not enough data -- disable tracing */
6118 return FALSE;
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;
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;
6141 if (mouse_code == NULL)
6143 xterm_trace = 0;
6144 return FALSE;
6147 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
6148 &win_x, &win_y, &mask_return);
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;
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));
6163 prev_row = row;
6164 prev_col = col;
6165 return TRUE;
6168 # if defined(FEAT_GUI) || defined(PROTO)
6170 * Destroy the display, window and app_context. Required for GTK.
6172 void
6173 clear_xterm_clip()
6175 if (xterm_Shell != (Widget)0)
6177 XtDestroyWidget(xterm_Shell);
6178 xterm_Shell = (Widget)0;
6180 if (xterm_dpy != NULL)
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;
6190 #if 0
6191 if (app_context != (XtAppContext)NULL)
6193 /* Lesstif and Solaris crash here, lose some memory */
6194 XtDestroyApplicationContext(app_context);
6195 app_context = (XtAppContext)NULL;
6197 #endif
6199 # endif
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.
6207 static void
6208 xterm_update()
6210 XEvent event;
6212 while (XtAppPending(app_context) && !vim_is_input_buf_full())
6214 XtAppNextEvent(app_context, &event);
6215 #ifdef FEAT_CLIENTSERVER
6217 XPropertyEvent *e = (XPropertyEvent *)&event;
6219 if (e->type == PropertyNotify && e->window == commWindow
6220 && e->atom == commProperty && e->state == PropertyNewValue)
6221 serverEventProc(xterm_dpy, &event);
6223 #endif
6224 XtDispatchEvent(&event);
6229 clip_xterm_own_selection(cbd)
6230 VimClipboard *cbd;
6232 if (xterm_Shell != (Widget)0)
6233 return clip_x11_own_selection(xterm_Shell, cbd);
6234 return FAIL;
6237 void
6238 clip_xterm_lose_selection(cbd)
6239 VimClipboard *cbd;
6241 if (xterm_Shell != (Widget)0)
6242 clip_x11_lose_selection(xterm_Shell, cbd);
6245 void
6246 clip_xterm_request_selection(cbd)
6247 VimClipboard *cbd;
6249 if (xterm_Shell != (Widget)0)
6250 clip_x11_request_selection(xterm_Shell, xterm_dpy, cbd);
6253 void
6254 clip_xterm_set_selection(cbd)
6255 VimClipboard *cbd;
6257 clip_x11_set_selection(cbd);
6259 #endif
6262 #if defined(USE_XSMP) || defined(PROTO)
6264 * Code for X Session Management Protocol.
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));
6273 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6274 static void xsmp_handle_interaction __ARGS((SmcConn smc_conn, SmPointer client_data));
6277 * This is our chance to ask the user if they want to save,
6278 * or abort the logout
6280 /*ARGSUSED*/
6281 static void
6282 xsmp_handle_interaction(smc_conn, client_data)
6283 SmcConn smc_conn;
6284 SmPointer client_data;
6286 cmdmod_T save_cmdmod;
6287 int cancel_shutdown = False;
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();
6298 /* Done interaction */
6299 SmcInteractDone(smc_conn, cancel_shutdown);
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)
6306 if (!cancel_shutdown)
6308 xsmp.save_yourself = False;
6309 SmcSaveYourselfDone(smc_conn, True);
6312 # endif
6315 * Callback that starts save-yourself.
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;
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;
6334 /* First up, preserve all files */
6335 out_flush();
6336 ml_sync_all(FALSE, FALSE); /* preserve all swap files */
6338 if (p_verbose > 0)
6339 verb_msg((char_u *)_("XSMP handling save-yourself request"));
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
6350 /* Can stop the cycle here */
6351 SmcSaveYourselfDone(smc_conn, True);
6352 xsmp.save_yourself = False;
6358 * Callback to warn us of imminent death.
6360 /*ARGSUSED*/
6361 static void
6362 xsmp_die(smc_conn, client_data)
6363 SmcConn smc_conn;
6364 SmPointer client_data;
6366 xsmp_close();
6368 /* quit quickly leaving swapfiles for modified buffers behind */
6369 getout_preserve_modified(0);
6374 * Callback to tell us that save-yourself has completed.
6376 /*ARGSUSED*/
6377 static void
6378 xsmp_save_complete(smc_conn, client_data)
6379 SmcConn smc_conn;
6380 SmPointer client_data;
6382 xsmp.save_yourself = False;
6387 * Callback to tell us that an instigated shutdown was cancelled
6388 * (maybe even by us)
6390 /*ARGSUSED*/
6391 static void
6392 xsmp_shutdown_cancelled(smc_conn, client_data)
6393 SmcConn smc_conn;
6394 SmPointer client_data;
6396 if (xsmp.save_yourself)
6397 SmcSaveYourselfDone(smc_conn, True);
6398 xsmp.save_yourself = False;
6399 xsmp.shutdown = False;
6404 * Callback to tell us that a new ICE connection has been established.
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;
6414 /* Intercept creation of ICE connection fd */
6415 if (opening)
6417 xsmp_icefd = IceConnectionNumber(iceConn);
6418 IceRemoveConnectionWatch(xsmp_ice_connection, NULL);
6423 /* Handle any ICE processing that's required; return FAIL if SM lost */
6425 xsmp_handle_requests()
6427 Bool rep;
6429 if (IceProcessMessages(xsmp.iceconn, NULL, &rep)
6430 == IceProcessMessagesIOError)
6432 /* Lost ICE */
6433 if (p_verbose > 0)
6434 verb_msg((char_u *)_("XSMP lost ICE connection"));
6435 xsmp_close();
6436 return FAIL;
6438 else
6439 return OK;
6442 static int dummy;
6444 /* Set up X Session Management Protocol */
6445 void
6446 xsmp_init(void)
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
6457 if (p_verbose > 0)
6458 verb_msg((char_u *)_("XSMP opening connection"));
6460 xsmp.save_yourself = xsmp.shutdown = False;
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;
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)
6476 if (p_verbose > 0)
6477 verb_msg((char_u *)_("XSMP ICE connection watch failed"));
6478 return;
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)
6496 char errorreport[132];
6498 if (p_verbose > 0)
6500 vim_snprintf(errorreport, sizeof(errorreport),
6501 _("XSMP SmcOpenConnection failed: %s"), errorstring);
6502 verb_msg((char_u *)errorreport);
6504 return;
6506 xsmp.iceconn = SmcGetIceConnection(xsmp.smcconn);
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;
6517 smprops[0] = &smnameprop;
6518 SmcSetProperties(xsmp.smcconn, 1, smprops);
6519 #endif
6523 /* Shut down XSMP comms. */
6524 void
6525 xsmp_close()
6527 if (xsmp_icefd != -1)
6529 SmcCloseConnection(xsmp.smcconn, 0, NULL);
6530 xsmp_icefd = -1;
6533 #endif /* USE_XSMP */
6536 #ifdef EBCDIC
6537 /* Translate character to its CTRL- value */
6538 char CtrlTable[] =
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,
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
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,
6644 #endif