Patch 7.0.208 (after 7.0.171 and 7.0.180)
[MacVim/jjgod.git] / src / os_unix.c
blob047bd84b30486c76d65ed698e880be12dd93a214
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 #if defined(HAVE_SELECT)
59 extern int select __ARGS((int, fd_set *, fd_set *, fd_set *, struct timeval *));
60 #endif
62 #ifdef FEAT_MOUSE_GPM
63 # include <gpm.h>
64 /* <linux/keyboard.h> contains defines conflicting with "keymap.h",
65 * I just copied relevant defines here. A cleaner solution would be to put gpm
66 * code into separate file and include there linux/keyboard.h
68 /* #include <linux/keyboard.h> */
69 # define KG_SHIFT 0
70 # define KG_CTRL 2
71 # define KG_ALT 3
72 # define KG_ALTGR 1
73 # define KG_SHIFTL 4
74 # define KG_SHIFTR 5
75 # define KG_CTRLL 6
76 # define KG_CTRLR 7
77 # define KG_CAPSSHIFT 8
79 static void gpm_close __ARGS((void));
80 static int gpm_open __ARGS((void));
81 static int mch_gpm_process __ARGS((void));
82 #endif
85 * end of autoconf section. To be extended...
88 /* Are the following #ifdefs still required? And why? Is that for X11? */
90 #if defined(ESIX) || defined(M_UNIX) && !defined(SCO)
91 # ifdef SIGWINCH
92 # undef SIGWINCH
93 # endif
94 # ifdef TIOCGWINSZ
95 # undef TIOCGWINSZ
96 # endif
97 #endif
99 #if defined(SIGWINDOW) && !defined(SIGWINCH) /* hpux 9.01 has it */
100 # define SIGWINCH SIGWINDOW
101 #endif
103 #ifdef FEAT_X11
104 # include <X11/Xlib.h>
105 # include <X11/Xutil.h>
106 # include <X11/Xatom.h>
107 # ifdef FEAT_XCLIPBOARD
108 # include <X11/Intrinsic.h>
109 # include <X11/Shell.h>
110 # include <X11/StringDefs.h>
111 static Widget xterm_Shell = (Widget)0;
112 static void xterm_update __ARGS((void));
113 # endif
115 # if defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE)
116 Window x11_window = 0;
117 # endif
118 Display *x11_display = NULL;
120 # ifdef FEAT_TITLE
121 static int get_x11_windis __ARGS((void));
122 static void set_x11_title __ARGS((char_u *));
123 static void set_x11_icon __ARGS((char_u *));
124 # endif
125 #endif
127 #ifdef FEAT_TITLE
128 static int get_x11_title __ARGS((int));
129 static int get_x11_icon __ARGS((int));
131 static char_u *oldtitle = NULL;
132 static int did_set_title = FALSE;
133 static char_u *oldicon = NULL;
134 static int did_set_icon = FALSE;
135 #endif
137 static void may_core_dump __ARGS((void));
139 static int WaitForChar __ARGS((long));
140 #if defined(__BEOS__)
141 int RealWaitForChar __ARGS((int, long, int *));
142 #else
143 static int RealWaitForChar __ARGS((int, long, int *));
144 #endif
146 #ifdef FEAT_XCLIPBOARD
147 static int do_xterm_trace __ARGS((void));
148 # define XT_TRACE_DELAY 50 /* delay for xterm tracing */
149 #endif
151 static void handle_resize __ARGS((void));
153 #if defined(SIGWINCH)
154 static RETSIGTYPE sig_winch __ARGS(SIGPROTOARG);
155 #endif
156 #if defined(SIGINT)
157 static RETSIGTYPE catch_sigint __ARGS(SIGPROTOARG);
158 #endif
159 #if defined(SIGPWR)
160 static RETSIGTYPE catch_sigpwr __ARGS(SIGPROTOARG);
161 #endif
162 #if defined(SIGALRM) && defined(FEAT_X11) \
163 && defined(FEAT_TITLE) && !defined(FEAT_GUI_GTK)
164 # define SET_SIG_ALARM
165 static RETSIGTYPE sig_alarm __ARGS(SIGPROTOARG);
166 static int sig_alarm_called;
167 #endif
168 static RETSIGTYPE deathtrap __ARGS(SIGPROTOARG);
170 static void catch_int_signal __ARGS((void));
171 static void set_signals __ARGS((void));
172 static void catch_signals __ARGS((RETSIGTYPE (*func_deadly)(), RETSIGTYPE (*func_other)()));
173 #ifndef __EMX__
174 static int have_wildcard __ARGS((int, char_u **));
175 static int have_dollars __ARGS((int, char_u **));
176 #endif
178 #ifndef __EMX__
179 static int save_patterns __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file));
180 #endif
182 #ifndef SIG_ERR
183 # define SIG_ERR ((RETSIGTYPE (*)())-1)
184 #endif
186 static int do_resize = FALSE;
187 #ifndef __EMX__
188 static char_u *extra_shell_arg = NULL;
189 static int show_shell_mess = TRUE;
190 #endif
191 static int deadly_signal = 0; /* The signal we caught */
193 static int curr_tmode = TMODE_COOK; /* contains current terminal mode */
195 #ifdef USE_XSMP
196 typedef struct
198 SmcConn smcconn; /* The SM connection ID */
199 IceConn iceconn; /* The ICE connection ID */
200 Bool save_yourself; /* If we're in the middle of a save_yourself */
201 Bool shutdown; /* If we're in shutdown mode */
202 } xsmp_config_T;
204 static xsmp_config_T xsmp;
205 #endif
207 #ifdef SYS_SIGLIST_DECLARED
209 * I have seen
210 * extern char *_sys_siglist[NSIG];
211 * on Irix, Linux, NetBSD and Solaris. It contains a nice list of strings
212 * that describe the signals. That is nearly what we want here. But
213 * autoconf does only check for sys_siglist (without the underscore), I
214 * do not want to change everything today.... jw.
215 * This is why AC_DECL_SYS_SIGLIST is commented out in configure.in
217 #endif
219 static struct signalinfo
221 int sig; /* Signal number, eg. SIGSEGV etc */
222 char *name; /* Signal name (not char_u!). */
223 char deadly; /* Catch as a deadly signal? */
224 } signal_info[] =
226 #ifdef SIGHUP
227 {SIGHUP, "HUP", TRUE},
228 #endif
229 #ifdef SIGQUIT
230 {SIGQUIT, "QUIT", TRUE},
231 #endif
232 #ifdef SIGILL
233 {SIGILL, "ILL", TRUE},
234 #endif
235 #ifdef SIGTRAP
236 {SIGTRAP, "TRAP", TRUE},
237 #endif
238 #ifdef SIGABRT
239 {SIGABRT, "ABRT", TRUE},
240 #endif
241 #ifdef SIGEMT
242 {SIGEMT, "EMT", TRUE},
243 #endif
244 #ifdef SIGFPE
245 {SIGFPE, "FPE", TRUE},
246 #endif
247 #ifdef SIGBUS
248 {SIGBUS, "BUS", TRUE},
249 #endif
250 #ifdef SIGSEGV
251 {SIGSEGV, "SEGV", TRUE},
252 #endif
253 #ifdef SIGSYS
254 {SIGSYS, "SYS", TRUE},
255 #endif
256 #ifdef SIGALRM
257 {SIGALRM, "ALRM", FALSE}, /* Perl's alarm() can trigger it */
258 #endif
259 #ifdef SIGTERM
260 {SIGTERM, "TERM", TRUE},
261 #endif
262 #ifdef SIGVTALRM
263 {SIGVTALRM, "VTALRM", TRUE},
264 #endif
265 #if defined(SIGPROF) && !defined(FEAT_MZSCHEME)
266 /* MzScheme uses SIGPROF for its own needs */
267 {SIGPROF, "PROF", TRUE},
268 #endif
269 #ifdef SIGXCPU
270 {SIGXCPU, "XCPU", TRUE},
271 #endif
272 #ifdef SIGXFSZ
273 {SIGXFSZ, "XFSZ", TRUE},
274 #endif
275 #ifdef SIGUSR1
276 {SIGUSR1, "USR1", TRUE},
277 #endif
278 #ifdef SIGUSR2
279 {SIGUSR2, "USR2", TRUE},
280 #endif
281 #ifdef SIGINT
282 {SIGINT, "INT", FALSE},
283 #endif
284 #ifdef SIGWINCH
285 {SIGWINCH, "WINCH", FALSE},
286 #endif
287 #ifdef SIGTSTP
288 {SIGTSTP, "TSTP", FALSE},
289 #endif
290 #ifdef SIGPIPE
291 {SIGPIPE, "PIPE", FALSE},
292 #endif
293 {-1, "Unknown!", FALSE}
296 void
297 mch_write(s, len)
298 char_u *s;
299 int len;
301 write(1, (char *)s, len);
302 if (p_wd) /* Unix is too fast, slow down a bit more */
303 RealWaitForChar(read_cmd_fd, p_wd, NULL);
307 * mch_inchar(): low level input funcion.
308 * Get a characters from the keyboard.
309 * Return the number of characters that are available.
310 * If wtime == 0 do not wait for characters.
311 * If wtime == n wait a short time for characters.
312 * If wtime == -1 wait forever for characters.
315 mch_inchar(buf, maxlen, wtime, tb_change_cnt)
316 char_u *buf;
317 int maxlen;
318 long wtime; /* don't use "time", MIPS cannot handle it */
319 int tb_change_cnt;
321 int len;
323 /* Check if window changed size while we were busy, perhaps the ":set
324 * columns=99" command was used. */
325 while (do_resize)
326 handle_resize();
328 if (wtime >= 0)
330 while (WaitForChar(wtime) == 0) /* no character available */
332 if (!do_resize) /* return if not interrupted by resize */
333 return 0;
334 handle_resize();
337 else /* wtime == -1 */
340 * If there is no character available within 'updatetime' seconds
341 * flush all the swap files to disk.
342 * Also done when interrupted by SIGWINCH.
344 if (WaitForChar(p_ut) == 0)
346 #ifdef FEAT_AUTOCMD
347 if (trigger_cursorhold() && maxlen >= 3
348 && !typebuf_changed(tb_change_cnt))
350 buf[0] = K_SPECIAL;
351 buf[1] = KS_EXTRA;
352 buf[2] = (int)KE_CURSORHOLD;
353 return 3;
355 #endif
356 before_blocking();
360 for (;;) /* repeat until we got a character */
362 while (do_resize) /* window changed size */
363 handle_resize();
365 * we want to be interrupted by the winch signal
367 WaitForChar(-1L);
368 if (do_resize) /* interrupted by SIGWINCH signal */
369 continue;
371 /* If input was put directly in typeahead buffer bail out here. */
372 if (typebuf_changed(tb_change_cnt))
373 return 0;
376 * For some terminals we only get one character at a time.
377 * We want the get all available characters, so we could keep on
378 * trying until none is available
379 * For some other terminals this is quite slow, that's why we don't do
380 * it.
382 len = read_from_input_buf(buf, (long)maxlen);
383 if (len > 0)
385 #ifdef OS2
386 int i;
388 for (i = 0; i < len; i++)
389 if (buf[i] == 0)
390 buf[i] = K_NUL;
391 #endif
392 return len;
397 static void
398 handle_resize()
400 do_resize = FALSE;
401 shell_resized();
405 * return non-zero if a character is available
408 mch_char_avail()
410 return WaitForChar(0L);
413 #if defined(HAVE_TOTAL_MEM) || defined(PROTO)
414 # ifdef HAVE_SYS_RESOURCE_H
415 # include <sys/resource.h>
416 # endif
417 # if defined(HAVE_SYS_SYSCTL_H) && defined(HAVE_SYSCTL)
418 # include <sys/sysctl.h>
419 # endif
420 # if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
421 # include <sys/sysinfo.h>
422 # endif
425 * Return total amount of memory available. Doesn't change when memory has
426 * been allocated.
428 /* ARGSUSED */
429 long_u
430 mch_total_mem(special)
431 int special;
433 # ifdef __EMX__
434 return ulimit(3, 0L); /* always 32MB? */
435 # else
436 long_u mem = 0;
438 # ifdef HAVE_SYSCTL
439 int mib[2], physmem;
440 size_t len;
442 /* BSD way of getting the amount of RAM available. */
443 mib[0] = CTL_HW;
444 mib[1] = HW_USERMEM;
445 len = sizeof(physmem);
446 if (sysctl(mib, 2, &physmem, &len, NULL, 0) == 0)
447 mem = (long_u)physmem;
448 # endif
450 # if defined(HAVE_SYS_SYSINFO_H) && defined(HAVE_SYSINFO)
451 if (mem == 0)
453 struct sysinfo sinfo;
455 /* Linux way of getting amount of RAM available */
456 if (sysinfo(&sinfo) == 0)
457 mem = sinfo.totalram;
459 # endif
461 # ifdef HAVE_SYSCONF
462 if (mem == 0)
464 long pagesize, pagecount;
466 /* Solaris way of getting amount of RAM available */
467 pagesize = sysconf(_SC_PAGESIZE);
468 pagecount = sysconf(_SC_PHYS_PAGES);
469 if (pagesize > 0 && pagecount > 0)
470 mem = (long_u)pagesize * pagecount;
472 # endif
474 /* Return the minimum of the physical memory and the user limit, because
475 * using more than the user limit may cause Vim to be terminated. */
476 # if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETRLIMIT)
478 struct rlimit rlp;
480 if (getrlimit(RLIMIT_DATA, &rlp) == 0
481 && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
482 # ifdef RLIM_INFINITY
483 && rlp.rlim_cur != RLIM_INFINITY
484 # endif
485 && (long_u)rlp.rlim_cur < mem
487 return (long_u)rlp.rlim_cur;
489 # endif
491 if (mem > 0)
492 return mem;
493 return (long_u)0x7fffffff;
494 # endif
496 #endif
498 void
499 mch_delay(msec, ignoreinput)
500 long msec;
501 int ignoreinput;
503 int old_tmode;
504 #ifdef FEAT_MZSCHEME
505 long total = msec; /* remember original value */
506 #endif
508 if (ignoreinput)
510 /* Go to cooked mode without echo, to allow SIGINT interrupting us
511 * here */
512 old_tmode = curr_tmode;
513 if (curr_tmode == TMODE_RAW)
514 settmode(TMODE_SLEEP);
517 * Everybody sleeps in a different way...
518 * Prefer nanosleep(), some versions of usleep() can only sleep up to
519 * one second.
521 #ifdef FEAT_MZSCHEME
524 /* if total is large enough, wait by portions in p_mzq */
525 if (total > p_mzq)
526 msec = p_mzq;
527 else
528 msec = total;
529 total -= msec;
530 #endif
531 #ifdef HAVE_NANOSLEEP
533 struct timespec ts;
535 ts.tv_sec = msec / 1000;
536 ts.tv_nsec = (msec % 1000) * 1000000;
537 (void)nanosleep(&ts, NULL);
539 #else
540 # ifdef HAVE_USLEEP
541 while (msec >= 1000)
543 usleep((unsigned int)(999 * 1000));
544 msec -= 999;
546 usleep((unsigned int)(msec * 1000));
547 # else
548 # ifndef HAVE_SELECT
549 poll(NULL, 0, (int)msec);
550 # else
551 # ifdef __EMX__
552 _sleep2(msec);
553 # else
555 struct timeval tv;
557 tv.tv_sec = msec / 1000;
558 tv.tv_usec = (msec % 1000) * 1000;
560 * NOTE: Solaris 2.6 has a bug that makes select() hang here. Get
561 * a patch from Sun to fix this. Reported by Gunnar Pedersen.
563 select(0, NULL, NULL, NULL, &tv);
565 # endif /* __EMX__ */
566 # endif /* HAVE_SELECT */
567 # endif /* HAVE_NANOSLEEP */
568 #endif /* HAVE_USLEEP */
569 #ifdef FEAT_MZSCHEME
571 while (total > 0);
572 #endif
574 settmode(old_tmode);
576 else
577 WaitForChar(msec);
580 #if 0 /* disabled, no longer needed now that regmatch() is not recursive */
581 # if defined(HAVE_GETRLIMIT)
582 # define HAVE_STACK_LIMIT
583 # endif
584 #endif
586 #if defined(HAVE_STACK_LIMIT) \
587 || (!defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGSTACK))
588 # define HAVE_CHECK_STACK_GROWTH
590 * Support for checking for an almost-out-of-stack-space situation.
594 * Return a pointer to an item on the stack. Used to find out if the stack
595 * grows up or down.
597 static void check_stack_growth __ARGS((char *p));
598 static int stack_grows_downwards;
601 * Find out if the stack grows upwards or downwards.
602 * "p" points to a variable on the stack of the caller.
604 static void
605 check_stack_growth(p)
606 char *p;
608 int i;
610 stack_grows_downwards = (p > (char *)&i);
612 #endif
614 #if defined(HAVE_STACK_LIMIT) || defined(PROTO)
615 static char *stack_limit = NULL;
617 #if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
618 # include <pthread.h>
619 # include <pthread_np.h>
620 #endif
623 * Find out until how var the stack can grow without getting into trouble.
624 * Called when starting up and when switching to the signal stack in
625 * deathtrap().
627 static void
628 get_stack_limit()
630 struct rlimit rlp;
631 int i;
632 long lim;
634 /* Set the stack limit to 15/16 of the allowable size. Skip this when the
635 * limit doesn't fit in a long (rlim_cur might be "long long"). */
636 if (getrlimit(RLIMIT_STACK, &rlp) == 0
637 && rlp.rlim_cur < ((rlim_t)1 << (sizeof(long_u) * 8 - 1))
638 # ifdef RLIM_INFINITY
639 && rlp.rlim_cur != RLIM_INFINITY
640 # endif
643 lim = (long)rlp.rlim_cur;
644 #if defined(_THREAD_SAFE) && defined(HAVE_PTHREAD_NP_H)
646 pthread_attr_t attr;
647 size_t size;
649 /* On FreeBSD the initial thread always has a fixed stack size, no
650 * matter what the limits are set to. Normally it's 1 Mbyte. */
651 pthread_attr_init(&attr);
652 if (pthread_attr_get_np(pthread_self(), &attr) == 0)
654 pthread_attr_getstacksize(&attr, &size);
655 if (lim > (long)size)
656 lim = (long)size;
658 pthread_attr_destroy(&attr);
660 #endif
661 if (stack_grows_downwards)
663 stack_limit = (char *)((long)&i - (lim / 16L * 15L));
664 if (stack_limit >= (char *)&i)
665 /* overflow, set to 1/16 of current stack position */
666 stack_limit = (char *)((long)&i / 16L);
668 else
670 stack_limit = (char *)((long)&i + (lim / 16L * 15L));
671 if (stack_limit <= (char *)&i)
672 stack_limit = NULL; /* overflow */
678 * Return FAIL when running out of stack space.
679 * "p" must point to any variable local to the caller that's on the stack.
682 mch_stackcheck(p)
683 char *p;
685 if (stack_limit != NULL)
687 if (stack_grows_downwards)
689 if (p < stack_limit)
690 return FAIL;
692 else if (p > stack_limit)
693 return FAIL;
695 return OK;
697 #endif
699 #if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
701 * Support for using the signal stack.
702 * This helps when we run out of stack space, which causes a SIGSEGV. The
703 * signal handler then must run on another stack, since the normal stack is
704 * completely full.
707 #ifndef SIGSTKSZ
708 # define SIGSTKSZ 8000 /* just a guess of how much stack is needed... */
709 #endif
711 # ifdef HAVE_SIGALTSTACK
712 static stack_t sigstk; /* for sigaltstack() */
713 # else
714 static struct sigstack sigstk; /* for sigstack() */
715 # endif
717 static void init_signal_stack __ARGS((void));
718 static char *signal_stack;
720 static void
721 init_signal_stack()
723 if (signal_stack != NULL)
725 # ifdef HAVE_SIGALTSTACK
726 # ifdef __APPLE__
727 /* missing prototype. Adding it to osdef?.h.in doesn't work, because
728 * "struct sigaltstack" needs to be declared. */
729 extern int sigaltstack __ARGS((const struct sigaltstack *ss, struct sigaltstack *oss));
730 # endif
732 # ifdef HAVE_SS_BASE
733 sigstk.ss_base = signal_stack;
734 # else
735 sigstk.ss_sp = signal_stack;
736 # endif
737 sigstk.ss_size = SIGSTKSZ;
738 sigstk.ss_flags = 0;
739 (void)sigaltstack(&sigstk, NULL);
740 # else
741 sigstk.ss_sp = signal_stack;
742 if (stack_grows_downwards)
743 sigstk.ss_sp += SIGSTKSZ - 1;
744 sigstk.ss_onstack = 0;
745 (void)sigstack(&sigstk, NULL);
746 # endif
749 #endif
752 * We need correct potatotypes for a signal function, otherwise mean compilers
753 * will barf when the second argument to signal() is ``wrong''.
754 * Let me try it with a few tricky defines from my own osdef.h (jw).
756 #if defined(SIGWINCH)
757 /* ARGSUSED */
758 static RETSIGTYPE
759 sig_winch SIGDEFARG(sigarg)
761 /* this is not required on all systems, but it doesn't hurt anybody */
762 signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
763 do_resize = TRUE;
764 SIGRETURN;
766 #endif
768 #if defined(SIGINT)
769 /* ARGSUSED */
770 static RETSIGTYPE
771 catch_sigint SIGDEFARG(sigarg)
773 /* this is not required on all systems, but it doesn't hurt anybody */
774 signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
775 got_int = TRUE;
776 SIGRETURN;
778 #endif
780 #if defined(SIGPWR)
781 /* ARGSUSED */
782 static RETSIGTYPE
783 catch_sigpwr SIGDEFARG(sigarg)
785 /* this is not required on all systems, but it doesn't hurt anybody */
786 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
788 * I'm not sure we get the SIGPWR signal when the system is really going
789 * down or when the batteries are almost empty. Just preserve the swap
790 * files and don't exit, that can't do any harm.
792 ml_sync_all(FALSE, FALSE);
793 SIGRETURN;
795 #endif
797 #ifdef SET_SIG_ALARM
799 * signal function for alarm().
801 /* ARGSUSED */
802 static RETSIGTYPE
803 sig_alarm SIGDEFARG(sigarg)
805 /* doesn't do anything, just to break a system call */
806 sig_alarm_called = TRUE;
807 SIGRETURN;
809 #endif
811 #if (defined(HAVE_SETJMP_H) \
812 && ((defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) \
813 || defined(FEAT_LIBCALL))) \
814 || defined(PROTO)
816 * A simplistic version of setjmp() that only allows one level of using.
817 * Don't call twice before calling mch_endjmp()!.
818 * Usage:
819 * mch_startjmp();
820 * if (SETJMP(lc_jump_env) != 0)
822 * mch_didjmp();
823 * EMSG("crash!");
825 * else
827 * do_the_work;
828 * mch_endjmp();
830 * Note: Can't move SETJMP() here, because a function calling setjmp() must
831 * not return before the saved environment is used.
832 * Returns OK for normal return, FAIL when the protected code caused a
833 * problem and LONGJMP() was used.
835 void
836 mch_startjmp()
838 #ifdef SIGHASARG
839 lc_signal = 0;
840 #endif
841 lc_active = TRUE;
844 void
845 mch_endjmp()
847 lc_active = FALSE;
850 void
851 mch_didjmp()
853 # if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
854 /* On FreeBSD the signal stack has to be reset after using siglongjmp(),
855 * otherwise catching the signal only works once. */
856 init_signal_stack();
857 # endif
859 #endif
862 * This function handles deadly signals.
863 * It tries to preserve any swap file and exit properly.
864 * (partly from Elvis).
866 static RETSIGTYPE
867 deathtrap SIGDEFARG(sigarg)
869 static int entered = 0; /* count the number of times we got here.
870 Note: when memory has been corrupted
871 this may get an arbitrary value! */
872 #ifdef SIGHASARG
873 int i;
874 #endif
876 #if defined(HAVE_SETJMP_H)
878 * Catch a crash in protected code.
879 * Restores the environment saved in lc_jump_env, which looks like
880 * SETJMP() returns 1.
882 if (lc_active)
884 # if defined(SIGHASARG)
885 lc_signal = sigarg;
886 # endif
887 lc_active = FALSE; /* don't jump again */
888 LONGJMP(lc_jump_env, 1);
889 /* NOTREACHED */
891 #endif
893 #ifdef SIGHASARG
894 /* When SIGHUP, SIGQUIT, etc. are blocked: postpone the effect and return
895 * here. This avoids that a non-reentrant function is interrupted, e.g.,
896 * free(). Calling free() again may then cause a crash. */
897 if (entered == 0
898 && (0
899 # ifdef SIGHUP
900 || sigarg == SIGHUP
901 # endif
902 # ifdef SIGQUIT
903 || sigarg == SIGQUIT
904 # endif
905 # ifdef SIGTERM
906 || sigarg == SIGTERM
907 # endif
908 # ifdef SIGPWR
909 || sigarg == SIGPWR
910 # endif
911 # ifdef SIGUSR1
912 || sigarg == SIGUSR1
913 # endif
914 # ifdef SIGUSR2
915 || sigarg == SIGUSR2
916 # endif
918 && !vim_handle_signal(sigarg))
919 SIGRETURN;
920 #endif
922 /* Remember how often we have been called. */
923 ++entered;
925 #ifdef FEAT_EVAL
926 /* Set the v:dying variable. */
927 set_vim_var_nr(VV_DYING, (long)entered);
928 #endif
930 #ifdef HAVE_STACK_LIMIT
931 /* Since we are now using the signal stack, need to reset the stack
932 * limit. Otherwise using a regexp will fail. */
933 get_stack_limit();
934 #endif
936 #if 0
937 /* This is for opening gdb the moment Vim crashes.
938 * You need to manually adjust the file name and Vim executable name.
939 * Suggested by SungHyun Nam. */
941 # define VI_GDB_FILE "/tmp/vimgdb"
942 # define VIM_NAME "/usr/bin/vim"
943 FILE *fp = fopen(VI_GDB_FILE, "w");
944 if (fp)
946 fprintf(fp,
947 "file %s\n"
948 "attach %d\n"
949 "set height 1000\n"
950 "bt full\n"
951 , VIM_NAME, getpid());
952 fclose(fp);
953 system("xterm -e gdb -x "VI_GDB_FILE);
954 unlink(VI_GDB_FILE);
957 #endif
959 #ifdef SIGHASARG
960 /* try to find the name of this signal */
961 for (i = 0; signal_info[i].sig != -1; i++)
962 if (sigarg == signal_info[i].sig)
963 break;
964 deadly_signal = sigarg;
965 #endif
967 full_screen = FALSE; /* don't write message to the GUI, it might be
968 * part of the problem... */
970 * If something goes wrong after entering here, we may get here again.
971 * When this happens, give a message and try to exit nicely (resetting the
972 * terminal mode, etc.)
973 * When this happens twice, just exit, don't even try to give a message,
974 * stack may be corrupt or something weird.
975 * When this still happens again (or memory was corrupted in such a way
976 * that "entered" was clobbered) use _exit(), don't try freeing resources.
978 if (entered >= 3)
980 reset_signals(); /* don't catch any signals anymore */
981 may_core_dump();
982 if (entered >= 4)
983 _exit(8);
984 exit(7);
986 if (entered == 2)
988 OUT_STR(_("Vim: Double signal, exiting\n"));
989 out_flush();
990 getout(1);
993 #ifdef SIGHASARG
994 sprintf((char *)IObuff, _("Vim: Caught deadly signal %s\n"),
995 signal_info[i].name);
996 #else
997 sprintf((char *)IObuff, _("Vim: Caught deadly signal\n"));
998 #endif
999 preserve_exit(); /* preserve files and exit */
1001 #ifdef NBDEBUG
1002 reset_signals();
1003 may_core_dump();
1004 abort();
1005 #endif
1007 SIGRETURN;
1010 #ifdef _REENTRANT
1012 * On Solaris with multi-threading, suspending might not work immediately.
1013 * Catch the SIGCONT signal, which will be used as an indication whether the
1014 * suspending has been done or not.
1016 static int sigcont_received;
1017 static RETSIGTYPE sigcont_handler __ARGS(SIGPROTOARG);
1020 * signal handler for SIGCONT
1022 /* ARGSUSED */
1023 static RETSIGTYPE
1024 sigcont_handler SIGDEFARG(sigarg)
1026 sigcont_received = TRUE;
1027 SIGRETURN;
1029 #endif
1032 * If the machine has job control, use it to suspend the program,
1033 * otherwise fake it by starting a new shell.
1035 void
1036 mch_suspend()
1038 /* BeOS does have SIGTSTP, but it doesn't work. */
1039 #if defined(SIGTSTP) && !defined(__BEOS__)
1040 out_flush(); /* needed to make cursor visible on some systems */
1041 settmode(TMODE_COOK);
1042 out_flush(); /* needed to disable mouse on some systems */
1044 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
1045 /* Since we are going to sleep, we can't respond to requests for the X
1046 * selections. Lose them, otherwise other applications will hang. But
1047 * first copy the text to cut buffer 0. */
1048 if (clip_star.owned || clip_plus.owned)
1050 x11_export_final_selection();
1051 if (clip_star.owned)
1052 clip_lose_selection(&clip_star);
1053 if (clip_plus.owned)
1054 clip_lose_selection(&clip_plus);
1055 if (x11_display != NULL)
1056 XFlush(x11_display);
1058 # endif
1060 # ifdef _REENTRANT
1061 sigcont_received = FALSE;
1062 # endif
1063 kill(0, SIGTSTP); /* send ourselves a STOP signal */
1064 # ifdef _REENTRANT
1065 /* When we didn't suspend immediately in the kill(), do it now. Happens
1066 * on multi-threaded Solaris. */
1067 if (!sigcont_received)
1068 pause();
1069 # endif
1071 # ifdef FEAT_TITLE
1073 * Set oldtitle to NULL, so the current title is obtained again.
1075 vim_free(oldtitle);
1076 oldtitle = NULL;
1077 # endif
1078 settmode(TMODE_RAW);
1079 need_check_timestamps = TRUE;
1080 did_check_timestamps = FALSE;
1081 #else
1082 suspend_shell();
1083 #endif
1086 void
1087 mch_init()
1089 Columns = 80;
1090 Rows = 24;
1092 out_flush();
1093 set_signals();
1095 #ifdef MACOS_CONVERT
1096 mac_conv_init();
1097 #endif
1100 static void
1101 set_signals()
1103 #if defined(SIGWINCH)
1105 * WINDOW CHANGE signal is handled with sig_winch().
1107 signal(SIGWINCH, (RETSIGTYPE (*)())sig_winch);
1108 #endif
1111 * We want the STOP signal to work, to make mch_suspend() work.
1112 * For "rvim" the STOP signal is ignored.
1114 #ifdef SIGTSTP
1115 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
1116 #endif
1117 #ifdef _REENTRANT
1118 signal(SIGCONT, sigcont_handler);
1119 #endif
1122 * We want to ignore breaking of PIPEs.
1124 #ifdef SIGPIPE
1125 signal(SIGPIPE, SIG_IGN);
1126 #endif
1128 #ifdef SIGINT
1129 catch_int_signal();
1130 #endif
1133 * Ignore alarm signals (Perl's alarm() generates it).
1135 #ifdef SIGALRM
1136 signal(SIGALRM, SIG_IGN);
1137 #endif
1140 * Catch SIGPWR (power failure?) to preserve the swap files, so that no
1141 * work will be lost.
1143 #ifdef SIGPWR
1144 signal(SIGPWR, (RETSIGTYPE (*)())catch_sigpwr);
1145 #endif
1148 * Arrange for other signals to gracefully shutdown Vim.
1150 catch_signals(deathtrap, SIG_ERR);
1152 #if defined(FEAT_GUI) && defined(SIGHUP)
1154 * When the GUI is running, ignore the hangup signal.
1156 if (gui.in_use)
1157 signal(SIGHUP, SIG_IGN);
1158 #endif
1161 #if defined(SIGINT) || defined(PROTO)
1163 * Catch CTRL-C (only works while in Cooked mode).
1165 static void
1166 catch_int_signal()
1168 signal(SIGINT, (RETSIGTYPE (*)())catch_sigint);
1170 #endif
1172 void
1173 reset_signals()
1175 catch_signals(SIG_DFL, SIG_DFL);
1176 #ifdef _REENTRANT
1177 /* SIGCONT isn't in the list, because its default action is ignore */
1178 signal(SIGCONT, SIG_DFL);
1179 #endif
1182 static void
1183 catch_signals(func_deadly, func_other)
1184 RETSIGTYPE (*func_deadly)();
1185 RETSIGTYPE (*func_other)();
1187 int i;
1189 for (i = 0; signal_info[i].sig != -1; i++)
1190 if (signal_info[i].deadly)
1192 #if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGACTION)
1193 struct sigaction sa;
1195 /* Setup to use the alternate stack for the signal function. */
1196 sa.sa_handler = func_deadly;
1197 sigemptyset(&sa.sa_mask);
1198 # if defined(__linux__) && defined(_REENTRANT)
1199 /* On Linux, with glibc compiled for kernel 2.2, there is a bug in
1200 * thread handling in combination with using the alternate stack:
1201 * pthread library functions try to use the stack pointer to
1202 * identify the current thread, causing a SEGV signal, which
1203 * recursively calls deathtrap() and hangs. */
1204 sa.sa_flags = 0;
1205 # else
1206 sa.sa_flags = SA_ONSTACK;
1207 # endif
1208 sigaction(signal_info[i].sig, &sa, NULL);
1209 #else
1210 # if defined(HAVE_SIGALTSTACK) && defined(HAVE_SIGVEC)
1211 struct sigvec sv;
1213 /* Setup to use the alternate stack for the signal function. */
1214 sv.sv_handler = func_deadly;
1215 sv.sv_mask = 0;
1216 sv.sv_flags = SV_ONSTACK;
1217 sigvec(signal_info[i].sig, &sv, NULL);
1218 # else
1219 signal(signal_info[i].sig, func_deadly);
1220 # endif
1221 #endif
1223 else if (func_other != SIG_ERR)
1224 signal(signal_info[i].sig, func_other);
1228 * Handling of SIGHUP, SIGQUIT and SIGTERM:
1229 * "when" == a signal: when busy, postpone, otherwise return TRUE
1230 * "when" == SIGNAL_BLOCK: Going to be busy, block signals
1231 * "when" == SIGNAL_UNBLOCK: Going wait, unblock signals
1232 * Returns TRUE when Vim should exit.
1235 vim_handle_signal(sig)
1236 int sig;
1238 static int got_signal = 0;
1239 static int blocked = TRUE;
1241 switch (sig)
1243 case SIGNAL_BLOCK: blocked = TRUE;
1244 break;
1246 case SIGNAL_UNBLOCK: blocked = FALSE;
1247 if (got_signal != 0)
1249 kill(getpid(), got_signal);
1250 got_signal = 0;
1252 break;
1254 default: if (!blocked)
1255 return TRUE; /* exit! */
1256 got_signal = sig;
1257 #ifdef SIGPWR
1258 if (sig != SIGPWR)
1259 #endif
1260 got_int = TRUE; /* break any loops */
1261 break;
1263 return FALSE;
1267 * Check_win checks whether we have an interactive stdout.
1269 /* ARGSUSED */
1271 mch_check_win(argc, argv)
1272 int argc;
1273 char **argv;
1275 #ifdef OS2
1277 * Store argv[0], may be used for $VIM. Only use it if it is an absolute
1278 * name, mostly it's just "vim" and found in the path, which is unusable.
1280 if (mch_isFullName(argv[0]))
1281 exe_name = vim_strsave((char_u *)argv[0]);
1282 #endif
1283 if (isatty(1))
1284 return OK;
1285 return FAIL;
1289 * Return TRUE if the input comes from a terminal, FALSE otherwise.
1292 mch_input_isatty()
1294 if (isatty(read_cmd_fd))
1295 return TRUE;
1296 return FALSE;
1299 #ifdef FEAT_X11
1301 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H) \
1302 && (defined(FEAT_XCLIPBOARD) || defined(FEAT_TITLE))
1304 static void xopen_message __ARGS((struct timeval *tvp));
1307 * Give a message about the elapsed time for opening the X window.
1309 static void
1310 xopen_message(tvp)
1311 struct timeval *tvp; /* must contain start time */
1313 struct timeval end_tv;
1315 /* Compute elapsed time. */
1316 gettimeofday(&end_tv, NULL);
1317 smsg((char_u *)_("Opening the X display took %ld msec"),
1318 (end_tv.tv_sec - tvp->tv_sec) * 1000L
1319 + (end_tv.tv_usec - tvp->tv_usec) / 1000L);
1321 # endif
1322 #endif
1324 #if defined(FEAT_X11) && (defined(FEAT_TITLE) || defined(FEAT_XCLIPBOARD))
1326 * A few functions shared by X11 title and clipboard code.
1328 static int x_error_handler __ARGS((Display *dpy, XErrorEvent *error_event));
1329 static int x_error_check __ARGS((Display *dpy, XErrorEvent *error_event));
1330 static int x_connect_to_server __ARGS((void));
1331 static int test_x11_window __ARGS((Display *dpy));
1333 static int got_x_error = FALSE;
1336 * X Error handler, otherwise X just exits! (very rude) -- webb
1338 static int
1339 x_error_handler(dpy, error_event)
1340 Display *dpy;
1341 XErrorEvent *error_event;
1343 XGetErrorText(dpy, error_event->error_code, (char *)IObuff, IOSIZE);
1344 STRCAT(IObuff, _("\nVim: Got X error\n"));
1346 /* We cannot print a message and continue, because no X calls are allowed
1347 * here (causes my system to hang). Silently continuing might be an
1348 * alternative... */
1349 preserve_exit(); /* preserve files and exit */
1351 return 0; /* NOTREACHED */
1355 * Another X Error handler, just used to check for errors.
1357 /* ARGSUSED */
1358 static int
1359 x_error_check(dpy, error_event)
1360 Display *dpy;
1361 XErrorEvent *error_event;
1363 got_x_error = TRUE;
1364 return 0;
1367 #if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
1368 # if defined(HAVE_SETJMP_H)
1370 * An X IO Error handler, used to catch error while opening the display.
1372 static int x_IOerror_check __ARGS((Display *dpy));
1374 /* ARGSUSED */
1375 static int
1376 x_IOerror_check(dpy)
1377 Display *dpy;
1379 /* This function should not return, it causes exit(). Longjump instead. */
1380 LONGJMP(lc_jump_env, 1);
1381 /*NOTREACHED*/
1382 return 0;
1384 # endif
1387 * An X IO Error handler, used to catch terminal errors.
1389 static int x_IOerror_handler __ARGS((Display *dpy));
1391 /* ARGSUSED */
1392 static int
1393 x_IOerror_handler(dpy)
1394 Display *dpy;
1396 xterm_dpy = NULL;
1397 x11_window = 0;
1398 x11_display = NULL;
1399 xterm_Shell = (Widget)0;
1401 /* This function should not return, it causes exit(). Longjump instead. */
1402 LONGJMP(x_jump_env, 1);
1403 /*NOTREACHED*/
1404 return 0;
1406 #endif
1409 * Return TRUE when connection to the X server is desired.
1411 static int
1412 x_connect_to_server()
1414 regmatch_T regmatch;
1416 #if defined(FEAT_CLIENTSERVER)
1417 if (x_force_connect)
1418 return TRUE;
1419 #endif
1420 if (x_no_connect)
1421 return FALSE;
1423 /* Check for a match with "exclude:" from 'clipboard'. */
1424 if (clip_exclude_prog != NULL)
1426 regmatch.rm_ic = FALSE; /* Don't ignore case */
1427 regmatch.regprog = clip_exclude_prog;
1428 if (vim_regexec(&regmatch, T_NAME, (colnr_T)0))
1429 return FALSE;
1431 return TRUE;
1435 * Test if "dpy" and x11_window are valid by getting the window title.
1436 * I don't actually want it yet, so there may be a simpler call to use, but
1437 * this will cause the error handler x_error_check() to be called if anything
1438 * is wrong, such as the window pointer being invalid (as can happen when the
1439 * user changes his DISPLAY, but not his WINDOWID) -- webb
1441 static int
1442 test_x11_window(dpy)
1443 Display *dpy;
1445 int (*old_handler)();
1446 XTextProperty text_prop;
1448 old_handler = XSetErrorHandler(x_error_check);
1449 got_x_error = FALSE;
1450 if (XGetWMName(dpy, x11_window, &text_prop))
1451 XFree((void *)text_prop.value);
1452 XSync(dpy, False);
1453 (void)XSetErrorHandler(old_handler);
1455 if (p_verbose > 0 && got_x_error)
1456 verb_msg((char_u *)_("Testing the X display failed"));
1458 return (got_x_error ? FAIL : OK);
1460 #endif
1462 #ifdef FEAT_TITLE
1464 #ifdef FEAT_X11
1466 static int get_x11_thing __ARGS((int get_title, int test_only));
1469 * try to get x11 window and display
1471 * return FAIL for failure, OK otherwise
1473 static int
1474 get_x11_windis()
1476 char *winid;
1477 static int result = -1;
1478 #define XD_NONE 0 /* x11_display not set here */
1479 #define XD_HERE 1 /* x11_display opened here */
1480 #define XD_GUI 2 /* x11_display used from gui.dpy */
1481 #define XD_XTERM 3 /* x11_display used from xterm_dpy */
1482 static int x11_display_from = XD_NONE;
1483 static int did_set_error_handler = FALSE;
1485 if (!did_set_error_handler)
1487 /* X just exits if it finds an error otherwise! */
1488 (void)XSetErrorHandler(x_error_handler);
1489 did_set_error_handler = TRUE;
1492 #if defined(FEAT_GUI_X11) || defined(FEAT_GUI_GTK)
1493 if (gui.in_use)
1496 * If the X11 display was opened here before, for the window where Vim
1497 * was started, close that one now to avoid a memory leak.
1499 if (x11_display_from == XD_HERE && x11_display != NULL)
1501 XCloseDisplay(x11_display);
1502 x11_display_from = XD_NONE;
1504 if (gui_get_x11_windis(&x11_window, &x11_display) == OK)
1506 x11_display_from = XD_GUI;
1507 return OK;
1509 x11_display = NULL;
1510 return FAIL;
1512 else if (x11_display_from == XD_GUI)
1514 /* GUI must have stopped somehow, clear x11_display */
1515 x11_window = 0;
1516 x11_display = NULL;
1517 x11_display_from = XD_NONE;
1519 #endif
1521 /* When started with the "-X" argument, don't try connecting. */
1522 if (!x_connect_to_server())
1523 return FAIL;
1526 * If WINDOWID not set, should try another method to find out
1527 * what the current window number is. The only code I know for
1528 * this is very complicated.
1529 * We assume that zero is invalid for WINDOWID.
1531 if (x11_window == 0 && (winid = getenv("WINDOWID")) != NULL)
1532 x11_window = (Window)atol(winid);
1534 #ifdef FEAT_XCLIPBOARD
1535 if (xterm_dpy != NULL && x11_window != 0)
1537 /* Checked it already. */
1538 if (x11_display_from == XD_XTERM)
1539 return OK;
1542 * If the X11 display was opened here before, for the window where Vim
1543 * was started, close that one now to avoid a memory leak.
1545 if (x11_display_from == XD_HERE && x11_display != NULL)
1546 XCloseDisplay(x11_display);
1547 x11_display = xterm_dpy;
1548 x11_display_from = XD_XTERM;
1549 if (test_x11_window(x11_display) == FAIL)
1551 /* probably bad $WINDOWID */
1552 x11_window = 0;
1553 x11_display = NULL;
1554 x11_display_from = XD_NONE;
1555 return FAIL;
1557 return OK;
1559 #endif
1561 if (x11_window == 0 || x11_display == NULL)
1562 result = -1;
1564 if (result != -1) /* Have already been here and set this */
1565 return result; /* Don't do all these X calls again */
1567 if (x11_window != 0 && x11_display == NULL)
1569 #ifdef SET_SIG_ALARM
1570 RETSIGTYPE (*sig_save)();
1571 #endif
1572 #if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1573 struct timeval start_tv;
1575 if (p_verbose > 0)
1576 gettimeofday(&start_tv, NULL);
1577 #endif
1579 #ifdef SET_SIG_ALARM
1581 * Opening the Display may hang if the DISPLAY setting is wrong, or
1582 * the network connection is bad. Set an alarm timer to get out.
1584 sig_alarm_called = FALSE;
1585 sig_save = (RETSIGTYPE (*)())signal(SIGALRM,
1586 (RETSIGTYPE (*)())sig_alarm);
1587 alarm(2);
1588 #endif
1589 x11_display = XOpenDisplay(NULL);
1591 #ifdef SET_SIG_ALARM
1592 alarm(0);
1593 signal(SIGALRM, (RETSIGTYPE (*)())sig_save);
1594 if (p_verbose > 0 && sig_alarm_called)
1595 verb_msg((char_u *)_("Opening the X display timed out"));
1596 #endif
1597 if (x11_display != NULL)
1599 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
1600 if (p_verbose > 0)
1602 verbose_enter();
1603 xopen_message(&start_tv);
1604 verbose_leave();
1606 # endif
1607 if (test_x11_window(x11_display) == FAIL)
1609 /* Maybe window id is bad */
1610 x11_window = 0;
1611 XCloseDisplay(x11_display);
1612 x11_display = NULL;
1614 else
1615 x11_display_from = XD_HERE;
1618 if (x11_window == 0 || x11_display == NULL)
1619 return (result = FAIL);
1620 return (result = OK);
1624 * Determine original x11 Window Title
1626 static int
1627 get_x11_title(test_only)
1628 int test_only;
1630 return get_x11_thing(TRUE, test_only);
1634 * Determine original x11 Window icon
1636 static int
1637 get_x11_icon(test_only)
1638 int test_only;
1640 int retval = FALSE;
1642 retval = get_x11_thing(FALSE, test_only);
1644 /* could not get old icon, use terminal name */
1645 if (oldicon == NULL && !test_only)
1647 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1648 oldicon = T_NAME + 8;
1649 else
1650 oldicon = T_NAME;
1653 return retval;
1656 static int
1657 get_x11_thing(get_title, test_only)
1658 int get_title; /* get title string */
1659 int test_only;
1661 XTextProperty text_prop;
1662 int retval = FALSE;
1663 Status status;
1665 if (get_x11_windis() == OK)
1667 /* Get window/icon name if any */
1668 if (get_title)
1669 status = XGetWMName(x11_display, x11_window, &text_prop);
1670 else
1671 status = XGetWMIconName(x11_display, x11_window, &text_prop);
1674 * If terminal is xterm, then x11_window may be a child window of the
1675 * outer xterm window that actually contains the window/icon name, so
1676 * keep traversing up the tree until a window with a title/icon is
1677 * found.
1679 /* Previously this was only done for xterm and alikes. I don't see a
1680 * reason why it would fail for other terminal emulators.
1681 * if (term_is_xterm) */
1683 Window root;
1684 Window parent;
1685 Window win = x11_window;
1686 Window *children;
1687 unsigned int num_children;
1689 while (!status || text_prop.value == NULL)
1691 if (!XQueryTree(x11_display, win, &root, &parent, &children,
1692 &num_children))
1693 break;
1694 if (children)
1695 XFree((void *)children);
1696 if (parent == root || parent == 0)
1697 break;
1699 win = parent;
1700 if (get_title)
1701 status = XGetWMName(x11_display, win, &text_prop);
1702 else
1703 status = XGetWMIconName(x11_display, win, &text_prop);
1706 if (status && text_prop.value != NULL)
1708 retval = TRUE;
1709 if (!test_only)
1711 #ifdef FEAT_XFONTSET
1712 if (text_prop.encoding == XA_STRING)
1714 #endif
1715 if (get_title)
1716 oldtitle = vim_strsave((char_u *)text_prop.value);
1717 else
1718 oldicon = vim_strsave((char_u *)text_prop.value);
1719 #ifdef FEAT_XFONTSET
1721 else
1723 char **cl;
1724 Status transform_status;
1725 int n = 0;
1727 transform_status = XmbTextPropertyToTextList(x11_display,
1728 &text_prop,
1729 &cl, &n);
1730 if (transform_status >= Success && n > 0 && cl[0])
1732 if (get_title)
1733 oldtitle = vim_strsave((char_u *) cl[0]);
1734 else
1735 oldicon = vim_strsave((char_u *) cl[0]);
1736 XFreeStringList(cl);
1738 else
1740 if (get_title)
1741 oldtitle = vim_strsave((char_u *)text_prop.value);
1742 else
1743 oldicon = vim_strsave((char_u *)text_prop.value);
1746 #endif
1748 XFree((void *)text_prop.value);
1751 return retval;
1754 /* Are Xutf8 functions available? Avoid error from old compilers. */
1755 #if defined(X_HAVE_UTF8_STRING) && defined(FEAT_MBYTE)
1756 # if X_HAVE_UTF8_STRING
1757 # define USE_UTF8_STRING
1758 # endif
1759 #endif
1762 * Set x11 Window Title
1764 * get_x11_windis() must be called before this and have returned OK
1766 static void
1767 set_x11_title(title)
1768 char_u *title;
1770 /* XmbSetWMProperties() and Xutf8SetWMProperties() should use a STRING
1771 * when possible, COMPOUND_TEXT otherwise. COMPOUND_TEXT isn't
1772 * supported everywhere and STRING doesn't work for multi-byte titles.
1774 #ifdef USE_UTF8_STRING
1775 if (enc_utf8)
1776 Xutf8SetWMProperties(x11_display, x11_window, (const char *)title,
1777 NULL, NULL, 0, NULL, NULL, NULL);
1778 else
1779 #endif
1781 #if XtSpecificationRelease >= 4
1782 # ifdef FEAT_XFONTSET
1783 XmbSetWMProperties(x11_display, x11_window, (const char *)title,
1784 NULL, NULL, 0, NULL, NULL, NULL);
1785 # else
1786 XTextProperty text_prop;
1787 char *c_title = (char *)title;
1789 /* directly from example 3-18 "basicwin" of Xlib Programming Manual */
1790 (void)XStringListToTextProperty(&c_title, 1, &text_prop);
1791 XSetWMProperties(x11_display, x11_window, &text_prop,
1792 NULL, NULL, 0, NULL, NULL, NULL);
1793 # endif
1794 #else
1795 XStoreName(x11_display, x11_window, (char *)title);
1796 #endif
1798 XFlush(x11_display);
1802 * Set x11 Window icon
1804 * get_x11_windis() must be called before this and have returned OK
1806 static void
1807 set_x11_icon(icon)
1808 char_u *icon;
1810 /* See above for comments about using X*SetWMProperties(). */
1811 #ifdef USE_UTF8_STRING
1812 if (enc_utf8)
1813 Xutf8SetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
1814 NULL, 0, NULL, NULL, NULL);
1815 else
1816 #endif
1818 #if XtSpecificationRelease >= 4
1819 # ifdef FEAT_XFONTSET
1820 XmbSetWMProperties(x11_display, x11_window, NULL, (const char *)icon,
1821 NULL, 0, NULL, NULL, NULL);
1822 # else
1823 XTextProperty text_prop;
1824 char *c_icon = (char *)icon;
1826 (void)XStringListToTextProperty(&c_icon, 1, &text_prop);
1827 XSetWMProperties(x11_display, x11_window, NULL, &text_prop,
1828 NULL, 0, NULL, NULL, NULL);
1829 # endif
1830 #else
1831 XSetIconName(x11_display, x11_window, (char *)icon);
1832 #endif
1834 XFlush(x11_display);
1837 #else /* FEAT_X11 */
1839 /*ARGSUSED*/
1840 static int
1841 get_x11_title(test_only)
1842 int test_only;
1844 return FALSE;
1847 static int
1848 get_x11_icon(test_only)
1849 int test_only;
1851 if (!test_only)
1853 if (STRNCMP(T_NAME, "builtin_", 8) == 0)
1854 oldicon = T_NAME + 8;
1855 else
1856 oldicon = T_NAME;
1858 return FALSE;
1861 #endif /* FEAT_X11 */
1864 mch_can_restore_title()
1866 return get_x11_title(TRUE);
1870 mch_can_restore_icon()
1872 return get_x11_icon(TRUE);
1876 * Set the window title and icon.
1878 void
1879 mch_settitle(title, icon)
1880 char_u *title;
1881 char_u *icon;
1883 int type = 0;
1884 static int recursive = 0;
1886 if (T_NAME == NULL) /* no terminal name (yet) */
1887 return;
1888 if (title == NULL && icon == NULL) /* nothing to do */
1889 return;
1891 /* When one of the X11 functions causes a deadly signal, we get here again
1892 * recursively. Avoid hanging then (something is probably locked). */
1893 if (recursive)
1894 return;
1895 ++recursive;
1898 * if the window ID and the display is known, we may use X11 calls
1900 #ifdef FEAT_X11
1901 if (get_x11_windis() == OK)
1902 type = 1;
1903 #else
1904 # if defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_GTK)
1905 if (gui.in_use)
1906 type = 1;
1907 # endif
1908 #endif
1911 * Note: if "t_TS" is set, title is set with escape sequence rather
1912 * than x11 calls, because the x11 calls don't always work
1914 if ((type || *T_TS != NUL) && title != NULL)
1916 if (oldtitle == NULL
1917 #ifdef FEAT_GUI
1918 && !gui.in_use
1919 #endif
1920 ) /* first call but not in GUI, save title */
1921 (void)get_x11_title(FALSE);
1923 if (*T_TS != NUL) /* it's OK if t_fs is empty */
1924 term_settitle(title);
1925 #ifdef FEAT_X11
1926 else
1927 # ifdef FEAT_GUI_GTK
1928 if (!gui.in_use) /* don't do this if GTK+ is running */
1929 # endif
1930 set_x11_title(title); /* x11 */
1931 #endif
1932 #if defined(FEAT_GUI_GTK) \
1933 || defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
1934 else
1935 gui_mch_settitle(title, icon);
1936 #endif
1937 did_set_title = TRUE;
1940 if ((type || *T_CIS != NUL) && icon != NULL)
1942 if (oldicon == NULL
1943 #ifdef FEAT_GUI
1944 && !gui.in_use
1945 #endif
1946 ) /* first call, save icon */
1947 get_x11_icon(FALSE);
1949 if (*T_CIS != NUL)
1951 out_str(T_CIS); /* set icon start */
1952 out_str_nf(icon);
1953 out_str(T_CIE); /* set icon end */
1954 out_flush();
1956 #ifdef FEAT_X11
1957 else
1958 # ifdef FEAT_GUI_GTK
1959 if (!gui.in_use) /* don't do this if GTK+ is running */
1960 # endif
1961 set_x11_icon(icon); /* x11 */
1962 #endif
1963 did_set_icon = TRUE;
1965 --recursive;
1969 * Restore the window/icon title.
1970 * "which" is one of:
1971 * 1 only restore title
1972 * 2 only restore icon
1973 * 3 restore title and icon
1975 void
1976 mch_restore_title(which)
1977 int which;
1979 /* only restore the title or icon when it has been set */
1980 mch_settitle(((which & 1) && did_set_title) ?
1981 (oldtitle ? oldtitle : p_titleold) : NULL,
1982 ((which & 2) && did_set_icon) ? oldicon : NULL);
1985 #endif /* FEAT_TITLE */
1988 * Return TRUE if "name" looks like some xterm name.
1989 * Seiichi Sato mentioned that "mlterm" works like xterm.
1992 vim_is_xterm(name)
1993 char_u *name;
1995 if (name == NULL)
1996 return FALSE;
1997 return (STRNICMP(name, "xterm", 5) == 0
1998 || STRNICMP(name, "nxterm", 6) == 0
1999 || STRNICMP(name, "kterm", 5) == 0
2000 || STRNICMP(name, "mlterm", 6) == 0
2001 || STRNICMP(name, "rxvt", 4) == 0
2002 || STRCMP(name, "builtin_xterm") == 0);
2005 #if defined(FEAT_MOUSE_TTY) || defined(PROTO)
2007 * Return non-zero when using an xterm mouse, according to 'ttymouse'.
2008 * Return 1 for "xterm".
2009 * Return 2 for "xterm2".
2012 use_xterm_mouse()
2014 if (ttym_flags == TTYM_XTERM2)
2015 return 2;
2016 if (ttym_flags == TTYM_XTERM)
2017 return 1;
2018 return 0;
2020 #endif
2023 vim_is_iris(name)
2024 char_u *name;
2026 if (name == NULL)
2027 return FALSE;
2028 return (STRNICMP(name, "iris-ansi", 9) == 0
2029 || STRCMP(name, "builtin_iris-ansi") == 0);
2033 vim_is_vt300(name)
2034 char_u *name;
2036 if (name == NULL)
2037 return FALSE; /* actually all ANSI comp. terminals should be here */
2038 /* catch VT100 - VT5xx */
2039 return ((STRNICMP(name, "vt", 2) == 0
2040 && vim_strchr((char_u *)"12345", name[2]) != NULL)
2041 || STRCMP(name, "builtin_vt320") == 0);
2045 * Return TRUE if "name" is a terminal for which 'ttyfast' should be set.
2046 * This should include all windowed terminal emulators.
2049 vim_is_fastterm(name)
2050 char_u *name;
2052 if (name == NULL)
2053 return FALSE;
2054 if (vim_is_xterm(name) || vim_is_vt300(name) || vim_is_iris(name))
2055 return TRUE;
2056 return ( STRNICMP(name, "hpterm", 6) == 0
2057 || STRNICMP(name, "sun-cmd", 7) == 0
2058 || STRNICMP(name, "screen", 6) == 0
2059 || STRNICMP(name, "dtterm", 6) == 0);
2063 * Insert user name in s[len].
2064 * Return OK if a name found.
2067 mch_get_user_name(s, len)
2068 char_u *s;
2069 int len;
2071 #ifdef VMS
2072 vim_strncpy(s, (char_u *)cuserid(NULL), len - 1);
2073 return OK;
2074 #else
2075 return mch_get_uname(getuid(), s, len);
2076 #endif
2080 * Insert user name for "uid" in s[len].
2081 * Return OK if a name found.
2084 mch_get_uname(uid, s, len)
2085 uid_t uid;
2086 char_u *s;
2087 int len;
2089 #if defined(HAVE_PWD_H) && defined(HAVE_GETPWUID)
2090 struct passwd *pw;
2092 if ((pw = getpwuid(uid)) != NULL
2093 && pw->pw_name != NULL && *(pw->pw_name) != NUL)
2095 vim_strncpy(s, (char_u *)pw->pw_name, len - 1);
2096 return OK;
2098 #endif
2099 sprintf((char *)s, "%d", (int)uid); /* assumes s is long enough */
2100 return FAIL; /* a number is not a name */
2104 * Insert host name is s[len].
2107 #ifdef HAVE_SYS_UTSNAME_H
2108 void
2109 mch_get_host_name(s, len)
2110 char_u *s;
2111 int len;
2113 struct utsname vutsname;
2115 if (uname(&vutsname) < 0)
2116 *s = NUL;
2117 else
2118 vim_strncpy(s, (char_u *)vutsname.nodename, len - 1);
2120 #else /* HAVE_SYS_UTSNAME_H */
2122 # ifdef HAVE_SYS_SYSTEMINFO_H
2123 # define gethostname(nam, len) sysinfo(SI_HOSTNAME, nam, len)
2124 # endif
2126 void
2127 mch_get_host_name(s, len)
2128 char_u *s;
2129 int len;
2131 # ifdef VAXC
2132 vaxc$gethostname((char *)s, len);
2133 # else
2134 gethostname((char *)s, len);
2135 # endif
2136 s[len - 1] = NUL; /* make sure it's terminated */
2138 #endif /* HAVE_SYS_UTSNAME_H */
2141 * return process ID
2143 long
2144 mch_get_pid()
2146 return (long)getpid();
2149 #if !defined(HAVE_STRERROR) && defined(USE_GETCWD)
2150 static char *strerror __ARGS((int));
2152 static char *
2153 strerror(err)
2154 int err;
2156 extern int sys_nerr;
2157 extern char *sys_errlist[];
2158 static char er[20];
2160 if (err > 0 && err < sys_nerr)
2161 return (sys_errlist[err]);
2162 sprintf(er, "Error %d", err);
2163 return er;
2165 #endif
2168 * Get name of current directory into buffer 'buf' of length 'len' bytes.
2169 * Return OK for success, FAIL for failure.
2172 mch_dirname(buf, len)
2173 char_u *buf;
2174 int len;
2176 #if defined(USE_GETCWD)
2177 if (getcwd((char *)buf, len) == NULL)
2179 STRCPY(buf, strerror(errno));
2180 return FAIL;
2182 return OK;
2183 #else
2184 return (getwd((char *)buf) != NULL ? OK : FAIL);
2185 #endif
2188 #if defined(OS2) || defined(PROTO)
2190 * Replace all slashes by backslashes.
2191 * When 'shellslash' set do it the other way around.
2193 void
2194 slash_adjust(p)
2195 char_u *p;
2197 while (*p)
2199 if (*p == psepcN)
2200 *p = psepc;
2201 mb_ptr_adv(p);
2204 #endif
2207 * Get absolute file name into "buf[len]".
2209 * return FAIL for failure, OK for success
2212 mch_FullName(fname, buf, len, force)
2213 char_u *fname, *buf;
2214 int len;
2215 int force; /* also expand when already absolute path */
2217 int l;
2218 #ifdef OS2
2219 int only_drive; /* file name is only a drive letter */
2220 #endif
2221 #ifdef HAVE_FCHDIR
2222 int fd = -1;
2223 static int dont_fchdir = FALSE; /* TRUE when fchdir() doesn't work */
2224 #endif
2225 char_u olddir[MAXPATHL];
2226 char_u *p;
2227 int retval = OK;
2229 #ifdef VMS
2230 fname = vms_fixfilename(fname);
2231 #endif
2233 /* expand it if forced or not an absolute path */
2234 if (force || !mch_isFullName(fname))
2237 * If the file name has a path, change to that directory for a moment,
2238 * and then do the getwd() (and get back to where we were).
2239 * This will get the correct path name with "../" things.
2241 #ifdef OS2
2242 only_drive = 0;
2243 if (((p = vim_strrchr(fname, '/')) != NULL)
2244 || ((p = vim_strrchr(fname, '\\')) != NULL)
2245 || (((p = vim_strchr(fname, ':')) != NULL) && ++only_drive))
2246 #else
2247 if ((p = vim_strrchr(fname, '/')) != NULL)
2248 #endif
2250 #ifdef HAVE_FCHDIR
2252 * Use fchdir() if possible, it's said to be faster and more
2253 * reliable. But on SunOS 4 it might not work. Check this by
2254 * doing a fchdir() right now.
2256 if (!dont_fchdir)
2258 fd = open(".", O_RDONLY | O_EXTRA, 0);
2259 if (fd >= 0 && fchdir(fd) < 0)
2261 close(fd);
2262 fd = -1;
2263 dont_fchdir = TRUE; /* don't try again */
2266 #endif
2268 /* Only change directory when we are sure we can return to where
2269 * we are now. After doing "su" chdir(".") might not work. */
2270 if (
2271 #ifdef HAVE_FCHDIR
2272 fd < 0 &&
2273 #endif
2274 (mch_dirname(olddir, MAXPATHL) == FAIL
2275 || mch_chdir((char *)olddir) != 0))
2277 p = NULL; /* can't get current dir: don't chdir */
2278 retval = FAIL;
2280 else
2282 #ifdef OS2
2284 * compensate for case where ':' from "D:" was the only
2285 * path separator detected in the file name; the _next_
2286 * character has to be removed, and then restored later.
2288 if (only_drive)
2289 p++;
2290 #endif
2291 /* The directory is copied into buf[], to be able to remove
2292 * the file name without changing it (could be a string in
2293 * read-only memory) */
2294 if (p - fname >= len)
2295 retval = FAIL;
2296 else
2298 vim_strncpy(buf, fname, p - fname);
2299 if (mch_chdir((char *)buf))
2300 retval = FAIL;
2301 else
2302 fname = p + 1;
2303 *buf = NUL;
2305 #ifdef OS2
2306 if (only_drive)
2308 p--;
2309 if (retval != FAIL)
2310 fname--;
2312 #endif
2315 if (mch_dirname(buf, len) == FAIL)
2317 retval = FAIL;
2318 *buf = NUL;
2320 if (p != NULL)
2322 #ifdef HAVE_FCHDIR
2323 if (fd >= 0)
2325 l = fchdir(fd);
2326 close(fd);
2328 else
2329 #endif
2330 l = mch_chdir((char *)olddir);
2331 if (l != 0)
2332 EMSG(_(e_prev_dir));
2335 l = STRLEN(buf);
2336 if (l >= len)
2337 retval = FAIL;
2338 #ifndef VMS
2339 else
2341 if (l > 0 && buf[l - 1] != '/' && *fname != NUL
2342 && STRCMP(fname, ".") != 0)
2343 STRCAT(buf, "/");
2345 #endif
2348 /* Catch file names which are too long. */
2349 if (retval == FAIL || STRLEN(buf) + STRLEN(fname) >= len)
2350 return FAIL;
2352 /* Do not append ".", "/dir/." is equal to "/dir". */
2353 if (STRCMP(fname, ".") != 0)
2354 STRCAT(buf, fname);
2356 return OK;
2360 * Return TRUE if "fname" does not depend on the current directory.
2363 mch_isFullName(fname)
2364 char_u *fname;
2366 #ifdef __EMX__
2367 return _fnisabs(fname);
2368 #else
2369 # ifdef VMS
2370 return ( fname[0] == '/' || fname[0] == '.' ||
2371 strchr((char *)fname,':') || strchr((char *)fname,'"') ||
2372 (strchr((char *)fname,'[') && strchr((char *)fname,']'))||
2373 (strchr((char *)fname,'<') && strchr((char *)fname,'>')) );
2374 # else
2375 return (*fname == '/' || *fname == '~');
2376 # endif
2377 #endif
2380 #if defined(USE_FNAME_CASE) || defined(PROTO)
2382 * Set the case of the file name, if it already exists. This will cause the
2383 * file name to remain exactly the same.
2384 * Only required for file systems where case is ingored and preserved.
2386 /*ARGSUSED*/
2387 void
2388 fname_case(name, len)
2389 char_u *name;
2390 int len; /* buffer size, only used when name gets longer */
2392 struct stat st;
2393 char_u *slash, *tail;
2394 DIR *dirp;
2395 struct dirent *dp;
2397 if (lstat((char *)name, &st) >= 0)
2399 /* Open the directory where the file is located. */
2400 slash = vim_strrchr(name, '/');
2401 if (slash == NULL)
2403 dirp = opendir(".");
2404 tail = name;
2406 else
2408 *slash = NUL;
2409 dirp = opendir((char *)name);
2410 *slash = '/';
2411 tail = slash + 1;
2414 if (dirp != NULL)
2416 while ((dp = readdir(dirp)) != NULL)
2418 /* Only accept names that differ in case and are the same byte
2419 * length. TODO: accept different length name. */
2420 if (STRICMP(tail, dp->d_name) == 0
2421 && STRLEN(tail) == STRLEN(dp->d_name))
2423 char_u newname[MAXPATHL + 1];
2424 struct stat st2;
2426 /* Verify the inode is equal. */
2427 vim_strncpy(newname, name, MAXPATHL);
2428 vim_strncpy(newname + (tail - name), (char_u *)dp->d_name,
2429 MAXPATHL - (tail - name));
2430 if (lstat((char *)newname, &st2) >= 0
2431 && st.st_ino == st2.st_ino
2432 && st.st_dev == st2.st_dev)
2434 STRCPY(tail, dp->d_name);
2435 break;
2440 closedir(dirp);
2444 #endif
2447 * Get file permissions for 'name'.
2448 * Returns -1 when it doesn't exist.
2450 long
2451 mch_getperm(name)
2452 char_u *name;
2454 struct stat statb;
2456 /* Keep the #ifdef outside of stat(), it may be a macro. */
2457 #ifdef VMS
2458 if (stat((char *)vms_fixfilename(name), &statb))
2459 #else
2460 if (stat((char *)name, &statb))
2461 #endif
2462 return -1;
2463 return statb.st_mode;
2467 * set file permission for 'name' to 'perm'
2469 * return FAIL for failure, OK otherwise
2472 mch_setperm(name, perm)
2473 char_u *name;
2474 long perm;
2476 return (chmod((char *)
2477 #ifdef VMS
2478 vms_fixfilename(name),
2479 #else
2480 name,
2481 #endif
2482 (mode_t)perm) == 0 ? OK : FAIL);
2485 #if defined(HAVE_ACL) || defined(PROTO)
2486 # ifdef HAVE_SYS_ACL_H
2487 # include <sys/acl.h>
2488 # endif
2489 # ifdef HAVE_SYS_ACCESS_H
2490 # include <sys/access.h>
2491 # endif
2493 # ifdef HAVE_SOLARIS_ACL
2494 typedef struct vim_acl_solaris_T {
2495 int acl_cnt;
2496 aclent_t *acl_entry;
2497 } vim_acl_solaris_T;
2498 # endif
2501 * Return a pointer to the ACL of file "fname" in allocated memory.
2502 * Return NULL if the ACL is not available for whatever reason.
2504 vim_acl_T
2505 mch_get_acl(fname)
2506 char_u *fname;
2508 vim_acl_T ret = NULL;
2509 #ifdef HAVE_POSIX_ACL
2510 ret = (vim_acl_T)acl_get_file((char *)fname, ACL_TYPE_ACCESS);
2511 #else
2512 #ifdef HAVE_SOLARIS_ACL
2513 vim_acl_solaris_T *aclent;
2515 aclent = malloc(sizeof(vim_acl_solaris_T));
2516 if ((aclent->acl_cnt = acl((char *)fname, GETACLCNT, 0, NULL)) < 0)
2518 free(aclent);
2519 return NULL;
2521 aclent->acl_entry = malloc(aclent->acl_cnt * sizeof(aclent_t));
2522 if (acl((char *)fname, GETACL, aclent->acl_cnt, aclent->acl_entry) < 0)
2524 free(aclent->acl_entry);
2525 free(aclent);
2526 return NULL;
2528 ret = (vim_acl_T)aclent;
2529 #else
2530 #if defined(HAVE_AIX_ACL)
2531 int aclsize;
2532 struct acl *aclent;
2534 aclsize = sizeof(struct acl);
2535 aclent = malloc(aclsize);
2536 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2538 if (errno == ENOSPC)
2540 aclsize = aclent->acl_len;
2541 aclent = realloc(aclent, aclsize);
2542 if (statacl((char *)fname, STX_NORMAL, aclent, aclsize) < 0)
2544 free(aclent);
2545 return NULL;
2548 else
2550 free(aclent);
2551 return NULL;
2554 ret = (vim_acl_T)aclent;
2555 #endif /* HAVE_AIX_ACL */
2556 #endif /* HAVE_SOLARIS_ACL */
2557 #endif /* HAVE_POSIX_ACL */
2558 return ret;
2562 * Set the ACL of file "fname" to "acl" (unless it's NULL).
2564 void
2565 mch_set_acl(fname, aclent)
2566 char_u *fname;
2567 vim_acl_T aclent;
2569 if (aclent == NULL)
2570 return;
2571 #ifdef HAVE_POSIX_ACL
2572 acl_set_file((char *)fname, ACL_TYPE_ACCESS, (acl_t)aclent);
2573 #else
2574 #ifdef HAVE_SOLARIS_ACL
2575 acl((char *)fname, SETACL, ((vim_acl_solaris_T *)aclent)->acl_cnt,
2576 ((vim_acl_solaris_T *)aclent)->acl_entry);
2577 #else
2578 #ifdef HAVE_AIX_ACL
2579 chacl((char *)fname, aclent, ((struct acl *)aclent)->acl_len);
2580 #endif /* HAVE_AIX_ACL */
2581 #endif /* HAVE_SOLARIS_ACL */
2582 #endif /* HAVE_POSIX_ACL */
2585 void
2586 mch_free_acl(aclent)
2587 vim_acl_T aclent;
2589 if (aclent == NULL)
2590 return;
2591 #ifdef HAVE_POSIX_ACL
2592 acl_free((acl_t)aclent);
2593 #else
2594 #ifdef HAVE_SOLARIS_ACL
2595 free(((vim_acl_solaris_T *)aclent)->acl_entry);
2596 free(aclent);
2597 #else
2598 #ifdef HAVE_AIX_ACL
2599 free(aclent);
2600 #endif /* HAVE_AIX_ACL */
2601 #endif /* HAVE_SOLARIS_ACL */
2602 #endif /* HAVE_POSIX_ACL */
2604 #endif
2607 * Set hidden flag for "name".
2609 /* ARGSUSED */
2610 void
2611 mch_hide(name)
2612 char_u *name;
2614 /* can't hide a file */
2618 * return TRUE if "name" is a directory
2619 * return FALSE if "name" is not a directory
2620 * return FALSE for error
2623 mch_isdir(name)
2624 char_u *name;
2626 struct stat statb;
2628 if (*name == NUL) /* Some stat()s don't flag "" as an error. */
2629 return FALSE;
2630 if (stat((char *)name, &statb))
2631 return FALSE;
2632 #ifdef _POSIX_SOURCE
2633 return (S_ISDIR(statb.st_mode) ? TRUE : FALSE);
2634 #else
2635 return ((statb.st_mode & S_IFMT) == S_IFDIR ? TRUE : FALSE);
2636 #endif
2639 static int executable_file __ARGS((char_u *name));
2642 * Return 1 if "name" is an executable file, 0 if not or it doesn't exist.
2644 static int
2645 executable_file(name)
2646 char_u *name;
2648 struct stat st;
2650 if (stat((char *)name, &st))
2651 return 0;
2652 return S_ISREG(st.st_mode) && mch_access((char *)name, X_OK) == 0;
2656 * Return 1 if "name" can be found in $PATH and executed, 0 if not.
2657 * Return -1 if unknown.
2660 mch_can_exe(name)
2661 char_u *name;
2663 char_u *buf;
2664 char_u *p, *e;
2665 int retval;
2667 /* If it's an absolute or relative path don't need to use $PATH. */
2668 if (mch_isFullName(name) || (name[0] == '.' && (name[1] == '/'
2669 || (name[1] == '.' && name[2] == '/'))))
2670 return executable_file(name);
2672 p = (char_u *)getenv("PATH");
2673 if (p == NULL || *p == NUL)
2674 return -1;
2675 buf = alloc((unsigned)(STRLEN(name) + STRLEN(p) + 2));
2676 if (buf == NULL)
2677 return -1;
2680 * Walk through all entries in $PATH to check if "name" exists there and
2681 * is an executable file.
2683 for (;;)
2685 e = (char_u *)strchr((char *)p, ':');
2686 if (e == NULL)
2687 e = p + STRLEN(p);
2688 if (e - p <= 1) /* empty entry means current dir */
2689 STRCPY(buf, "./");
2690 else
2692 vim_strncpy(buf, p, e - p);
2693 add_pathsep(buf);
2695 STRCAT(buf, name);
2696 retval = executable_file(buf);
2697 if (retval == 1)
2698 break;
2700 if (*e != ':')
2701 break;
2702 p = e + 1;
2705 vim_free(buf);
2706 return retval;
2710 * Check what "name" is:
2711 * NODE_NORMAL: file or directory (or doesn't exist)
2712 * NODE_WRITABLE: writable device, socket, fifo, etc.
2713 * NODE_OTHER: non-writable things
2716 mch_nodetype(name)
2717 char_u *name;
2719 struct stat st;
2721 if (stat((char *)name, &st))
2722 return NODE_NORMAL;
2723 if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))
2724 return NODE_NORMAL;
2725 #ifndef OS2
2726 if (S_ISBLK(st.st_mode)) /* block device isn't writable */
2727 return NODE_OTHER;
2728 #endif
2729 /* Everything else is writable? */
2730 return NODE_WRITABLE;
2733 void
2734 mch_early_init()
2736 #ifdef HAVE_CHECK_STACK_GROWTH
2737 int i;
2739 check_stack_growth((char *)&i);
2741 # ifdef HAVE_STACK_LIMIT
2742 get_stack_limit();
2743 # endif
2745 #endif
2748 * Setup an alternative stack for signals. Helps to catch signals when
2749 * running out of stack space.
2750 * Use of sigaltstack() is preferred, it's more portable.
2751 * Ignore any errors.
2753 #if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2754 signal_stack = malloc(SIGSTKSZ);
2755 init_signal_stack();
2756 #endif
2759 #if defined(EXITFREE) || defined(PROTO)
2760 void
2761 mch_free_mem()
2763 # if defined(FEAT_CLIPBOARD) && defined(FEAT_X11)
2764 if (clip_star.owned)
2765 clip_lose_selection(&clip_star);
2766 if (clip_plus.owned)
2767 clip_lose_selection(&clip_plus);
2768 # endif
2769 # if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
2770 if (xterm_Shell != (Widget)0)
2771 XtDestroyWidget(xterm_Shell);
2772 if (xterm_dpy != NULL)
2773 XtCloseDisplay(xterm_dpy);
2774 if (app_context != (XtAppContext)NULL)
2775 XtDestroyApplicationContext(app_context);
2776 # endif
2777 # ifdef FEAT_X11
2778 if (x11_display != NULL && x11_display != xterm_dpy)
2779 XCloseDisplay(x11_display);
2780 # endif
2781 # if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
2782 vim_free(signal_stack);
2783 signal_stack = NULL;
2784 # endif
2785 # ifdef FEAT_TITLE
2786 vim_free(oldtitle);
2787 vim_free(oldicon);
2788 # endif
2790 #endif
2792 static void exit_scroll __ARGS((void));
2795 * Output a newline when exiting.
2796 * Make sure the newline goes to the same stream as the text.
2798 static void
2799 exit_scroll()
2801 if (silent_mode)
2802 return;
2803 if (newline_on_exit || msg_didout)
2805 if (msg_use_printf())
2807 if (info_message)
2808 mch_msg("\n");
2809 else
2810 mch_errmsg("\r\n");
2812 else
2813 out_char('\n');
2815 else
2817 restore_cterm_colors(); /* get original colors back */
2818 msg_clr_eos_force(); /* clear the rest of the display */
2819 windgoto((int)Rows - 1, 0); /* may have moved the cursor */
2823 void
2824 mch_exit(r)
2825 int r;
2827 exiting = TRUE;
2829 #if defined(FEAT_X11) && defined(FEAT_CLIPBOARD)
2830 x11_export_final_selection();
2831 #endif
2833 #ifdef FEAT_GUI
2834 if (!gui.in_use)
2835 #endif
2837 settmode(TMODE_COOK);
2838 #ifdef FEAT_TITLE
2839 mch_restore_title(3); /* restore xterm title and icon name */
2840 #endif
2842 * When t_ti is not empty but it doesn't cause swapping terminal
2843 * pages, need to output a newline when msg_didout is set. But when
2844 * t_ti does swap pages it should not go to the shell page. Do this
2845 * before stoptermcap().
2847 if (swapping_screen() && !newline_on_exit)
2848 exit_scroll();
2850 /* Stop termcap: May need to check for T_CRV response, which
2851 * requires RAW mode. */
2852 stoptermcap();
2855 * A newline is only required after a message in the alternate screen.
2856 * This is set to TRUE by wait_return().
2858 if (!swapping_screen() || newline_on_exit)
2859 exit_scroll();
2861 /* Cursor may have been switched off without calling starttermcap()
2862 * when doing "vim -u vimrc" and vimrc contains ":q". */
2863 if (full_screen)
2864 cursor_on();
2866 out_flush();
2867 ml_close_all(TRUE); /* remove all memfiles */
2868 may_core_dump();
2869 #ifdef FEAT_GUI
2870 if (gui.in_use)
2871 gui_exit(r);
2872 #endif
2874 #ifdef MACOS_CONVERT
2875 mac_conv_cleanup();
2876 #endif
2878 #ifdef __QNX__
2879 /* A core dump won't be created if the signal handler
2880 * doesn't return, so we can't call exit() */
2881 if (deadly_signal != 0)
2882 return;
2883 #endif
2885 #ifdef FEAT_NETBEANS_INTG
2886 if (usingNetbeans)
2887 netbeans_send_disconnect();
2888 #endif
2890 #ifdef EXITFREE
2891 free_all_mem();
2892 #endif
2894 exit(r);
2897 static void
2898 may_core_dump()
2900 if (deadly_signal != 0)
2902 signal(deadly_signal, SIG_DFL);
2903 kill(getpid(), deadly_signal); /* Die using the signal we caught */
2907 #ifndef VMS
2909 void
2910 mch_settmode(tmode)
2911 int tmode;
2913 static int first = TRUE;
2915 /* Why is NeXT excluded here (and not in os_unixx.h)? */
2916 #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
2918 * for "new" tty systems
2920 # ifdef HAVE_TERMIOS_H
2921 static struct termios told;
2922 struct termios tnew;
2923 # else
2924 static struct termio told;
2925 struct termio tnew;
2926 # endif
2928 if (first)
2930 first = FALSE;
2931 # if defined(HAVE_TERMIOS_H)
2932 tcgetattr(read_cmd_fd, &told);
2933 # else
2934 ioctl(read_cmd_fd, TCGETA, &told);
2935 # endif
2938 tnew = told;
2939 if (tmode == TMODE_RAW)
2942 * ~ICRNL enables typing ^V^M
2944 tnew.c_iflag &= ~ICRNL;
2945 tnew.c_lflag &= ~(ICANON | ECHO | ISIG | ECHOE
2946 # if defined(IEXTEN) && !defined(__MINT__)
2947 | IEXTEN /* IEXTEN enables typing ^V on SOLARIS */
2948 /* but it breaks function keys on MINT */
2949 # endif
2951 # ifdef ONLCR /* don't map NL -> CR NL, we do it ourselves */
2952 tnew.c_oflag &= ~ONLCR;
2953 # endif
2954 tnew.c_cc[VMIN] = 1; /* return after 1 char */
2955 tnew.c_cc[VTIME] = 0; /* don't wait */
2957 else if (tmode == TMODE_SLEEP)
2958 tnew.c_lflag &= ~(ECHO);
2960 # if defined(HAVE_TERMIOS_H)
2962 int n = 10;
2964 /* A signal may cause tcsetattr() to fail (e.g., SIGCONT). Retry a
2965 * few times. */
2966 while (tcsetattr(read_cmd_fd, TCSANOW, &tnew) == -1
2967 && errno == EINTR && n > 0)
2968 --n;
2970 # else
2971 ioctl(read_cmd_fd, TCSETA, &tnew);
2972 # endif
2974 #else
2977 * for "old" tty systems
2979 # ifndef TIOCSETN
2980 # define TIOCSETN TIOCSETP /* for hpux 9.0 */
2981 # endif
2982 static struct sgttyb ttybold;
2983 struct sgttyb ttybnew;
2985 if (first)
2987 first = FALSE;
2988 ioctl(read_cmd_fd, TIOCGETP, &ttybold);
2991 ttybnew = ttybold;
2992 if (tmode == TMODE_RAW)
2994 ttybnew.sg_flags &= ~(CRMOD | ECHO);
2995 ttybnew.sg_flags |= RAW;
2997 else if (tmode == TMODE_SLEEP)
2998 ttybnew.sg_flags &= ~(ECHO);
2999 ioctl(read_cmd_fd, TIOCSETN, &ttybnew);
3000 #endif
3001 curr_tmode = tmode;
3005 * Try to get the code for "t_kb" from the stty setting
3007 * Even if termcap claims a backspace key, the user's setting *should*
3008 * prevail. stty knows more about reality than termcap does, and if
3009 * somebody's usual erase key is DEL (which, for most BSD users, it will
3010 * be), they're going to get really annoyed if their erase key starts
3011 * doing forward deletes for no reason. (Eric Fischer)
3013 void
3014 get_stty()
3016 char_u buf[2];
3017 char_u *p;
3019 /* Why is NeXT excluded here (and not in os_unixx.h)? */
3020 #if defined(ECHOE) && defined(ICANON) && (defined(HAVE_TERMIO_H) || defined(HAVE_TERMIOS_H)) && !defined(__NeXT__)
3021 /* for "new" tty systems */
3022 # ifdef HAVE_TERMIOS_H
3023 struct termios keys;
3024 # else
3025 struct termio keys;
3026 # endif
3028 # if defined(HAVE_TERMIOS_H)
3029 if (tcgetattr(read_cmd_fd, &keys) != -1)
3030 # else
3031 if (ioctl(read_cmd_fd, TCGETA, &keys) != -1)
3032 # endif
3034 buf[0] = keys.c_cc[VERASE];
3035 intr_char = keys.c_cc[VINTR];
3036 #else
3037 /* for "old" tty systems */
3038 struct sgttyb keys;
3040 if (ioctl(read_cmd_fd, TIOCGETP, &keys) != -1)
3042 buf[0] = keys.sg_erase;
3043 intr_char = keys.sg_kill;
3044 #endif
3045 buf[1] = NUL;
3046 add_termcode((char_u *)"kb", buf, FALSE);
3049 * If <BS> and <DEL> are now the same, redefine <DEL>.
3051 p = find_termcode((char_u *)"kD");
3052 if (p != NULL && p[0] == buf[0] && p[1] == buf[1])
3053 do_fixdel(NULL);
3055 #if 0
3056 } /* to keep cindent happy */
3057 #endif
3060 #endif /* VMS */
3062 #if defined(FEAT_MOUSE_TTY) || defined(PROTO)
3064 * Set mouse clicks on or off.
3066 void
3067 mch_setmouse(on)
3068 int on;
3070 static int ison = FALSE;
3071 int xterm_mouse_vers;
3073 if (on == ison) /* return quickly if nothing to do */
3074 return;
3076 xterm_mouse_vers = use_xterm_mouse();
3077 if (xterm_mouse_vers > 0)
3079 if (on) /* enable mouse events, use mouse tracking if available */
3080 out_str_nf((char_u *)
3081 (xterm_mouse_vers > 1
3082 ? IF_EB("\033[?1002h", ESC_STR "[?1002h")
3083 : IF_EB("\033[?1000h", ESC_STR "[?1000h")));
3084 else /* disable mouse events, could probably always send the same */
3085 out_str_nf((char_u *)
3086 (xterm_mouse_vers > 1
3087 ? IF_EB("\033[?1002l", ESC_STR "[?1002l")
3088 : IF_EB("\033[?1000l", ESC_STR "[?1000l")));
3089 ison = on;
3092 # ifdef FEAT_MOUSE_DEC
3093 else if (ttym_flags == TTYM_DEC)
3095 if (on) /* enable mouse events */
3096 out_str_nf((char_u *)"\033[1;2'z\033[1;3'{");
3097 else /* disable mouse events */
3098 out_str_nf((char_u *)"\033['z");
3099 ison = on;
3101 # endif
3103 # ifdef FEAT_MOUSE_GPM
3104 else
3106 if (on)
3108 if (gpm_open())
3109 ison = TRUE;
3111 else
3113 gpm_close();
3114 ison = FALSE;
3117 # endif
3119 # ifdef FEAT_MOUSE_JSB
3120 else
3122 if (on)
3124 /* D - Enable Mouse up/down messages
3125 * L - Enable Left Button Reporting
3126 * M - Enable Middle Button Reporting
3127 * R - Enable Right Button Reporting
3128 * K - Enable SHIFT and CTRL key Reporting
3129 * + - Enable Advanced messaging of mouse moves and up/down messages
3130 * Q - Quiet No Ack
3131 * # - Numeric value of mouse pointer required
3132 * 0 = Multiview 2000 cursor, used as standard
3133 * 1 = Windows Arrow
3134 * 2 = Windows I Beam
3135 * 3 = Windows Hour Glass
3136 * 4 = Windows Cross Hair
3137 * 5 = Windows UP Arrow
3139 #ifdef JSBTERM_MOUSE_NONADVANCED /* Disables full feedback of pointer movements */
3140 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK1Q\033\\",
3141 ESC_STR "[0~ZwLMRK1Q" ESC_STR "\\"));
3142 #else
3143 out_str_nf((char_u *)IF_EB("\033[0~ZwLMRK+1Q\033\\",
3144 ESC_STR "[0~ZwLMRK+1Q" ESC_STR "\\"));
3145 #endif
3146 ison = TRUE;
3148 else
3150 out_str_nf((char_u *)IF_EB("\033[0~ZwQ\033\\",
3151 ESC_STR "[0~ZwQ" ESC_STR "\\"));
3152 ison = FALSE;
3155 # endif
3156 # ifdef FEAT_MOUSE_PTERM
3157 else
3159 /* 1 = button press, 6 = release, 7 = drag, 1h...9l = right button */
3160 if (on)
3161 out_str_nf("\033[>1h\033[>6h\033[>7h\033[>1h\033[>9l");
3162 else
3163 out_str_nf("\033[>1l\033[>6l\033[>7l\033[>1l\033[>9h");
3164 ison = on;
3166 # endif
3170 * Set the mouse termcode, depending on the 'term' and 'ttymouse' options.
3172 void
3173 check_mouse_termcode()
3175 # ifdef FEAT_MOUSE_XTERM
3176 if (use_xterm_mouse()
3177 # ifdef FEAT_GUI
3178 && !gui.in_use
3179 # endif
3182 set_mouse_termcode(KS_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3183 ? IF_EB("\233M", CSI_STR "M")
3184 : IF_EB("\033[M", ESC_STR "[M")));
3185 if (*p_mouse != NUL)
3187 /* force mouse off and maybe on to send possibly new mouse
3188 * activation sequence to the xterm, with(out) drag tracing. */
3189 mch_setmouse(FALSE);
3190 setmouse();
3193 else
3194 del_mouse_termcode(KS_MOUSE);
3195 # endif
3197 # ifdef FEAT_MOUSE_GPM
3198 if (!use_xterm_mouse()
3199 # ifdef FEAT_GUI
3200 && !gui.in_use
3201 # endif
3203 set_mouse_termcode(KS_MOUSE, (char_u *)IF_EB("\033MG", ESC_STR "MG"));
3204 # endif
3206 # ifdef FEAT_MOUSE_JSB
3207 /* conflicts with xterm mouse: "\033[" and "\033[M" ??? */
3208 if (!use_xterm_mouse()
3209 # ifdef FEAT_GUI
3210 && !gui.in_use
3211 # endif
3213 set_mouse_termcode(KS_JSBTERM_MOUSE,
3214 (char_u *)IF_EB("\033[0~zw", ESC_STR "[0~zw"));
3215 else
3216 del_mouse_termcode(KS_JSBTERM_MOUSE);
3217 # endif
3219 # ifdef FEAT_MOUSE_NET
3220 /* There is no conflict, but one may type "ESC }" from Insert mode. Don't
3221 * define it in the GUI or when using an xterm. */
3222 if (!use_xterm_mouse()
3223 # ifdef FEAT_GUI
3224 && !gui.in_use
3225 # endif
3227 set_mouse_termcode(KS_NETTERM_MOUSE,
3228 (char_u *)IF_EB("\033}", ESC_STR "}"));
3229 else
3230 del_mouse_termcode(KS_NETTERM_MOUSE);
3231 # endif
3233 # ifdef FEAT_MOUSE_DEC
3234 /* conflicts with xterm mouse: "\033[" and "\033[M" */
3235 if (!use_xterm_mouse()
3236 # ifdef FEAT_GUI
3237 && !gui.in_use
3238 # endif
3240 set_mouse_termcode(KS_DEC_MOUSE, (char_u *)(term_is_8bit(T_NAME)
3241 ? IF_EB("\233", CSI_STR) : IF_EB("\033[", ESC_STR "[")));
3242 else
3243 del_mouse_termcode(KS_DEC_MOUSE);
3244 # endif
3245 # ifdef FEAT_MOUSE_PTERM
3246 /* same as the dec mouse */
3247 if (!use_xterm_mouse()
3248 # ifdef FEAT_GUI
3249 && !gui.in_use
3250 # endif
3252 set_mouse_termcode(KS_PTERM_MOUSE,
3253 (char_u *) IF_EB("\033[", ESC_STR "["));
3254 else
3255 del_mouse_termcode(KS_PTERM_MOUSE);
3256 # endif
3258 #endif
3261 * set screen mode, always fails.
3263 /* ARGSUSED */
3265 mch_screenmode(arg)
3266 char_u *arg;
3268 EMSG(_(e_screenmode));
3269 return FAIL;
3272 #ifndef VMS
3275 * Try to get the current window size:
3276 * 1. with an ioctl(), most accurate method
3277 * 2. from the environment variables LINES and COLUMNS
3278 * 3. from the termcap
3279 * 4. keep using the old values
3280 * Return OK when size could be determined, FAIL otherwise.
3283 mch_get_shellsize()
3285 long rows = 0;
3286 long columns = 0;
3287 char_u *p;
3290 * For OS/2 use _scrsize().
3292 # ifdef __EMX__
3294 int s[2];
3296 _scrsize(s);
3297 columns = s[0];
3298 rows = s[1];
3300 # endif
3303 * 1. try using an ioctl. It is the most accurate method.
3305 * Try using TIOCGWINSZ first, some systems that have it also define
3306 * TIOCGSIZE but don't have a struct ttysize.
3308 # ifdef TIOCGWINSZ
3310 struct winsize ws;
3311 int fd = 1;
3313 /* When stdout is not a tty, use stdin for the ioctl(). */
3314 if (!isatty(fd) && isatty(read_cmd_fd))
3315 fd = read_cmd_fd;
3316 if (ioctl(fd, TIOCGWINSZ, &ws) == 0)
3318 columns = ws.ws_col;
3319 rows = ws.ws_row;
3322 # else /* TIOCGWINSZ */
3323 # ifdef TIOCGSIZE
3325 struct ttysize ts;
3326 int fd = 1;
3328 /* When stdout is not a tty, use stdin for the ioctl(). */
3329 if (!isatty(fd) && isatty(read_cmd_fd))
3330 fd = read_cmd_fd;
3331 if (ioctl(fd, TIOCGSIZE, &ts) == 0)
3333 columns = ts.ts_cols;
3334 rows = ts.ts_lines;
3337 # endif /* TIOCGSIZE */
3338 # endif /* TIOCGWINSZ */
3341 * 2. get size from environment
3342 * When being POSIX compliant ('|' flag in 'cpoptions') this overrules
3343 * the ioctl() values!
3345 if (columns == 0 || rows == 0 || vim_strchr(p_cpo, CPO_TSIZE) != NULL)
3347 if ((p = (char_u *)getenv("LINES")))
3348 rows = atoi((char *)p);
3349 if ((p = (char_u *)getenv("COLUMNS")))
3350 columns = atoi((char *)p);
3353 #ifdef HAVE_TGETENT
3355 * 3. try reading "co" and "li" entries from termcap
3357 if (columns == 0 || rows == 0)
3358 getlinecol(&columns, &rows);
3359 #endif
3362 * 4. If everything fails, use the old values
3364 if (columns <= 0 || rows <= 0)
3365 return FAIL;
3367 Rows = rows;
3368 Columns = columns;
3369 return OK;
3373 * Try to set the window size to Rows and Columns.
3375 void
3376 mch_set_shellsize()
3378 if (*T_CWS)
3381 * NOTE: if you get an error here that term_set_winsize() is
3382 * undefined, check the output of configure. It could probably not
3383 * find a ncurses, termcap or termlib library.
3385 term_set_winsize((int)Rows, (int)Columns);
3386 out_flush();
3387 screen_start(); /* don't know where cursor is now */
3391 #endif /* VMS */
3394 * Rows and/or Columns has changed.
3396 void
3397 mch_new_shellsize()
3399 /* Nothing to do. */
3402 #ifndef USE_SYSTEM
3403 static void append_ga_line __ARGS((garray_T *gap));
3406 * Append the text in "gap" below the cursor line and clear "gap".
3408 static void
3409 append_ga_line(gap)
3410 garray_T *gap;
3412 /* Remove trailing CR. */
3413 if (gap->ga_len > 0
3414 && !curbuf->b_p_bin
3415 && ((char_u *)gap->ga_data)[gap->ga_len - 1] == CAR)
3416 --gap->ga_len;
3417 ga_append(gap, NUL);
3418 ml_append(curwin->w_cursor.lnum++, gap->ga_data, 0, FALSE);
3419 gap->ga_len = 0;
3421 #endif
3424 mch_call_shell(cmd, options)
3425 char_u *cmd;
3426 int options; /* SHELL_*, see vim.h */
3428 #ifdef VMS
3429 char *ifn = NULL;
3430 char *ofn = NULL;
3431 #endif
3432 int tmode = cur_tmode;
3433 #ifdef USE_SYSTEM /* use system() to start the shell: simple but slow */
3434 int x;
3435 # ifndef __EMX__
3436 char_u *newcmd; /* only needed for unix */
3437 # else
3439 * Set the preferred shell in the EMXSHELL environment variable (but
3440 * only if it is different from what is already in the environment).
3441 * Emx then takes care of whether to use "/c" or "-c" in an
3442 * intelligent way. Simply pass the whole thing to emx's system() call.
3443 * Emx also starts an interactive shell if system() is passed an empty
3444 * string.
3446 char_u *p, *old;
3448 if (((old = (char_u *)getenv("EMXSHELL")) == NULL) || STRCMP(old, p_sh))
3450 /* should check HAVE_SETENV, but I know we don't have it. */
3451 p = alloc(10 + strlen(p_sh));
3452 if (p)
3454 sprintf((char *)p, "EMXSHELL=%s", p_sh);
3455 putenv((char *)p); /* don't free the pointer! */
3458 # endif
3460 out_flush();
3462 if (options & SHELL_COOKED)
3463 settmode(TMODE_COOK); /* set to normal mode */
3465 # ifdef __EMX__
3466 if (cmd == NULL)
3467 x = system(""); /* this starts an interactive shell in emx */
3468 else
3469 x = system((char *)cmd);
3470 /* system() returns -1 when error occurs in starting shell */
3471 if (x == -1 && !emsg_silent)
3473 MSG_PUTS(_("\nCannot execute shell "));
3474 msg_outtrans(p_sh);
3475 msg_putchar('\n');
3477 # else /* not __EMX__ */
3478 if (cmd == NULL)
3479 x = system((char *)p_sh);
3480 else
3482 # ifdef VMS
3483 if (ofn = strchr((char *)cmd, '>'))
3484 *ofn++ = '\0';
3485 if (ifn = strchr((char *)cmd, '<'))
3487 char *p;
3489 *ifn++ = '\0';
3490 p = strchr(ifn,' '); /* chop off any trailing spaces */
3491 if (p)
3492 *p = '\0';
3494 if (ofn)
3495 x = vms_sys((char *)cmd, ofn, ifn);
3496 else
3497 x = system((char *)cmd);
3498 # else
3499 newcmd = lalloc(STRLEN(p_sh)
3500 + (extra_shell_arg == NULL ? 0 : STRLEN(extra_shell_arg))
3501 + STRLEN(p_shcf) + STRLEN(cmd) + 4, TRUE);
3502 if (newcmd == NULL)
3503 x = 0;
3504 else
3506 sprintf((char *)newcmd, "%s %s %s %s", p_sh,
3507 extra_shell_arg == NULL ? "" : (char *)extra_shell_arg,
3508 (char *)p_shcf,
3509 (char *)cmd);
3510 x = system((char *)newcmd);
3511 vim_free(newcmd);
3513 # endif
3515 # ifdef VMS
3516 x = vms_sys_status(x);
3517 # endif
3518 if (emsg_silent)
3520 else if (x == 127)
3521 MSG_PUTS(_("\nCannot execute shell sh\n"));
3522 # endif /* __EMX__ */
3523 else if (x && !(options & SHELL_SILENT))
3525 MSG_PUTS(_("\nshell returned "));
3526 msg_outnum((long)x);
3527 msg_putchar('\n');
3530 if (tmode == TMODE_RAW)
3531 settmode(TMODE_RAW); /* set to raw mode */
3532 # ifdef FEAT_TITLE
3533 resettitle();
3534 # endif
3535 return x;
3537 #else /* USE_SYSTEM */ /* don't use system(), use fork()/exec() */
3539 # define EXEC_FAILED 122 /* Exit code when shell didn't execute. Don't use
3540 127, some shells use that already */
3542 char_u *newcmd = NULL;
3543 pid_t pid;
3544 pid_t wpid = 0;
3545 pid_t wait_pid = 0;
3546 # ifdef HAVE_UNION_WAIT
3547 union wait status;
3548 # else
3549 int status = -1;
3550 # endif
3551 int retval = -1;
3552 char **argv = NULL;
3553 int argc;
3554 int i;
3555 char_u *p;
3556 int inquote;
3557 int pty_master_fd = -1; /* for pty's */
3558 # ifdef FEAT_GUI
3559 int pty_slave_fd = -1;
3560 char *tty_name;
3561 # endif
3562 int fd_toshell[2]; /* for pipes */
3563 int fd_fromshell[2];
3564 int pipe_error = FALSE;
3565 # ifdef HAVE_SETENV
3566 char envbuf[50];
3567 # else
3568 static char envbuf_Rows[20];
3569 static char envbuf_Columns[20];
3570 # endif
3571 int did_settmode = FALSE; /* settmode(TMODE_RAW) called */
3573 out_flush();
3574 if (options & SHELL_COOKED)
3575 settmode(TMODE_COOK); /* set to normal mode */
3577 newcmd = vim_strsave(p_sh);
3578 if (newcmd == NULL) /* out of memory */
3579 goto error;
3582 * Do this loop twice:
3583 * 1: find number of arguments
3584 * 2: separate them and build argv[]
3586 for (i = 0; i < 2; ++i)
3588 p = newcmd;
3589 inquote = FALSE;
3590 argc = 0;
3591 for (;;)
3593 if (i == 1)
3594 argv[argc] = (char *)p;
3595 ++argc;
3596 while (*p && (inquote || (*p != ' ' && *p != TAB)))
3598 if (*p == '"')
3599 inquote = !inquote;
3600 ++p;
3602 if (*p == NUL)
3603 break;
3604 if (i == 1)
3605 *p++ = NUL;
3606 p = skipwhite(p);
3608 if (argv == NULL)
3610 argv = (char **)alloc((unsigned)((argc + 4) * sizeof(char *)));
3611 if (argv == NULL) /* out of memory */
3612 goto error;
3615 if (cmd != NULL)
3617 if (extra_shell_arg != NULL)
3618 argv[argc++] = (char *)extra_shell_arg;
3619 argv[argc++] = (char *)p_shcf;
3620 argv[argc++] = (char *)cmd;
3622 argv[argc] = NULL;
3625 * For the GUI, when writing the output into the buffer and when reading
3626 * input from the buffer: Try using a pseudo-tty to get the stdin/stdout
3627 * of the executed command into the Vim window. Or use a pipe.
3629 if ((options & (SHELL_READ|SHELL_WRITE))
3630 # ifdef FEAT_GUI
3631 || (gui.in_use && show_shell_mess)
3632 # endif
3635 # ifdef FEAT_GUI
3637 * Try to open a master pty.
3638 * If this works, open the slave pty.
3639 * If the slave can't be opened, close the master pty.
3641 if (p_guipty && !(options & (SHELL_READ|SHELL_WRITE)))
3643 pty_master_fd = OpenPTY(&tty_name); /* open pty */
3644 if (pty_master_fd >= 0 && ((pty_slave_fd =
3645 open(tty_name, O_RDWR | O_EXTRA, 0)) < 0))
3647 close(pty_master_fd);
3648 pty_master_fd = -1;
3652 * If not opening a pty or it didn't work, try using pipes.
3654 if (pty_master_fd < 0)
3655 # endif
3657 pipe_error = (pipe(fd_toshell) < 0);
3658 if (!pipe_error) /* pipe create OK */
3660 pipe_error = (pipe(fd_fromshell) < 0);
3661 if (pipe_error) /* pipe create failed */
3663 close(fd_toshell[0]);
3664 close(fd_toshell[1]);
3667 if (pipe_error)
3669 MSG_PUTS(_("\nCannot create pipes\n"));
3670 out_flush();
3675 if (!pipe_error) /* pty or pipe opened or not used */
3677 # ifdef __BEOS__
3678 beos_cleanup_read_thread();
3679 # endif
3681 if ((pid = fork()) == -1) /* maybe we should use vfork() */
3683 MSG_PUTS(_("\nCannot fork\n"));
3684 if ((options & (SHELL_READ|SHELL_WRITE))
3685 # ifdef FEAT_GUI
3686 || (gui.in_use && show_shell_mess)
3687 # endif
3690 # ifdef FEAT_GUI
3691 if (pty_master_fd >= 0) /* close the pseudo tty */
3693 close(pty_master_fd);
3694 close(pty_slave_fd);
3696 else /* close the pipes */
3697 # endif
3699 close(fd_toshell[0]);
3700 close(fd_toshell[1]);
3701 close(fd_fromshell[0]);
3702 close(fd_fromshell[1]);
3706 else if (pid == 0) /* child */
3708 reset_signals(); /* handle signals normally */
3710 if (!show_shell_mess || (options & SHELL_EXPAND))
3712 int fd;
3715 * Don't want to show any message from the shell. Can't just
3716 * close stdout and stderr though, because some systems will
3717 * break if you try to write to them after that, so we must
3718 * use dup() to replace them with something else -- webb
3719 * Connect stdin to /dev/null too, so ":n `cat`" doesn't hang,
3720 * waiting for input.
3722 fd = open("/dev/null", O_RDWR | O_EXTRA, 0);
3723 fclose(stdin);
3724 fclose(stdout);
3725 fclose(stderr);
3728 * If any of these open()'s and dup()'s fail, we just continue
3729 * anyway. It's not fatal, and on most systems it will make
3730 * no difference at all. On a few it will cause the execvp()
3731 * to exit with a non-zero status even when the completion
3732 * could be done, which is nothing too serious. If the open()
3733 * or dup() failed we'd just do the same thing ourselves
3734 * anyway -- webb
3736 if (fd >= 0)
3738 dup(fd); /* To replace stdin (file descriptor 0) */
3739 dup(fd); /* To replace stdout (file descriptor 1) */
3740 dup(fd); /* To replace stderr (file descriptor 2) */
3742 /* Don't need this now that we've duplicated it */
3743 close(fd);
3746 else if ((options & (SHELL_READ|SHELL_WRITE))
3747 # ifdef FEAT_GUI
3748 || gui.in_use
3749 # endif
3753 # ifdef HAVE_SETSID
3754 /* Create our own process group, so that the child and all its
3755 * children can be kill()ed. Don't do this when using pipes,
3756 * because stdin is not a tty, we would loose /dev/tty. */
3757 if (p_stmp)
3758 (void)setsid();
3759 # endif
3760 # ifdef FEAT_GUI
3761 if (pty_slave_fd >= 0)
3763 /* push stream discipline modules */
3764 if (options & SHELL_COOKED)
3765 SetupSlavePTY(pty_slave_fd);
3766 # ifdef TIOCSCTTY
3767 /* Try to become controlling tty (probably doesn't work,
3768 * unless run by root) */
3769 ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL);
3770 # endif
3772 # endif
3773 /* Simulate to have a dumb terminal (for now) */
3774 # ifdef HAVE_SETENV
3775 setenv("TERM", "dumb", 1);
3776 sprintf((char *)envbuf, "%ld", Rows);
3777 setenv("ROWS", (char *)envbuf, 1);
3778 sprintf((char *)envbuf, "%ld", Rows);
3779 setenv("LINES", (char *)envbuf, 1);
3780 sprintf((char *)envbuf, "%ld", Columns);
3781 setenv("COLUMNS", (char *)envbuf, 1);
3782 # else
3784 * Putenv does not copy the string, it has to remain valid.
3785 * Use a static array to avoid loosing allocated memory.
3787 putenv("TERM=dumb");
3788 sprintf(envbuf_Rows, "ROWS=%ld", Rows);
3789 putenv(envbuf_Rows);
3790 sprintf(envbuf_Rows, "LINES=%ld", Rows);
3791 putenv(envbuf_Rows);
3792 sprintf(envbuf_Columns, "COLUMNS=%ld", Columns);
3793 putenv(envbuf_Columns);
3794 # endif
3797 * stderr is only redirected when using the GUI, so that a
3798 * program like gpg can still access the terminal to get a
3799 * passphrase using stderr.
3801 # ifdef FEAT_GUI
3802 if (pty_master_fd >= 0)
3804 close(pty_master_fd); /* close master side of pty */
3806 /* set up stdin/stdout/stderr for the child */
3807 close(0);
3808 dup(pty_slave_fd);
3809 close(1);
3810 dup(pty_slave_fd);
3811 if (gui.in_use)
3813 close(2);
3814 dup(pty_slave_fd);
3817 close(pty_slave_fd); /* has been dupped, close it now */
3819 else
3820 # endif
3822 /* set up stdin for the child */
3823 close(fd_toshell[1]);
3824 close(0);
3825 dup(fd_toshell[0]);
3826 close(fd_toshell[0]);
3828 /* set up stdout for the child */
3829 close(fd_fromshell[0]);
3830 close(1);
3831 dup(fd_fromshell[1]);
3832 close(fd_fromshell[1]);
3834 # ifdef FEAT_GUI
3835 if (gui.in_use)
3837 /* set up stderr for the child */
3838 close(2);
3839 dup(1);
3841 # endif
3846 * There is no type cast for the argv, because the type may be
3847 * different on different machines. This may cause a warning
3848 * message with strict compilers, don't worry about it.
3849 * Call _exit() instead of exit() to avoid closing the connection
3850 * to the X server (esp. with GTK, which uses atexit()).
3852 execvp(argv[0], argv);
3853 _exit(EXEC_FAILED); /* exec failed, return failure code */
3855 else /* parent */
3858 * While child is running, ignore terminating signals.
3859 * Do catch CTRL-C, so that "got_int" is set.
3861 catch_signals(SIG_IGN, SIG_ERR);
3862 catch_int_signal();
3865 * For the GUI we redirect stdin, stdout and stderr to our window.
3866 * This is also used to pipe stdin/stdout to/from the external
3867 * command.
3869 if ((options & (SHELL_READ|SHELL_WRITE))
3870 # ifdef FEAT_GUI
3871 || (gui.in_use && show_shell_mess)
3872 # endif
3875 # define BUFLEN 100 /* length for buffer, pseudo tty limit is 128 */
3876 char_u buffer[BUFLEN + 1];
3877 # ifdef FEAT_MBYTE
3878 int buffer_off = 0; /* valid bytes in buffer[] */
3879 # endif
3880 char_u ta_buf[BUFLEN + 1]; /* TypeAHead */
3881 int ta_len = 0; /* valid bytes in ta_buf[] */
3882 int len;
3883 int p_more_save;
3884 int old_State;
3885 int c;
3886 int toshell_fd;
3887 int fromshell_fd;
3888 garray_T ga;
3889 int noread_cnt;
3891 # ifdef FEAT_GUI
3892 if (pty_master_fd >= 0)
3894 close(pty_slave_fd); /* close slave side of pty */
3895 fromshell_fd = pty_master_fd;
3896 toshell_fd = dup(pty_master_fd);
3898 else
3899 # endif
3901 close(fd_toshell[0]);
3902 close(fd_fromshell[1]);
3903 toshell_fd = fd_toshell[1];
3904 fromshell_fd = fd_fromshell[0];
3908 * Write to the child if there are typed characters.
3909 * Read from the child if there are characters available.
3910 * Repeat the reading a few times if more characters are
3911 * available. Need to check for typed keys now and then, but
3912 * not too often (delays when no chars are available).
3913 * This loop is quit if no characters can be read from the pty
3914 * (WaitForChar detected special condition), or there are no
3915 * characters available and the child has exited.
3916 * Only check if the child has exited when there is no more
3917 * output. The child may exit before all the output has
3918 * been printed.
3920 * Currently this busy loops!
3921 * This can probably dead-lock when the write blocks!
3923 p_more_save = p_more;
3924 p_more = FALSE;
3925 old_State = State;
3926 State = EXTERNCMD; /* don't redraw at window resize */
3928 if ((options & SHELL_WRITE) && toshell_fd >= 0)
3930 /* Fork a process that will write the lines to the
3931 * external program. */
3932 if ((wpid = fork()) == -1)
3934 MSG_PUTS(_("\nCannot fork\n"));
3936 else if (wpid == 0)
3938 linenr_T lnum = curbuf->b_op_start.lnum;
3939 int written = 0;
3940 char_u *lp = ml_get(lnum);
3941 char_u *s;
3942 size_t l;
3944 /* child */
3945 close(fromshell_fd);
3946 for (;;)
3948 l = STRLEN(lp + written);
3949 if (l == 0)
3950 len = 0;
3951 else if (lp[written] == NL)
3952 /* NL -> NUL translation */
3953 len = write(toshell_fd, "", (size_t)1);
3954 else
3956 s = vim_strchr(lp + written, NL);
3957 len = write(toshell_fd, (char *)lp + written,
3958 s == NULL ? l : s - (lp + written));
3960 if (len == l)
3962 /* Finished a line, add a NL, unless this line
3963 * should not have one. */
3964 if (lnum != curbuf->b_op_end.lnum
3965 || !curbuf->b_p_bin
3966 || (lnum != write_no_eol_lnum
3967 && (lnum !=
3968 curbuf->b_ml.ml_line_count
3969 || curbuf->b_p_eol)))
3970 write(toshell_fd, "\n", (size_t)1);
3971 ++lnum;
3972 if (lnum > curbuf->b_op_end.lnum)
3974 /* finished all the lines, close pipe */
3975 close(toshell_fd);
3976 toshell_fd = -1;
3977 break;
3979 lp = ml_get(lnum);
3980 written = 0;
3982 else if (len > 0)
3983 written += len;
3985 _exit(0);
3987 else
3989 close(toshell_fd);
3990 toshell_fd = -1;
3994 if (options & SHELL_READ)
3995 ga_init2(&ga, 1, BUFLEN);
3997 noread_cnt = 0;
3999 for (;;)
4002 * Check if keys have been typed, write them to the child
4003 * if there are any.
4004 * Don't do this if we are expanding wild cards (would eat
4005 * typeahead).
4006 * Don't do this when filtering and terminal is in cooked
4007 * mode, the shell command will handle the I/O. Avoids
4008 * that a typed password is echoed for ssh or gpg command.
4009 * Don't get characters when the child has already
4010 * finished (wait_pid == 0).
4011 * Don't get extra characters when we already have one.
4012 * Don't read characters unless we didn't get output for a
4013 * while, avoids that ":r !ls" eats typeahead.
4015 len = 0;
4016 if (!(options & SHELL_EXPAND)
4017 && ((options &
4018 (SHELL_READ|SHELL_WRITE|SHELL_COOKED))
4019 != (SHELL_READ|SHELL_WRITE|SHELL_COOKED)
4020 #ifdef FEAT_GUI
4021 || gui.in_use
4022 #endif
4024 && wait_pid == 0
4025 && (ta_len > 0
4026 || (noread_cnt > 4
4027 && (len = ui_inchar(ta_buf,
4028 BUFLEN, 10L, 0)) > 0)))
4031 * For pipes:
4032 * Check for CTRL-C: send interrupt signal to child.
4033 * Check for CTRL-D: EOF, close pipe to child.
4035 if (len == 1 && (pty_master_fd < 0 || cmd != NULL))
4037 # ifdef SIGINT
4039 * Send SIGINT to the child's group or all
4040 * processes in our group.
4042 if (ta_buf[ta_len] == Ctrl_C
4043 || ta_buf[ta_len] == intr_char)
4045 # ifdef HAVE_SETSID
4046 kill(-pid, SIGINT);
4047 # else
4048 kill(0, SIGINT);
4049 # endif
4050 if (wpid > 0)
4051 kill(wpid, SIGINT);
4053 # endif
4054 if (pty_master_fd < 0 && toshell_fd >= 0
4055 && ta_buf[ta_len] == Ctrl_D)
4057 close(toshell_fd);
4058 toshell_fd = -1;
4062 /* replace K_BS by <BS> and K_DEL by <DEL> */
4063 for (i = ta_len; i < ta_len + len; ++i)
4065 if (ta_buf[i] == CSI && len - i > 2)
4067 c = TERMCAP2KEY(ta_buf[i + 1], ta_buf[i + 2]);
4068 if (c == K_DEL || c == K_KDEL || c == K_BS)
4070 mch_memmove(ta_buf + i + 1, ta_buf + i + 3,
4071 (size_t)(len - i - 2));
4072 if (c == K_DEL || c == K_KDEL)
4073 ta_buf[i] = DEL;
4074 else
4075 ta_buf[i] = Ctrl_H;
4076 len -= 2;
4079 else if (ta_buf[i] == '\r')
4080 ta_buf[i] = '\n';
4081 # ifdef FEAT_MBYTE
4082 if (has_mbyte)
4083 i += (*mb_ptr2len)(ta_buf + i) - 1;
4084 # endif
4088 * For pipes: echo the typed characters.
4089 * For a pty this does not seem to work.
4091 if (pty_master_fd < 0)
4093 for (i = ta_len; i < ta_len + len; ++i)
4095 if (ta_buf[i] == '\n' || ta_buf[i] == '\b')
4096 msg_putchar(ta_buf[i]);
4097 # ifdef FEAT_MBYTE
4098 else if (has_mbyte)
4100 int l = (*mb_ptr2len)(ta_buf + i);
4102 msg_outtrans_len(ta_buf + i, l);
4103 i += l - 1;
4105 # endif
4106 else
4107 msg_outtrans_len(ta_buf + i, 1);
4109 windgoto(msg_row, msg_col);
4110 out_flush();
4113 ta_len += len;
4116 * Write the characters to the child, unless EOF has
4117 * been typed for pipes. Write one character at a
4118 * time, to avoid loosing too much typeahead.
4119 * When writing buffer lines, drop the typed
4120 * characters (only check for CTRL-C).
4122 if (options & SHELL_WRITE)
4123 ta_len = 0;
4124 else if (toshell_fd >= 0)
4126 len = write(toshell_fd, (char *)ta_buf, (size_t)1);
4127 if (len > 0)
4129 ta_len -= len;
4130 mch_memmove(ta_buf, ta_buf + len, ta_len);
4131 noread_cnt = 0;
4136 if (got_int)
4138 /* CTRL-C sends a signal to the child, we ignore it
4139 * ourselves */
4140 # ifdef HAVE_SETSID
4141 kill(-pid, SIGINT);
4142 # else
4143 kill(0, SIGINT);
4144 # endif
4145 if (wpid > 0)
4146 kill(wpid, SIGINT);
4147 got_int = FALSE;
4151 * Check if the child has any characters to be printed.
4152 * Read them and write them to our window. Repeat this as
4153 * long as there is something to do, avoid the 10ms wait
4154 * for mch_inchar(), or sending typeahead characters to
4155 * the external process.
4156 * TODO: This should handle escape sequences, compatible
4157 * to some terminal (vt52?).
4159 ++noread_cnt;
4160 while (RealWaitForChar(fromshell_fd, 10L, NULL))
4162 len = read(fromshell_fd, (char *)buffer
4163 # ifdef FEAT_MBYTE
4164 + buffer_off, (size_t)(BUFLEN - buffer_off)
4165 # else
4166 , (size_t)BUFLEN
4167 # endif
4169 if (len <= 0) /* end of file or error */
4170 goto finished;
4172 noread_cnt = 0;
4173 if (options & SHELL_READ)
4175 /* Do NUL -> NL translation, append NL separated
4176 * lines to the current buffer. */
4177 for (i = 0; i < len; ++i)
4179 if (buffer[i] == NL)
4180 append_ga_line(&ga);
4181 else if (buffer[i] == NUL)
4182 ga_append(&ga, NL);
4183 else
4184 ga_append(&ga, buffer[i]);
4187 # ifdef FEAT_MBYTE
4188 else if (has_mbyte)
4190 int l;
4192 len += buffer_off;
4193 buffer[len] = NUL;
4195 /* Check if the last character in buffer[] is
4196 * incomplete, keep these bytes for the next
4197 * round. */
4198 for (p = buffer; p < buffer + len; p += l)
4200 l = mb_cptr2len(p);
4201 if (l == 0)
4202 l = 1; /* NUL byte? */
4203 else if (MB_BYTE2LEN(*p) != l)
4204 break;
4206 if (p == buffer) /* no complete character */
4208 /* avoid getting stuck at an illegal byte */
4209 if (len >= 12)
4210 ++p;
4211 else
4213 buffer_off = len;
4214 continue;
4217 c = *p;
4218 *p = NUL;
4219 msg_puts(buffer);
4220 if (p < buffer + len)
4222 *p = c;
4223 buffer_off = (buffer + len) - p;
4224 mch_memmove(buffer, p, buffer_off);
4225 continue;
4227 buffer_off = 0;
4229 # endif /* FEAT_MBYTE */
4230 else
4232 buffer[len] = NUL;
4233 msg_puts(buffer);
4236 windgoto(msg_row, msg_col);
4237 cursor_on();
4238 out_flush();
4239 if (got_int)
4240 break;
4243 /* If we already detected the child has finished break the
4244 * loop now. */
4245 if (wait_pid == pid)
4246 break;
4249 * Check if the child still exists, before checking for
4250 * typed characters (otherwise we would loose typeahead).
4252 # ifdef __NeXT__
4253 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *) 0);
4254 # else
4255 wait_pid = waitpid(pid, &status, WNOHANG);
4256 # endif
4257 if ((wait_pid == (pid_t)-1 && errno == ECHILD)
4258 || (wait_pid == pid && WIFEXITED(status)))
4260 /* Don't break the loop yet, try reading more
4261 * characters from "fromshell_fd" first. When using
4262 * pipes there might still be something to read and
4263 * then we'll break the loop at the "break" above. */
4264 wait_pid = pid;
4266 else
4267 wait_pid = 0;
4269 finished:
4270 p_more = p_more_save;
4271 if (options & SHELL_READ)
4273 if (ga.ga_len > 0)
4275 append_ga_line(&ga);
4276 /* remember that the NL was missing */
4277 write_no_eol_lnum = curwin->w_cursor.lnum;
4279 else
4280 write_no_eol_lnum = 0;
4281 ga_clear(&ga);
4285 * Give all typeahead that wasn't used back to ui_inchar().
4287 if (ta_len)
4288 ui_inchar_undo(ta_buf, ta_len);
4289 State = old_State;
4290 if (toshell_fd >= 0)
4291 close(toshell_fd);
4292 close(fromshell_fd);
4296 * Wait until our child has exited.
4297 * Ignore wait() returning pids of other children and returning
4298 * because of some signal like SIGWINCH.
4299 * Don't wait if wait_pid was already set above, indicating the
4300 * child already exited.
4302 while (wait_pid != pid)
4304 # ifdef _THREAD_SAFE
4305 /* Ugly hack: when compiled with Python threads are probably
4306 * used, in which case wait() sometimes hangs for no obvious
4307 * reason. Use waitpid() instead and loop (like the GUI). */
4308 # ifdef __NeXT__
4309 wait_pid = wait4(pid, &status, WNOHANG, (struct rusage *)0);
4310 # else
4311 wait_pid = waitpid(pid, &status, WNOHANG);
4312 # endif
4313 if (wait_pid == 0)
4315 /* Wait for 1/100 sec before trying again. */
4316 mch_delay(10L, TRUE);
4317 continue;
4319 # else
4320 wait_pid = wait(&status);
4321 # endif
4322 if (wait_pid <= 0
4323 # ifdef ECHILD
4324 && errno == ECHILD
4325 # endif
4327 break;
4330 /* Make sure the child that writes to the external program is
4331 * dead. */
4332 if (wpid > 0)
4333 kill(wpid, SIGKILL);
4336 * Set to raw mode right now, otherwise a CTRL-C after
4337 * catch_signals() will kill Vim.
4339 if (tmode == TMODE_RAW)
4340 settmode(TMODE_RAW);
4341 did_settmode = TRUE;
4342 set_signals();
4344 if (WIFEXITED(status))
4346 /* LINTED avoid "bitwise operation on signed value" */
4347 retval = WEXITSTATUS(status);
4348 if (retval && !emsg_silent)
4350 if (retval == EXEC_FAILED)
4352 MSG_PUTS(_("\nCannot execute shell "));
4353 msg_outtrans(p_sh);
4354 msg_putchar('\n');
4356 else if (!(options & SHELL_SILENT))
4358 MSG_PUTS(_("\nshell returned "));
4359 msg_outnum((long)retval);
4360 msg_putchar('\n');
4364 else
4365 MSG_PUTS(_("\nCommand terminated\n"));
4368 vim_free(argv);
4370 error:
4371 if (!did_settmode)
4372 if (tmode == TMODE_RAW)
4373 settmode(TMODE_RAW); /* set to raw mode */
4374 # ifdef FEAT_TITLE
4375 resettitle();
4376 # endif
4377 vim_free(newcmd);
4379 return retval;
4381 #endif /* USE_SYSTEM */
4385 * Check for CTRL-C typed by reading all available characters.
4386 * In cooked mode we should get SIGINT, no need to check.
4388 void
4389 mch_breakcheck()
4391 if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL))
4392 fill_input_buf(FALSE);
4396 * Wait "msec" msec until a character is available from the keyboard or from
4397 * inbuf[]. msec == -1 will block forever.
4398 * When a GUI is being used, this will never get called -- webb
4400 static int
4401 WaitForChar(msec)
4402 long msec;
4404 #ifdef FEAT_MOUSE_GPM
4405 int gpm_process_wanted;
4406 #endif
4407 #ifdef FEAT_XCLIPBOARD
4408 int rest;
4409 #endif
4410 int avail;
4412 if (input_available()) /* something in inbuf[] */
4413 return 1;
4415 #if defined(FEAT_MOUSE_DEC)
4416 /* May need to query the mouse position. */
4417 if (WantQueryMouse)
4419 WantQueryMouse = FALSE;
4420 mch_write((char_u *)IF_EB("\033[1'|", ESC_STR "[1'|"), 5);
4422 #endif
4425 * For FEAT_MOUSE_GPM and FEAT_XCLIPBOARD we loop here to process mouse
4426 * events. This is a bit complicated, because they might both be defined.
4428 #if defined(FEAT_MOUSE_GPM) || defined(FEAT_XCLIPBOARD)
4429 # ifdef FEAT_XCLIPBOARD
4430 rest = 0;
4431 if (do_xterm_trace())
4432 rest = msec;
4433 # endif
4436 # ifdef FEAT_XCLIPBOARD
4437 if (rest != 0)
4439 msec = XT_TRACE_DELAY;
4440 if (rest >= 0 && rest < XT_TRACE_DELAY)
4441 msec = rest;
4442 if (rest >= 0)
4443 rest -= msec;
4445 # endif
4446 # ifdef FEAT_MOUSE_GPM
4447 gpm_process_wanted = 0;
4448 avail = RealWaitForChar(read_cmd_fd, msec, &gpm_process_wanted);
4449 # else
4450 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4451 # endif
4452 if (!avail)
4454 if (input_available())
4455 return 1;
4456 # ifdef FEAT_XCLIPBOARD
4457 if (rest == 0 || !do_xterm_trace())
4458 # endif
4459 break;
4462 while (FALSE
4463 # ifdef FEAT_MOUSE_GPM
4464 || (gpm_process_wanted && mch_gpm_process() == 0)
4465 # endif
4466 # ifdef FEAT_XCLIPBOARD
4467 || (!avail && rest != 0)
4468 # endif
4471 #else
4472 avail = RealWaitForChar(read_cmd_fd, msec, NULL);
4473 #endif
4474 return avail;
4478 * Wait "msec" msec until a character is available from file descriptor "fd".
4479 * Time == -1 will block forever.
4480 * When a GUI is being used, this will not be used for input -- webb
4481 * Returns also, when a request from Sniff is waiting -- toni.
4482 * Or when a Linux GPM mouse event is waiting.
4484 /* ARGSUSED */
4485 #if defined(__BEOS__)
4487 #else
4488 static int
4489 #endif
4490 RealWaitForChar(fd, msec, check_for_gpm)
4491 int fd;
4492 long msec;
4493 int *check_for_gpm;
4495 int ret;
4496 #if defined(FEAT_XCLIPBOARD) || defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4497 static int busy = FALSE;
4499 /* May retry getting characters after an event was handled. */
4500 # define MAY_LOOP
4502 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
4503 /* Remember at what time we started, so that we know how much longer we
4504 * should wait after being interrupted. */
4505 # define USE_START_TV
4506 struct timeval start_tv;
4508 if (msec > 0 && (
4509 # ifdef FEAT_XCLIPBOARD
4510 xterm_Shell != (Widget)0
4511 # if defined(USE_XSMP) || defined(FEAT_MZSCHEME)
4513 # endif
4514 # endif
4515 # ifdef USE_XSMP
4516 xsmp_icefd != -1
4517 # ifdef FEAT_MZSCHEME
4519 # endif
4520 # endif
4521 # ifdef FEAT_MZSCHEME
4522 (mzthreads_allowed() && p_mzq > 0)
4523 # endif
4525 gettimeofday(&start_tv, NULL);
4526 # endif
4528 /* Handle being called recursively. This may happen for the session
4529 * manager stuff, it may save the file, which does a breakcheck. */
4530 if (busy)
4531 return 0;
4532 #endif
4534 #ifdef MAY_LOOP
4535 for (;;)
4536 #endif
4538 #ifdef MAY_LOOP
4539 int finished = TRUE; /* default is to 'loop' just once */
4540 # ifdef FEAT_MZSCHEME
4541 int mzquantum_used = FALSE;
4542 # endif
4543 #endif
4544 #ifndef HAVE_SELECT
4545 struct pollfd fds[5];
4546 int nfd;
4547 # ifdef FEAT_XCLIPBOARD
4548 int xterm_idx = -1;
4549 # endif
4550 # ifdef FEAT_MOUSE_GPM
4551 int gpm_idx = -1;
4552 # endif
4553 # ifdef USE_XSMP
4554 int xsmp_idx = -1;
4555 # endif
4556 int towait = (int)msec;
4558 # ifdef FEAT_MZSCHEME
4559 mzvim_check_threads();
4560 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4562 towait = (int)p_mzq; /* don't wait longer than 'mzquantum' */
4563 mzquantum_used = TRUE;
4565 # endif
4566 fds[0].fd = fd;
4567 fds[0].events = POLLIN;
4568 nfd = 1;
4570 # ifdef FEAT_SNIFF
4571 # define SNIFF_IDX 1
4572 if (want_sniff_request)
4574 fds[SNIFF_IDX].fd = fd_from_sniff;
4575 fds[SNIFF_IDX].events = POLLIN;
4576 nfd++;
4578 # endif
4579 # ifdef FEAT_XCLIPBOARD
4580 if (xterm_Shell != (Widget)0)
4582 xterm_idx = nfd;
4583 fds[nfd].fd = ConnectionNumber(xterm_dpy);
4584 fds[nfd].events = POLLIN;
4585 nfd++;
4587 # endif
4588 # ifdef FEAT_MOUSE_GPM
4589 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4591 gpm_idx = nfd;
4592 fds[nfd].fd = gpm_fd;
4593 fds[nfd].events = POLLIN;
4594 nfd++;
4596 # endif
4597 # ifdef USE_XSMP
4598 if (xsmp_icefd != -1)
4600 xsmp_idx = nfd;
4601 fds[nfd].fd = xsmp_icefd;
4602 fds[nfd].events = POLLIN;
4603 nfd++;
4605 # endif
4607 ret = poll(fds, nfd, towait);
4608 # ifdef FEAT_MZSCHEME
4609 if (ret == 0 && mzquantum_used)
4610 /* MzThreads scheduling is required and timeout occured */
4611 finished = FALSE;
4612 # endif
4614 # ifdef FEAT_SNIFF
4615 if (ret < 0)
4616 sniff_disconnect(1);
4617 else if (want_sniff_request)
4619 if (fds[SNIFF_IDX].revents & POLLHUP)
4620 sniff_disconnect(1);
4621 if (fds[SNIFF_IDX].revents & POLLIN)
4622 sniff_request_waiting = 1;
4624 # endif
4625 # ifdef FEAT_XCLIPBOARD
4626 if (xterm_Shell != (Widget)0 && (fds[xterm_idx].revents & POLLIN))
4628 xterm_update(); /* Maybe we should hand out clipboard */
4629 if (--ret == 0 && !input_available())
4630 /* Try again */
4631 finished = FALSE;
4633 # endif
4634 # ifdef FEAT_MOUSE_GPM
4635 if (gpm_idx >= 0 && (fds[gpm_idx].revents & POLLIN))
4637 *check_for_gpm = 1;
4639 # endif
4640 # ifdef USE_XSMP
4641 if (xsmp_idx >= 0 && (fds[xsmp_idx].revents & (POLLIN | POLLHUP)))
4643 if (fds[xsmp_idx].revents & POLLIN)
4645 busy = TRUE;
4646 xsmp_handle_requests();
4647 busy = FALSE;
4649 else if (fds[xsmp_idx].revents & POLLHUP)
4651 if (p_verbose > 0)
4652 verb_msg((char_u *)_("XSMP lost ICE connection"));
4653 xsmp_close();
4655 if (--ret == 0)
4656 finished = FALSE; /* Try again */
4658 # endif
4661 #else /* HAVE_SELECT */
4663 struct timeval tv;
4664 struct timeval *tvp;
4665 fd_set rfds, efds;
4666 int maxfd;
4667 long towait = msec;
4669 # ifdef FEAT_MZSCHEME
4670 mzvim_check_threads();
4671 if (mzthreads_allowed() && p_mzq > 0 && (msec < 0 || msec > p_mzq))
4673 towait = p_mzq; /* don't wait longer than 'mzquantum' */
4674 mzquantum_used = TRUE;
4676 # endif
4677 # ifdef __EMX__
4678 /* don't check for incoming chars if not in raw mode, because select()
4679 * always returns TRUE then (in some version of emx.dll) */
4680 if (curr_tmode != TMODE_RAW)
4681 return 0;
4682 # endif
4684 if (towait >= 0)
4686 tv.tv_sec = towait / 1000;
4687 tv.tv_usec = (towait % 1000) * (1000000/1000);
4688 tvp = &tv;
4690 else
4691 tvp = NULL;
4694 * Select on ready for reading and exceptional condition (end of file).
4696 FD_ZERO(&rfds); /* calls bzero() on a sun */
4697 FD_ZERO(&efds);
4698 FD_SET(fd, &rfds);
4699 # if !defined(__QNX__) && !defined(__CYGWIN32__)
4700 /* For QNX select() always returns 1 if this is set. Why? */
4701 FD_SET(fd, &efds);
4702 # endif
4703 maxfd = fd;
4705 # ifdef FEAT_SNIFF
4706 if (want_sniff_request)
4708 FD_SET(fd_from_sniff, &rfds);
4709 FD_SET(fd_from_sniff, &efds);
4710 if (maxfd < fd_from_sniff)
4711 maxfd = fd_from_sniff;
4713 # endif
4714 # ifdef FEAT_XCLIPBOARD
4715 if (xterm_Shell != (Widget)0)
4717 FD_SET(ConnectionNumber(xterm_dpy), &rfds);
4718 if (maxfd < ConnectionNumber(xterm_dpy))
4719 maxfd = ConnectionNumber(xterm_dpy);
4721 # endif
4722 # ifdef FEAT_MOUSE_GPM
4723 if (check_for_gpm != NULL && gpm_flag && gpm_fd >= 0)
4725 FD_SET(gpm_fd, &rfds);
4726 FD_SET(gpm_fd, &efds);
4727 if (maxfd < gpm_fd)
4728 maxfd = gpm_fd;
4730 # endif
4731 # ifdef USE_XSMP
4732 if (xsmp_icefd != -1)
4734 FD_SET(xsmp_icefd, &rfds);
4735 FD_SET(xsmp_icefd, &efds);
4736 if (maxfd < xsmp_icefd)
4737 maxfd = xsmp_icefd;
4739 # endif
4741 # ifdef OLD_VMS
4742 /* Old VMS as v6.2 and older have broken select(). It waits more than
4743 * required. Should not be used */
4744 ret = 0;
4745 # else
4746 ret = select(maxfd + 1, &rfds, NULL, &efds, tvp);
4747 # endif
4748 # ifdef __TANDEM
4749 if (ret == -1 && errno == ENOTSUP)
4751 FD_ZERO(&rfds);
4752 FD_ZERO(&efds);
4753 ret = 0;
4755 #endif
4756 # ifdef FEAT_MZSCHEME
4757 if (ret == 0 && mzquantum_used)
4758 /* loop if MzThreads must be scheduled and timeout occured */
4759 finished = FALSE;
4760 # endif
4762 # ifdef FEAT_SNIFF
4763 if (ret < 0 )
4764 sniff_disconnect(1);
4765 else if (ret > 0 && want_sniff_request)
4767 if (FD_ISSET(fd_from_sniff, &efds))
4768 sniff_disconnect(1);
4769 if (FD_ISSET(fd_from_sniff, &rfds))
4770 sniff_request_waiting = 1;
4772 # endif
4773 # ifdef FEAT_XCLIPBOARD
4774 if (ret > 0 && xterm_Shell != (Widget)0
4775 && FD_ISSET(ConnectionNumber(xterm_dpy), &rfds))
4777 xterm_update(); /* Maybe we should hand out clipboard */
4778 /* continue looping when we only got the X event and the input
4779 * buffer is empty */
4780 if (--ret == 0 && !input_available())
4782 /* Try again */
4783 finished = FALSE;
4786 # endif
4787 # ifdef FEAT_MOUSE_GPM
4788 if (ret > 0 && gpm_flag && check_for_gpm != NULL && gpm_fd >= 0)
4790 if (FD_ISSET(gpm_fd, &efds))
4791 gpm_close();
4792 else if (FD_ISSET(gpm_fd, &rfds))
4793 *check_for_gpm = 1;
4795 # endif
4796 # ifdef USE_XSMP
4797 if (ret > 0 && xsmp_icefd != -1)
4799 if (FD_ISSET(xsmp_icefd, &efds))
4801 if (p_verbose > 0)
4802 verb_msg((char_u *)_("XSMP lost ICE connection"));
4803 xsmp_close();
4804 if (--ret == 0)
4805 finished = FALSE; /* keep going if event was only one */
4807 else if (FD_ISSET(xsmp_icefd, &rfds))
4809 busy = TRUE;
4810 xsmp_handle_requests();
4811 busy = FALSE;
4812 if (--ret == 0)
4813 finished = FALSE; /* keep going if event was only one */
4816 # endif
4818 #endif /* HAVE_SELECT */
4820 #ifdef MAY_LOOP
4821 if (finished || msec == 0)
4822 break;
4824 /* We're going to loop around again, find out for how long */
4825 if (msec > 0)
4827 # ifdef USE_START_TV
4828 struct timeval mtv;
4830 /* Compute remaining wait time. */
4831 gettimeofday(&mtv, NULL);
4832 msec -= (mtv.tv_sec - start_tv.tv_sec) * 1000L
4833 + (mtv.tv_usec - start_tv.tv_usec) / 1000L;
4834 # else
4835 /* Guess we got interrupted halfway. */
4836 msec = msec / 2;
4837 # endif
4838 if (msec <= 0)
4839 break; /* waited long enough */
4841 #endif
4844 return (ret > 0);
4847 #ifndef VMS
4849 #ifndef NO_EXPANDPATH
4851 * Expand a path into all matching files and/or directories. Handles "*",
4852 * "?", "[a-z]", "**", etc.
4853 * "path" has backslashes before chars that are not to be expanded.
4854 * Returns the number of matches found.
4857 mch_expandpath(gap, path, flags)
4858 garray_T *gap;
4859 char_u *path;
4860 int flags; /* EW_* flags */
4862 return unix_expandpath(gap, path, 0, flags, FALSE);
4864 #endif
4867 * mch_expand_wildcards() - this code does wild-card pattern matching using
4868 * the shell
4870 * return OK for success, FAIL for error (you may lose some memory) and put
4871 * an error message in *file.
4873 * num_pat is number of input patterns
4874 * pat is array of pointers to input patterns
4875 * num_file is pointer to number of matched file names
4876 * file is pointer to array of pointers to matched file names
4879 #ifndef SEEK_SET
4880 # define SEEK_SET 0
4881 #endif
4882 #ifndef SEEK_END
4883 # define SEEK_END 2
4884 #endif
4886 #define SHELL_SPECIAL (char_u *)"\t \"&'$;<>()\\|"
4888 /* ARGSUSED */
4890 mch_expand_wildcards(num_pat, pat, num_file, file, flags)
4891 int num_pat;
4892 char_u **pat;
4893 int *num_file;
4894 char_u ***file;
4895 int flags; /* EW_* flags */
4897 int i;
4898 size_t len;
4899 char_u *p;
4900 int dir;
4901 #ifdef __EMX__
4902 # define EXPL_ALLOC_INC 16
4903 char_u **expl_files;
4904 size_t files_alloced, files_free;
4905 char_u *buf;
4906 int has_wildcard;
4908 *num_file = 0; /* default: no files found */
4909 files_alloced = EXPL_ALLOC_INC; /* how much space is allocated */
4910 files_free = EXPL_ALLOC_INC; /* how much space is not used */
4911 *file = (char_u **)alloc(sizeof(char_u **) * files_alloced);
4912 if (*file == NULL)
4913 return FAIL;
4915 for (; num_pat > 0; num_pat--, pat++)
4917 expl_files = NULL;
4918 if (vim_strchr(*pat, '$') || vim_strchr(*pat, '~'))
4919 /* expand environment var or home dir */
4920 buf = expand_env_save(*pat);
4921 else
4922 buf = vim_strsave(*pat);
4923 expl_files = NULL;
4924 has_wildcard = mch_has_exp_wildcard(buf); /* (still) wildcards? */
4925 if (has_wildcard) /* yes, so expand them */
4926 expl_files = (char_u **)_fnexplode(buf);
4929 * return value of buf if no wildcards left,
4930 * OR if no match AND EW_NOTFOUND is set.
4932 if ((!has_wildcard && ((flags & EW_NOTFOUND) || mch_getperm(buf) >= 0))
4933 || (expl_files == NULL && (flags & EW_NOTFOUND)))
4934 { /* simply save the current contents of *buf */
4935 expl_files = (char_u **)alloc(sizeof(char_u **) * 2);
4936 if (expl_files != NULL)
4938 expl_files[0] = vim_strsave(buf);
4939 expl_files[1] = NULL;
4942 vim_free(buf);
4945 * Count number of names resulting from expansion,
4946 * At the same time add a backslash to the end of names that happen to
4947 * be directories, and replace slashes with backslashes.
4949 if (expl_files)
4951 for (i = 0; (p = expl_files[i]) != NULL; i++)
4953 dir = mch_isdir(p);
4954 /* If we don't want dirs and this is one, skip it */
4955 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
4956 continue;
4958 /* Skip files that are not executable if we check for that. */
4959 if (!dir && (flags & EW_EXEC) && !mch_can_exe(p))
4960 continue;
4962 if (--files_free == 0)
4964 /* need more room in table of pointers */
4965 files_alloced += EXPL_ALLOC_INC;
4966 *file = (char_u **)vim_realloc(*file,
4967 sizeof(char_u **) * files_alloced);
4968 if (*file == NULL)
4970 EMSG(_(e_outofmem));
4971 *num_file = 0;
4972 return FAIL;
4974 files_free = EXPL_ALLOC_INC;
4976 slash_adjust(p);
4977 if (dir)
4979 /* For a directory we add a '/', unless it's already
4980 * there. */
4981 len = STRLEN(p);
4982 if (((*file)[*num_file] = alloc(len + 2)) != NULL)
4984 STRCPY((*file)[*num_file], p);
4985 if (!after_pathsep((*file)[*num_file],
4986 (*file)[*num_file] + len))
4988 (*file)[*num_file][len] = psepc;
4989 (*file)[*num_file][len + 1] = NUL;
4993 else
4995 (*file)[*num_file] = vim_strsave(p);
4999 * Error message already given by either alloc or vim_strsave.
5000 * Should return FAIL, but returning OK works also.
5002 if ((*file)[*num_file] == NULL)
5003 break;
5004 (*num_file)++;
5006 _fnexplodefree((char **)expl_files);
5009 return OK;
5011 #else /* __EMX__ */
5013 int j;
5014 char_u *tempname;
5015 char_u *command;
5016 FILE *fd;
5017 char_u *buffer;
5018 #define STYLE_ECHO 0 /* use "echo" to expand */
5019 #define STYLE_GLOB 1 /* use "glob" to expand, for csh */
5020 #define STYLE_PRINT 2 /* use "print -N" to expand, for zsh */
5021 #define STYLE_BT 3 /* `cmd` expansion, execute the pattern directly */
5022 int shell_style = STYLE_ECHO;
5023 int check_spaces;
5024 static int did_find_nul = FALSE;
5025 int ampersent = FALSE;
5027 *num_file = 0; /* default: no files found */
5028 *file = NULL;
5031 * If there are no wildcards, just copy the names to allocated memory.
5032 * Saves a lot of time, because we don't have to start a new shell.
5034 if (!have_wildcard(num_pat, pat))
5035 return save_patterns(num_pat, pat, num_file, file);
5037 # ifdef HAVE_SANDBOX
5038 /* Don't allow any shell command in the sandbox. */
5039 if (sandbox != 0 && check_secure())
5040 return FAIL;
5041 # endif
5044 * Don't allow the use of backticks in secure and restricted mode.
5046 if (secure || restricted)
5047 for (i = 0; i < num_pat; ++i)
5048 if (vim_strchr(pat[i], '`') != NULL
5049 && (check_restricted() || check_secure()))
5050 return FAIL;
5053 * get a name for the temp file
5055 if ((tempname = vim_tempname('o')) == NULL)
5057 EMSG(_(e_notmp));
5058 return FAIL;
5062 * Let the shell expand the patterns and write the result into the temp
5063 * file. if expanding `cmd` execute it directly.
5064 * If we use csh, glob will work better than echo.
5065 * If we use zsh, print -N will work better than glob.
5067 if (num_pat == 1 && *pat[0] == '`'
5068 && (len = STRLEN(pat[0])) > 2
5069 && *(pat[0] + len - 1) == '`')
5070 shell_style = STYLE_BT;
5071 else if ((len = STRLEN(p_sh)) >= 3)
5073 if (STRCMP(p_sh + len - 3, "csh") == 0)
5074 shell_style = STYLE_GLOB;
5075 else if (STRCMP(p_sh + len - 3, "zsh") == 0)
5076 shell_style = STYLE_PRINT;
5079 /* "unset nonomatch; print -N >" plus two is 29 */
5080 len = STRLEN(tempname) + 29;
5081 for (i = 0; i < num_pat; ++i)
5083 /* Count the length of the patterns in the same way as they are put in
5084 * "command" below. */
5085 #ifdef USE_SYSTEM
5086 len += STRLEN(pat[i]) + 3; /* add space and two quotes */
5087 #else
5088 ++len; /* add space */
5089 for (j = 0; pat[i][j] != NUL; ++j)
5091 if (vim_strchr(SHELL_SPECIAL, pat[i][j]) != NULL)
5092 ++len; /* may add a backslash */
5093 ++len;
5095 #endif
5097 command = alloc(len);
5098 if (command == NULL)
5100 /* out of memory */
5101 vim_free(tempname);
5102 return FAIL;
5106 * Build the shell command:
5107 * - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell
5108 * recognizes this).
5109 * - Add the shell command to print the expanded names.
5110 * - Add the temp file name.
5111 * - Add the file name patterns.
5113 if (shell_style == STYLE_BT)
5115 /* change `command; command& ` to (command; command ) */
5116 STRCPY(command, "(");
5117 STRCAT(command, pat[0] + 1); /* exclude first backtick */
5118 p = command + STRLEN(command) - 1;
5119 *p-- = ')'; /* remove last backtick */
5120 while (p > command && vim_iswhite(*p))
5121 --p;
5122 if (*p == '&') /* remove trailing '&' */
5124 ampersent = TRUE;
5125 *p = ' ';
5127 STRCAT(command, ">");
5129 else
5131 if (flags & EW_NOTFOUND)
5132 STRCPY(command, "set nonomatch; ");
5133 else
5134 STRCPY(command, "unset nonomatch; ");
5135 if (shell_style == STYLE_GLOB)
5136 STRCAT(command, "glob >");
5137 else if (shell_style == STYLE_PRINT)
5138 STRCAT(command, "print -N >");
5139 else
5140 STRCAT(command, "echo >");
5142 STRCAT(command, tempname);
5143 if (shell_style != STYLE_BT)
5144 for (i = 0; i < num_pat; ++i)
5146 /* When using system() always add extra quotes, because the shell
5147 * is started twice. Otherwise put a backslash before special
5148 * characters, except insice ``. */
5149 #ifdef USE_SYSTEM
5150 STRCAT(command, " \"");
5151 STRCAT(command, pat[i]);
5152 STRCAT(command, "\"");
5153 #else
5154 int intick = FALSE;
5156 p = command + STRLEN(command);
5157 *p++ = ' ';
5158 for (j = 0; pat[i][j] != NUL; ++j)
5160 if (pat[i][j] == '`')
5161 intick = !intick;
5162 else if (pat[i][j] == '\\' && pat[i][j + 1] != NUL)
5164 /* Remove a backslash, take char literally. But keep
5165 * backslash inside backticks, before a special character
5166 * and before a backtick. */
5167 if (intick
5168 || vim_strchr(SHELL_SPECIAL, pat[i][j + 1]) != NULL
5169 || pat[i][j + 1] == '`')
5170 *p++ = '\\';
5171 ++j;
5173 else if (!intick && vim_strchr(SHELL_SPECIAL,
5174 pat[i][j]) != NULL)
5175 /* Put a backslash before a special character, but not
5176 * when inside ``. */
5177 *p++ = '\\';
5179 /* Copy one character. */
5180 *p++ = pat[i][j];
5182 *p = NUL;
5183 #endif
5185 if (flags & EW_SILENT)
5186 show_shell_mess = FALSE;
5187 if (ampersent)
5188 STRCAT(command, "&"); /* put the '&' back after the
5189 redirection */
5192 * Using zsh -G: If a pattern has no matches, it is just deleted from
5193 * the argument list, otherwise zsh gives an error message and doesn't
5194 * expand any other pattern.
5196 if (shell_style == STYLE_PRINT)
5197 extra_shell_arg = (char_u *)"-G"; /* Use zsh NULL_GLOB option */
5200 * If we use -f then shell variables set in .cshrc won't get expanded.
5201 * vi can do it, so we will too, but it is only necessary if there is a "$"
5202 * in one of the patterns, otherwise we can still use the fast option.
5204 else if (shell_style == STYLE_GLOB && !have_dollars(num_pat, pat))
5205 extra_shell_arg = (char_u *)"-f"; /* Use csh fast option */
5208 * execute the shell command
5210 i = call_shell(command, SHELL_EXPAND | SHELL_SILENT);
5212 /* When running in the background, give it some time to create the temp
5213 * file, but don't wait for it to finish. */
5214 if (ampersent)
5215 mch_delay(10L, TRUE);
5217 extra_shell_arg = NULL; /* cleanup */
5218 show_shell_mess = TRUE;
5219 vim_free(command);
5221 if (i) /* mch_call_shell() failed */
5223 mch_remove(tempname);
5224 vim_free(tempname);
5226 * With interactive completion, the error message is not printed.
5227 * However with USE_SYSTEM, I don't know how to turn off error messages
5228 * from the shell, so screen may still get messed up -- webb.
5230 #ifndef USE_SYSTEM
5231 if (!(flags & EW_SILENT))
5232 #endif
5234 redraw_later_clear(); /* probably messed up screen */
5235 msg_putchar('\n'); /* clear bottom line quickly */
5236 cmdline_row = Rows - 1; /* continue on last line */
5237 #ifdef USE_SYSTEM
5238 if (!(flags & EW_SILENT))
5239 #endif
5241 MSG(_(e_wildexpand));
5242 msg_start(); /* don't overwrite this message */
5245 /* If a `cmd` expansion failed, don't list `cmd` as a match, even when
5246 * EW_NOTFOUND is given */
5247 if (shell_style == STYLE_BT)
5248 return FAIL;
5249 goto notfound;
5253 * read the names from the file into memory
5255 fd = fopen((char *)tempname, READBIN);
5256 if (fd == NULL)
5258 /* Something went wrong, perhaps a file name with a special char. */
5259 if (!(flags & EW_SILENT))
5261 MSG(_(e_wildexpand));
5262 msg_start(); /* don't overwrite this message */
5264 vim_free(tempname);
5265 goto notfound;
5267 fseek(fd, 0L, SEEK_END);
5268 len = ftell(fd); /* get size of temp file */
5269 fseek(fd, 0L, SEEK_SET);
5270 buffer = alloc(len + 1);
5271 if (buffer == NULL)
5273 /* out of memory */
5274 mch_remove(tempname);
5275 vim_free(tempname);
5276 fclose(fd);
5277 return FAIL;
5279 i = fread((char *)buffer, 1, len, fd);
5280 fclose(fd);
5281 mch_remove(tempname);
5282 if (i != len)
5284 /* unexpected read error */
5285 EMSG2(_(e_notread), tempname);
5286 vim_free(tempname);
5287 vim_free(buffer);
5288 return FAIL;
5290 vim_free(tempname);
5292 #if defined(__CYGWIN__) || defined(__CYGWIN32__)
5293 /* Translate <CR><NL> into <NL>. Caution, buffer may contain NUL. */
5294 p = buffer;
5295 for (i = 0; i < len; ++i)
5296 if (!(buffer[i] == CAR && buffer[i + 1] == NL))
5297 *p++ = buffer[i];
5298 len = p - buffer;
5299 # endif
5302 /* file names are separated with Space */
5303 if (shell_style == STYLE_ECHO)
5305 buffer[len] = '\n'; /* make sure the buffer ends in NL */
5306 p = buffer;
5307 for (i = 0; *p != '\n'; ++i) /* count number of entries */
5309 while (*p != ' ' && *p != '\n')
5310 ++p;
5311 p = skipwhite(p); /* skip to next entry */
5314 /* file names are separated with NL */
5315 else if (shell_style == STYLE_BT)
5317 buffer[len] = NUL; /* make sure the buffer ends in NUL */
5318 p = buffer;
5319 for (i = 0; *p != NUL; ++i) /* count number of entries */
5321 while (*p != '\n' && *p != NUL)
5322 ++p;
5323 if (*p != NUL)
5324 ++p;
5325 p = skipwhite(p); /* skip leading white space */
5328 /* file names are separated with NUL */
5329 else
5332 * Some versions of zsh use spaces instead of NULs to separate
5333 * results. Only do this when there is no NUL before the end of the
5334 * buffer, otherwise we would never be able to use file names with
5335 * embedded spaces when zsh does use NULs.
5336 * When we found a NUL once, we know zsh is OK, set did_find_nul and
5337 * don't check for spaces again.
5339 check_spaces = FALSE;
5340 if (shell_style == STYLE_PRINT && !did_find_nul)
5342 /* If there is a NUL, set did_find_nul, else set check_spaces */
5343 if (len && (int)STRLEN(buffer) < len - 1)
5344 did_find_nul = TRUE;
5345 else
5346 check_spaces = TRUE;
5350 * Make sure the buffer ends with a NUL. For STYLE_PRINT there
5351 * already is one, for STYLE_GLOB it needs to be added.
5353 if (len && buffer[len - 1] == NUL)
5354 --len;
5355 else
5356 buffer[len] = NUL;
5357 i = 0;
5358 for (p = buffer; p < buffer + len; ++p)
5359 if (*p == NUL || (*p == ' ' && check_spaces)) /* count entry */
5361 ++i;
5362 *p = NUL;
5364 if (len)
5365 ++i; /* count last entry */
5367 if (i == 0)
5370 * Can happen when using /bin/sh and typing ":e $NO_SUCH_VAR^I".
5371 * /bin/sh will happily expand it to nothing rather than returning an
5372 * error; and hey, it's good to check anyway -- webb.
5374 vim_free(buffer);
5375 goto notfound;
5377 *num_file = i;
5378 *file = (char_u **)alloc(sizeof(char_u *) * i);
5379 if (*file == NULL)
5381 /* out of memory */
5382 vim_free(buffer);
5383 return FAIL;
5387 * Isolate the individual file names.
5389 p = buffer;
5390 for (i = 0; i < *num_file; ++i)
5392 (*file)[i] = p;
5393 /* Space or NL separates */
5394 if (shell_style == STYLE_ECHO || shell_style == STYLE_BT)
5396 while (!(shell_style == STYLE_ECHO && *p == ' ')
5397 && *p != '\n' && *p != NUL)
5398 ++p;
5399 if (p == buffer + len) /* last entry */
5400 *p = NUL;
5401 else
5403 *p++ = NUL;
5404 p = skipwhite(p); /* skip to next entry */
5407 else /* NUL separates */
5409 while (*p && p < buffer + len) /* skip entry */
5410 ++p;
5411 ++p; /* skip NUL */
5416 * Move the file names to allocated memory.
5418 for (j = 0, i = 0; i < *num_file; ++i)
5420 /* Require the files to exist. Helps when using /bin/sh */
5421 if (!(flags & EW_NOTFOUND) && mch_getperm((*file)[i]) < 0)
5422 continue;
5424 /* check if this entry should be included */
5425 dir = (mch_isdir((*file)[i]));
5426 if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE)))
5427 continue;
5429 /* Skip files that are not executable if we check for that. */
5430 if (!dir && (flags & EW_EXEC) && !mch_can_exe((*file)[i]))
5431 continue;
5433 p = alloc((unsigned)(STRLEN((*file)[i]) + 1 + dir));
5434 if (p)
5436 STRCPY(p, (*file)[i]);
5437 if (dir)
5438 STRCAT(p, "/"); /* add '/' to a directory name */
5439 (*file)[j++] = p;
5442 vim_free(buffer);
5443 *num_file = j;
5445 if (*num_file == 0) /* rejected all entries */
5447 vim_free(*file);
5448 *file = NULL;
5449 goto notfound;
5452 return OK;
5454 notfound:
5455 if (flags & EW_NOTFOUND)
5456 return save_patterns(num_pat, pat, num_file, file);
5457 return FAIL;
5459 #endif /* __EMX__ */
5462 #endif /* VMS */
5464 #ifndef __EMX__
5465 static int
5466 save_patterns(num_pat, pat, num_file, file)
5467 int num_pat;
5468 char_u **pat;
5469 int *num_file;
5470 char_u ***file;
5472 int i;
5473 char_u *s;
5475 *file = (char_u **)alloc(num_pat * sizeof(char_u *));
5476 if (*file == NULL)
5477 return FAIL;
5478 for (i = 0; i < num_pat; i++)
5480 s = vim_strsave(pat[i]);
5481 if (s != NULL)
5482 /* Be compatible with expand_filename(): halve the number of
5483 * backslashes. */
5484 backslash_halve(s);
5485 (*file)[i] = s;
5487 *num_file = num_pat;
5488 return OK;
5490 #endif
5494 * Return TRUE if the string "p" contains a wildcard that mch_expandpath() can
5495 * expand.
5498 mch_has_exp_wildcard(p)
5499 char_u *p;
5501 for ( ; *p; mb_ptr_adv(p))
5503 #ifndef OS2
5504 if (*p == '\\' && p[1] != NUL)
5505 ++p;
5506 else
5507 #endif
5508 if (vim_strchr((char_u *)
5509 #ifdef VMS
5510 "*?%"
5511 #else
5512 # ifdef OS2
5513 "*?"
5514 # else
5515 "*?[{'"
5516 # endif
5517 #endif
5518 , *p) != NULL)
5519 return TRUE;
5521 return FALSE;
5525 * Return TRUE if the string "p" contains a wildcard.
5526 * Don't recognize '~' at the end as a wildcard.
5529 mch_has_wildcard(p)
5530 char_u *p;
5532 for ( ; *p; mb_ptr_adv(p))
5534 #ifndef OS2
5535 if (*p == '\\' && p[1] != NUL)
5536 ++p;
5537 else
5538 #endif
5539 if (vim_strchr((char_u *)
5540 #ifdef VMS
5541 "*?%$"
5542 #else
5543 # ifdef OS2
5544 # ifdef VIM_BACKTICK
5545 "*?$`"
5546 # else
5547 "*?$"
5548 # endif
5549 # else
5550 "*?[{`'$"
5551 # endif
5552 #endif
5553 , *p) != NULL
5554 || (*p == '~' && p[1] != NUL))
5555 return TRUE;
5557 return FALSE;
5560 #ifndef __EMX__
5561 static int
5562 have_wildcard(num, file)
5563 int num;
5564 char_u **file;
5566 int i;
5568 for (i = 0; i < num; i++)
5569 if (mch_has_wildcard(file[i]))
5570 return 1;
5571 return 0;
5574 static int
5575 have_dollars(num, file)
5576 int num;
5577 char_u **file;
5579 int i;
5581 for (i = 0; i < num; i++)
5582 if (vim_strchr(file[i], '$') != NULL)
5583 return TRUE;
5584 return FALSE;
5586 #endif /* ifndef __EMX__ */
5588 #ifndef HAVE_RENAME
5590 * Scaled-down version of rename(), which is missing in Xenix.
5591 * This version can only move regular files and will fail if the
5592 * destination exists.
5595 mch_rename(src, dest)
5596 const char *src, *dest;
5598 struct stat st;
5600 if (stat(dest, &st) >= 0) /* fail if destination exists */
5601 return -1;
5602 if (link(src, dest) != 0) /* link file to new name */
5603 return -1;
5604 if (mch_remove(src) == 0) /* delete link to old name */
5605 return 0;
5606 return -1;
5608 #endif /* !HAVE_RENAME */
5610 #ifdef FEAT_MOUSE_GPM
5612 * Initializes connection with gpm (if it isn't already opened)
5613 * Return 1 if succeeded (or connection already opened), 0 if failed
5615 static int
5616 gpm_open()
5618 static Gpm_Connect gpm_connect; /* Must it be kept till closing ? */
5620 if (!gpm_flag)
5622 gpm_connect.eventMask = (GPM_UP | GPM_DRAG | GPM_DOWN);
5623 gpm_connect.defaultMask = ~GPM_HARD;
5624 /* Default handling for mouse move*/
5625 gpm_connect.minMod = 0; /* Handle any modifier keys */
5626 gpm_connect.maxMod = 0xffff;
5627 if (Gpm_Open(&gpm_connect, 0) > 0)
5629 /* gpm library tries to handling TSTP causes
5630 * problems. Anyways, we close connection to Gpm whenever
5631 * we are going to suspend or starting an external process
5632 * so we should'nt have problem with this
5634 signal(SIGTSTP, restricted ? SIG_IGN : SIG_DFL);
5635 return 1; /* succeed */
5637 if (gpm_fd == -2)
5638 Gpm_Close(); /* We don't want to talk to xterm via gpm */
5639 return 0;
5641 return 1; /* already open */
5645 * Closes connection to gpm
5646 * returns non-zero if connection succesfully closed
5648 static void
5649 gpm_close()
5651 if (gpm_flag && gpm_fd >= 0) /* if Open */
5652 Gpm_Close();
5655 /* Reads gpm event and adds special keys to input buf. Returns length of
5656 * generated key sequence.
5657 * This function is made after gui_send_mouse_event
5659 static int
5660 mch_gpm_process()
5662 int button;
5663 static Gpm_Event gpm_event;
5664 char_u string[6];
5665 int_u vim_modifiers;
5666 int row,col;
5667 unsigned char buttons_mask;
5668 unsigned char gpm_modifiers;
5669 static unsigned char old_buttons = 0;
5671 Gpm_GetEvent(&gpm_event);
5673 #ifdef FEAT_GUI
5674 /* Don't put events in the input queue now. */
5675 if (hold_gui_events)
5676 return 0;
5677 #endif
5679 row = gpm_event.y - 1;
5680 col = gpm_event.x - 1;
5682 string[0] = ESC; /* Our termcode */
5683 string[1] = 'M';
5684 string[2] = 'G';
5685 switch (GPM_BARE_EVENTS(gpm_event.type))
5687 case GPM_DRAG:
5688 string[3] = MOUSE_DRAG;
5689 break;
5690 case GPM_DOWN:
5691 buttons_mask = gpm_event.buttons & ~old_buttons;
5692 old_buttons = gpm_event.buttons;
5693 switch (buttons_mask)
5695 case GPM_B_LEFT:
5696 button = MOUSE_LEFT;
5697 break;
5698 case GPM_B_MIDDLE:
5699 button = MOUSE_MIDDLE;
5700 break;
5701 case GPM_B_RIGHT:
5702 button = MOUSE_RIGHT;
5703 break;
5704 default:
5705 return 0;
5706 /*Don't know what to do. Can more than one button be
5707 * reported in one event? */
5709 string[3] = (char_u)(button | 0x20);
5710 SET_NUM_MOUSE_CLICKS(string[3], gpm_event.clicks + 1);
5711 break;
5712 case GPM_UP:
5713 string[3] = MOUSE_RELEASE;
5714 old_buttons &= ~gpm_event.buttons;
5715 break;
5716 default:
5717 return 0;
5719 /*This code is based on gui_x11_mouse_cb in gui_x11.c */
5720 gpm_modifiers = gpm_event.modifiers;
5721 vim_modifiers = 0x0;
5722 /* I ignore capslock stats. Aren't we all just hate capslock mixing with
5723 * Vim commands ? Besides, gpm_event.modifiers is unsigned char, and
5724 * K_CAPSSHIFT is defined 8, so it probably isn't even reported
5726 if (gpm_modifiers & ((1 << KG_SHIFT) | (1 << KG_SHIFTR) | (1 << KG_SHIFTL)))
5727 vim_modifiers |= MOUSE_SHIFT;
5729 if (gpm_modifiers & ((1 << KG_CTRL) | (1 << KG_CTRLR) | (1 << KG_CTRLL)))
5730 vim_modifiers |= MOUSE_CTRL;
5731 if (gpm_modifiers & ((1 << KG_ALT) | (1 << KG_ALTGR)))
5732 vim_modifiers |= MOUSE_ALT;
5733 string[3] |= vim_modifiers;
5734 string[4] = (char_u)(col + ' ' + 1);
5735 string[5] = (char_u)(row + ' ' + 1);
5736 add_to_input_buf(string, 6);
5737 return 6;
5739 #endif /* FEAT_MOUSE_GPM */
5741 #if defined(FEAT_LIBCALL) || defined(PROTO)
5742 typedef char_u * (*STRPROCSTR)__ARGS((char_u *));
5743 typedef char_u * (*INTPROCSTR)__ARGS((int));
5744 typedef int (*STRPROCINT)__ARGS((char_u *));
5745 typedef int (*INTPROCINT)__ARGS((int));
5748 * Call a DLL routine which takes either a string or int param
5749 * and returns an allocated string.
5752 mch_libcall(libname, funcname, argstring, argint, string_result, number_result)
5753 char_u *libname;
5754 char_u *funcname;
5755 char_u *argstring; /* NULL when using a argint */
5756 int argint;
5757 char_u **string_result;/* NULL when using number_result */
5758 int *number_result;
5760 # if defined(USE_DLOPEN)
5761 void *hinstLib;
5762 char *dlerr = NULL;
5763 # else
5764 shl_t hinstLib;
5765 # endif
5766 STRPROCSTR ProcAdd;
5767 INTPROCSTR ProcAddI;
5768 char_u *retval_str = NULL;
5769 int retval_int = 0;
5770 int success = FALSE;
5773 * Get a handle to the DLL module.
5775 # if defined(USE_DLOPEN)
5776 /* First clear any error, it's not cleared by the dlopen() call. */
5777 (void)dlerror();
5779 hinstLib = dlopen((char *)libname, RTLD_LAZY
5780 # ifdef RTLD_LOCAL
5781 | RTLD_LOCAL
5782 # endif
5784 if (hinstLib == NULL)
5786 /* "dlerr" must be used before dlclose() */
5787 dlerr = (char *)dlerror();
5788 if (dlerr != NULL)
5789 EMSG2(_("dlerror = \"%s\""), dlerr);
5791 # else
5792 hinstLib = shl_load((const char*)libname, BIND_IMMEDIATE|BIND_VERBOSE, 0L);
5793 # endif
5795 /* If the handle is valid, try to get the function address. */
5796 if (hinstLib != NULL)
5798 # ifdef HAVE_SETJMP_H
5800 * Catch a crash when calling the library function. For example when
5801 * using a number where a string pointer is expected.
5803 mch_startjmp();
5804 if (SETJMP(lc_jump_env) != 0)
5806 success = FALSE;
5807 # if defined(USE_DLOPEN)
5808 dlerr = NULL;
5809 # endif
5810 mch_didjmp();
5812 else
5813 # endif
5815 retval_str = NULL;
5816 retval_int = 0;
5818 if (argstring != NULL)
5820 # if defined(USE_DLOPEN)
5821 ProcAdd = (STRPROCSTR)dlsym(hinstLib, (const char *)funcname);
5822 dlerr = (char *)dlerror();
5823 # else
5824 if (shl_findsym(&hinstLib, (const char *)funcname,
5825 TYPE_PROCEDURE, (void *)&ProcAdd) < 0)
5826 ProcAdd = NULL;
5827 # endif
5828 if ((success = (ProcAdd != NULL
5829 # if defined(USE_DLOPEN)
5830 && dlerr == NULL
5831 # endif
5834 if (string_result == NULL)
5835 retval_int = ((STRPROCINT)ProcAdd)(argstring);
5836 else
5837 retval_str = (ProcAdd)(argstring);
5840 else
5842 # if defined(USE_DLOPEN)
5843 ProcAddI = (INTPROCSTR)dlsym(hinstLib, (const char *)funcname);
5844 dlerr = (char *)dlerror();
5845 # else
5846 if (shl_findsym(&hinstLib, (const char *)funcname,
5847 TYPE_PROCEDURE, (void *)&ProcAddI) < 0)
5848 ProcAddI = NULL;
5849 # endif
5850 if ((success = (ProcAddI != NULL
5851 # if defined(USE_DLOPEN)
5852 && dlerr == NULL
5853 # endif
5856 if (string_result == NULL)
5857 retval_int = ((INTPROCINT)ProcAddI)(argint);
5858 else
5859 retval_str = (ProcAddI)(argint);
5863 /* Save the string before we free the library. */
5864 /* Assume that a "1" or "-1" result is an illegal pointer. */
5865 if (string_result == NULL)
5866 *number_result = retval_int;
5867 else if (retval_str != NULL
5868 && retval_str != (char_u *)1
5869 && retval_str != (char_u *)-1)
5870 *string_result = vim_strsave(retval_str);
5873 # ifdef HAVE_SETJMP_H
5874 mch_endjmp();
5875 # ifdef SIGHASARG
5876 if (lc_signal != 0)
5878 int i;
5880 /* try to find the name of this signal */
5881 for (i = 0; signal_info[i].sig != -1; i++)
5882 if (lc_signal == signal_info[i].sig)
5883 break;
5884 EMSG2("E368: got SIG%s in libcall()", signal_info[i].name);
5886 # endif
5887 # endif
5889 # if defined(USE_DLOPEN)
5890 /* "dlerr" must be used before dlclose() */
5891 if (dlerr != NULL)
5892 EMSG2(_("dlerror = \"%s\""), dlerr);
5894 /* Free the DLL module. */
5895 (void)dlclose(hinstLib);
5896 # else
5897 (void)shl_unload(hinstLib);
5898 # endif
5901 if (!success)
5903 EMSG2(_(e_libcall), funcname);
5904 return FAIL;
5907 return OK;
5909 #endif
5911 #if (defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)) || defined(PROTO)
5912 static int xterm_trace = -1; /* default: disabled */
5913 static int xterm_button;
5916 * Setup a dummy window for X selections in a terminal.
5918 void
5919 setup_term_clip()
5921 int z = 0;
5922 char *strp = "";
5923 Widget AppShell;
5925 if (!x_connect_to_server())
5926 return;
5928 open_app_context();
5929 if (app_context != NULL && xterm_Shell == (Widget)0)
5931 int (*oldhandler)();
5932 #if defined(HAVE_SETJMP_H)
5933 int (*oldIOhandler)();
5934 #endif
5935 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
5936 struct timeval start_tv;
5938 if (p_verbose > 0)
5939 gettimeofday(&start_tv, NULL);
5940 # endif
5942 /* Ignore X errors while opening the display */
5943 oldhandler = XSetErrorHandler(x_error_check);
5945 #if defined(HAVE_SETJMP_H)
5946 /* Ignore X IO errors while opening the display */
5947 oldIOhandler = XSetIOErrorHandler(x_IOerror_check);
5948 mch_startjmp();
5949 if (SETJMP(lc_jump_env) != 0)
5951 mch_didjmp();
5952 xterm_dpy = NULL;
5954 else
5955 #endif
5957 xterm_dpy = XtOpenDisplay(app_context, xterm_display,
5958 "vim_xterm", "Vim_xterm", NULL, 0, &z, &strp);
5959 #if defined(HAVE_SETJMP_H)
5960 mch_endjmp();
5961 #endif
5964 #if defined(HAVE_SETJMP_H)
5965 /* Now handle X IO errors normally. */
5966 (void)XSetIOErrorHandler(oldIOhandler);
5967 #endif
5968 /* Now handle X errors normally. */
5969 (void)XSetErrorHandler(oldhandler);
5971 if (xterm_dpy == NULL)
5973 if (p_verbose > 0)
5974 verb_msg((char_u *)_("Opening the X display failed"));
5975 return;
5978 /* Catch terminating error of the X server connection. */
5979 (void)XSetIOErrorHandler(x_IOerror_handler);
5981 # if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_SYS_TIME_H)
5982 if (p_verbose > 0)
5984 verbose_enter();
5985 xopen_message(&start_tv);
5986 verbose_leave();
5988 # endif
5990 /* Create a Shell to make converters work. */
5991 AppShell = XtVaAppCreateShell("vim_xterm", "Vim_xterm",
5992 applicationShellWidgetClass, xterm_dpy,
5993 NULL);
5994 if (AppShell == (Widget)0)
5995 return;
5996 xterm_Shell = XtVaCreatePopupShell("VIM",
5997 topLevelShellWidgetClass, AppShell,
5998 XtNmappedWhenManaged, 0,
5999 XtNwidth, 1,
6000 XtNheight, 1,
6001 NULL);
6002 if (xterm_Shell == (Widget)0)
6003 return;
6005 x11_setup_atoms(xterm_dpy);
6006 if (x11_display == NULL)
6007 x11_display = xterm_dpy;
6009 XtRealizeWidget(xterm_Shell);
6010 XSync(xterm_dpy, False);
6011 xterm_update();
6013 if (xterm_Shell != (Widget)0)
6015 clip_init(TRUE);
6016 if (x11_window == 0 && (strp = getenv("WINDOWID")) != NULL)
6017 x11_window = (Window)atol(strp);
6018 /* Check if $WINDOWID is valid. */
6019 if (test_x11_window(xterm_dpy) == FAIL)
6020 x11_window = 0;
6021 if (x11_window != 0)
6022 xterm_trace = 0;
6026 void
6027 start_xterm_trace(button)
6028 int button;
6030 if (x11_window == 0 || xterm_trace < 0 || xterm_Shell == (Widget)0)
6031 return;
6032 xterm_trace = 1;
6033 xterm_button = button;
6034 do_xterm_trace();
6038 void
6039 stop_xterm_trace()
6041 if (xterm_trace < 0)
6042 return;
6043 xterm_trace = 0;
6047 * Query the xterm pointer and generate mouse termcodes if necessary
6048 * return TRUE if dragging is active, else FALSE
6050 static int
6051 do_xterm_trace()
6053 Window root, child;
6054 int root_x, root_y;
6055 int win_x, win_y;
6056 int row, col;
6057 int_u mask_return;
6058 char_u buf[50];
6059 char_u *strp;
6060 long got_hints;
6061 static char_u *mouse_code;
6062 static char_u mouse_name[2] = {KS_MOUSE, KE_FILLER};
6063 static int prev_row = 0, prev_col = 0;
6064 static XSizeHints xterm_hints;
6066 if (xterm_trace <= 0)
6067 return FALSE;
6069 if (xterm_trace == 1)
6071 /* Get the hints just before tracking starts. The font size might
6072 * have changed recently */
6073 XGetWMNormalHints(xterm_dpy, x11_window, &xterm_hints, &got_hints);
6074 if (!(got_hints & PResizeInc)
6075 || xterm_hints.width_inc <= 1
6076 || xterm_hints.height_inc <= 1)
6078 xterm_trace = -1; /* Not enough data -- disable tracing */
6079 return FALSE;
6082 /* Rely on the same mouse code for the duration of this */
6083 mouse_code = find_termcode(mouse_name);
6084 prev_row = mouse_row;
6085 prev_row = mouse_col;
6086 xterm_trace = 2;
6088 /* Find the offset of the chars, there might be a scrollbar on the
6089 * left of the window and/or a menu on the top (eterm etc.) */
6090 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
6091 &win_x, &win_y, &mask_return);
6092 xterm_hints.y = win_y - (xterm_hints.height_inc * mouse_row)
6093 - (xterm_hints.height_inc / 2);
6094 if (xterm_hints.y <= xterm_hints.height_inc / 2)
6095 xterm_hints.y = 2;
6096 xterm_hints.x = win_x - (xterm_hints.width_inc * mouse_col)
6097 - (xterm_hints.width_inc / 2);
6098 if (xterm_hints.x <= xterm_hints.width_inc / 2)
6099 xterm_hints.x = 2;
6100 return TRUE;
6102 if (mouse_code == NULL)
6104 xterm_trace = 0;
6105 return FALSE;
6108 XQueryPointer(xterm_dpy, x11_window, &root, &child, &root_x, &root_y,
6109 &win_x, &win_y, &mask_return);
6111 row = check_row((win_y - xterm_hints.y) / xterm_hints.height_inc);
6112 col = check_col((win_x - xterm_hints.x) / xterm_hints.width_inc);
6113 if (row == prev_row && col == prev_col)
6114 return TRUE;
6116 STRCPY(buf, mouse_code);
6117 strp = buf + STRLEN(buf);
6118 *strp++ = (xterm_button | MOUSE_DRAG) & ~0x20;
6119 *strp++ = (char_u)(col + ' ' + 1);
6120 *strp++ = (char_u)(row + ' ' + 1);
6121 *strp = 0;
6122 add_to_input_buf(buf, STRLEN(buf));
6124 prev_row = row;
6125 prev_col = col;
6126 return TRUE;
6129 # if defined(FEAT_GUI) || defined(PROTO)
6131 * Destroy the display, window and app_context. Required for GTK.
6133 void
6134 clear_xterm_clip()
6136 if (xterm_Shell != (Widget)0)
6138 XtDestroyWidget(xterm_Shell);
6139 xterm_Shell = (Widget)0;
6141 if (xterm_dpy != NULL)
6143 #if 0
6144 /* Lesstif and Solaris crash here, lose some memory */
6145 XtCloseDisplay(xterm_dpy);
6146 #endif
6147 if (x11_display == xterm_dpy)
6148 x11_display = NULL;
6149 xterm_dpy = NULL;
6151 #if 0
6152 if (app_context != (XtAppContext)NULL)
6154 /* Lesstif and Solaris crash here, lose some memory */
6155 XtDestroyApplicationContext(app_context);
6156 app_context = (XtAppContext)NULL;
6158 #endif
6160 # endif
6163 * Catch up with any queued X events. This may put keyboard input into the
6164 * input buffer, call resize call-backs, trigger timers etc. If there is
6165 * nothing in the X event queue (& no timers pending), then we return
6166 * immediately.
6168 static void
6169 xterm_update()
6171 XEvent event;
6173 while (XtAppPending(app_context) && !vim_is_input_buf_full())
6175 XtAppNextEvent(app_context, &event);
6176 #ifdef FEAT_CLIENTSERVER
6178 XPropertyEvent *e = (XPropertyEvent *)&event;
6180 if (e->type == PropertyNotify && e->window == commWindow
6181 && e->atom == commProperty && e->state == PropertyNewValue)
6182 serverEventProc(xterm_dpy, &event);
6184 #endif
6185 XtDispatchEvent(&event);
6190 clip_xterm_own_selection(cbd)
6191 VimClipboard *cbd;
6193 if (xterm_Shell != (Widget)0)
6194 return clip_x11_own_selection(xterm_Shell, cbd);
6195 return FAIL;
6198 void
6199 clip_xterm_lose_selection(cbd)
6200 VimClipboard *cbd;
6202 if (xterm_Shell != (Widget)0)
6203 clip_x11_lose_selection(xterm_Shell, cbd);
6206 void
6207 clip_xterm_request_selection(cbd)
6208 VimClipboard *cbd;
6210 if (xterm_Shell != (Widget)0)
6211 clip_x11_request_selection(xterm_Shell, xterm_dpy, cbd);
6214 void
6215 clip_xterm_set_selection(cbd)
6216 VimClipboard *cbd;
6218 clip_x11_set_selection(cbd);
6220 #endif
6223 #if defined(USE_XSMP) || defined(PROTO)
6225 * Code for X Session Management Protocol.
6227 static void xsmp_handle_save_yourself __ARGS((SmcConn smc_conn, SmPointer client_data, int save_type, Bool shutdown, int interact_style, Bool fast));
6228 static void xsmp_die __ARGS((SmcConn smc_conn, SmPointer client_data));
6229 static void xsmp_save_complete __ARGS((SmcConn smc_conn, SmPointer client_data));
6230 static void xsmp_shutdown_cancelled __ARGS((SmcConn smc_conn, SmPointer client_data));
6231 static void xsmp_ice_connection __ARGS((IceConn iceConn, IcePointer clientData, Bool opening, IcePointer *watchData));
6234 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6235 static void xsmp_handle_interaction __ARGS((SmcConn smc_conn, SmPointer client_data));
6238 * This is our chance to ask the user if they want to save,
6239 * or abort the logout
6241 /*ARGSUSED*/
6242 static void
6243 xsmp_handle_interaction(smc_conn, client_data)
6244 SmcConn smc_conn;
6245 SmPointer client_data;
6247 cmdmod_T save_cmdmod;
6248 int cancel_shutdown = False;
6250 save_cmdmod = cmdmod;
6251 cmdmod.confirm = TRUE;
6252 if (check_changed_any(FALSE))
6253 /* Mustn't logout */
6254 cancel_shutdown = True;
6255 cmdmod = save_cmdmod;
6256 setcursor(); /* position cursor */
6257 out_flush();
6259 /* Done interaction */
6260 SmcInteractDone(smc_conn, cancel_shutdown);
6262 /* Finish off
6263 * Only end save-yourself here if we're not cancelling shutdown;
6264 * we'll get a cancelled callback later in which we'll end it.
6265 * Hopefully get around glitchy SMs (like GNOME-1)
6267 if (!cancel_shutdown)
6269 xsmp.save_yourself = False;
6270 SmcSaveYourselfDone(smc_conn, True);
6273 # endif
6276 * Callback that starts save-yourself.
6278 /*ARGSUSED*/
6279 static void
6280 xsmp_handle_save_yourself(smc_conn, client_data, save_type,
6281 shutdown, interact_style, fast)
6282 SmcConn smc_conn;
6283 SmPointer client_data;
6284 int save_type;
6285 Bool shutdown;
6286 int interact_style;
6287 Bool fast;
6289 /* Handle already being in saveyourself */
6290 if (xsmp.save_yourself)
6291 SmcSaveYourselfDone(smc_conn, True);
6292 xsmp.save_yourself = True;
6293 xsmp.shutdown = shutdown;
6295 /* First up, preserve all files */
6296 out_flush();
6297 ml_sync_all(FALSE, FALSE); /* preserve all swap files */
6299 if (p_verbose > 0)
6300 verb_msg((char_u *)_("XSMP handling save-yourself request"));
6302 # if defined(FEAT_GUI) && defined(USE_XSMP_INTERACT)
6303 /* Now see if we can ask about unsaved files */
6304 if (shutdown && !fast && gui.in_use)
6305 /* Need to interact with user, but need SM's permission */
6306 SmcInteractRequest(smc_conn, SmDialogError,
6307 xsmp_handle_interaction, client_data);
6308 else
6309 # endif
6311 /* Can stop the cycle here */
6312 SmcSaveYourselfDone(smc_conn, True);
6313 xsmp.save_yourself = False;
6319 * Callback to warn us of imminent death.
6321 /*ARGSUSED*/
6322 static void
6323 xsmp_die(smc_conn, client_data)
6324 SmcConn smc_conn;
6325 SmPointer client_data;
6327 xsmp_close();
6329 /* quit quickly leaving swapfiles for modified buffers behind */
6330 getout_preserve_modified(0);
6335 * Callback to tell us that save-yourself has completed.
6337 /*ARGSUSED*/
6338 static void
6339 xsmp_save_complete(smc_conn, client_data)
6340 SmcConn smc_conn;
6341 SmPointer client_data;
6343 xsmp.save_yourself = False;
6348 * Callback to tell us that an instigated shutdown was cancelled
6349 * (maybe even by us)
6351 /*ARGSUSED*/
6352 static void
6353 xsmp_shutdown_cancelled(smc_conn, client_data)
6354 SmcConn smc_conn;
6355 SmPointer client_data;
6357 if (xsmp.save_yourself)
6358 SmcSaveYourselfDone(smc_conn, True);
6359 xsmp.save_yourself = False;
6360 xsmp.shutdown = False;
6365 * Callback to tell us that a new ICE connection has been established.
6367 /*ARGSUSED*/
6368 static void
6369 xsmp_ice_connection(iceConn, clientData, opening, watchData)
6370 IceConn iceConn;
6371 IcePointer clientData;
6372 Bool opening;
6373 IcePointer *watchData;
6375 /* Intercept creation of ICE connection fd */
6376 if (opening)
6378 xsmp_icefd = IceConnectionNumber(iceConn);
6379 IceRemoveConnectionWatch(xsmp_ice_connection, NULL);
6384 /* Handle any ICE processing that's required; return FAIL if SM lost */
6386 xsmp_handle_requests()
6388 Bool rep;
6390 if (IceProcessMessages(xsmp.iceconn, NULL, &rep)
6391 == IceProcessMessagesIOError)
6393 /* Lost ICE */
6394 if (p_verbose > 0)
6395 verb_msg((char_u *)_("XSMP lost ICE connection"));
6396 xsmp_close();
6397 return FAIL;
6399 else
6400 return OK;
6403 static int dummy;
6405 /* Set up X Session Management Protocol */
6406 void
6407 xsmp_init(void)
6409 char errorstring[80];
6410 char *clientid;
6411 SmcCallbacks smcallbacks;
6412 #if 0
6413 SmPropValue smname;
6414 SmProp smnameprop;
6415 SmProp *smprops[1];
6416 #endif
6418 if (p_verbose > 0)
6419 verb_msg((char_u *)_("XSMP opening connection"));
6421 xsmp.save_yourself = xsmp.shutdown = False;
6423 /* Set up SM callbacks - must have all, even if they're not used */
6424 smcallbacks.save_yourself.callback = xsmp_handle_save_yourself;
6425 smcallbacks.save_yourself.client_data = NULL;
6426 smcallbacks.die.callback = xsmp_die;
6427 smcallbacks.die.client_data = NULL;
6428 smcallbacks.save_complete.callback = xsmp_save_complete;
6429 smcallbacks.save_complete.client_data = NULL;
6430 smcallbacks.shutdown_cancelled.callback = xsmp_shutdown_cancelled;
6431 smcallbacks.shutdown_cancelled.client_data = NULL;
6433 /* Set up a watch on ICE connection creations. The "dummy" argument is
6434 * apparently required for FreeBSD (we get a BUS error when using NULL). */
6435 if (IceAddConnectionWatch(xsmp_ice_connection, &dummy) == 0)
6437 if (p_verbose > 0)
6438 verb_msg((char_u *)_("XSMP ICE connection watch failed"));
6439 return;
6442 /* Create an SM connection */
6443 xsmp.smcconn = SmcOpenConnection(
6444 NULL,
6445 NULL,
6446 SmProtoMajor,
6447 SmProtoMinor,
6448 SmcSaveYourselfProcMask | SmcDieProcMask
6449 | SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask,
6450 &smcallbacks,
6451 NULL,
6452 &clientid,
6453 sizeof(errorstring),
6454 errorstring);
6455 if (xsmp.smcconn == NULL)
6457 char errorreport[132];
6459 if (p_verbose > 0)
6461 vim_snprintf(errorreport, sizeof(errorreport),
6462 _("XSMP SmcOpenConnection failed: %s"), errorstring);
6463 verb_msg((char_u *)errorreport);
6465 return;
6467 xsmp.iceconn = SmcGetIceConnection(xsmp.smcconn);
6469 #if 0
6470 /* ID ourselves */
6471 smname.value = "vim";
6472 smname.length = 3;
6473 smnameprop.name = "SmProgram";
6474 smnameprop.type = "SmARRAY8";
6475 smnameprop.num_vals = 1;
6476 smnameprop.vals = &smname;
6478 smprops[0] = &smnameprop;
6479 SmcSetProperties(xsmp.smcconn, 1, smprops);
6480 #endif
6484 /* Shut down XSMP comms. */
6485 void
6486 xsmp_close()
6488 if (xsmp_icefd != -1)
6490 SmcCloseConnection(xsmp.smcconn, 0, NULL);
6491 xsmp_icefd = -1;
6494 #endif /* USE_XSMP */
6497 #ifdef EBCDIC
6498 /* Translate character to its CTRL- value */
6499 char CtrlTable[] =
6501 /* 00 - 5E */
6502 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6503 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6504 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6505 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6506 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6507 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6508 /* ^ */ 0x1E,
6509 /* - */ 0x1F,
6510 /* 61 - 6C */
6511 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6512 /* _ */ 0x1F,
6513 /* 6E - 80 */
6514 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6515 /* a */ 0x01,
6516 /* b */ 0x02,
6517 /* c */ 0x03,
6518 /* d */ 0x37,
6519 /* e */ 0x2D,
6520 /* f */ 0x2E,
6521 /* g */ 0x2F,
6522 /* h */ 0x16,
6523 /* i */ 0x05,
6524 /* 8A - 90 */
6525 0, 0, 0, 0, 0, 0, 0,
6526 /* j */ 0x15,
6527 /* k */ 0x0B,
6528 /* l */ 0x0C,
6529 /* m */ 0x0D,
6530 /* n */ 0x0E,
6531 /* o */ 0x0F,
6532 /* p */ 0x10,
6533 /* q */ 0x11,
6534 /* r */ 0x12,
6535 /* 9A - A1 */
6536 0, 0, 0, 0, 0, 0, 0, 0,
6537 /* s */ 0x13,
6538 /* t */ 0x3C,
6539 /* u */ 0x3D,
6540 /* v */ 0x32,
6541 /* w */ 0x26,
6542 /* x */ 0x18,
6543 /* y */ 0x19,
6544 /* z */ 0x3F,
6545 /* AA - AC */
6546 0, 0, 0,
6547 /* [ */ 0x27,
6548 /* AE - BC */
6549 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6550 /* ] */ 0x1D,
6551 /* BE - C0 */ 0, 0, 0,
6552 /* A */ 0x01,
6553 /* B */ 0x02,
6554 /* C */ 0x03,
6555 /* D */ 0x37,
6556 /* E */ 0x2D,
6557 /* F */ 0x2E,
6558 /* G */ 0x2F,
6559 /* H */ 0x16,
6560 /* I */ 0x05,
6561 /* CA - D0 */ 0, 0, 0, 0, 0, 0, 0,
6562 /* J */ 0x15,
6563 /* K */ 0x0B,
6564 /* L */ 0x0C,
6565 /* M */ 0x0D,
6566 /* N */ 0x0E,
6567 /* O */ 0x0F,
6568 /* P */ 0x10,
6569 /* Q */ 0x11,
6570 /* R */ 0x12,
6571 /* DA - DF */ 0, 0, 0, 0, 0, 0,
6572 /* \ */ 0x1C,
6573 /* E1 */ 0,
6574 /* S */ 0x13,
6575 /* T */ 0x3C,
6576 /* U */ 0x3D,
6577 /* V */ 0x32,
6578 /* W */ 0x26,
6579 /* X */ 0x18,
6580 /* Y */ 0x19,
6581 /* Z */ 0x3F,
6582 /* EA - FF*/ 0, 0, 0, 0, 0, 0,
6583 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
6586 char MetaCharTable[]=
6587 {/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6588 0, 0, 0, 0,'\\', 0,'F', 0,'W','M','N', 0, 0, 0, 0, 0,
6589 0, 0, 0, 0,']', 0, 0,'G', 0, 0,'R','O', 0, 0, 0, 0,
6590 '@','A','B','C','D','E', 0, 0,'H','I','J','K','L', 0, 0, 0,
6591 'P','Q', 0,'S','T','U','V', 0,'X','Y','Z','[', 0, 0,'^', 0
6595 /* TODO: Use characters NOT numbers!!! */
6596 char CtrlCharTable[]=
6597 {/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
6598 124,193,194,195, 0,201, 0, 0, 0, 0, 0,210,211,212,213,214,
6599 215,216,217,226, 0,209,200, 0,231,232, 0, 0,224,189, 95,109,
6600 0, 0, 0, 0, 0, 0,230,173, 0, 0, 0, 0, 0,197,198,199,
6601 0, 0,229, 0, 0, 0, 0,196, 0, 0, 0, 0,227,228, 0,233,
6605 #endif