Deleted junk files.
[MacVim/jjgod.git] / src / os_unix.c
blobd0a1c521b0eba91c4dcf1c7d3c11d37aced611ef
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 #ifdef __INTERIX
2503 /* The top bit makes the value negative, which means the file doesn't
2504 * exist. Remove the bit, we don't use it. */
2505 return statb.st_mode & ~S_ADDACE;
2506 #else
2507 return statb.st_mode;
2508 #endif
2512 * set file permission for 'name' to 'perm'
2514 * return FAIL for failure, OK otherwise
2517 mch_setperm(name, perm)
2518 char_u *name;
2519 long perm;
2521 return (chmod((char *)
2522 #ifdef VMS
2523 vms_fixfilename(name),
2524 #else
2525 name,
2526 #endif
2527 (mode_t)perm) == 0 ? OK : FAIL);
2530 #if defined(HAVE_ACL) || defined(PROTO)
2531 # ifdef HAVE_SYS_ACL_H
2532 # include <sys/acl.h>
2533 # endif
2534 # ifdef HAVE_SYS_ACCESS_H
2535 # include <sys/access.h>
2536 # endif
2538 # ifdef HAVE_SOLARIS_ACL
2539 typedef struct vim_acl_solaris_T {
2540 int acl_cnt;
2541 aclent_t *acl_entry;
2542 } vim_acl_solaris_T;
2543 # endif
2546 * Return a pointer to the ACL of file "fname" in allocated memory.
2547 * Return NULL if the ACL is not available for whatever reason.
2549 vim_acl_T
2550 mch_get_acl(fname)
2551 char_u *fname;
2553 vim_acl_T ret = NULL;
2554 #ifdef HAVE_POSIX_ACL
2555 ret = (vim_acl_T)acl_get_file((char *)fname, ACL_TYPE_ACCESS);
2556 #else
2557 #ifdef HAVE_SOLARIS_ACL
2558 vim_acl_solaris_T *aclent;
2560 aclent = malloc(sizeof(vim_acl_solaris_T));
2561 if ((aclent->acl_cnt = acl((char *)fname, GETACLCNT, 0, NULL)) < 0)
2563 free(aclent);
2564 return NULL;
2566 aclent->acl_entry = malloc(aclent->acl_cnt * sizeof(aclent_t));
2567 if (acl((char *)fname, GETACL, aclent->acl_cnt, aclent->acl_entry) < 0)
2569 free(aclent->acl_entry);
2570 free(aclent);
2571 return NULL;
2573 ret = (vim_acl_T)aclent;
2574 #else
2575 #if defined(HAVE_AIX_ACL)
2576 int aclsize;
2577 struct acl *aclent;
2579 aclsize = sizeof(struct acl);
2580 aclent = malloc(aclsize);
2581 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2583 if (errno == ENOSPC)
2585 aclsize = aclent->acl_len;
2586 aclent = realloc(aclent, aclsize);
2587 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2589 free(aclent);
2590 return NULL;
2593 else
2595 free(aclent);
2596 return NULL;
2599 ret = (vim_acl_T)aclent;
2600 #endif /* HAVE_AIX_ACL */
2601 #endif /* HAVE_SOLARIS_ACL */
2602 #endif /* HAVE_POSIX_ACL */
2603 return ret;
2607 * Set the ACL of file "fname" to "acl" (unless it's NULL).
2609 void
2610 mch_set_acl(fname, aclent)
2611 char_u *fname;
2612 vim_acl_T aclent;
2614 if (aclent == NULL)
2615 return;
2616 #ifdef HAVE_POSIX_ACL
2617 acl_set_file((char *)fname, ACL_TYPE_ACCESS, (acl_t)aclent);
2618 #else
2619 #ifdef HAVE_SOLARIS_ACL
2620 acl((char *)fname, SETACL, ((vim_acl_solaris_T *)aclent)->acl_cnt,
2621 ((vim_acl_solaris_T *)aclent)->acl_entry);
2622 #else
2623 #ifdef HAVE_AIX_ACL
2624 chacl((char *)fname, aclent, ((struct acl *)aclent)->acl_len);
2625 #endif /* HAVE_AIX_ACL */
2626 #endif /* HAVE_SOLARIS_ACL */
2627 #endif /* HAVE_POSIX_ACL */
2630 void
2631 mch_free_acl(aclent)
2632 vim_acl_T aclent;
2634 if (aclent == NULL)
2635 return;
2636 #ifdef HAVE_POSIX_ACL
2637 acl_free((acl_t)aclent);
2638 #else
2639 #ifdef HAVE_SOLARIS_ACL
2640 free(((vim_acl_solaris_T *)aclent)->acl_entry);
2641 free(aclent);
2642 #else
2643 #ifdef HAVE_AIX_ACL
2644 free(aclent);
2645 #endif /* HAVE_AIX_ACL */
2646 #endif /* HAVE_SOLARIS_ACL */
2647 #endif /* HAVE_POSIX_ACL */
2649 #endif
2652 * Set hidden flag for "name".
2654 /* ARGSUSED */
2655 void
2656 mch_hide(name)
2657 char_u *name;
2659 /* can't hide a file */
2663 * return TRUE if "name" is a directory
2664 * return FALSE if "name" is not a directory
2665 * return FALSE for error
2668 mch_isdir(name)
2669 char_u *name;
2671 struct stat statb;
2673 if (*name == NUL) /* Some stat()s don't flag "" as an error. */
2674 return FALSE;
2675 if (stat((char *)name, &statb))
2676 return FALSE;
2677 #ifdef _POSIX_SOURCE
2678 return (S_ISDIR(statb.st_mode) ? TRUE : FALSE);
2679 #else
2680 return ((statb.st_mode & S_IFMT) == S_IFDIR ? TRUE : FALSE);
2681 #endif
2684 static int executable_file __ARGS((char_u *name));
2687 * Return 1 if "name" is an executable file, 0 if not or it doesn't exist.
2689 static int
2690 executable_file(name)
2691 char_u *name;
2693 struct stat st;
2695 if (stat((char *)name, &st))
2696 return 0;
2697 return S_ISREG(st.st_mode) && mch_access((char *)name, X_OK) == 0;
2701 * Return 1 if "name" can be found in $PATH and executed, 0 if not.
2702 * Return -1 if unknown.
2705 mch_can_exe(name)
2706 char_u *name;
2708 char_u *buf;
2709 char_u *p, *e;
2710 int retval;
2712 /* If it's an absolute or relative path don't need to use $PATH. */
2713 if (mch_isFullName(name) || (name[0] == '.' && (name[1] == '/'
2714 || (name[1] == '.' && name[2] == '/'))))
2715 return executable_file(name);
2717 p = (char_u *)getenv("PATH");
2718 if (p == NULL || *p == NUL)
2719 return -1;
2720 buf = alloc((unsigned)(STRLEN(name) + STRLEN(p) + 2));
2721 if (buf == NULL)
2722 return -1;
2725 * Walk through all entries in $PATH to check if "name" exists there and
2726 * is an executable file.
2728 for (;;)
2730 e = (char_u *)strchr((char *)p, ':');
2731 if (e == NULL)
2732 e = p + STRLEN(p);
2733 if (e - p <= 1) /* empty entry means current dir */
2734 STRCPY(buf, "./");
2735 else
2737 vim_strncpy(buf, p, e - p);
2738 add_pathsep(buf);
2740 STRCAT(buf, name);
2741 retval = executable_file(buf);
2742 if (retval == 1)
2743 break;
2745 if (*e != ':')
2746 break;
2747 p = e + 1;
2750 vim_free(buf);
2751 return retval;
2755 * Check what "name" is:
2756 * NODE_NORMAL: file or directory (or doesn't exist)
2757 * NODE_WRITABLE: writable device, socket, fifo, etc.
2758 * NODE_OTHER: non-writable things
2761 mch_nodetype(name)
2762 char_u *name;
2764 struct stat st;
2766 if (stat((char *)name, &st))
2767 return NODE_NORMAL;
2768 if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
2769 return NODE_NORMAL;
2770 #ifndef OS2
2771 if (S_ISBLK(st.st_mode)) /* block device isn't writable */
2772 return NODE_OTHER;
2773 #endif
2774 /* Everything else is writable? */
2775 return NODE_WRITABLE;
2778 void
2779 mch_early_init()
2781 #ifdef HAVE_CHECK_STACK_GROWTH
2782 int i;
2784 check_stack_growth((char *)&i);
2786 # ifdef HAVE_STACK_LIMIT
2787 get_stack_limit();
2788 # endif
2790 #endif
2793 * Setup an alternative stack for signals. Helps to catch signals when
2794 * running out of stack space.
2795 * Use of sigaltstack() is preferred, it's more portable.
2796 * Ignore any errors.
2798 #if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2799 signal_stack = malloc(SIGSTKSZ);
2800 init_signal_stack();
2801 #endif
2804 #if defined(EXITFREE) || defined(PROTO)
2805 void
2806 mch_free_mem()
2808 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
2809 if (clip_star.owned)
2810 clip_lose_selection(&clip_star);
2811 if (clip_plus.owned)
2812 clip_lose_selection(&clip_plus);
2813 # endif
2814 # if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
2815 if (xterm_Shell != (Widget)0)
2816 XtDestroyWidget(xterm_Shell);
2817 if (xterm_dpy != NULL)
2818 XtCloseDisplay(xterm_dpy);
2819 if (app_context != (XtAppContext)NULL)
2820 XtDestroyApplicationContext(app_context);
2821 # endif
2822 # ifdef FEAT_X11
2823 if (x11_display != NULL && x11_display != xterm_dpy)
2824 XCloseDisplay(x11_display);
2825 # endif
2826 # if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2827 vim_free(signal_stack);
2828 signal_stack = NULL;
2829 # endif
2830 # ifdef FEAT_TITLE
2831 vim_free(oldtitle);
2832 vim_free(oldicon);
2833 # endif
2835 #endif
2837 static void exit_scroll __ARGS((void));
2840 * Output a newline when exiting.
2841 * Make sure the newline goes to the same stream as the text.
2843 static void
2844 exit_scroll()
2846 if (silent_mode)
2847 return;
2848 if (newline_on_exit || msg_didout)
2850 if (msg_use_printf())
2852 if (info_message)
2853 mch_msg("\n");
2854 else
2855 mch_errmsg("\r\n");
2857 else
2858 out_char('\n');
2860 else
2862 restore_cterm_colors(); /* get original colors back */
2863 msg_clr_eos_force(); /* clear the rest of the display */
2864 windgoto((int)Rows - 1, 0); /* may have moved the cursor */
2868 void
2869 mch_exit(r)
2870 int r;
2872 exiting = TRUE;
2874 #if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
2875 x11_export_final_selection();
2876 #endif
2878 #ifdef FEAT_GUI
2879 if (!gui.in_use)
2880 #endif
2882 settmode(TMODE_COOK);
2883 #ifdef FEAT_TITLE
2884 mch_restore_title(3); /* restore xterm title and icon name */
2885 #endif
2887 * When t_ti is not empty but it doesn't cause swapping terminal
2888 * pages, need to output a newline when msg_didout is set. But when
2889 * t_ti does swap pages it should not go to the shell page. Do this
2890 * before stoptermcap().
2892 if (swapping_screen() && !newline_on_exit)
2893 exit_scroll();
2895 /* Stop termcap: May need to check for T_CRV response, which
2896 * requires RAW mode. */
2897 stoptermcap();
2900 * A newline is only required after a message in the alternate screen.
2901 * This is set to TRUE by wait_return().
2903 if (!swapping_screen() || newline_on_exit)
2904 exit_scroll();
2906 /* Cursor may have been switched off without calling starttermcap()
2907 * when doing "vim -u vimrc" and vimrc contains ":q". */
2908 if (full_screen)
2909 cursor_on();
2911 out_flush();
2912 ml_close_all(TRUE); /* remove all memfiles */
2913 may_core_dump();
2914 #ifdef FEAT_GUI
2915 if (gui.in_use)
2916 gui_exit(r);
2917 #endif
2919 #ifdef MACOS_CONVERT
2920 mac_conv_cleanup();
2921 #endif
2923 #ifdef __QNX__
2924 /* A core dump won't be created if the signal handler
2925 * doesn't return, so we can't call exit() */
2926 if (deadly_signal != 0)
2927 return;
2928 #endif
2930 #ifdef FEAT_NETBEANS_INTG
2931 if (usingNetbeans)
2932 netbeans_send_disconnect();
2933 #endif
2935 #ifdef EXITFREE
2936 free_all_mem();
2937 #endif
2939 exit(r);
2942 static void
2943 may_core_dump()
2945 if (deadly_signal != 0)
2947 signal(deadly_signal, SIG_DFL);
2948 kill(getpid(), deadly_signal); /* Die using the signal we caught */
2952 #ifndef VMS
2954 void
2955 mch_settmode(tmode)
2956 int tmode;
2958 static int first = TRUE;
2960 /* Why is NeXT excluded here (and not in os_unixx.h)? */
2961 #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
2963 * for "new" tty systems
2965 # ifdef HAVE_TERMIOS_H
2966 static struct termios told;
2967 struct termios tnew;
2968 # else
2969 static struct termio told;
2970 struct termio tnew;
2971 # endif
2973 if (first)
2975 first = FALSE;
2976 # if defined(HAVE_TERMIOS_H)
2977 tcgetattr(read_cmd_fd, &told);
2978 # else
2979 ioctl(read_cmd_fd, TCGETA, &told);
2980 # endif
2983 tnew = told;
2984 if (tmode == TMODE_RAW)
2987 * ~ICRNL enables typing ^V^M
2989 tnew.c_iflag &= ~ICRNL;
2990 tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE
2991 # if defined(IEXTEN) && !defined(__MINT__)
2992 | IEXTEN /* IEXTEN enables typing ^V on SOLARIS */
2993 /* but it breaks function keys on MINT */
2994 # endif
2996 # ifdef ONLCR /* don't map NL -> CR NL, we do it ourselves */
2997 tnew.c_oflag &= ~ONLCR;
2998 # endif
2999 tnew.c_cc[VMIN] = 1; /* return after 1 char */
3000 tnew.c_cc[VTIME] = 0; /* don't wait */
3002 else if (tmode == TMODE_SLEEP)
3003 tnew.c_lflag &= ~(ECHO);
3005 # if defined(HAVE_TERMIOS_H)
3007 int n = 10;
3009 /* A signal may cause tcsetattr() to fail (e.g., SIGCONT). Retry a
3010 * few times. */
3011 while (tcsetattr(read_cmd_fd, TCSANOW, &tnew) == -1
3012 && errno == EINTR && n > 0)
3013 --n;
3015 # else
3016 ioctl(read_cmd_fd, TCSETA, &tnew);
3017 # endif
3019 #else
3022 * for "old" tty systems
3024 # ifndef TIOCSETN
3025 # define TIOCSETN TIOCSETP /* for hpux 9.0 */
3026 # endif
3027 static struct sgttyb ttybold;
3028 struct sgttyb ttybnew;
3030 if (first)
3032 first = FALSE;
3033 ioctl(read_cmd_fd, TIOCGETP, &ttybold);
3036 ttybnew = ttybold;
3037 if (tmode == TMODE_RAW)
3039 ttybnew.sg_flags &= ~(CRMOD | ECHO);
3040 ttybnew.sg_flags |= RAW;
3042 else if (tmode == TMODE_SLEEP)
3043 ttybnew.sg_flags &= ~(ECHO);
3044 ioctl(read_cmd_fd, TIOCSETN, &ttybnew);
3045 #endif
3046 curr_tmode = tmode;
3050 * Try to get the code for "t_kb" from the stty setting
3052 * Even if termcap claims a backspace key, the user's setting *should*
3053 * prevail. stty knows more about reality than termcap does, and if
3054 * somebody's usual erase key is DEL (which, for most BSD users, it will
3055 * be), they're going to get really annoyed if their erase key starts
3056 * doing forward deletes for no reason. (Eric Fischer)
3058 void
3059 get_stty()
3061 char_u buf[2];
3062 char_u *p;
3064 /* Why is NeXT excluded here (and not in os_unixx.h)? */
3065 #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
3066 /* for "new" tty systems */
3067 # ifdef HAVE_TERMIOS_H
3068 struct termios keys;
3069 # else
3070 struct termio keys;
3071 # endif
3073 # if defined(HAVE_TERMIOS_H)
3074 if (tcgetattr(read_cmd_fd, &keys) != -1)
3075 # else
3076 if (ioctl(read_cmd_fd, TCGETA, &keys) != -1)
3077 # endif
3079 buf[0] = keys.c_cc[VERASE];
3080 intr_char = keys.c_cc[VINTR];
3081 #else
3082 /* for "old" tty systems */
3083 struct sgttyb keys;
3085 if (ioctl(read_cmd_fd, TIOCGETP, &keys) != -1)
3087 buf[0] = keys.sg_erase;
3088 intr_char = keys.sg_kill;
3089 #endif
3090 buf[1] = NUL;
3091 add_termcode((char_u *)"kb", buf, FALSE);
3094 * If <BS> and <DEL> are now the same, redefine <DEL>.
3096 p = find_termcode((char_u *)"kD");
3097 if (p != NULL && p[0] == buf[0] && p[1] == buf[1])
3098 do_fixdel(NULL);
3100 #if 0
3101 } /* to keep cindent happy */
3102 #endif
3105 #endif /* VMS */
3107 #if defined(FEAT_MOUSE_TTY) || defined(PROTO)
3109 * Set mouse clicks on or off.
3111 void
3112 mch_setmouse(on)
3113 int on;
3115 static int ison = FALSE;
3116 int xterm_mouse_vers;
3118 if (on == ison) /* return quickly if nothing to do */
3119 return;
3121 xterm_mouse_vers = use_xterm_mouse();
3122 if (xterm_mouse_vers > 0)
3124 if (on) /* enable mouse events, use mouse tracking if available */
3125 out_str_nf((char_u *)
3126 (xterm_mouse_vers > 1
3127 ? IF_EB("\033[?1002h", ESC_STR "[?1002h")
3128 : IF_EB("\033[?1000h", ESC_STR "[?1000h")));
3129 else /* disable mouse events, could probably always send the same */
3130 out_str_nf((char_u *)
3131 (xterm_mouse_vers > 1
3132 ? IF_EB("\033[?1002l", ESC_STR "[?1002l")
3133 : IF_EB("\033[?1000l", ESC_STR "[?1000l")));
3134 ison = on;
3137 # ifdef FEAT_MOUSE_DEC
3138 else if (ttym_flags == TTYM_DEC)
3140 if (on) /* enable mouse events */
3141 out_str_nf((char_u *)"\033[1;2'z\033[1;3'{");
3142 else /* disable mouse events */
3143 out_str_nf((char_u *)"\033['z");
3144 ison = on;
3146 # endif
3148 # ifdef FEAT_MOUSE_GPM
3149 else
3151 if (on)
3153 if (gpm_open())
3154 ison = TRUE;
3156 else
3158 gpm_close();
3159 ison = FALSE;
3162 # endif
3164 # ifdef FEAT_MOUSE_JSB
3165 else
3167 if (on)
3169 /* D - Enable Mouse up/down messages
3170 * L - Enable Left Button Reporting
3171 * M - Enable Middle Button Reporting
3172 * R - Enable Right Button Reporting
3173 * K - Enable SHIFT and CTRL key Reporting
3174 * + - Enable Advanced messaging of mouse moves and up/down messages
3175 * Q - Quiet No Ack
3176 * # - Numeric value of mouse pointer required
3177 * 0 = Multiview 2000 cursor, used as standard
3178 * 1 = Windows Arrow
3179 * 2 = Windows I Beam
3180 * 3 = Windows Hour Glass
3181 * 4 = Windows Cross Hair
3182 * 5 = Windows UP Arrow
3184 #ifdef JSBTERM_MOUSE_NONADVANCED /* Disables full feedback of pointer movements */
3185 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK1Q\033\\",
3186 ESC_STR "[0~ZwLMRK1Q" ESC_STR "\\"));
3187 #else
3188 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK+1Q\033\\",
3189 ESC_STR "[0~ZwLMRK+1Q" ESC_STR "\\"));
3190 #endif
3191 ison = TRUE;
3193 else
3195 out_str_nf((char_u *)IF_EB("\033[0~ZwQ\033\\",
3196 ESC_STR "[0~ZwQ" ESC_STR "\\"));
3197 ison = FALSE;
3200 # endif
3201 # ifdef FEAT_MOUSE_PTERM
3202 else
3204 /* 1 = button press, 6 = release, 7 = drag, 1h...9l = right button */
3205 if (on)
3206 out_str_nf("\033[>1h\033[>6h\033[>7h\033[>1h\033[>9l");
3207 else
3208 out_str_nf("\033[>1l\033[>6l\033[>7l\033[>1l\033[>9h");
3209 ison = on;
3211 # endif
3215 * Set the mouse termcode, depending on the 'term' and 'ttymouse' options.
3217 void
3218 check_mouse_termcode()
3220 # ifdef FEAT_MOUSE_XTERM
3221 if (use_xterm_mouse()
3222 # ifdef FEAT_GUI
3223 && !gui.in_use
3224 # endif
3227 set_mouse_termcode(KS_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3228 ? IF_EB("\233M", CSI_STR "M")
3229 : IF_EB("\033[M", ESC_STR "[M")));
3230 if (*p_mouse != NUL)
3232 /* force mouse off and maybe on to send possibly new mouse
3233 * activation sequence to the xterm, with(out) drag tracing. */
3234 mch_setmouse(FALSE);
3235 setmouse();
3238 else
3239 del_mouse_termcode(KS_MOUSE);
3240 # endif
3242 # ifdef FEAT_MOUSE_GPM
3243 if (!use_xterm_mouse()
3244 # ifdef FEAT_GUI
3245 && !gui.in_use
3246 # endif
3248 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MG", ESC_STR "MG"));
3249 # endif
3251 # ifdef FEAT_MOUSE_JSB
3252 /* conflicts with xterm mouse: "\033[" and "\033[M" ??? */
3253 if (!use_xterm_mouse()
3254 # ifdef FEAT_GUI
3255 && !gui.in_use
3256 # endif
3258 set_mouse_termcode(KS_JSBTERM_MOUSE,
3259 (char_u *)IF_EB("\033[0~zw", ESC_STR "[0~zw"));
3260 else
3261 del_mouse_termcode(KS_JSBTERM_MOUSE);
3262 # endif
3264 # ifdef FEAT_MOUSE_NET
3265 /* There is no conflict, but one may type "ESC }" from Insert mode. Don't
3266 * define it in the GUI or when using an xterm. */
3267 if (!use_xterm_mouse()
3268 # ifdef FEAT_GUI
3269 && !gui.in_use
3270 # endif
3272 set_mouse_termcode(KS_NETTERM_MOUSE,
3273 (char_u *)IF_EB("\033}", ESC_STR "}"));
3274 else
3275 del_mouse_termcode(KS_NETTERM_MOUSE);
3276 # endif
3278 # ifdef FEAT_MOUSE_DEC
3279 /* conflicts with xterm mouse: "\033[" and "\033[M" */
3280 if (!use_xterm_mouse()
3281 # ifdef FEAT_GUI
3282 && !gui.in_use
3283 # endif
3285 set_mouse_termcode(KS_DEC_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3286 ? IF_EB("\233", CSI_STR) : IF_EB("\033[", ESC_STR "[")));
3287 else
3288 del_mouse_termcode(KS_DEC_MOUSE);
3289 # endif
3290 # ifdef FEAT_MOUSE_PTERM
3291 /* same as the dec mouse */
3292 if (!use_xterm_mouse()
3293 # ifdef FEAT_GUI
3294 && !gui.in_use
3295 # endif
3297 set_mouse_termcode(KS_PTERM_MOUSE,
3298 (char_u *) IF_EB("\033[", ESC_STR "["));
3299 else
3300 del_mouse_termcode(KS_PTERM_MOUSE);
3301 # endif
3303 #endif
3306 * set screen mode, always fails.
3308 /* ARGSUSED */
3310 mch_screenmode(arg)
3311 char_u *arg;
3313 EMSG(_(e_screenmode));
3314 return FAIL;
3317 #ifndef VMS
3320 * Try to get the current window size:
3321 * 1. with an ioctl(), most accurate method
3322 * 2. from the environment variables LINES and COLUMNS
3323 * 3. from the termcap
3324 * 4. keep using the old values
3325 * Return OK when size could be determined, FAIL otherwise.
3328 mch_get_shellsize()
3330 long rows = 0;
3331 long columns = 0;
3332 char_u *p;
3335 * For OS/2 use _scrsize().
3337 # ifdef __EMX__
3339 int s[2];
3341 _scrsize(s);
3342 columns = s[0];
3343 rows = s[1];
3345 # endif
3348 * 1. try using an ioctl. It is the most accurate method.
3350 * Try using TIOCGWINSZ first, some systems that have it also define
3351 * TIOCGSIZE but don't have a struct ttysize.
3353 # ifdef TIOCGWINSZ
3355 struct winsize ws;
3356 int fd = 1;
3358 /* When stdout is not a tty, use stdin for the ioctl(). */
3359 if (!isatty(fd) && isatty(read_cmd_fd))
3360 fd = read_cmd_fd;
3361 if (ioctl(fd, TIOCGWINSZ, &ws) == 0)
3363 columns = ws.ws_col;
3364 rows = ws.ws_row;
3367 # else /* TIOCGWINSZ */
3368 # ifdef TIOCGSIZE
3370 struct ttysize ts;
3371 int fd = 1;
3373 /* When stdout is not a tty, use stdin for the ioctl(). */
3374 if (!isatty(fd) && isatty(read_cmd_fd))
3375 fd = read_cmd_fd;
3376 if (ioctl(fd, TIOCGSIZE, &ts) == 0)
3378 columns = ts.ts_cols;
3379 rows = ts.ts_lines;
3382 # endif /* TIOCGSIZE */
3383 # endif /* TIOCGWINSZ */
3386 * 2. get size from environment
3387 * When being POSIX compliant ('|' flag in 'cpoptions') this overrules
3388 * the ioctl() values!
3390 if (columns == 0 || rows == 0 || vim_strchr(p_cpo, CPO_TSIZE) != NULL)
3392 if ((p = (char_u *)getenv("LINES")))
3393 rows = atoi((char *)p);
3394 if ((p = (char_u *)getenv("COLUMNS")))
3395 columns = atoi((char *)p);
3398 #ifdef HAVE_TGETENT
3400 * 3. try reading "co" and "li" entries from termcap
3402 if (columns == 0 || rows == 0)
3403 getlinecol(&columns, &rows);
3404 #endif
3407 * 4. If everything fails, use the old values
3409 if (columns <= 0 || rows <= 0)
3410 return FAIL;
3412 Rows = rows;
3413 Columns = columns;
3414 return OK;
3418 * Try to set the window size to Rows and Columns.
3420 void
3421 mch_set_shellsize()
3423 if (*T_CWS)
3426 * NOTE: if you get an error here that term_set_winsize() is
3427 * undefined, check the output of configure. It could probably not
3428 * find a ncurses, termcap or termlib library.
3430 term_set_winsize((int)Rows, (int)Columns);
3431 out_flush();
3432 screen_start(); /* don't know where cursor is now */
3436 #endif /* VMS */
3439 * Rows and/or Columns has changed.
3441 void
3442 mch_new_shellsize()
3444 /* Nothing to do. */
3447 #ifndef USE_SYSTEM
3448 static void append_ga_line __ARGS((garray_T *gap));
3451 * Append the text in "gap" below the cursor line and clear "gap".
3453 static void
3454 append_ga_line(gap)
3455 garray_T *gap;
3457 /* Remove trailing CR. */
3458 if (gap->ga_len > 0
3459 && !curbuf->b_p_bin
3460 && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR)
3461 --gap->ga_len;
3462 ga_append(gap, NUL);
3463 ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE);
3464 gap->ga_len = 0;
3466 #endif
3469 mch_call_shell(cmd, options)
3470 char_u *cmd;
3471 int options; /* SHELL_*, see vim.h */
3473 #ifdef VMS
3474 char *ifn = NULL;
3475 char *ofn = NULL;
3476 #endif
3477 int tmode = cur_tmode;
3478 #ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
3479 int x;
3480 # ifndef __EMX__
3481 char_u *newcmd; /* only needed for unix */
3482 # else
3484 * Set the preferred shell in the EMXSHELL environment variable (but
3485 * only if it is different from what is already in the environment).
3486 * Emx then takes care of whether to use "/c" or "-c" in an
3487 * intelligent way. Simply pass the whole thing to emx's system() call.
3488 * Emx also starts an interactive shell if system() is passed an empty
3489 * string.
3491 char_u *p, *old;
3493 if (((old = (char_u *)getenv("EMXSHELL")) == NULL) || STRCMP(old, p_sh))
3495 /* should check HAVE_SETENV, but I know we don't have it. */
3496 p = alloc(10 + strlen(p_sh));
3497 if (p)
3499 sprintf((char *)p, "EMXSHELL=%s", p_sh);
3500 putenv((char *)p); /* don't free the pointer! */
3503 # endif
3505 out_flush();
3507 if (options & SHELL_COOKED)
3508 settmode(TMODE_COOK); /* set to normal mode */
3510 # ifdef __EMX__
3511 if (cmd == NULL)
3512 x = system(""); /* this starts an interactive shell in emx */
3513 else
3514 x = system((char *)cmd);
3515 /* system() returns -1 when error occurs in starting shell */
3516 if (x == -1 && !emsg_silent)
3518 MSG_PUTS(_("\nCannot execute shell "));
3519 msg_outtrans(p_sh);
3520 msg_putchar('\n');
3522 # else /* not __EMX__ */
3523 if (cmd == NULL)
3524 x = system((char *)p_sh);
3525 else
3527 # ifdef VMS
3528 if (ofn = strchr((char *)cmd, '>'))
3529 *ofn++ = '\0';
3530 if (ifn = strchr((char *)cmd, '<'))
3532 char *p;
3534 *ifn++ = '\0';
3535 p = strchr(ifn,' '); /* chop off any trailing spaces */
3536 if (p)
3537 *p = '\0';
3539 if (ofn)
3540 x = vms_sys((char *)cmd, ofn, ifn);
3541 else
3542 x = system((char *)cmd);
3543 # else
3544 newcmd = lalloc(STRLEN(p_sh)
3545 + (extra_shell_arg == NULL ? 0 : STRLEN(extra_shell_arg))
3546 + STRLEN(p_shcf) + STRLEN(cmd) + 4, TRUE);
3547 if (newcmd == NULL)
3548 x = 0;
3549 else
3551 sprintf((char *)newcmd, "%s %s %s %s", p_sh,
3552 extra_shell_arg == NULL ? "" : (char *)extra_shell_arg,
3553 (char *)p_shcf,
3554 (char *)cmd);
3555 x = system((char *)newcmd);
3556 vim_free(newcmd);
3558 # endif
3560 # ifdef VMS
3561 x = vms_sys_status(x);
3562 # endif
3563 if (emsg_silent)
3565 else if (x == 127)
3566 MSG_PUTS(_("\nCannot execute shell sh\n"));
3567 # endif /* __EMX__ */
3568 else if (x && !(options & SHELL_SILENT))
3570 MSG_PUTS(_("\nshell returned "));
3571 msg_outnum((long)x);
3572 msg_putchar('\n');
3575 if (tmode == TMODE_RAW)
3576 settmode(TMODE_RAW); /* set to raw mode */
3577 # ifdef FEAT_TITLE
3578 resettitle();
3579 # endif
3580 return x;
3582 #else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
3584 # define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
3585 127, some shells use that already */
3587 char_u *newcmd = NULL;
3588 pid_t pid;
3589 pid_t wpid = 0;
3590 pid_t wait_pid = 0;
3591 # ifdef HAVE_UNION_WAIT
3592 union wait status;
3593 # else
3594 int status = -1;
3595 # endif
3596 int retval = -1;
3597 char **argv = NULL;
3598 int argc;
3599 int i;
3600 char_u *p;
3601 int inquote;
3602 int pty_master_fd = -1; /* for pty's */
3603 # ifdef FEAT_GUI
3604 int pty_slave_fd = -1;
3605 char *tty_name;
3606 # endif
3607 int fd_toshell[2]; /* for pipes */
3608 int fd_fromshell[2];
3609 int pipe_error = FALSE;
3610 # ifdef HAVE_SETENV
3611 char envbuf[50];
3612 # else
3613 static char envbuf_Rows[20];
3614 static char envbuf_Columns[20];
3615 # endif
3616 int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
3618 out_flush();
3619 if (options & SHELL_COOKED)
3620 settmode(TMODE_COOK); /* set to normal mode */
3622 newcmd = vim_strsave(p_sh);
3623 if (newcmd == NULL) /* out of memory */
3624 goto error;
3627 * Do this loop twice:
3628 * 1: find number of arguments
3629 * 2: separate them and build argv[]
3631 for (i = 0; i < 2; ++i)
3633 p = newcmd;
3634 inquote = FALSE;
3635 argc = 0;
3636 for (;;)
3638 if (i == 1)
3639 argv[argc] = (char *)p;
3640 ++argc;
3641 while (*p && (inquote || (*p != ' ' && *p != TAB)))
3643 if (*p == '"')
3644 inquote = !inquote;
3645 ++p;
3647 if (*p == NUL)
3648 break;
3649 if (i == 1)
3650 *p++ = NUL;
3651 p = skipwhite(p);
3653 if (argv == NULL)
3655 argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *)));
3656 if (argv == NULL) /* out of memory */
3657 goto error;
3660 if (cmd != NULL)
3662 if (extra_shell_arg != NULL)
3663 argv[argc++] = (char *)extra_shell_arg;
3664 argv[argc++] = (char *)p_shcf;
3665 argv[argc++] = (char *)cmd;
3667 argv[argc] = NULL;
3670 * For the GUI, when writing the output into the buffer and when reading
3671 * input from the buffer: Try using a pseudo-tty to get the stdin/stdout
3672 * of the executed command into the Vim window. Or use a pipe.
3674 if ((options & (SHELL_READ|SHELL_WRITE))
3675 # ifdef FEAT_GUI
3676 || (gui.in_use && show_shell_mess)
3677 # endif
3680 # ifdef FEAT_GUI
3682 * Try to open a master pty.
3683 * If this works, open the slave pty.
3684 * If the slave can't be opened, close the master pty.
3686 if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
3688 pty_master_fd = OpenPTY(&tty_name); /* open pty */
3689 if (pty_master_fd >= 0 && ((pty_slave_fd =
3690 open(tty_name, O_RDWR | O_EXTRA, 0)) < 0))
3692 close(pty_master_fd);
3693 pty_master_fd = -1;
3697 * If not opening a pty or it didn't work, try using pipes.
3699 if (pty_master_fd < 0)
3700 # endif
3702 pipe_error = (pipe(fd_toshell) < 0);
3703 if (!pipe_error) /* pipe create OK */
3705 pipe_error = (pipe(fd_fromshell) < 0);
3706 if (pipe_error) /* pipe create failed */
3708 close(fd_toshell[0]);
3709 close(fd_toshell[1]);
3712 if (pipe_error)
3714 MSG_PUTS(_("\nCannot create pipes\n"));
3715 out_flush();
3720 if (!pipe_error) /* pty or pipe opened or not used */
3722 # ifdef __BEOS__
3723 beos_cleanup_read_thread();
3724 # endif
3726 if ((pid = fork()) == -1) /* maybe we should use vfork() */
3728 MSG_PUTS(_("\nCannot fork\n"));
3729 if ((options & (SHELL_READ|SHELL_WRITE))
3730 # ifdef FEAT_GUI
3731 || (gui.in_use && show_shell_mess)
3732 # endif
3735 # ifdef FEAT_GUI
3736 if (pty_master_fd >= 0) /* close the pseudo tty */
3738 close(pty_master_fd);
3739 close(pty_slave_fd);
3741 else /* close the pipes */
3742 # endif
3744 close(fd_toshell[0]);
3745 close(fd_toshell[1]);
3746 close(fd_fromshell[0]);
3747 close(fd_fromshell[1]);
3751 else if (pid == 0) /* child */
3753 reset_signals(); /* handle signals normally */
3755 if (!show_shell_mess || (options & SHELL_EXPAND))
3757 int fd;
3760 * Don't want to show any message from the shell. Can't just
3761 * close stdout and stderr though, because some systems will
3762 * break if you try to write to them after that, so we must
3763 * use dup() to replace them with something else -- webb
3764 * Connect stdin to /dev/null too, so ":n `cat`" doesn't hang,
3765 * waiting for input.
3767 fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
3768 fclose(stdin);
3769 fclose(stdout);
3770 fclose(stderr);
3773 * If any of these open()'s and dup()'s fail, we just continue
3774 * anyway. It's not fatal, and on most systems it will make
3775 * no difference at all. On a few it will cause the execvp()
3776 * to exit with a non-zero status even when the completion
3777 * could be done, which is nothing too serious. If the open()
3778 * or dup() failed we'd just do the same thing ourselves
3779 * anyway -- webb
3781 if (fd >= 0)
3783 dup(fd); /* To replace stdin (file descriptor 0) */
3784 dup(fd); /* To replace stdout (file descriptor 1) */
3785 dup(fd); /* To replace stderr (file descriptor 2) */
3787 /* Don't need this now that we've duplicated it */
3788 close(fd);
3791 else if ((options & (SHELL_READ|SHELL_WRITE))
3792 # ifdef FEAT_GUI
3793 || gui.in_use
3794 # endif
3798 # ifdef HAVE_SETSID
3799 /* Create our own process group, so that the child and all its
3800 * children can be kill()ed. Don't do this when using pipes,
3801 * because stdin is not a tty, we would loose /dev/tty. */
3802 if (p_stmp)
3803 (void)setsid();
3804 # endif
3805 # ifdef FEAT_GUI
3806 if (pty_slave_fd >= 0)
3808 /* push stream discipline modules */
3809 if (options & SHELL_COOKED)
3810 SetupSlavePTY(pty_slave_fd);
3811 # ifdef TIOCSCTTY
3812 /* Try to become controlling tty (probably doesn't work,
3813 * unless run by root) */
3814 ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
3815 # endif
3817 # endif
3818 /* Simulate to have a dumb terminal (for now) */
3819 # ifdef HAVE_SETENV
3820 setenv("TERM", "dumb", 1);
3821 sprintf((char *)envbuf, "%ld", Rows);
3822 setenv("ROWS", (char *)envbuf, 1);
3823 sprintf((char *)envbuf, "%ld", Rows);
3824 setenv("LINES", (char *)envbuf, 1);
3825 sprintf((char *)envbuf, "%ld", Columns);
3826 setenv("COLUMNS", (char *)envbuf, 1);
3827 # else
3829 * Putenv does not copy the string, it has to remain valid.
3830 * Use a static array to avoid loosing allocated memory.
3832 putenv("TERM=dumb");
3833 sprintf(envbuf_Rows, "ROWS=%ld", Rows);
3834 putenv(envbuf_Rows);
3835 sprintf(envbuf_Rows, "LINES=%ld", Rows);
3836 putenv(envbuf_Rows);
3837 sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
3838 putenv(envbuf_Columns);
3839 # endif
3842 * stderr is only redirected when using the GUI, so that a
3843 * program like gpg can still access the terminal to get a
3844 * passphrase using stderr.
3846 # ifdef FEAT_GUI
3847 if (pty_master_fd >= 0)
3849 close(pty_master_fd); /* close master side of pty */
3851 /* set up stdin/stdout/stderr for the child */
3852 close(0);
3853 dup(pty_slave_fd);
3854 close(1);
3855 dup(pty_slave_fd);
3856 if (gui.in_use)
3858 close(2);
3859 dup(pty_slave_fd);
3862 close(pty_slave_fd); /* has been dupped, close it now */
3864 else
3865 # endif
3867 /* set up stdin for the child */
3868 close(fd_toshell[1]);
3869 close(0);
3870 dup(fd_toshell[0]);
3871 close(fd_toshell[0]);
3873 /* set up stdout for the child */
3874 close(fd_fromshell[0]);
3875 close(1);
3876 dup(fd_fromshell[1]);
3877 close(fd_fromshell[1]);
3879 # ifdef FEAT_GUI
3880 if (gui.in_use)
3882 /* set up stderr for the child */
3883 close(2);
3884 dup(1);
3886 # endif
3891 * There is no type cast for the argv, because the type may be
3892 * different on different machines. This may cause a warning
3893 * message with strict compilers, don't worry about it.
3894 * Call _exit() instead of exit() to avoid closing the connection
3895 * to the X server (esp. with GTK, which uses atexit()).
3897 execvp(argv[0], argv);
3898 _exit(EXEC_FAILED); /* exec failed, return failure code */
3900 else /* parent */
3903 * While child is running, ignore terminating signals.
3904 * Do catch CTRL-C, so that "got_int" is set.
3906 catch_signals(SIG_IGN, SIG_ERR);
3907 catch_int_signal();
3910 * For the GUI we redirect stdin, stdout and stderr to our window.
3911 * This is also used to pipe stdin/stdout to/from the external
3912 * command.
3914 if ((options & (SHELL_READ|SHELL_WRITE))
3915 # ifdef FEAT_GUI
3916 || (gui.in_use && show_shell_mess)
3917 # endif
3920 # define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
3921 char_u buffer[BUFLEN + 1];
3922 # ifdef FEAT_MBYTE
3923 int buffer_off = 0; /* valid bytes in buffer[] */
3924 # endif
3925 char_u ta_buf[BUFLEN + 1]; /* TypeAHead */
3926 int ta_len = 0; /* valid bytes in ta_buf[] */
3927 int len;
3928 int p_more_save;
3929 int old_State;
3930 int c;
3931 int toshell_fd;
3932 int fromshell_fd;
3933 garray_T ga;
3934 int noread_cnt;
3936 # ifdef FEAT_GUI
3937 if (pty_master_fd >= 0)
3939 close(pty_slave_fd); /* close slave side of pty */
3940 fromshell_fd = pty_master_fd;
3941 toshell_fd = dup(pty_master_fd);
3943 else
3944 # endif
3946 close(fd_toshell[0]);
3947 close(fd_fromshell[1]);
3948 toshell_fd = fd_toshell[1];
3949 fromshell_fd = fd_fromshell[0];
3953 * Write to the child if there are typed characters.
3954 * Read from the child if there are characters available.
3955 * Repeat the reading a few times if more characters are
3956 * available. Need to check for typed keys now and then, but
3957 * not too often (delays when no chars are available).
3958 * This loop is quit if no characters can be read from the pty
3959 * (WaitForChar detected special condition), or there are no
3960 * characters available and the child has exited.
3961 * Only check if the child has exited when there is no more
3962 * output. The child may exit before all the output has
3963 * been printed.
3965 * Currently this busy loops!
3966 * This can probably dead-lock when the write blocks!
3968 p_more_save = p_more;
3969 p_more = FALSE;
3970 old_State = State;
3971 State = EXTERNCMD; /* don't redraw at window resize */
3973 if ((options & SHELL_WRITE) && toshell_fd >= 0)
3975 /* Fork a process that will write the lines to the
3976 * external program. */
3977 if ((wpid = fork()) == -1)
3979 MSG_PUTS(_("\nCannot fork\n"));
3981 else if (wpid == 0)
3983 linenr_T lnum = curbuf->b_op_start.lnum;
3984 int written = 0;
3985 char_u *lp = ml_get(lnum);
3986 char_u *s;
3987 size_t l;
3989 /* child */
3990 close(fromshell_fd);
3991 for (;;)
3993 l = STRLEN(lp + written);
3994 if (l == 0)
3995 len = 0;
3996 else if (lp[written] == NL)
3997 /* NL -> NUL translation */
3998 len = write(toshell_fd, "", (size_t)1);
3999 else
4001 s = vim_strchr(lp + written, NL);
4002 len = write(toshell_fd, (char *)lp + written,
4003 s == NULL ? l : s - (lp + written));
4005 if (len == l)
4007 /* Finished a line, add a NL, unless this line
4008 * should not have one. */
4009 if (lnum != curbuf->b_op_end.lnum
4010 || !curbuf->b_p_bin
4011 || (lnum != write_no_eol_lnum
4012 && (lnum !=
4013 curbuf->b_ml.ml_line_count
4014 || curbuf->b_p_eol)))
4015 write(toshell_fd, "\n", (size_t)1);
4016 ++lnum;
4017 if (lnum > curbuf->b_op_end.lnum)
4019 /* finished all the lines, close pipe */
4020 close(toshell_fd);
4021 toshell_fd = -1;
4022 break;
4024 lp = ml_get(lnum);
4025 written = 0;
4027 else if (len > 0)
4028 written += len;
4030 _exit(0);
4032 else
4034 close(toshell_fd);
4035 toshell_fd = -1;
4039 if (options & SHELL_READ)
4040 ga_init2(&ga, 1, BUFLEN);
4042 noread_cnt = 0;
4044 for (;;)
4047 * Check if keys have been typed, write them to the child
4048 * if there are any.
4049 * Don't do this if we are expanding wild cards (would eat
4050 * typeahead).
4051 * Don't do this when filtering and terminal is in cooked
4052 * mode, the shell command will handle the I/O. Avoids
4053 * that a typed password is echoed for ssh or gpg command.
4054 * Don't get characters when the child has already
4055 * finished (wait_pid == 0).
4056 * Don't get extra characters when we already have one.
4057 * Don't read characters unless we didn't get output for a
4058 * while, avoids that ":r !ls" eats typeahead.
4060 len = 0;
4061 if (!(options & SHELL_EXPAND)
4062 && ((options &
4063 (SHELL_READ|SHELL_WRITE|SHELL_COOKED))
4064 != (SHELL_READ|SHELL_WRITE|SHELL_COOKED)
4065 #ifdef FEAT_GUI
4066 || gui.in_use
4067 #endif
4069 && wait_pid == 0
4070 && (ta_len > 0
4071 || (noread_cnt > 4
4072 && (len = ui_inchar(ta_buf,
4073 BUFLEN, 10L, 0)) > 0)))
4076 * For pipes:
4077 * Check for CTRL-C: send interrupt signal to child.
4078 * Check for CTRL-D: EOF, close pipe to child.
4080 if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
4082 # ifdef SIGINT
4084 * Send SIGINT to the child's group or all
4085 * processes in our group.
4087 if (ta_buf[ta_len] == Ctrl_C
4088 || ta_buf[ta_len] == intr_char)
4090 # ifdef HAVE_SETSID
4091 kill(-pid, SIGINT);
4092 # else
4093 kill(0, SIGINT);
4094 # endif
4095 if (wpid > 0)
4096 kill(wpid, SIGINT);
4098 # endif
4099 if (pty_master_fd < 0 && toshell_fd >= 0
4100 && ta_buf[ta_len] == Ctrl_D)
4102 close(toshell_fd);
4103 toshell_fd = -1;
4107 /* replace K_BS by <BS> and K_DEL by <DEL> */
4108 for (i = ta_len; i < ta_len + len; ++i)
4110 if (ta_buf[i] == CSI && len - i > 2)
4112 c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]);
4113 if (c == K_DEL || c == K_KDEL || c == K_BS)
4115 mch_memmove(ta_buf + i + 1, ta_buf + i + 3,
4116 (size_t)(len - i - 2));
4117 if (c == K_DEL || c == K_KDEL)
4118 ta_buf[i] = DEL;
4119 else
4120 ta_buf[i] = Ctrl_H;
4121 len -= 2;
4124 else if (ta_buf[i] == '\r')
4125 ta_buf[i] = '\n';
4126 # ifdef FEAT_MBYTE
4127 if (has_mbyte)
4128 i += (*mb_ptr2len)(ta_buf + i) - 1;
4129 # endif
4133 * For pipes: echo the typed characters.
4134 * For a pty this does not seem to work.
4136 if (pty_master_fd < 0)
4138 for (i = ta_len; i < ta_len + len; ++i)
4140 if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
4141 msg_putchar(ta_buf[i]);
4142 # ifdef FEAT_MBYTE
4143 else if (has_mbyte)
4145 int l = (*mb_ptr2len)(ta_buf + i);
4147 msg_outtrans_len(ta_buf + i, l);
4148 i += l - 1;
4150 # endif
4151 else
4152 msg_outtrans_len(ta_buf + i, 1);
4154 windgoto(msg_row, msg_col);
4155 out_flush();
4158 ta_len += len;
4161 * Write the characters to the child, unless EOF has
4162 * been typed for pipes. Write one character at a
4163 * time, to avoid loosing too much typeahead.
4164 * When writing buffer lines, drop the typed
4165 * characters (only check for CTRL-C).
4167 if (options & SHELL_WRITE)
4168 ta_len = 0;
4169 else if (toshell_fd >= 0)
4171 len = write(toshell_fd, (char *)ta_buf, (size_t)1);
4172 if (len > 0)
4174 ta_len -= len;
4175 mch_memmove(ta_buf, ta_buf + len, ta_len);
4176 noread_cnt = 0;
4181 if (got_int)
4183 /* CTRL-C sends a signal to the child, we ignore it
4184 * ourselves */
4185 # ifdef HAVE_SETSID
4186 kill(-pid, SIGINT);
4187 # else
4188 kill(0, SIGINT);
4189 # endif
4190 if (wpid > 0)
4191 kill(wpid, SIGINT);
4192 got_int = FALSE;
4196 * Check if the child has any characters to be printed.
4197 * Read them and write them to our window. Repeat this as
4198 * long as there is something to do, avoid the 10ms wait
4199 * for mch_inchar(), or sending typeahead characters to
4200 * the external process.
4201 * TODO: This should handle escape sequences, compatible
4202 * to some terminal (vt52?).
4204 ++noread_cnt;
4205 while (RealWaitForChar(fromshell_fd, 10L, NULL))
4207 len = read(fromshell_fd, (char *)buffer
4208 # ifdef FEAT_MBYTE
4209 + buffer_off, (size_t)(BUFLEN - buffer_off)
4210 # else
4211 , (size_t)BUFLEN
4212 # endif
4214 if (len <= 0) /* end of file or error */
4215 goto finished;
4217 noread_cnt = 0;
4218 if (options & SHELL_READ)
4220 /* Do NUL -> NL translation, append NL separated
4221 * lines to the current buffer. */
4222 for (i = 0; i < len; ++i)
4224 if (buffer[i] == NL)
4225 append_ga_line(&ga);
4226 else if (buffer[i] == NUL)
4227 ga_append(&ga, NL);
4228 else
4229 ga_append(&ga, buffer[i]);
4232 # ifdef FEAT_MBYTE
4233 else if (has_mbyte)
4235 int l;
4237 len += buffer_off;
4238 buffer[len] = NUL;
4240 /* Check if the last character in buffer[] is
4241 * incomplete, keep these bytes for the next
4242 * round. */
4243 for (p = buffer; p < buffer + len; p += l)
4245 l = mb_cptr2len(p);
4246 if (l == 0)
4247 l = 1; /* NUL byte? */
4248 else if (MB_BYTE2LEN(*p) != l)
4249 break;
4251 if (p == buffer) /* no complete character */
4253 /* avoid getting stuck at an illegal byte */
4254 if (len >= 12)
4255 ++p;
4256 else
4258 buffer_off = len;
4259 continue;
4262 c = *p;
4263 *p = NUL;
4264 msg_puts(buffer);
4265 if (p < buffer + len)
4267 *p = c;
4268 buffer_off = (buffer + len) - p;
4269 mch_memmove(buffer, p, buffer_off);
4270 continue;
4272 buffer_off = 0;
4274 # endif /* FEAT_MBYTE */
4275 else
4277 buffer[len] = NUL;
4278 msg_puts(buffer);
4281 windgoto(msg_row, msg_col);
4282 cursor_on();
4283 out_flush();
4284 if (got_int)
4285 break;
4288 /* If we already detected the child has finished break the
4289 * loop now. */
4290 if (wait_pid == pid)
4291 break;
4294 * Check if the child still exists, before checking for
4295 * typed characters (otherwise we would loose typeahead).
4297 # ifdef __NeXT__
4298 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *) 0);
4299 # else
4300 wait_pid = waitpid(pid, &status, WNOHANG);
4301 # endif
4302 if ((wait_pid == (pid_t)-1 && errno == ECHILD)
4303 || (wait_pid == pid && WIFEXITED(status)))
4305 /* Don't break the loop yet, try reading more
4306 * characters from "fromshell_fd" first. When using
4307 * pipes there might still be something to read and
4308 * then we'll break the loop at the "break" above. */
4309 wait_pid = pid;
4311 else
4312 wait_pid = 0;
4314 finished:
4315 p_more = p_more_save;
4316 if (options & SHELL_READ)
4318 if (ga.ga_len > 0)
4320 append_ga_line(&ga);
4321 /* remember that the NL was missing */
4322 write_no_eol_lnum = curwin->w_cursor.lnum;
4324 else
4325 write_no_eol_lnum = 0;
4326 ga_clear(&ga);
4330 * Give all typeahead that wasn't used back to ui_inchar().
4332 if (ta_len)
4333 ui_inchar_undo(ta_buf, ta_len);
4334 State = old_State;
4335 if (toshell_fd >= 0)
4336 close(toshell_fd);
4337 close(fromshell_fd);
4341 * Wait until our child has exited.
4342 * Ignore wait() returning pids of other children and returning
4343 * because of some signal like SIGWINCH.
4344 * Don't wait if wait_pid was already set above, indicating the
4345 * child already exited.
4347 while (wait_pid != pid)
4349 # ifdef _THREAD_SAFE
4350 /* Ugly hack: when compiled with Python threads are probably
4351 * used, in which case wait() sometimes hangs for no obvious
4352 * reason. Use waitpid() instead and loop (like the GUI). */
4353 # ifdef __NeXT__
4354 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0);
4355 # else
4356 wait_pid = waitpid(pid, &status, WNOHANG);
4357 # endif
4358 if (wait_pid == 0)
4360 /* Wait for 1/100 sec before trying again. */
4361 mch_delay(10L, TRUE);
4362 continue;
4364 # else
4365 wait_pid = wait(&status);
4366 # endif
4367 if (wait_pid <= 0
4368 # ifdef ECHILD
4369 && errno == ECHILD
4370 # endif
4372 break;
4375 /* Make sure the child that writes to the external program is
4376 * dead. */
4377 if (wpid > 0)
4378 kill(wpid, SIGKILL);
4381 * Set to raw mode right now, otherwise a CTRL-C after
4382 * catch_signals() will kill Vim.
4384 if (tmode == TMODE_RAW)
4385 settmode(TMODE_RAW);
4386 did_settmode = TRUE;
4387 set_signals();
4389 if (WIFEXITED(status))
4391 /* LINTED avoid "bitwise operation on signed value" */
4392 retval = WEXITSTATUS(status);
4393 if (retval && !emsg_silent)
4395 if (retval == EXEC_FAILED)
4397 MSG_PUTS(_("\nCannot execute shell "));
4398 msg_outtrans(p_sh);
4399 msg_putchar('\n');
4401 else if (!(options & SHELL_SILENT))
4403 MSG_PUTS(_("\nshell returned "));
4404 msg_outnum((long)retval);
4405 msg_putchar('\n');
4409 else
4410 MSG_PUTS(_("\nCommand terminated\n"));
4413 vim_free(argv);
4415 error:
4416 if (!did_settmode)
4417 if (tmode == TMODE_RAW)
4418 settmode(TMODE_RAW); /* set to raw mode */
4419 # ifdef FEAT_TITLE
4420 resettitle();
4421 # endif
4422 vim_free(newcmd);
4424 return retval;
4426 #endif /* USE_SYSTEM */
4430 * Check for CTRL-C typed by reading all available characters.
4431 * In cooked mode we should get SIGINT, no need to check.
4433 void
4434 mch_breakcheck()
4436 if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL))
4437 fill_input_buf(FALSE);
4441 * Wait "msec" msec until a character is available from the keyboard or from
4442 * inbuf[]. msec == -1 will block forever.
4443 * When a GUI is being used, this will never get called -- webb
4445 static int
4446 WaitForChar(msec)
4447 long msec;
4449 #ifdef FEAT_MOUSE_GPM
4450 int gpm_process_wanted;
4451 #endif
4452 #ifdef FEAT_XCLIPBOARD
4453 int rest;
4454 #endif
4455 int avail;
4457 if (input_available()) /* something in inbuf[] */
4458 return 1;
4460 #if defined(FEAT_MOUSE_DEC)
4461 /* May need to query the mouse position. */
4462 if (WantQueryMouse)
4464 WantQueryMouse = FALSE;
4465 mch_write((char_u *)IF_EB("\033[1'|", ESC_STR "[1'|"), 5);
4467 #endif
4470 * For FEAT_MOUSE_GPM and FEAT_XCLIPBOARD we loop here to process mouse
4471 * events. This is a bit complicated, because they might both be defined.
4473 #if defined(FEAT_MOUSE_GPM) || defined(FEAT_XCLIPBOARD)
4474 # ifdef FEAT_XCLIPBOARD
4475 rest = 0;
4476 if (do_xterm_trace())
4477 rest = msec;
4478 # endif
4481 # ifdef FEAT_XCLIPBOARD
4482 if (rest != 0)
4484 msec = XT_TRACE_DELAY;
4485 if (rest >= 0 && rest < XT_TRACE_DELAY)
4486 msec = rest;
4487 if (rest >= 0)
4488 rest -= msec;
4490 # endif
4491 # ifdef FEAT_MOUSE_GPM
4492 gpm_process_wanted = 0;
4493 avail = RealWaitForChar(read_cmd_fd, msec, &gpm_process_wanted);
4494 # else
4495 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4496 # endif
4497 if (!avail)
4499 if (input_available())
4500 return 1;
4501 # ifdef FEAT_XCLIPBOARD
4502 if (rest == 0 || !do_xterm_trace())
4503 # endif
4504 break;
4507 while (FALSE
4508 # ifdef FEAT_MOUSE_GPM
4509 || (gpm_process_wanted && mch_gpm_process() == 0)
4510 # endif
4511 # ifdef FEAT_XCLIPBOARD
4512 || (!avail && rest != 0)
4513 # endif
4516 #else
4517 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4518 #endif
4519 return avail;
4523 * Wait "msec" msec until a character is available from file descriptor "fd".
4524 * Time == -1 will block forever.
4525 * When a GUI is being used, this will not be used for input -- webb
4526 * Returns also, when a request from Sniff is waiting -- toni.
4527 * Or when a Linux GPM mouse event is waiting.
4529 /* ARGSUSED */
4530 #if defined(__BEOS__)
4532 #else
4533 static int
4534 #endif
4535 RealWaitForChar(fd, msec, check_for_gpm)
4536 int fd;
4537 long msec;
4538 int *check_for_gpm;
4540 int ret;
4541 #if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4542 static int busy = FALSE;
4544 /* May retry getting characters after an event was handled. */
4545 # define MAY_LOOP
4547 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4548 /* Remember at what time we started, so that we know how much longer we
4549 * should wait after being interrupted. */
4550 # define USE_START_TV
4551 struct timeval start_tv;
4553 if (msec > 0 && (
4554 # ifdef FEAT_XCLIPBOARD
4555 xterm_Shell != (Widget)0
4556 # if defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4558 # endif
4559 # endif
4560 # ifdef USE_XSMP
4561 xsmp_icefd != -1
4562 # ifdef FEAT_MZSCHEME
4564 # endif
4565 # endif
4566 # ifdef FEAT_MZSCHEME
4567 (mzthreads_allowed() && p_mzq > 0)
4568 # endif
4570 gettimeofday(&start_tv, NULL);
4571 # endif
4573 /* Handle being called recursively. This may happen for the session
4574 * manager stuff, it may save the file, which does a breakcheck. */
4575 if (busy)
4576 return 0;
4577 #endif
4579 #ifdef MAY_LOOP
4580 for (;;)
4581 #endif
4583 #ifdef MAY_LOOP
4584 int finished = TRUE; /* default is to 'loop' just once */
4585 # ifdef FEAT_MZSCHEME
4586 int mzquantum_used = FALSE;
4587 # endif
4588 #endif
4589 #ifndef HAVE_SELECT
4590 struct pollfd fds[5];
4591 int nfd;
4592 # ifdef FEAT_XCLIPBOARD
4593 int xterm_idx = -1;
4594 # endif
4595 # ifdef FEAT_MOUSE_GPM
4596 int gpm_idx = -1;
4597 # endif
4598 # ifdef USE_XSMP
4599 int xsmp_idx = -1;
4600 # endif
4601 int towait = (int)msec;
4603 # ifdef FEAT_MZSCHEME
4604 mzvim_check_threads();
4605 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4607 towait = (int)p_mzq; /* don't wait longer than 'mzquantum' */
4608 mzquantum_used = TRUE;
4610 # endif
4611 fds[0].fd = fd;
4612 fds[0].events = POLLIN;
4613 nfd = 1;
4615 # ifdef FEAT_SNIFF
4616 # define SNIFF_IDX 1
4617 if (want_sniff_request)
4619 fds[SNIFF_IDX].fd = fd_from_sniff;
4620 fds[SNIFF_IDX].events = POLLIN;
4621 nfd++;
4623 # endif
4624 # ifdef FEAT_XCLIPBOARD
4625 if (xterm_Shell != (Widget)0)
4627 xterm_idx = nfd;
4628 fds[nfd].fd = ConnectionNumber(xterm_dpy);
4629 fds[nfd].events = POLLIN;
4630 nfd++;
4632 # endif
4633 # ifdef FEAT_MOUSE_GPM
4634 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4636 gpm_idx = nfd;
4637 fds[nfd].fd = gpm_fd;
4638 fds[nfd].events = POLLIN;
4639 nfd++;
4641 # endif
4642 # ifdef USE_XSMP
4643 if (xsmp_icefd != -1)
4645 xsmp_idx = nfd;
4646 fds[nfd].fd = xsmp_icefd;
4647 fds[nfd].events = POLLIN;
4648 nfd++;
4650 # endif
4652 ret = poll(fds, nfd, towait);
4653 # ifdef FEAT_MZSCHEME
4654 if (ret == 0 && mzquantum_used)
4655 /* MzThreads scheduling is required and timeout occured */
4656 finished = FALSE;
4657 # endif
4659 # ifdef FEAT_SNIFF
4660 if (ret < 0)
4661 sniff_disconnect(1);
4662 else if (want_sniff_request)
4664 if (fds[SNIFF_IDX].revents & POLLHUP)
4665 sniff_disconnect(1);
4666 if (fds[SNIFF_IDX].revents & POLLIN)
4667 sniff_request_waiting = 1;
4669 # endif
4670 # ifdef FEAT_XCLIPBOARD
4671 if (xterm_Shell != (Widget)0 && (fds[xterm_idx].revents & POLLIN))
4673 xterm_update(); /* Maybe we should hand out clipboard */
4674 if (--ret == 0 && !input_available())
4675 /* Try again */
4676 finished = FALSE;
4678 # endif
4679 # ifdef FEAT_MOUSE_GPM
4680 if (gpm_idx >= 0 && (fds[gpm_idx].revents & POLLIN))
4682 *check_for_gpm = 1;
4684 # endif
4685 # ifdef USE_XSMP
4686 if (xsmp_idx >= 0 && (fds[xsmp_idx].revents & (POLLIN | POLLHUP)))
4688 if (fds[xsmp_idx].revents & POLLIN)
4690 busy = TRUE;
4691 xsmp_handle_requests();
4692 busy = FALSE;
4694 else if (fds[xsmp_idx].revents & POLLHUP)
4696 if (p_verbose > 0)
4697 verb_msg((char_u *)_("XSMP lost ICE connection"));
4698 xsmp_close();
4700 if (--ret == 0)
4701 finished = FALSE; /* Try again */
4703 # endif
4706 #else /* HAVE_SELECT */
4708 struct timeval tv;
4709 struct timeval *tvp;
4710 fd_set rfds, efds;
4711 int maxfd;
4712 long towait = msec;
4714 # ifdef FEAT_MZSCHEME
4715 mzvim_check_threads();
4716 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4718 towait = p_mzq; /* don't wait longer than 'mzquantum' */
4719 mzquantum_used = TRUE;
4721 # endif
4722 # ifdef __EMX__
4723 /* don't check for incoming chars if not in raw mode, because select()
4724 * always returns TRUE then (in some version of emx.dll) */
4725 if (curr_tmode != TMODE_RAW)
4726 return 0;
4727 # endif
4729 if (towait >= 0)
4731 tv.tv_sec = towait / 1000;
4732 tv.tv_usec = (towait % 1000) * (1000000/1000);
4733 tvp = &tv;
4735 else
4736 tvp = NULL;
4739 * Select on ready for reading and exceptional condition (end of file).
4741 FD_ZERO(&rfds); /* calls bzero() on a sun */
4742 FD_ZERO(&efds);
4743 FD_SET(fd, &rfds);
4744 # if !defined(__QNX__) && !defined(__CYGWIN32__)
4745 /* For QNX select() always returns 1 if this is set. Why? */
4746 FD_SET(fd, &efds);
4747 # endif
4748 maxfd = fd;
4750 # ifdef FEAT_SNIFF
4751 if (want_sniff_request)
4753 FD_SET(fd_from_sniff, &rfds);
4754 FD_SET(fd_from_sniff, &efds);
4755 if (maxfd < fd_from_sniff)
4756 maxfd = fd_from_sniff;
4758 # endif
4759 # ifdef FEAT_XCLIPBOARD
4760 if (xterm_Shell != (Widget)0)
4762 FD_SET(ConnectionNumber(xterm_dpy), &rfds);
4763 if (maxfd < ConnectionNumber(xterm_dpy))
4764 maxfd = ConnectionNumber(xterm_dpy);
4766 # endif
4767 # ifdef FEAT_MOUSE_GPM
4768 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4770 FD_SET(gpm_fd, &rfds);
4771 FD_SET(gpm_fd, &efds);
4772 if (maxfd < gpm_fd)
4773 maxfd = gpm_fd;
4775 # endif
4776 # ifdef USE_XSMP
4777 if (xsmp_icefd != -1)
4779 FD_SET(xsmp_icefd, &rfds);
4780 FD_SET(xsmp_icefd, &efds);
4781 if (maxfd < xsmp_icefd)
4782 maxfd = xsmp_icefd;
4784 # endif
4786 # ifdef OLD_VMS
4787 /* Old VMS as v6.2 and older have broken select(). It waits more than
4788 * required. Should not be used */
4789 ret = 0;
4790 # else
4791 ret = select(maxfd + 1, &rfds, NULL, &efds, tvp);
4792 # endif
4793 # ifdef __TANDEM
4794 if (ret == -1 && errno == ENOTSUP)
4796 FD_ZERO(&rfds);
4797 FD_ZERO(&efds);
4798 ret = 0;
4800 #endif
4801 # ifdef FEAT_MZSCHEME
4802 if (ret == 0 && mzquantum_used)
4803 /* loop if MzThreads must be scheduled and timeout occured */
4804 finished = FALSE;
4805 # endif
4807 # ifdef FEAT_SNIFF
4808 if (ret < 0 )
4809 sniff_disconnect(1);
4810 else if (ret > 0 && want_sniff_request)
4812 if (FD_ISSET(fd_from_sniff, &efds))
4813 sniff_disconnect(1);
4814 if (FD_ISSET(fd_from_sniff, &rfds))
4815 sniff_request_waiting = 1;
4817 # endif
4818 # ifdef FEAT_XCLIPBOARD
4819 if (ret > 0 && xterm_Shell != (Widget)0
4820 && FD_ISSET(ConnectionNumber(xterm_dpy), &rfds))
4822 xterm_update(); /* Maybe we should hand out clipboard */
4823 /* continue looping when we only got the X event and the input
4824 * buffer is empty */
4825 if (--ret == 0 && !input_available())
4827 /* Try again */
4828 finished = FALSE;
4831 # endif
4832 # ifdef FEAT_MOUSE_GPM
4833 if (ret > 0 && gpm_flag && check_for_gpm != NULL && gpm_fd >= 0)
4835 if (FD_ISSET(gpm_fd, &efds))
4836 gpm_close();
4837 else if (FD_ISSET(gpm_fd, &rfds))
4838 *check_for_gpm = 1;
4840 # endif
4841 # ifdef USE_XSMP
4842 if (ret > 0 && xsmp_icefd != -1)
4844 if (FD_ISSET(xsmp_icefd, &efds))
4846 if (p_verbose > 0)
4847 verb_msg((char_u *)_("XSMP lost ICE connection"));
4848 xsmp_close();
4849 if (--ret == 0)
4850 finished = FALSE; /* keep going if event was only one */
4852 else if (FD_ISSET(xsmp_icefd, &rfds))
4854 busy = TRUE;
4855 xsmp_handle_requests();
4856 busy = FALSE;
4857 if (--ret == 0)
4858 finished = FALSE; /* keep going if event was only one */
4861 # endif
4863 #endif /* HAVE_SELECT */
4865 #ifdef MAY_LOOP
4866 if (finished || msec == 0)
4867 break;
4869 /* We're going to loop around again, find out for how long */
4870 if (msec > 0)
4872 # ifdef USE_START_TV
4873 struct timeval mtv;
4875 /* Compute remaining wait time. */
4876 gettimeofday(&mtv, NULL);
4877 msec -= (mtv.tv_sec - start_tv.tv_sec) * 1000L
4878 + (mtv.tv_usec - start_tv.tv_usec) / 1000L;
4879 # else
4880 /* Guess we got interrupted halfway. */
4881 msec = msec / 2;
4882 # endif
4883 if (msec <= 0)
4884 break; /* waited long enough */
4886 #endif
4889 return (ret > 0);
4892 #ifndef VMS
4894 #ifndef NO_EXPANDPATH
4896 * Expand a path into all matching files and/or directories. Handles "*",
4897 * "?", "[a-z]", "**", etc.
4898 * "path" has backslashes before chars that are not to be expanded.
4899 * Returns the number of matches found.
4902 mch_expandpath(gap, path, flags)
4903 garray_T *gap;
4904 char_u *path;
4905 int flags; /* EW_* flags */
4907 return unix_expandpath(gap, path, 0, flags, FALSE);
4909 #endif
4912 * mch_expand_wildcards() - this code does wild-card pattern matching using
4913 * the shell
4915 * return OK for success, FAIL for error (you may lose some memory) and put
4916 * an error message in *file.
4918 * num_pat is number of input patterns
4919 * pat is array of pointers to input patterns
4920 * num_file is pointer to number of matched file names
4921 * file is pointer to array of pointers to matched file names
4924 #ifndef SEEK_SET
4925 # define SEEK_SET 0
4926 #endif
4927 #ifndef SEEK_END
4928 # define SEEK_END 2
4929 #endif
4931 #define SHELL_SPECIAL (char_u *)"\t \"&'$;<>()\\|"
4933 /* ARGSUSED */
4935 mch_expand_wildcards(num_pat, pat, num_file, file, flags)
4936 int num_pat;
4937 char_u **pat;
4938 int *num_file;
4939 char_u ***file;
4940 int flags; /* EW_* flags */
4942 int i;
4943 size_t len;
4944 char_u *p;
4945 int dir;
4946 #ifdef __EMX__
4947 # define EXPL_ALLOC_INC 16
4948 char_u **expl_files;
4949 size_t files_alloced, files_free;
4950 char_u *buf;
4951 int has_wildcard;
4953 *num_file = 0; /* default: no files found */
4954 files_alloced = EXPL_ALLOC_INC; /* how much space is allocated */
4955 files_free = EXPL_ALLOC_INC; /* how much space is not used */
4956 *file = (char_u **)alloc(sizeof(char_u **) * files_alloced);
4957 if (*file == NULL)
4958 return FAIL;
4960 for (; num_pat > 0; num_pat--, pat++)
4962 expl_files = NULL;
4963 if (vim_strchr(*pat, '$') || vim_strchr(*pat, '~'))
4964 /* expand environment var or home dir */
4965 buf = expand_env_save(*pat);
4966 else
4967 buf = vim_strsave(*pat);
4968 expl_files = NULL;
4969 has_wildcard = mch_has_exp_wildcard(buf); /* (still) wildcards? */
4970 if (has_wildcard) /* yes, so expand them */
4971 expl_files = (char_u **)_fnexplode(buf);
4974 * return value of buf if no wildcards left,
4975 * OR if no match AND EW_NOTFOUND is set.
4977 if ((!has_wildcard && ((flags & EW_NOTFOUND) || mch_getperm(buf) >= 0))
4978 || (expl_files == NULL && (flags & EW_NOTFOUND)))
4979 { /* simply save the current contents of *buf */
4980 expl_files = (char_u **)alloc(sizeof(char_u **) * 2);
4981 if (expl_files != NULL)
4983 expl_files[0] = vim_strsave(buf);
4984 expl_files[1] = NULL;
4987 vim_free(buf);
4990 * Count number of names resulting from expansion,
4991 * At the same time add a backslash to the end of names that happen to
4992 * be directories, and replace slashes with backslashes.
4994 if (expl_files)
4996 for (i = 0; (p = expl_files[i]) != NULL; i++)
4998 dir = mch_isdir(p);
4999 /* If we don't want dirs and this is one, skip it */
5000 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5001 continue;
5003 /* Skip files that are not executable if we check for that. */
5004 if (!dir && (flags & EW_EXEC) && !mch_can_exe(p))
5005 continue;
5007 if (--files_free == 0)
5009 /* need more room in table of pointers */
5010 files_alloced += EXPL_ALLOC_INC;
5011 *file = (char_u **)vim_realloc(*file,
5012 sizeof(char_u **) * files_alloced);
5013 if (*file == NULL)
5015 EMSG(_(e_outofmem));
5016 *num_file = 0;
5017 return FAIL;
5019 files_free = EXPL_ALLOC_INC;
5021 slash_adjust(p);
5022 if (dir)
5024 /* For a directory we add a '/', unless it's already
5025 * there. */
5026 len = STRLEN(p);
5027 if (((*file)[*num_file] = alloc(len + 2)) != NULL)
5029 STRCPY((*file)[*num_file], p);
5030 if (!after_pathsep((*file)[*num_file],
5031 (*file)[*num_file] + len))
5033 (*file)[*num_file][len] = psepc;
5034 (*file)[*num_file][len + 1] = NUL;
5038 else
5040 (*file)[*num_file] = vim_strsave(p);
5044 * Error message already given by either alloc or vim_strsave.
5045 * Should return FAIL, but returning OK works also.
5047 if ((*file)[*num_file] == NULL)
5048 break;
5049 (*num_file)++;
5051 _fnexplodefree((char **)expl_files);
5054 return OK;
5056 #else /* __EMX__ */
5058 int j;
5059 char_u *tempname;
5060 char_u *command;
5061 FILE *fd;
5062 char_u *buffer;
5063 #define STYLE_ECHO 0 /* use "echo" to expand */
5064 #define STYLE_GLOB 1 /* use "glob" to expand, for csh */
5065 #define STYLE_PRINT 2 /* use "print -N" to expand, for zsh */
5066 #define STYLE_BT 3 /* `cmd` expansion, execute the pattern directly */
5067 int shell_style = STYLE_ECHO;
5068 int check_spaces;
5069 static int did_find_nul = FALSE;
5070 int ampersent = FALSE;
5072 *num_file = 0; /* default: no files found */
5073 *file = NULL;
5076 * If there are no wildcards, just copy the names to allocated memory.
5077 * Saves a lot of time, because we don't have to start a new shell.
5079 if (!have_wildcard(num_pat, pat))
5080 return save_patterns(num_pat, pat, num_file, file);
5082 # ifdef HAVE_SANDBOX
5083 /* Don't allow any shell command in the sandbox. */
5084 if (sandbox != 0 && check_secure())
5085 return FAIL;
5086 # endif
5089 * Don't allow the use of backticks in secure and restricted mode.
5091 if (secure || restricted)
5092 for (i = 0; i < num_pat; ++i)
5093 if (vim_strchr(pat[i], '`') != NULL
5094 && (check_restricted() || check_secure()))
5095 return FAIL;
5098 * get a name for the temp file
5100 if ((tempname = vim_tempname('o')) == NULL)
5102 EMSG(_(e_notmp));
5103 return FAIL;
5107 * Let the shell expand the patterns and write the result into the temp
5108 * file. if expanding `cmd` execute it directly.
5109 * If we use csh, glob will work better than echo.
5110 * If we use zsh, print -N will work better than glob.
5112 if (num_pat == 1 && *pat[0] == '`'
5113 && (len = STRLEN(pat[0])) > 2
5114 && *(pat[0] + len - 1) == '`')
5115 shell_style = STYLE_BT;
5116 else if ((len = STRLEN(p_sh)) >= 3)
5118 if (STRCMP(p_sh + len - 3, "csh") == 0)
5119 shell_style = STYLE_GLOB;
5120 else if (STRCMP(p_sh + len - 3, "zsh") == 0)
5121 shell_style = STYLE_PRINT;
5124 /* "unset nonomatch; print -N >" plus two is 29 */
5125 len = STRLEN(tempname) + 29;
5126 for (i = 0; i < num_pat; ++i)
5128 /* Count the length of the patterns in the same way as they are put in
5129 * "command" below. */
5130 #ifdef USE_SYSTEM
5131 len += STRLEN(pat[i]) + 3; /* add space and two quotes */
5132 #else
5133 ++len; /* add space */
5134 for (j = 0; pat[i][j] != NUL; ++j)
5136 if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL)
5137 ++len; /* may add a backslash */
5138 ++len;
5140 #endif
5142 command = alloc(len);
5143 if (command == NULL)
5145 /* out of memory */
5146 vim_free(tempname);
5147 return FAIL;
5151 * Build the shell command:
5152 * - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell
5153 * recognizes this).
5154 * - Add the shell command to print the expanded names.
5155 * - Add the temp file name.
5156 * - Add the file name patterns.
5158 if (shell_style == STYLE_BT)
5160 /* change `command; command& ` to (command; command ) */
5161 STRCPY(command, "(");
5162 STRCAT(command, pat[0] + 1); /* exclude first backtick */
5163 p = command + STRLEN(command) - 1;
5164 *p-- = ')'; /* remove last backtick */
5165 while (p > command && vim_iswhite(*p))
5166 --p;
5167 if (*p == '&') /* remove trailing '&' */
5169 ampersent = TRUE;
5170 *p = ' ';
5172 STRCAT(command, ">");
5174 else
5176 if (flags & EW_NOTFOUND)
5177 STRCPY(command, "set nonomatch; ");
5178 else
5179 STRCPY(command, "unset nonomatch; ");
5180 if (shell_style == STYLE_GLOB)
5181 STRCAT(command, "glob >");
5182 else if (shell_style == STYLE_PRINT)
5183 STRCAT(command, "print -N >");
5184 else
5185 STRCAT(command, "echo >");
5187 STRCAT(command, tempname);
5188 if (shell_style != STYLE_BT)
5189 for (i = 0; i < num_pat; ++i)
5191 /* When using system() always add extra quotes, because the shell
5192 * is started twice. Otherwise put a backslash before special
5193 * characters, except insice ``. */
5194 #ifdef USE_SYSTEM
5195 STRCAT(command, " \"");
5196 STRCAT(command, pat[i]);
5197 STRCAT(command, "\"");
5198 #else
5199 int intick = FALSE;
5201 p = command + STRLEN(command);
5202 *p++ = ' ';
5203 for (j = 0; pat[i][j] != NUL; ++j)
5205 if (pat[i][j] == '`')
5206 intick = !intick;
5207 else if (pat[i][j] == '\\' && pat[i][j + 1] != NUL)
5209 /* Remove a backslash, take char literally. But keep
5210 * backslash inside backticks, before a special character
5211 * and before a backtick. */
5212 if (intick
5213 || vim_strchr(SHELL_SPECIAL, pat[i][j + 1]) != NULL
5214 || pat[i][j + 1] == '`')
5215 *p++ = '\\';
5216 ++j;
5218 else if (!intick && vim_strchr(SHELL_SPECIAL,
5219 pat[i][j]) != NULL)
5220 /* Put a backslash before a special character, but not
5221 * when inside ``. */
5222 *p++ = '\\';
5224 /* Copy one character. */
5225 *p++ = pat[i][j];
5227 *p = NUL;
5228 #endif
5230 if (flags & EW_SILENT)
5231 show_shell_mess = FALSE;
5232 if (ampersent)
5233 STRCAT(command, "&"); /* put the '&' back after the
5234 redirection */
5237 * Using zsh -G: If a pattern has no matches, it is just deleted from
5238 * the argument list, otherwise zsh gives an error message and doesn't
5239 * expand any other pattern.
5241 if (shell_style == STYLE_PRINT)
5242 extra_shell_arg = (char_u *)"-G"; /* Use zsh NULL_GLOB option */
5245 * If we use -f then shell variables set in .cshrc won't get expanded.
5246 * vi can do it, so we will too, but it is only necessary if there is a "$"
5247 * in one of the patterns, otherwise we can still use the fast option.
5249 else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat))
5250 extra_shell_arg = (char_u *)"-f"; /* Use csh fast option */
5253 * execute the shell command
5255 i = call_shell(command, SHELL_EXPAND | SHELL_SILENT);
5257 /* When running in the background, give it some time to create the temp
5258 * file, but don't wait for it to finish. */
5259 if (ampersent)
5260 mch_delay(10L, TRUE);
5262 extra_shell_arg = NULL; /* cleanup */
5263 show_shell_mess = TRUE;
5264 vim_free(command);
5266 if (i) /* mch_call_shell() failed */
5268 mch_remove(tempname);
5269 vim_free(tempname);
5271 * With interactive completion, the error message is not printed.
5272 * However with USE_SYSTEM, I don't know how to turn off error messages
5273 * from the shell, so screen may still get messed up -- webb.
5275 #ifndef USE_SYSTEM
5276 if (!(flags & EW_SILENT))
5277 #endif
5279 redraw_later_clear(); /* probably messed up screen */
5280 msg_putchar('\n'); /* clear bottom line quickly */
5281 cmdline_row = Rows - 1; /* continue on last line */
5282 #ifdef USE_SYSTEM
5283 if (!(flags & EW_SILENT))
5284 #endif
5286 MSG(_(e_wildexpand));
5287 msg_start(); /* don't overwrite this message */
5290 /* If a `cmd` expansion failed, don't list `cmd` as a match, even when
5291 * EW_NOTFOUND is given */
5292 if (shell_style == STYLE_BT)
5293 return FAIL;
5294 goto notfound;
5298 * read the names from the file into memory
5300 fd = fopen((char *)tempname, READBIN);
5301 if (fd == NULL)
5303 /* Something went wrong, perhaps a file name with a special char. */
5304 if (!(flags & EW_SILENT))
5306 MSG(_(e_wildexpand));
5307 msg_start(); /* don't overwrite this message */
5309 vim_free(tempname);
5310 goto notfound;
5312 fseek(fd, 0L, SEEK_END);
5313 len = ftell(fd); /* get size of temp file */
5314 fseek(fd, 0L, SEEK_SET);
5315 buffer = alloc(len + 1);
5316 if (buffer == NULL)
5318 /* out of memory */
5319 mch_remove(tempname);
5320 vim_free(tempname);
5321 fclose(fd);
5322 return FAIL;
5324 i = fread((char *)buffer, 1, len, fd);
5325 fclose(fd);
5326 mch_remove(tempname);
5327 if (i != len)
5329 /* unexpected read error */
5330 EMSG2(_(e_notread), tempname);
5331 vim_free(tempname);
5332 vim_free(buffer);
5333 return FAIL;
5335 vim_free(tempname);
5337 #if defined(__CYGWIN__) || defined(__CYGWIN32__)
5338 /* Translate <CR><NL> into <NL>. Caution, buffer may contain NUL. */
5339 p = buffer;
5340 for (i = 0; i < len; ++i)
5341 if (!(buffer[i] == CAR && buffer[i + 1] == NL))
5342 *p++ = buffer[i];
5343 len = p - buffer;
5344 # endif
5347 /* file names are separated with Space */
5348 if (shell_style == STYLE_ECHO)
5350 buffer[len] = '\n'; /* make sure the buffer ends in NL */
5351 p = buffer;
5352 for (i = 0; *p != '\n'; ++i) /* count number of entries */
5354 while (*p != ' ' && *p != '\n')
5355 ++p;
5356 p = skipwhite(p); /* skip to next entry */
5359 /* file names are separated with NL */
5360 else if (shell_style == STYLE_BT)
5362 buffer[len] = NUL; /* make sure the buffer ends in NUL */
5363 p = buffer;
5364 for (i = 0; *p != NUL; ++i) /* count number of entries */
5366 while (*p != '\n' && *p != NUL)
5367 ++p;
5368 if (*p != NUL)
5369 ++p;
5370 p = skipwhite(p); /* skip leading white space */
5373 /* file names are separated with NUL */
5374 else
5377 * Some versions of zsh use spaces instead of NULs to separate
5378 * results. Only do this when there is no NUL before the end of the
5379 * buffer, otherwise we would never be able to use file names with
5380 * embedded spaces when zsh does use NULs.
5381 * When we found a NUL once, we know zsh is OK, set did_find_nul and
5382 * don't check for spaces again.
5384 check_spaces = FALSE;
5385 if (shell_style == STYLE_PRINT && !did_find_nul)
5387 /* If there is a NUL, set did_find_nul, else set check_spaces */
5388 if (len && (int)STRLEN(buffer) < len - 1)
5389 did_find_nul = TRUE;
5390 else
5391 check_spaces = TRUE;
5395 * Make sure the buffer ends with a NUL. For STYLE_PRINT there
5396 * already is one, for STYLE_GLOB it needs to be added.
5398 if (len && buffer[len - 1] == NUL)
5399 --len;
5400 else
5401 buffer[len] = NUL;
5402 i = 0;
5403 for (p = buffer; p < buffer + len; ++p)
5404 if (*p == NUL || (*p == ' ' && check_spaces)) /* count entry */
5406 ++i;
5407 *p = NUL;
5409 if (len)
5410 ++i; /* count last entry */
5412 if (i == 0)
5415 * Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I".
5416 * /bin/sh will happily expand it to nothing rather than returning an
5417 * error; and hey, it's good to check anyway -- webb.
5419 vim_free(buffer);
5420 goto notfound;
5422 *num_file = i;
5423 *file = (char_u **)alloc(sizeof(char_u *) * i);
5424 if (*file == NULL)
5426 /* out of memory */
5427 vim_free(buffer);
5428 return FAIL;
5432 * Isolate the individual file names.
5434 p = buffer;
5435 for (i = 0; i < *num_file; ++i)
5437 (*file)[i] = p;
5438 /* Space or NL separates */
5439 if (shell_style == STYLE_ECHO || shell_style == STYLE_BT)
5441 while (!(shell_style == STYLE_ECHO && *p == ' ')
5442 && *p != '\n' && *p != NUL)
5443 ++p;
5444 if (p == buffer + len) /* last entry */
5445 *p = NUL;
5446 else
5448 *p++ = NUL;
5449 p = skipwhite(p); /* skip to next entry */
5452 else /* NUL separates */
5454 while (*p && p < buffer + len) /* skip entry */
5455 ++p;
5456 ++p; /* skip NUL */
5461 * Move the file names to allocated memory.
5463 for (j = 0, i = 0; i < *num_file; ++i)
5465 /* Require the files to exist. Helps when using /bin/sh */
5466 if (!(flags & EW_NOTFOUND) && mch_getperm((*file)[i]) < 0)
5467 continue;
5469 /* check if this entry should be included */
5470 dir = (mch_isdir((*file)[i]));
5471 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5472 continue;
5474 /* Skip files that are not executable if we check for that. */
5475 if (!dir && (flags & EW_EXEC) && !mch_can_exe((*file)[i]))
5476 continue;
5478 p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir));
5479 if (p)
5481 STRCPY(p, (*file)[i]);
5482 if (dir)
5483 STRCAT(p, "/"); /* add '/' to a directory name */
5484 (*file)[j++] = p;
5487 vim_free(buffer);
5488 *num_file = j;
5490 if (*num_file == 0) /* rejected all entries */
5492 vim_free(*file);
5493 *file = NULL;
5494 goto notfound;
5497 return OK;
5499 notfound:
5500 if (flags & EW_NOTFOUND)
5501 return save_patterns(num_pat, pat, num_file, file);
5502 return FAIL;
5504 #endif /* __EMX__ */
5507 #endif /* VMS */
5509 #ifndef __EMX__
5510 static int
5511 save_patterns(num_pat, pat, num_file, file)
5512 int num_pat;
5513 char_u **pat;
5514 int *num_file;
5515 char_u ***file;
5517 int i;
5518 char_u *s;
5520 *file = (char_u **)alloc(num_pat * sizeof(char_u *));
5521 if (*file == NULL)
5522 return FAIL;
5523 for (i = 0; i < num_pat; i++)
5525 s = vim_strsave(pat[i]);
5526 if (s != NULL)
5527 /* Be compatible with expand_filename(): halve the number of
5528 * backslashes. */
5529 backslash_halve(s);
5530 (*file)[i] = s;
5532 *num_file = num_pat;
5533 return OK;
5535 #endif
5539 * Return TRUE if the string "p" contains a wildcard that mch_expandpath() can
5540 * expand.
5543 mch_has_exp_wildcard(p)
5544 char_u *p;
5546 for ( ; *p; mb_ptr_adv(p))
5548 #ifndef OS2
5549 if (*p == '\\' && p[1] != NUL)
5550 ++p;
5551 else
5552 #endif
5553 if (vim_strchr((char_u *)
5554 #ifdef VMS
5555 "*?%"
5556 #else
5557 # ifdef OS2
5558 "*?"
5559 # else
5560 "*?[{'"
5561 # endif
5562 #endif
5563 , *p) != NULL)
5564 return TRUE;
5566 return FALSE;
5570 * Return TRUE if the string "p" contains a wildcard.
5571 * Don't recognize '~' at the end as a wildcard.
5574 mch_has_wildcard(p)
5575 char_u *p;
5577 for ( ; *p; mb_ptr_adv(p))
5579 #ifndef OS2
5580 if (*p == '\\' && p[1] != NUL)
5581 ++p;
5582 else
5583 #endif
5584 if (vim_strchr((char_u *)
5585 #ifdef VMS
5586 "*?%$"
5587 #else
5588 # ifdef OS2
5589 # ifdef VIM_BACKTICK
5590 "*?$`"
5591 # else
5592 "*?$"
5593 # endif
5594 # else
5595 "*?[{`'$"
5596 # endif
5597 #endif
5598 , *p) != NULL
5599 || (*p == '~' && p[1] != NUL))
5600 return TRUE;
5602 return FALSE;
5605 #ifndef __EMX__
5606 static int
5607 have_wildcard(num, file)
5608 int num;
5609 char_u **file;
5611 int i;
5613 for (i = 0; i < num; i++)
5614 if (mch_has_wildcard(file[i]))
5615 return 1;
5616 return 0;
5619 static int
5620 have_dollars(num, file)
5621 int num;
5622 char_u **file;
5624 int i;
5626 for (i = 0; i < num; i++)
5627 if (vim_strchr(file[i], '$') != NULL)
5628 return TRUE;
5629 return FALSE;
5631 #endif /* ifndef __EMX__ */
5633 #ifndef HAVE_RENAME
5635 * Scaled-down version of rename(), which is missing in Xenix.
5636 * This version can only move regular files and will fail if the
5637 * destination exists.
5640 mch_rename(src, dest)
5641 const char *src, *dest;
5643 struct stat st;
5645 if (stat(dest, &st) >= 0) /* fail if destination exists */
5646 return -1;
5647 if (link(src, dest) != 0) /* link file to new name */
5648 return -1;
5649 if (mch_remove(src) == 0) /* delete link to old name */
5650 return 0;
5651 return -1;
5653 #endif /* !HAVE_RENAME */
5655 #ifdef FEAT_MOUSE_GPM
5657 * Initializes connection with gpm (if it isn't already opened)
5658 * Return 1 if succeeded (or connection already opened), 0 if failed
5660 static int
5661 gpm_open()
5663 static Gpm_Connect gpm_connect; /* Must it be kept till closing ? */
5665 if (!gpm_flag)
5667 gpm_connect.eventMask = (GPM_UP | GPM_DRAG | GPM_DOWN);
5668 gpm_connect.defaultMask = ~GPM_HARD;
5669 /* Default handling for mouse move*/
5670 gpm_connect.minMod = 0; /* Handle any modifier keys */
5671 gpm_connect.maxMod = 0xffff;
5672 if (Gpm_Open(&gpm_connect, 0) > 0)
5674 /* gpm library tries to handling TSTP causes
5675 * problems. Anyways, we close connection to Gpm whenever
5676 * we are going to suspend or starting an external process
5677 * so we should'nt have problem with this
5679 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
5680 return 1; /* succeed */
5682 if (gpm_fd == -2)
5683 Gpm_Close(); /* We don't want to talk to xterm via gpm */
5684 return 0;
5686 return 1; /* already open */
5690 * Closes connection to gpm
5691 * returns non-zero if connection succesfully closed
5693 static void
5694 gpm_close()
5696 if (gpm_flag && gpm_fd >= 0) /* if Open */
5697 Gpm_Close();
5700 /* Reads gpm event and adds special keys to input buf. Returns length of
5701 * generated key sequence.
5702 * This function is made after gui_send_mouse_event
5704 static int
5705 mch_gpm_process()
5707 int button;
5708 static Gpm_Event gpm_event;
5709 char_u string[6];
5710 int_u vim_modifiers;
5711 int row,col;
5712 unsigned char buttons_mask;
5713 unsigned char gpm_modifiers;
5714 static unsigned char old_buttons = 0;
5716 Gpm_GetEvent(&gpm_event);
5718 #ifdef FEAT_GUI
5719 /* Don't put events in the input queue now. */
5720 if (hold_gui_events)
5721 return 0;
5722 #endif
5724 row = gpm_event.y - 1;
5725 col = gpm_event.x - 1;
5727 string[0] = ESC; /* Our termcode */
5728 string[1] = 'M';
5729 string[2] = 'G';
5730 switch (GPM_BARE_EVENTS(gpm_event.type))
5732 case GPM_DRAG:
5733 string[3] = MOUSE_DRAG;
5734 break;
5735 case GPM_DOWN:
5736 buttons_mask = gpm_event.buttons & ~old_buttons;
5737 old_buttons = gpm_event.buttons;
5738 switch (buttons_mask)
5740 case GPM_B_LEFT:
5741 button = MOUSE_LEFT;
5742 break;
5743 case GPM_B_MIDDLE:
5744 button = MOUSE_MIDDLE;
5745 break;
5746 case GPM_B_RIGHT:
5747 button = MOUSE_RIGHT;
5748 break;
5749 default:
5750 return 0;
5751 /*Don't know what to do. Can more than one button be
5752 * reported in one event? */
5754 string[3] = (char_u)(button | 0x20);
5755 SET_NUM_MOUSE_CLICKS(string[3], gpm_event.clicks + 1);
5756 break;
5757 case GPM_UP:
5758 string[3] = MOUSE_RELEASE;
5759 old_buttons &= ~gpm_event.buttons;
5760 break;
5761 default:
5762 return 0;
5764 /*This code is based on gui_x11_mouse_cb in gui_x11.c */
5765 gpm_modifiers = gpm_event.modifiers;
5766 vim_modifiers = 0x0;
5767 /* I ignore capslock stats. Aren't we all just hate capslock mixing with
5768 * Vim commands ? Besides, gpm_event.modifiers is unsigned char, and
5769 * K_CAPSSHIFT is defined 8, so it probably isn't even reported
5771 if (gpm_modifiers & ((1 << KG_SHIFT) | (1 << KG_SHIFTR) | (1 << KG_SHIFTL)))
5772 vim_modifiers |= MOUSE_SHIFT;
5774 if (gpm_modifiers & ((1 << KG_CTRL) | (1 << KG_CTRLR) | (1 << KG_CTRLL)))
5775 vim_modifiers |= MOUSE_CTRL;
5776 if (gpm_modifiers & ((1 << KG_ALT) | (1 << KG_ALTGR)))
5777 vim_modifiers |= MOUSE_ALT;
5778 string[3] |= vim_modifiers;
5779 string[4] = (char_u)(col + ' ' + 1);
5780 string[5] = (char_u)(row + ' ' + 1);
5781 add_to_input_buf(string, 6);
5782 return 6;
5784 #endif /* FEAT_MOUSE_GPM */
5786 #if defined(FEAT_LIBCALL) || defined(PROTO)
5787 typedef char_u * (*STRPROCSTR)__ARGS((char_u *));
5788 typedef char_u * (*INTPROCSTR)__ARGS((int));
5789 typedef int (*STRPROCINT)__ARGS((char_u *));
5790 typedef int (*INTPROCINT)__ARGS((int));
5793 * Call a DLL routine which takes either a string or int param
5794 * and returns an allocated string.
5797 mch_libcall(libname, funcname, argstring, argint, string_result, number_result)
5798 char_u *libname;
5799 char_u *funcname;
5800 char_u *argstring; /* NULL when using a argint */
5801 int argint;
5802 char_u **string_result;/* NULL when using number_result */
5803 int *number_result;
5805 # if defined(USE_DLOPEN)
5806 void *hinstLib;
5807 char *dlerr = NULL;
5808 # else
5809 shl_t hinstLib;
5810 # endif
5811 STRPROCSTR ProcAdd;
5812 INTPROCSTR ProcAddI;
5813 char_u *retval_str = NULL;
5814 int retval_int = 0;
5815 int success = FALSE;
5818 * Get a handle to the DLL module.
5820 # if defined(USE_DLOPEN)
5821 /* First clear any error, it's not cleared by the dlopen() call. */
5822 (void)dlerror();
5824 hinstLib = dlopen((char *)libname, RTLD_LAZY
5825 # ifdef RTLD_LOCAL
5826 | RTLD_LOCAL
5827 # endif
5829 if (hinstLib == NULL)
5831 /* "dlerr" must be used before dlclose() */
5832 dlerr = (char *)dlerror();
5833 if (dlerr != NULL)
5834 EMSG2(_("dlerror = \"%s\""), dlerr);
5836 # else
5837 hinstLib = shl_load((const char*)libname, BIND_IMMEDIATE|BIND_VERBOSE, 0L);
5838 # endif
5840 /* If the handle is valid, try to get the function address. */
5841 if (hinstLib != NULL)
5843 # ifdef HAVE_SETJMP_H
5845 * Catch a crash when calling the library function. For example when
5846 * using a number where a string pointer is expected.
5848 mch_startjmp();
5849 if (SETJMP(lc_jump_env) != 0)
5851 success = FALSE;
5852 # if defined(USE_DLOPEN)
5853 dlerr = NULL;
5854 # endif
5855 mch_didjmp();
5857 else
5858 # endif
5860 retval_str = NULL;
5861 retval_int = 0;
5863 if (argstring != NULL)
5865 # if defined(USE_DLOPEN)
5866 ProcAdd = (STRPROCSTR)dlsym(hinstLib, (const char *)funcname);
5867 dlerr = (char *)dlerror();
5868 # else
5869 if (shl_findsym(&hinstLib, (const char *)funcname,
5870 TYPE_PROCEDURE, (void *)&ProcAdd) < 0)
5871 ProcAdd = NULL;
5872 # endif
5873 if ((success = (ProcAdd != NULL
5874 # if defined(USE_DLOPEN)
5875 && dlerr == NULL
5876 # endif
5879 if (string_result == NULL)
5880 retval_int = ((STRPROCINT)ProcAdd)(argstring);
5881 else
5882 retval_str = (ProcAdd)(argstring);
5885 else
5887 # if defined(USE_DLOPEN)
5888 ProcAddI = (INTPROCSTR)dlsym(hinstLib, (const char *)funcname);
5889 dlerr = (char *)dlerror();
5890 # else
5891 if (shl_findsym(&hinstLib, (const char *)funcname,
5892 TYPE_PROCEDURE, (void *)&ProcAddI) < 0)
5893 ProcAddI = NULL;
5894 # endif
5895 if ((success = (ProcAddI != NULL
5896 # if defined(USE_DLOPEN)
5897 && dlerr == NULL
5898 # endif
5901 if (string_result == NULL)
5902 retval_int = ((INTPROCINT)ProcAddI)(argint);
5903 else
5904 retval_str = (ProcAddI)(argint);
5908 /* Save the string before we free the library. */
5909 /* Assume that a "1" or "-1" result is an illegal pointer. */
5910 if (string_result == NULL)
5911 *number_result = retval_int;
5912 else if (retval_str != NULL
5913 && retval_str != (char_u *)1
5914 && retval_str != (char_u *)-1)
5915 *string_result = vim_strsave(retval_str);
5918 # ifdef HAVE_SETJMP_H
5919 mch_endjmp();
5920 # ifdef SIGHASARG
5921 if (lc_signal != 0)
5923 int i;
5925 /* try to find the name of this signal */
5926 for (i = 0; signal_info[i].sig != -1; i++)
5927 if (lc_signal == signal_info[i].sig)
5928 break;
5929 EMSG2("E368: got SIG%s in libcall()", signal_info[i].name);
5931 # endif
5932 # endif
5934 # if defined(USE_DLOPEN)
5935 /* "dlerr" must be used before dlclose() */
5936 if (dlerr != NULL)
5937 EMSG2(_("dlerror = \"%s\""), dlerr);
5939 /* Free the DLL module. */
5940 (void)dlclose(hinstLib);
5941 # else
5942 (void)shl_unload(hinstLib);
5943 # endif
5946 if (!success)
5948 EMSG2(_(e_libcall), funcname);
5949 return FAIL;
5952 return OK;
5954 #endif
5956 #if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
5957 static int xterm_trace = -1; /* default: disabled */
5958 static int xterm_button;
5961 * Setup a dummy window for X selections in a terminal.
5963 void
5964 setup_term_clip()
5966 int z = 0;
5967 char *strp = "";
5968 Widget AppShell;
5970 if (!x_connect_to_server())
5971 return;
5973 open_app_context();
5974 if (app_context != NULL && xterm_Shell == (Widget)0)
5976 int (*oldhandler)();
5977 #if defined(HAVE_SETJMP_H)
5978 int (*oldIOhandler)();
5979 #endif
5980 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
5981 struct timeval start_tv;
5983 if (p_verbose > 0)
5984 gettimeofday(&start_tv, NULL);
5985 # endif
5987 /* Ignore X errors while opening the display */
5988 oldhandler = XSetErrorHandler(x_error_check);
5990 #if defined(HAVE_SETJMP_H)
5991 /* Ignore X IO errors while opening the display */
5992 oldIOhandler = XSetIOErrorHandler(x_IOerror_check);
5993 mch_startjmp();
5994 if (SETJMP(lc_jump_env) != 0)
5996 mch_didjmp();
5997 xterm_dpy = NULL;
5999 else
6000 #endif
6002 xterm_dpy = XtOpenDisplay(app_context, xterm_display,
6003 "vim_xterm", "Vim_xterm", NULL, 0, &z, &strp);
6004 #if defined(HAVE_SETJMP_H)
6005 mch_endjmp();
6006 #endif
6009 #if defined(HAVE_SETJMP_H)
6010 /* Now handle X IO errors normally. */
6011 (void)XSetIOErrorHandler(oldIOhandler);
6012 #endif
6013 /* Now handle X errors normally. */
6014 (void)XSetErrorHandler(oldhandler);
6016 if (xterm_dpy == NULL)
6018 if (p_verbose > 0)
6019 verb_msg((char_u *)_("Opening the X display failed"));
6020 return;
6023 /* Catch terminating error of the X server connection. */
6024 (void)XSetIOErrorHandler(x_IOerror_handler);
6026 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
6027 if (p_verbose > 0)
6029 verbose_enter();
6030 xopen_message(&start_tv);
6031 verbose_leave();
6033 # endif
6035 /* Create a Shell to make converters work. */
6036 AppShell = XtVaAppCreateShell("vim_xterm", "Vim_xterm",
6037 applicationShellWidgetClass, xterm_dpy,
6038 NULL);
6039 if (AppShell == (Widget)0)
6040 return;
6041 xterm_Shell = XtVaCreatePopupShell("VIM",
6042 topLevelShellWidgetClass, AppShell,
6043 XtNmappedWhenManaged, 0,
6044 XtNwidth, 1,
6045 XtNheight, 1,
6046 NULL);
6047 if (xterm_Shell == (Widget)0)
6048 return;
6050 x11_setup_atoms(xterm_dpy);
6051 if (x11_display == NULL)
6052 x11_display = xterm_dpy;
6054 XtRealizeWidget(xterm_Shell);
6055 XSync(xterm_dpy, False);
6056 xterm_update();
6058 if (xterm_Shell != (Widget)0)
6060 clip_init(TRUE);
6061 if (x11_window == 0 && (strp = getenv("WINDOWID")) != NULL)
6062 x11_window = (Window)atol(strp);
6063 /* Check if $WINDOWID is valid. */
6064 if (test_x11_window(xterm_dpy) == FAIL)
6065 x11_window = 0;
6066 if (x11_window != 0)
6067 xterm_trace = 0;
6071 void
6072 start_xterm_trace(button)
6073 int button;
6075 if (x11_window == 0 || xterm_trace < 0 || xterm_Shell == (Widget)0)
6076 return;
6077 xterm_trace = 1;
6078 xterm_button = button;
6079 do_xterm_trace();
6083 void
6084 stop_xterm_trace()
6086 if (xterm_trace < 0)
6087 return;
6088 xterm_trace = 0;
6092 * Query the xterm pointer and generate mouse termcodes if necessary
6093 * return TRUE if dragging is active, else FALSE
6095 static int
6096 do_xterm_trace()
6098 Window root, child;
6099 int root_x, root_y;
6100 int win_x, win_y;
6101 int row, col;
6102 int_u mask_return;
6103 char_u buf[50];
6104 char_u *strp;
6105 long got_hints;
6106 static char_u *mouse_code;
6107 static char_u mouse_name[2] = {KS_MOUSE, KE_FILLER};
6108 static int prev_row = 0, prev_col = 0;
6109 static XSizeHints xterm_hints;
6111 if (xterm_trace <= 0)
6112 return FALSE;
6114 if (xterm_trace == 1)
6116 /* Get the hints just before tracking starts. The font size might
6117 * have changed recently */
6118 XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints);
6119 if (!(got_hints & PResizeInc)
6120 || xterm_hints.width_inc <= 1
6121 || xterm_hints.height_inc <= 1)
6123 xterm_trace = -1; /* Not enough data -- disable tracing */
6124 return FALSE;
6127 /* Rely on the same mouse code for the duration of this */
6128 mouse_code = find_termcode(mouse_name);
6129 prev_row = mouse_row;
6130 prev_row = mouse_col;
6131 xterm_trace = 2;
6133 /* Find the offset of the chars, there might be a scrollbar on the
6134 * left of the window and/or a menu on the top (eterm etc.) */
6135 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
6136 &win_x, &win_y, &mask_return);
6137 xterm_hints.y = win_y - (xterm_hints.height_inc * mouse_row)
6138 - (xterm_hints.height_inc / 2);
6139 if (xterm_hints.y <= xterm_hints.height_inc / 2)
6140 xterm_hints.y = 2;
6141 xterm_hints.x = win_x - (xterm_hints.width_inc * mouse_col)
6142 - (xterm_hints.width_inc / 2);
6143 if (xterm_hints.x <= xterm_hints.width_inc / 2)
6144 xterm_hints.x = 2;
6145 return TRUE;
6147 if (mouse_code == NULL)
6149 xterm_trace = 0;
6150 return FALSE;
6153 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
6154 &win_x, &win_y, &mask_return);
6156 row = check_row((win_y - xterm_hints.y) / xterm_hints.height_inc);
6157 col = check_col((win_x - xterm_hints.x) / xterm_hints.width_inc);
6158 if (row == prev_row && col == prev_col)
6159 return TRUE;
6161 STRCPY(buf, mouse_code);
6162 strp = buf + STRLEN(buf);
6163 *strp++ = (xterm_button | MOUSE_DRAG) & ~0x20;
6164 *strp++ = (char_u)(col + ' ' + 1);
6165 *strp++ = (char_u)(row + ' ' + 1);
6166 *strp = 0;
6167 add_to_input_buf(buf, STRLEN(buf));
6169 prev_row = row;
6170 prev_col = col;
6171 return TRUE;
6174 # if defined(FEAT_GUI) || defined(PROTO)
6176 * Destroy the display, window and app_context. Required for GTK.
6178 void
6179 clear_xterm_clip()
6181 if (xterm_Shell != (Widget)0)
6183 XtDestroyWidget(xterm_Shell);
6184 xterm_Shell = (Widget)0;
6186 if (xterm_dpy != NULL)
6188 #if 0
6189 /* Lesstif and Solaris crash here, lose some memory */
6190 XtCloseDisplay(xterm_dpy);
6191 #endif
6192 if (x11_display == xterm_dpy)
6193 x11_display = NULL;
6194 xterm_dpy = NULL;
6196 #if 0
6197 if (app_context != (XtAppContext)NULL)
6199 /* Lesstif and Solaris crash here, lose some memory */
6200 XtDestroyApplicationContext(app_context);
6201 app_context = (XtAppContext)NULL;
6203 #endif
6205 # endif
6208 * Catch up with any queued X events. This may put keyboard input into the
6209 * input buffer, call resize call-backs, trigger timers etc. If there is
6210 * nothing in the X event queue (& no timers pending), then we return
6211 * immediately.
6213 static void
6214 xterm_update()
6216 XEvent event;
6218 while (XtAppPending(app_context) && !vim_is_input_buf_full())
6220 XtAppNextEvent(app_context, &event);
6221 #ifdef FEAT_CLIENTSERVER
6223 XPropertyEvent *e = (XPropertyEvent *)&event;
6225 if (e->type == PropertyNotify && e->window == commWindow
6226 && e->atom == commProperty && e->state == PropertyNewValue)
6227 serverEventProc(xterm_dpy, &event);
6229 #endif
6230 XtDispatchEvent(&event);
6235 clip_xterm_own_selection(cbd)
6236 VimClipboard *cbd;
6238 if (xterm_Shell != (Widget)0)
6239 return clip_x11_own_selection(xterm_Shell, cbd);
6240 return FAIL;
6243 void
6244 clip_xterm_lose_selection(cbd)
6245 VimClipboard *cbd;
6247 if (xterm_Shell != (Widget)0)
6248 clip_x11_lose_selection(xterm_Shell, cbd);
6251 void
6252 clip_xterm_request_selection(cbd)
6253 VimClipboard *cbd;
6255 if (xterm_Shell != (Widget)0)
6256 clip_x11_request_selection(xterm_Shell, xterm_dpy, cbd);
6259 void
6260 clip_xterm_set_selection(cbd)
6261 VimClipboard *cbd;
6263 clip_x11_set_selection(cbd);
6265 #endif
6268 #if defined(USE_XSMP) || defined(PROTO)
6270 * Code for X Session Management Protocol.
6272 static void xsmp_handle_save_yourself __ARGS((SmcConn smc_conn, SmPointer client_data, int save_type, Bool shutdown, int interact_style, Bool fast));
6273 static void xsmp_die __ARGS((SmcConn smc_conn, SmPointer client_data));
6274 static void xsmp_save_complete __ARGS((SmcConn smc_conn, SmPointer client_data));
6275 static void xsmp_shutdown_cancelled __ARGS((SmcConn smc_conn, SmPointer client_data));
6276 static void xsmp_ice_connection __ARGS((IceConn iceConn, IcePointer clientData, Bool opening, IcePointer *watchData));
6279 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6280 static void xsmp_handle_interaction __ARGS((SmcConn smc_conn, SmPointer client_data));
6283 * This is our chance to ask the user if they want to save,
6284 * or abort the logout
6286 /*ARGSUSED*/
6287 static void
6288 xsmp_handle_interaction(smc_conn, client_data)
6289 SmcConn smc_conn;
6290 SmPointer client_data;
6292 cmdmod_T save_cmdmod;
6293 int cancel_shutdown = False;
6295 save_cmdmod = cmdmod;
6296 cmdmod.confirm = TRUE;
6297 if (check_changed_any(FALSE))
6298 /* Mustn't logout */
6299 cancel_shutdown = True;
6300 cmdmod = save_cmdmod;
6301 setcursor(); /* position cursor */
6302 out_flush();
6304 /* Done interaction */
6305 SmcInteractDone(smc_conn, cancel_shutdown);
6307 /* Finish off
6308 * Only end save-yourself here if we're not cancelling shutdown;
6309 * we'll get a cancelled callback later in which we'll end it.
6310 * Hopefully get around glitchy SMs (like GNOME-1)
6312 if (!cancel_shutdown)
6314 xsmp.save_yourself = False;
6315 SmcSaveYourselfDone(smc_conn, True);
6318 # endif
6321 * Callback that starts save-yourself.
6323 /*ARGSUSED*/
6324 static void
6325 xsmp_handle_save_yourself(smc_conn, client_data, save_type,
6326 shutdown, interact_style, fast)
6327 SmcConn smc_conn;
6328 SmPointer client_data;
6329 int save_type;
6330 Bool shutdown;
6331 int interact_style;
6332 Bool fast;
6334 /* Handle already being in saveyourself */
6335 if (xsmp.save_yourself)
6336 SmcSaveYourselfDone(smc_conn, True);
6337 xsmp.save_yourself = True;
6338 xsmp.shutdown = shutdown;
6340 /* First up, preserve all files */
6341 out_flush();
6342 ml_sync_all(FALSE, FALSE); /* preserve all swap files */
6344 if (p_verbose > 0)
6345 verb_msg((char_u *)_("XSMP handling save-yourself request"));
6347 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6348 /* Now see if we can ask about unsaved files */
6349 if (shutdown && !fast && gui.in_use)
6350 /* Need to interact with user, but need SM's permission */
6351 SmcInteractRequest(smc_conn, SmDialogError,
6352 xsmp_handle_interaction, client_data);
6353 else
6354 # endif
6356 /* Can stop the cycle here */
6357 SmcSaveYourselfDone(smc_conn, True);
6358 xsmp.save_yourself = False;
6364 * Callback to warn us of imminent death.
6366 /*ARGSUSED*/
6367 static void
6368 xsmp_die(smc_conn, client_data)
6369 SmcConn smc_conn;
6370 SmPointer client_data;
6372 xsmp_close();
6374 /* quit quickly leaving swapfiles for modified buffers behind */
6375 getout_preserve_modified(0);
6380 * Callback to tell us that save-yourself has completed.
6382 /*ARGSUSED*/
6383 static void
6384 xsmp_save_complete(smc_conn, client_data)
6385 SmcConn smc_conn;
6386 SmPointer client_data;
6388 xsmp.save_yourself = False;
6393 * Callback to tell us that an instigated shutdown was cancelled
6394 * (maybe even by us)
6396 /*ARGSUSED*/
6397 static void
6398 xsmp_shutdown_cancelled(smc_conn, client_data)
6399 SmcConn smc_conn;
6400 SmPointer client_data;
6402 if (xsmp.save_yourself)
6403 SmcSaveYourselfDone(smc_conn, True);
6404 xsmp.save_yourself = False;
6405 xsmp.shutdown = False;
6410 * Callback to tell us that a new ICE connection has been established.
6412 /*ARGSUSED*/
6413 static void
6414 xsmp_ice_connection(iceConn, clientData, opening, watchData)
6415 IceConn iceConn;
6416 IcePointer clientData;
6417 Bool opening;
6418 IcePointer *watchData;
6420 /* Intercept creation of ICE connection fd */
6421 if (opening)
6423 xsmp_icefd = IceConnectionNumber(iceConn);
6424 IceRemoveConnectionWatch(xsmp_ice_connection, NULL);
6429 /* Handle any ICE processing that's required; return FAIL if SM lost */
6431 xsmp_handle_requests()
6433 Bool rep;
6435 if (IceProcessMessages(xsmp.iceconn, NULL, &rep)
6436 == IceProcessMessagesIOError)
6438 /* Lost ICE */
6439 if (p_verbose > 0)
6440 verb_msg((char_u *)_("XSMP lost ICE connection"));
6441 xsmp_close();
6442 return FAIL;
6444 else
6445 return OK;
6448 static int dummy;
6450 /* Set up X Session Management Protocol */
6451 void
6452 xsmp_init(void)
6454 char errorstring[80];
6455 char *clientid;
6456 SmcCallbacks smcallbacks;
6457 #if 0
6458 SmPropValue smname;
6459 SmProp smnameprop;
6460 SmProp *smprops[1];
6461 #endif
6463 if (p_verbose > 0)
6464 verb_msg((char_u *)_("XSMP opening connection"));
6466 xsmp.save_yourself = xsmp.shutdown = False;
6468 /* Set up SM callbacks - must have all, even if they're not used */
6469 smcallbacks.save_yourself.callback = xsmp_handle_save_yourself;
6470 smcallbacks.save_yourself.client_data = NULL;
6471 smcallbacks.die.callback = xsmp_die;
6472 smcallbacks.die.client_data = NULL;
6473 smcallbacks.save_complete.callback = xsmp_save_complete;
6474 smcallbacks.save_complete.client_data = NULL;
6475 smcallbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
6476 smcallbacks.shutdown_cancelled.client_data = NULL;
6478 /* Set up a watch on ICE connection creations. The "dummy" argument is
6479 * apparently required for FreeBSD (we get a BUS error when using NULL). */
6480 if (IceAddConnectionWatch(xsmp_ice_connection, &dummy) == 0)
6482 if (p_verbose > 0)
6483 verb_msg((char_u *)_("XSMP ICE connection watch failed"));
6484 return;
6487 /* Create an SM connection */
6488 xsmp.smcconn = SmcOpenConnection(
6489 NULL,
6490 NULL,
6491 SmProtoMajor,
6492 SmProtoMinor,
6493 SmcSaveYourselfProcMask | SmcDieProcMask
6494 | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
6495 &smcallbacks,
6496 NULL,
6497 &clientid,
6498 sizeof(errorstring),
6499 errorstring);
6500 if (xsmp.smcconn == NULL)
6502 char errorreport[132];
6504 if (p_verbose > 0)
6506 vim_snprintf(errorreport, sizeof(errorreport),
6507 _("XSMP SmcOpenConnection failed: %s"), errorstring);
6508 verb_msg((char_u *)errorreport);
6510 return;
6512 xsmp.iceconn = SmcGetIceConnection(xsmp.smcconn);
6514 #if 0
6515 /* ID ourselves */
6516 smname.value = "vim";
6517 smname.length = 3;
6518 smnameprop.name = "SmProgram";
6519 smnameprop.type = "SmARRAY8";
6520 smnameprop.num_vals = 1;
6521 smnameprop.vals = &smname;
6523 smprops[0] = &smnameprop;
6524 SmcSetProperties(xsmp.smcconn, 1, smprops);
6525 #endif
6529 /* Shut down XSMP comms. */
6530 void
6531 xsmp_close()
6533 if (xsmp_icefd != -1)
6535 SmcCloseConnection(xsmp.smcconn, 0, NULL);
6536 xsmp_icefd = -1;
6539 #endif /* USE_XSMP */
6542 #ifdef EBCDIC
6543 /* Translate character to its CTRL- value */
6544 char CtrlTable[] =
6546 /* 00 - 5E */
6547 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6548 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6549 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6550 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6551 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6552 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6553 /* ^ */ 0x1E,
6554 /* - */ 0x1F,
6555 /* 61 - 6C */
6556 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6557 /* _ */ 0x1F,
6558 /* 6E - 80 */
6559 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6560 /* a */ 0x01,
6561 /* b */ 0x02,
6562 /* c */ 0x03,
6563 /* d */ 0x37,
6564 /* e */ 0x2D,
6565 /* f */ 0x2E,
6566 /* g */ 0x2F,
6567 /* h */ 0x16,
6568 /* i */ 0x05,
6569 /* 8A - 90 */
6570 0, 0, 0, 0, 0, 0, 0,
6571 /* j */ 0x15,
6572 /* k */ 0x0B,
6573 /* l */ 0x0C,
6574 /* m */ 0x0D,
6575 /* n */ 0x0E,
6576 /* o */ 0x0F,
6577 /* p */ 0x10,
6578 /* q */ 0x11,
6579 /* r */ 0x12,
6580 /* 9A - A1 */
6581 0, 0, 0, 0, 0, 0, 0, 0,
6582 /* s */ 0x13,
6583 /* t */ 0x3C,
6584 /* u */ 0x3D,
6585 /* v */ 0x32,
6586 /* w */ 0x26,
6587 /* x */ 0x18,
6588 /* y */ 0x19,
6589 /* z */ 0x3F,
6590 /* AA - AC */
6591 0, 0, 0,
6592 /* [ */ 0x27,
6593 /* AE - BC */
6594 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6595 /* ] */ 0x1D,
6596 /* BE - C0 */ 0, 0, 0,
6597 /* A */ 0x01,
6598 /* B */ 0x02,
6599 /* C */ 0x03,
6600 /* D */ 0x37,
6601 /* E */ 0x2D,
6602 /* F */ 0x2E,
6603 /* G */ 0x2F,
6604 /* H */ 0x16,
6605 /* I */ 0x05,
6606 /* CA - D0 */ 0, 0, 0, 0, 0, 0, 0,
6607 /* J */ 0x15,
6608 /* K */ 0x0B,
6609 /* L */ 0x0C,
6610 /* M */ 0x0D,
6611 /* N */ 0x0E,
6612 /* O */ 0x0F,
6613 /* P */ 0x10,
6614 /* Q */ 0x11,
6615 /* R */ 0x12,
6616 /* DA - DF */ 0, 0, 0, 0, 0, 0,
6617 /* \ */ 0x1C,
6618 /* E1 */ 0,
6619 /* S */ 0x13,
6620 /* T */ 0x3C,
6621 /* U */ 0x3D,
6622 /* V */ 0x32,
6623 /* W */ 0x26,
6624 /* X */ 0x18,
6625 /* Y */ 0x19,
6626 /* Z */ 0x3F,
6627 /* EA - FF*/ 0, 0, 0, 0, 0, 0,
6628 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6631 char MetaCharTable[]=
6632 {/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6633 0, 0, 0, 0,'\\', 0,'F', 0,'W','M','N', 0, 0, 0, 0, 0,
6634 0, 0, 0, 0,']', 0, 0,'G', 0, 0,'R','O', 0, 0, 0, 0,
6635 '@','A','B','C','D','E', 0, 0,'H','I','J','K','L', 0, 0, 0,
6636 'P','Q', 0,'S','T','U','V', 0,'X','Y','Z','[', 0, 0,'^', 0
6640 /* TODO: Use characters NOT numbers!!! */
6641 char CtrlCharTable[]=
6642 {/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6643 124,193,194,195, 0,201, 0, 0, 0, 0, 0,210,211,212,213,214,
6644 215,216,217,226, 0,209,200, 0,231,232, 0, 0,224,189, 95,109,
6645 0, 0, 0, 0, 0, 0,230,173, 0, 0, 0, 0, 0,197,198,199,
6646 0, 0,229, 0, 0, 0, 0,196, 0, 0, 0, 0,227,228, 0,233,
6650 #endif