diff options
| author | Peter Wemm <peter@FreeBSD.org> | 2013-08-11 08:38:10 +0000 |
|---|---|---|
| committer | Peter Wemm <peter@FreeBSD.org> | 2013-08-11 08:38:10 +0000 |
| commit | 84ed61ee234d2654ec965be5bfdda4269f9dc4fd (patch) | |
| tree | fcfc8dee7b416cacdea763f18f34e0930234186a /contrib/nvi/cl | |
| parent | 17c17f89c51e74499873b6115c9516b3302f2eb6 (diff) | |
Notes
Diffstat (limited to 'contrib/nvi/cl')
| -rw-r--r-- | contrib/nvi/cl/README.signal | 174 | ||||
| -rw-r--r-- | contrib/nvi/cl/cl.h | 78 | ||||
| -rw-r--r-- | contrib/nvi/cl/cl_bsd.c | 346 | ||||
| -rw-r--r-- | contrib/nvi/cl/cl_funcs.c | 704 | ||||
| -rw-r--r-- | contrib/nvi/cl/cl_main.c | 471 | ||||
| -rw-r--r-- | contrib/nvi/cl/cl_read.c | 334 | ||||
| -rw-r--r-- | contrib/nvi/cl/cl_screen.c | 581 | ||||
| -rw-r--r-- | contrib/nvi/cl/cl_term.c | 460 |
8 files changed, 0 insertions, 3148 deletions
diff --git a/contrib/nvi/cl/README.signal b/contrib/nvi/cl/README.signal deleted file mode 100644 index 7faa45673b75..000000000000 --- a/contrib/nvi/cl/README.signal +++ /dev/null @@ -1,174 +0,0 @@ -# @(#)README.signal 10.1 (Berkeley) 6/23/95 - -There are six (normally) asynchronous actions about which vi cares: -SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGTSTP and SIGWINCH. - -The assumptions: - 1: The DB routines are not reentrant. - 2: The curses routines may not be reentrant. - 3: Neither DB nor curses will restart system calls. - -XXX -Note, most C library functions don't restart system calls. So, we should -*probably* start blocking around any imported function that we don't know -doesn't make a system call. This is going to be a genuine annoyance... - -SIGHUP, SIGTERM - Used for file recovery. The DB routines can't be reentered, nor - can they handle interrupted system calls, so the vi routines that - call DB block signals. This means that DB routines could be - called at interrupt time, if necessary. - -SIGQUIT - Disabled by the signal initialization routines. Historically, ^\ - switched vi into ex mode, and we continue that practice. - -SIGWINCH: - The interrupt routine sets a global bit which is checked by the - key-read routine, so there are no reentrancy issues. This means - that the screen will not resize until vi runs out of keys, but - that doesn't seem like a problem. - -SIGINT and SIGTSTP are a much more difficult issue to resolve. Vi has -to permit the user to interrupt long-running operations. Generally, a -search, substitution or read/write is done on a large file, or, the user -creates a key mapping with an infinite loop. This problem will become -worse as more complex semantics are added to vi, especially things like -making it a pure text widget. There are four major solutions on the table, -each of which have minor permutations. - -1: Run in raw mode. - - The up side is that there's no asynchronous behavior to worry about, - and obviously no reentrancy problems. The down side is that it's easy - to misinterpret characters (e.g. :w big_file^Mi^V^C is going to look - like an interrupt) and it's easy to get into places where we won't see - interrupt characters (e.g. ":map a ixx^[hxxaXXX" infinitely loops in - historic implementations of vi). Periodically reading the terminal - input buffer might solve the latter problem, but it's not going to be - pretty. - - Also, we're going to be checking for ^C's and ^Z's both, all over - the place -- I hate to litter the source code with that. For example, - the historic version of vi didn't permit you to suspend the screen if - you were on the colon command line. This isn't right. ^Z isn't a vi - command, it's a terminal event. (Dammit.) - -2: Run in cbreak mode. There are two problems in this area. First, the - current curses implementations (both System V and Berkeley) don't give - you clean cbreak modes. For example, the IEXTEN bit is left on, turning - on DISCARD and LNEXT. To clarify, what vi WANTS is 8-bit clean, with - the exception that flow control and signals are turned on, and curses - cbreak mode doesn't give you this. - - We can either set raw mode and twiddle the tty, or cbreak mode and - twiddle the tty. I chose to use raw mode, on the grounds that raw - mode is better defined and I'm less likely to be surprised by a curses - implementation down the road. The twiddling consists of setting ISIG, - IXON/IXOFF, and disabling some of the interrupt characters (see the - comments in cl_init.c). This is all found in historic System V (SVID - 3) and POSIX 1003.1-1992, so it should be fairly portable. - - The second problem is that vi permits you to enter literal signal - characters, e.g. ^V^C. There are two possible solutions. First, you - can turn off signals when you get a ^V, but that means that a network - packet containing ^V and ^C will lose, since the ^C may take effect - before vi reads the ^V. (This is particularly problematic if you're - talking over a protocol that recognizes signals locally and sends OOB - packets when it sees them.) Second, you can turn the ^C into a literal - character in vi, but that means that there's a race between entering - ^V<character>^C, i.e. the sequence may end up being ^V^C<character>. - Also, the second solution doesn't work for flow control characters, as - they aren't delivered to the program as signals. - - Generally, this is what historic vi did. (It didn't have the curses - problems because it didn't use curses.) It entered signals following - ^V characters into the input stream, (which is why there's no way to - enter a literal flow control character). - -3: Run in mostly raw mode; turn signals on when doing an operation the - user might want to interrupt, but leave them off most of the time. - - This works well for things like file reads and writes. This doesn't - work well for trying to detect infinite maps. The problem is that - you can write the code so that you don't have to turn on interrupts - per keystroke, but the code isn't pretty and it's hard to make sure - that an optimization doesn't cover up an infinite loop. This also - requires interaction or state between the vi parser and the key - reading routines, as an infinite loop may still be returning keys - to the parser. - - Also, if the user inserts an interrupt into the tty queue while the - interrupts are turned off, the key won't be treated as an interrupt, - and requiring the user to pound the keyboard to catch an interrupt - window is nasty. - -4: Run in mostly raw mode, leaving signals on all of the time. Done - by setting raw mode, and twiddling the tty's termios ISIG bit. - - This works well for the interrupt cases, because the code only has - to check to see if the interrupt flag has been set, and can otherwise - ignore signals. It's also less likely that we'll miss a case, and we - don't have to worry about synchronizing between the vi parser and the - key read routines. - - The down side is that we have to turn signals off if the user wants - to enter a literal character (e.g. ^V^C). If the user enters the - combination fast enough, or as part of a single network packet, - the text input routines will treat it as a signal instead of as a - literal character. To some extent, we have this problem already, - since we turn off flow control so that the user can enter literal - XON/XOFF characters. - - This is probably the easiest to code, and provides the smoothest - programming interface. - -There are a couple of other problems to consider. - -First, System V's curses doesn't handle SIGTSTP correctly. If you use the -newterm() interface, the TSTP signal will leave you in raw mode, and the -final endwin() will leave you in the correct shell mode. If you use the -initscr() interface, the TSTP signal will return you to the correct shell -mode, but the final endwin() will leave you in raw mode. There you have -it: proof that drug testing is not making any significant headway in the -computer industry. The 4BSD curses is deficient in that it does not have -an interface to the terminal keypad. So, regardless, we have to do our -own SIGTSTP handling. - -The problem with this is that if we do our own SIGTSTP handling, in either -models #3 or #4, we're going to have to call curses routines at interrupt -time, which means that we might be reentering curses, which is something we -don't want to do. - -Second, SIGTSTP has its own little problems. It's broadcast to the entire -process group, not sent to a single process. The scenario goes something -like this: the shell execs the mail program, which execs vi. The user hits -^Z, and all three programs get the signal, in some random order. The mail -program goes to sleep immediately (since it probably didn't have a SIGTSTP -handler in place). The shell gets a SIGCHLD, does a wait, and finds out -that the only child in its foreground process group (of which it's aware) -is asleep. It then optionally resets the terminal (because the modes aren't -how it left them), and starts prompting the user for input. The problem is -that somewhere in the middle of all of this, vi is resetting the terminal, -and getting ready to send a SIGTSTP to the process group in order to put -itself to sleep. There's a solution to all of this: when vi starts, it puts -itself into its own process group, and then only it (and possible child -processes) receive the SIGTSTP. This permits it to clean up the terminal -and switch back to the original process group, where it sends that process -group a SIGTSTP, putting everyone to sleep and waking the shell. - -Third, handing SIGTSTP asynchronously is further complicated by the child -processes vi may fork off. If vi calls ex, ex resets the terminal and -starts running some filter, and SIGTSTP stops them both, vi has to know -when it restarts that it can't repaint the screen until ex's child has -finished running. This is solveable, but it's annoying. - -Well, somebody had to make a decision, and this is the way it's going to be -(unless I get talked out of it). SIGINT is handled asynchronously, so -that we can pretty much guarantee that the user can interrupt any operation -at any time. SIGTSTP is handled synchronously, so that we don't have to -reenter curses and so that we don't have to play the process group games. -^Z is recognized in the standard text input and command modes. (^Z should -also be recognized during operations that may potentially take a long time. -The simplest solution is probably to twiddle the tty, install a handler for -SIGTSTP, and then restore normal tty modes when the operation is complete.) diff --git a/contrib/nvi/cl/cl.h b/contrib/nvi/cl/cl.h deleted file mode 100644 index 2ef2b8d1f81e..000000000000 --- a/contrib/nvi/cl/cl.h +++ /dev/null @@ -1,78 +0,0 @@ -/*- - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * Copyright (c) 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - * - * See the LICENSE file for redistribution information. - * - * @(#)cl.h 10.19 (Berkeley) 9/24/96 - */ - -typedef struct _cl_private { - CHAR_T ibuf[256]; /* Input keys. */ - - int eof_count; /* EOF count. */ - - struct termios orig; /* Original terminal values. */ - struct termios ex_enter;/* Terminal values to enter ex. */ - struct termios vi_enter;/* Terminal values to enter vi. */ - - char *el; /* Clear to EOL terminal string. */ - char *cup; /* Cursor movement terminal string. */ - char *cuu1; /* Cursor up terminal string. */ - char *rmso, *smso; /* Inverse video terminal strings. */ - char *smcup, *rmcup; /* Terminal start/stop strings. */ - - int killersig; /* Killer signal. */ -#define INDX_HUP 0 -#define INDX_INT 1 -#define INDX_TERM 2 -#define INDX_WINCH 3 -#define INDX_MAX 4 /* Original signal information. */ - struct sigaction oact[INDX_MAX]; - - enum { /* Tty group write mode. */ - TGW_UNKNOWN=0, TGW_SET, TGW_UNSET } tgw; - - enum { /* Terminal initialization strings. */ - TE_SENT=0, TI_SENT } ti_te; - -#define CL_IN_EX 0x0001 /* Currently running ex. */ -#define CL_RENAME 0x0002 /* X11 xterm icon/window renamed. */ -#define CL_RENAME_OK 0x0004 /* User wants the windows renamed. */ -#define CL_SCR_EX_INIT 0x0008 /* Ex screen initialized. */ -#define CL_SCR_VI_INIT 0x0010 /* Vi screen initialized. */ -#define CL_SIGHUP 0x0020 /* SIGHUP arrived. */ -#define CL_SIGINT 0x0040 /* SIGINT arrived. */ -#define CL_SIGTERM 0x0080 /* SIGTERM arrived. */ -#define CL_SIGWINCH 0x0100 /* SIGWINCH arrived. */ -#define CL_STDIN_TTY 0x0200 /* Talking to a terminal. */ - u_int32_t flags; -} CL_PRIVATE; - -#define CLP(sp) ((CL_PRIVATE *)((sp)->gp->cl_private)) -#define GCLP(gp) ((CL_PRIVATE *)gp->cl_private) - -/* Return possibilities from the keyboard read routine. */ -typedef enum { INP_OK=0, INP_EOF, INP_ERR, INP_INTR, INP_TIMEOUT } input_t; - -/* The screen line relative to a specific window. */ -#define RLNO(sp, lno) (sp)->woff + (lno) - -/* X11 xterm escape sequence to rename the icon/window. */ -#define XTERM_RENAME "\033]0;%s\007" - -/* - * XXX - * Some implementations of curses.h don't define these for us. Used for - * compatibility only. - */ -#ifndef TRUE -#define TRUE 1 -#endif -#ifndef FALSE -#define FALSE 0 -#endif - -#include "cl_extern.h" diff --git a/contrib/nvi/cl/cl_bsd.c b/contrib/nvi/cl/cl_bsd.c deleted file mode 100644 index 22124e5780b2..000000000000 --- a/contrib/nvi/cl/cl_bsd.c +++ /dev/null @@ -1,346 +0,0 @@ -/*- - * Copyright (c) 1995, 1996 - * Keith Bostic. All rights reserved. - * - * See the LICENSE file for redistribution information. - */ - -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)cl_bsd.c 8.29 (Berkeley) 7/1/96"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <ctype.h> -#include <curses.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "../common/common.h" -#include "../vi/vi.h" -#include "cl.h" - -static char *ke; /* Keypad on. */ -static char *ks; /* Keypad off. */ -static char *vb; /* Visible bell string. */ - -/* - * HP's support the entire System V curses package except for the tigetstr - * and tigetnum functions. Ultrix supports the BSD curses package except - * for the idlok function. Cthulu only knows why. Break things up into a - * minimal set of functions. - */ - -#ifndef HAVE_CURSES_ADDNSTR -/* - * addnstr -- - * - * PUBLIC: #ifndef HAVE_CURSES_ADDNSTR - * PUBLIC: int addnstr __P((char *, int)); - * PUBLIC: #endif - */ -int -addnstr(s, n) - char *s; - int n; -{ - int ch; - - while (n-- && (ch = *s++)) - addch(ch); - return (OK); -} -#endif - -#ifndef HAVE_CURSES_BEEP -/* - * beep -- - * - * PUBLIC: #ifndef HAVE_CURSES_BEEP - * PUBLIC: void beep __P((void)); - * PUBLIC: #endif - */ -void -beep() -{ - (void)write(1, "\007", 1); /* '\a' */ -} -#endif /* !HAVE_CURSES_BEEP */ - -#ifndef HAVE_CURSES_FLASH -/* - * flash -- - * Flash the screen. - * - * PUBLIC: #ifndef HAVE_CURSES_FLASH - * PUBLIC: void flash __P((void)); - * PUBLIC: #endif - */ -void -flash() -{ - if (vb != NULL) { - (void)tputs(vb, 1, cl_putchar); - (void)fflush(stdout); - } else - beep(); -} -#endif /* !HAVE_CURSES_FLASH */ - -#ifndef HAVE_CURSES_IDLOK -/* - * idlok -- - * Turn on/off hardware line insert/delete. - * - * PUBLIC: #ifndef HAVE_CURSES_IDLOK - * PUBLIC: void idlok __P((WINDOW *, int)); - * PUBLIC: #endif - */ -void -idlok(win, bf) - WINDOW *win; - int bf; -{ - return; -} -#endif /* !HAVE_CURSES_IDLOK */ - -#ifndef HAVE_CURSES_KEYPAD -/* - * keypad -- - * Put the keypad/cursor arrows into or out of application mode. - * - * PUBLIC: #ifndef HAVE_CURSES_KEYPAD - * PUBLIC: int keypad __P((void *, int)); - * PUBLIC: #endif - */ -int -keypad(a, on) - void *a; - int on; -{ - char *p; - - if ((p = tigetstr(on ? "smkx" : "rmkx")) != (char *)-1) { - (void)tputs(p, 0, cl_putchar); - (void)fflush(stdout); - } - return (0); -} -#endif /* !HAVE_CURSES_KEYPAD */ - -#ifndef HAVE_CURSES_NEWTERM -/* - * newterm -- - * Create a new curses screen. - * - * PUBLIC: #ifndef HAVE_CURSES_NEWTERM - * PUBLIC: void *newterm __P((const char *, FILE *, FILE *)); - * PUBLIC: #endif - */ -void * -newterm(a, b, c) - const char *a; - FILE *b, *c; -{ - return (initscr()); -} -#endif /* !HAVE_CURSES_NEWTERM */ - -#ifndef HAVE_CURSES_SETUPTERM -/* - * setupterm -- - * Set up terminal. - * - * PUBLIC: #ifndef HAVE_CURSES_SETUPTERM - * PUBLIC: void setupterm __P((char *, int, int *)); - * PUBLIC: #endif - */ -void -setupterm(ttype, fno, errp) - char *ttype; - int fno, *errp; -{ - static char buf[2048]; - char *p; - - if ((*errp = tgetent(buf, ttype)) > 0) { - if (ke != NULL) - free(ke); - ke = ((p = tigetstr("rmkx")) == (char *)-1) ? - NULL : strdup(p); - if (ks != NULL) - free(ks); - ks = ((p = tigetstr("smkx")) == (char *)-1) ? - NULL : strdup(p); - if (vb != NULL) - free(vb); - vb = ((p = tigetstr("flash")) == (char *)-1) ? - NULL : strdup(p); - } -} -#endif /* !HAVE_CURSES_SETUPTERM */ - -#ifndef HAVE_CURSES_TIGETSTR -/* Terminfo-to-termcap translation table. */ -typedef struct _tl { - char *terminfo; /* Terminfo name. */ - char *termcap; /* Termcap name. */ -} TL; -static const TL list[] = { - "cols", "co", /* Terminal columns. */ - "cup", "cm", /* Cursor up. */ - "cuu1", "up", /* Cursor up. */ - "el", "ce", /* Clear to end-of-line. */ - "flash", "vb", /* Visible bell. */ - "kcub1", "kl", /* Cursor left. */ - "kcud1", "kd", /* Cursor down. */ - "kcuf1", "kr", /* Cursor right. */ - "kcuu1", "ku", /* Cursor up. */ - "kdch1", "kD", /* Delete character. */ - "kdl1", "kL", /* Delete line. */ - "ked", "kS", /* Delete to end of screen. */ - "kel", "kE", /* Delete to eol. */ - "kend", "@7", /* Go to eol. */ - "khome", "kh", /* Go to sol. */ - "kich1", "kI", /* Insert at cursor. */ - "kil1", "kA", /* Insert line. */ - "kind", "kF", /* Scroll down. */ - "kll", "kH", /* Go to eol. */ - "knp", "kN", /* Page down. */ - "kpp", "kP", /* Page up. */ - "kri", "kR", /* Scroll up. */ - "lines", "li", /* Terminal lines. */ - "rmcup", "te", /* Terminal end string. */ - "rmkx", "ke", /* Exit "keypad-transmit" mode. */ - "rmso", "se", /* Standout end. */ - "smcup", "ti", /* Terminal initialization string. */ - "smkx", "ks", /* Enter "keypad-transmit" mode. */ - "smso", "so", /* Standout begin. */ -}; - -#ifdef _AIX -/* - * AIX's implementation for function keys greater than 10 is different and - * only goes as far as 36. - */ -static const char codes[] = { -/* 0-10 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';', -/* 11-20 */ '<', '>', '!', '@', '#', '$', '%', '^', '&', '*', -/* 21-30 */ '(', ')', '-', '_', '+', ',', ':', '?', '[', ']', -/* 31-36 */ '{', '}', '|', '~', '/', '=' -}; - -#else - -/* - * !!! - * Historically, the 4BSD termcap code didn't support functions keys greater - * than 9. This was silently enforced -- asking for key k12 would return the - * value for k1. We try and get around this by using the tables specified in - * the terminfo(TI_ENV) man page from the 3rd Edition SVID. This assumes the - * implementors of any System V compatibility code or an extended termcap used - * those codes. - */ -static const char codes[] = { -/* 0-10 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';', -/* 11-19 */ '1', '2', '3', '4', '5', '6', '7', '8', '9', -/* 20-63 */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', - 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', - 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', -}; -#endif /* _AIX */ - -/* - * lcmp -- - * list comparison routine for bsearch. - */ -static int -lcmp(a, b) - const void *a, *b; -{ - return (strcmp(a, ((TL *)b)->terminfo)); -} - -/* - * tigetstr -- - * - * Vendors put the prototype for tigetstr into random include files, including - * <term.h>, which we can't include because it makes other systems unhappy. - * Try and work around the problem, since we only care about the return value. - * - * PUBLIC: #ifdef HAVE_CURSES_TIGETSTR - * PUBLIC: char *tigetstr(); - * PUBLIC: #else - * PUBLIC: char *tigetstr __P((char *)); - * PUBLIC: #endif - */ -char * -tigetstr(name) - char *name; -{ - static char sbuf[256]; - TL *tlp; - int n; - char *p, keyname[3]; - - if ((tlp = bsearch(name, - list, sizeof(list) / sizeof(TL), sizeof(TL), lcmp)) == NULL) { -#ifdef _AIX - if (name[0] == 'k' && - name[1] == 'f' && (n = atoi(name + 2)) <= 36) { - keyname[0] = 'k'; - keyname[1] = codes[n]; - keyname[2] = '\0'; -#else - if (name[0] == 'k' && - name[1] == 'f' && (n = atoi(name + 2)) <= 63) { - keyname[0] = n <= 10 ? 'k' : 'F'; - keyname[1] = codes[n]; - keyname[2] = '\0'; -#endif - name = keyname; - } - } else - name = tlp->termcap; - - p = sbuf; -#ifdef _AIX - return ((p = tgetstr(name, &p)) == NULL ? (char *)-1 : strcpy(sbuf, p)); -#else - return (tgetstr(name, &p) == NULL ? (char *)-1 : sbuf); -#endif -} - -/* - * tigetnum -- - * - * PUBLIC: #ifndef HAVE_CURSES_TIGETSTR - * PUBLIC: int tigetnum __P((char *)); - * PUBLIC: #endif - */ -int -tigetnum(name) - char *name; -{ - TL *tlp; - int val; - - if ((tlp = bsearch(name, - list, sizeof(list) / sizeof(TL), sizeof(TL), lcmp)) != NULL) { - name = tlp->termcap; - } - - return ((val = tgetnum(name)) == -1 ? -2 : val); -} -#endif /* !HAVE_CURSES_TIGETSTR */ diff --git a/contrib/nvi/cl/cl_funcs.c b/contrib/nvi/cl/cl_funcs.c deleted file mode 100644 index 40315ee85e89..000000000000 --- a/contrib/nvi/cl/cl_funcs.c +++ /dev/null @@ -1,704 +0,0 @@ -/*- - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * Copyright (c) 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - * - * See the LICENSE file for redistribution information. - */ - -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)cl_funcs.c 10.50 (Berkeley) 9/24/96"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/time.h> - -#include <bitstring.h> -#include <ctype.h> -#include <curses.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "../common/common.h" -#include "../vi/vi.h" -#include "cl.h" - -/* - * cl_addstr -- - * Add len bytes from the string at the cursor, advancing the cursor. - * - * PUBLIC: int cl_addstr __P((SCR *, const char *, size_t)); - */ -int -cl_addstr(sp, str, len) - SCR *sp; - const char *str; - size_t len; -{ - CL_PRIVATE *clp; - size_t oldy, oldx; - int iv; - - clp = CLP(sp); - - /* - * If ex isn't in control, it's the last line of the screen and - * it's a split screen, use inverse video. - */ - iv = 0; - getyx(stdscr, oldy, oldx); - if (!F_ISSET(sp, SC_SCR_EXWROTE) && - oldy == RLNO(sp, LASTLINE(sp)) && IS_SPLIT(sp)) { - iv = 1; - (void)standout(); - } - - if (addnstr(str, len) == ERR) - return (1); - - if (iv) - (void)standend(); - return (0); -} - -/* - * cl_attr -- - * Toggle a screen attribute on/off. - * - * PUBLIC: int cl_attr __P((SCR *, scr_attr_t, int)); - */ -int -cl_attr(sp, attribute, on) - SCR *sp; - scr_attr_t attribute; - int on; -{ - CL_PRIVATE *clp; - - clp = CLP(sp); - - switch (attribute) { - case SA_ALTERNATE: - /* - * !!! - * There's a major layering violation here. The problem is that the - * X11 xterm screen has what's known as an "alternate" screen. Some - * xterm termcap/terminfo entries include sequences to switch to/from - * that alternate screen as part of the ti/te (smcup/rmcup) strings. - * Vi runs in the alternate screen, so that you are returned to the - * same screen contents on exit from vi that you had when you entered - * vi. Further, when you run :shell, or :!date or similar ex commands, - * you also see the original screen contents. This wasn't deliberate - * on vi's part, it's just that it historically sent terminal init/end - * sequences at those times, and the addition of the alternate screen - * sequences to the strings changed the behavior of vi. The problem - * caused by this is that we don't want to switch back to the alternate - * screen while getting a new command from the user, when the user is - * continuing to enter ex commands, e.g.: - * - * :!date <<< switch to original screen - * [Hit return to continue] <<< prompt user to continue - * :command <<< get command from user - * - * Note that the :command input is a true vi input mode, e.g., input - * maps and abbreviations are being done. So, we need to be able to - * switch back into the vi screen mode, without flashing the screen. - * - * To make matters worse, the curses initscr() and endwin() calls will - * do this automatically -- so, this attribute isn't as controlled by - * the higher level screen as closely as one might like. - */ - if (on) { - if (clp->ti_te != TI_SENT) { - clp->ti_te = TI_SENT; - if (clp->smcup == NULL) - (void)cl_getcap(sp, "smcup", &clp->smcup); - if (clp->smcup != NULL) - (void)tputs(clp->smcup, 1, cl_putchar); - } - } else - if (clp->ti_te != TE_SENT) { - clp->ti_te = TE_SENT; - if (clp->rmcup == NULL) - (void)cl_getcap(sp, "rmcup", &clp->rmcup); - if (clp->rmcup != NULL) - (void)tputs(clp->rmcup, 1, cl_putchar); - (void)fflush(stdout); - } - (void)fflush(stdout); - break; - case SA_INVERSE: - if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE)) { - if (clp->smso == NULL) - return (1); - if (on) - (void)tputs(clp->smso, 1, cl_putchar); - else - (void)tputs(clp->rmso, 1, cl_putchar); - (void)fflush(stdout); - } else { - if (on) - (void)standout(); - else - (void)standend(); - } - break; - default: - abort(); - } - return (0); -} - -/* - * cl_baud -- - * Return the baud rate. - * - * PUBLIC: int cl_baud __P((SCR *, u_long *)); - */ -int -cl_baud(sp, ratep) - SCR *sp; - u_long *ratep; -{ - CL_PRIVATE *clp; - - /* - * XXX - * There's no portable way to get a "baud rate" -- cfgetospeed(3) - * returns the value associated with some #define, which we may - * never have heard of, or which may be a purely local speed. Vi - * only cares if it's SLOW (w300), slow (w1200) or fast (w9600). - * Try and detect the slow ones, and default to fast. - */ - clp = CLP(sp); - switch (cfgetospeed(&clp->orig)) { - case B50: - case B75: - case B110: - case B134: - case B150: - case B200: - case B300: - case B600: - *ratep = 600; - break; - case B1200: - *ratep = 1200; - break; - default: - *ratep = 9600; - break; - } - return (0); -} - -/* - * cl_bell -- - * Ring the bell/flash the screen. - * - * PUBLIC: int cl_bell __P((SCR *)); - */ -int -cl_bell(sp) - SCR *sp; -{ - if (F_ISSET(sp, SC_EX | SC_SCR_EXWROTE)) - (void)write(STDOUT_FILENO, "\07", 1); /* \a */ - else { - /* - * Vi has an edit option which determines if the terminal - * should be beeped or the screen flashed. - */ - if (O_ISSET(sp, O_FLASH)) - (void)flash(); - else - (void)beep(); - } - return (0); -} - -/* - * cl_clrtoeol -- - * Clear from the current cursor to the end of the line. - * - * PUBLIC: int cl_clrtoeol __P((SCR *)); - */ -int -cl_clrtoeol(sp) - SCR *sp; -{ - return (clrtoeol() == ERR); -} - -/* - * cl_cursor -- - * Return the current cursor position. - * - * PUBLIC: int cl_cursor __P((SCR *, size_t *, size_t *)); - */ -int -cl_cursor(sp, yp, xp) - SCR *sp; - size_t *yp, *xp; -{ - /* - * The curses screen support splits a single underlying curses screen - * into multiple screens to support split screen semantics. For this - * reason the returned value must be adjusted to be relative to the - * current screen, and not absolute. Screens that implement the split - * using physically distinct screens won't need this hack. - */ - getyx(stdscr, *yp, *xp); - *yp -= sp->woff; - return (0); -} - -/* - * cl_deleteln -- - * Delete the current line, scrolling all lines below it. - * - * PUBLIC: int cl_deleteln __P((SCR *)); - */ -int -cl_deleteln(sp) - SCR *sp; -{ - CHAR_T ch; - CL_PRIVATE *clp; - size_t col, lno, spcnt, oldy, oldx; - - clp = CLP(sp); - - /* - * This clause is required because the curses screen uses reverse - * video to delimit split screens. If the screen does not do this, - * this code won't be necessary. - * - * If the bottom line was in reverse video, rewrite it in normal - * video before it's scrolled. - * - * Check for the existence of a chgat function; XSI requires it, but - * historic implementations of System V curses don't. If it's not - * a #define, we'll fall back to doing it by hand, which is slow but - * acceptable. - * - * By hand means walking through the line, retrieving and rewriting - * each character. Curses has no EOL marker, so track strings of - * spaces, and copy the trailing spaces only if there's a non-space - * character following. - */ - if (!F_ISSET(sp, SC_SCR_EXWROTE) && IS_SPLIT(sp)) { - getyx(stdscr, oldy, oldx); -#ifdef mvchgat - mvchgat(RLNO(sp, LASTLINE(sp)), 0, -1, A_NORMAL, 0, NULL); -#else - for (lno = RLNO(sp, LASTLINE(sp)), col = spcnt = 0;;) { - (void)move(lno, col); - ch = winch(stdscr); - if (isblank(ch)) - ++spcnt; - else { - (void)move(lno, col - spcnt); - for (; spcnt > 0; --spcnt) - (void)addch(' '); - (void)addch(ch); - } - if (++col >= sp->cols) - break; - } -#endif - (void)move(oldy, oldx); - } - - /* - * The bottom line is expected to be blank after this operation, - * and other screens must support that semantic. - */ - return (deleteln() == ERR); -} - -/* - * cl_ex_adjust -- - * Adjust the screen for ex. This routine is purely for standalone - * ex programs. All special purpose, all special case. - * - * PUBLIC: int cl_ex_adjust __P((SCR *, exadj_t)); - */ -int -cl_ex_adjust(sp, action) - SCR *sp; - exadj_t action; -{ - CL_PRIVATE *clp; - int cnt; - - clp = CLP(sp); - switch (action) { - case EX_TERM_SCROLL: - /* Move the cursor up one line if that's possible. */ - if (clp->cuu1 != NULL) - (void)tputs(clp->cuu1, 1, cl_putchar); - else if (clp->cup != NULL) - (void)tputs(tgoto(clp->cup, - 0, LINES - 2), 1, cl_putchar); - else - return (0); - /* FALLTHROUGH */ - case EX_TERM_CE: - /* Clear the line. */ - if (clp->el != NULL) { - (void)putchar('\r'); - (void)tputs(clp->el, 1, cl_putchar); - } else { - /* - * Historically, ex didn't erase the line, so, if the - * displayed line was only a single glyph, and <eof> - * was more than one glyph, the output would not fully - * overwrite the user's input. To fix this, output - * the maxiumum character number of spaces. Note, - * this won't help if the user entered extra prompt - * or <blank> characters before the command character. - * We'd have to do a lot of work to make that work, and - * it's almost certainly not worth the effort. - */ - for (cnt = 0; cnt < MAX_CHARACTER_COLUMNS; ++cnt) - (void)putchar('\b'); - for (cnt = 0; cnt < MAX_CHARACTER_COLUMNS; ++cnt) - (void)putchar(' '); - (void)putchar('\r'); - (void)fflush(stdout); - } - break; - default: - abort(); - } - return (0); -} - -/* - * cl_insertln -- - * Push down the current line, discarding the bottom line. - * - * PUBLIC: int cl_insertln __P((SCR *)); - */ -int -cl_insertln(sp) - SCR *sp; -{ - /* - * The current line is expected to be blank after this operation, - * and the screen must support that semantic. - */ - return (insertln() == ERR); -} - -/* - * cl_keyval -- - * Return the value for a special key. - * - * PUBLIC: int cl_keyval __P((SCR *, scr_keyval_t, CHAR_T *, int *)); - */ -int -cl_keyval(sp, val, chp, dnep) - SCR *sp; - scr_keyval_t val; - CHAR_T *chp; - int *dnep; -{ - CL_PRIVATE *clp; - - /* - * VEOF, VERASE and VKILL are required by POSIX 1003.1-1990, - * VWERASE is a 4BSD extension. - */ - clp = CLP(sp); - switch (val) { - case KEY_VEOF: - *dnep = (*chp = clp->orig.c_cc[VEOF]) == _POSIX_VDISABLE; - break; - case KEY_VERASE: - *dnep = (*chp = clp->orig.c_cc[VERASE]) == _POSIX_VDISABLE; - break; - case KEY_VKILL: - *dnep = (*chp = clp->orig.c_cc[VKILL]) == _POSIX_VDISABLE; - break; -#ifdef VWERASE - case KEY_VWERASE: - *dnep = (*chp = clp->orig.c_cc[VWERASE]) == _POSIX_VDISABLE; - break; -#endif - default: - *dnep = 1; - break; - } - return (0); -} - -/* - * cl_move -- - * Move the cursor. - * - * PUBLIC: int cl_move __P((SCR *, size_t, size_t)); - */ -int -cl_move(sp, lno, cno) - SCR *sp; - size_t lno, cno; -{ - /* See the comment in cl_cursor. */ - if (move(RLNO(sp, lno), cno) == ERR) { - msgq(sp, M_ERR, - "Error: move: l(%u) c(%u) o(%u)", lno, cno, sp->woff); - return (1); - } - return (0); -} - -/* - * cl_refresh -- - * Refresh the screen. - * - * PUBLIC: int cl_refresh __P((SCR *, int)); - */ -int -cl_refresh(sp, repaint) - SCR *sp; - int repaint; -{ - CL_PRIVATE *clp; - - clp = CLP(sp); - - /* - * If we received a killer signal, we're done, there's no point - * in refreshing the screen. - */ - if (clp->killersig) - return (0); - - /* - * If repaint is set, the editor is telling us that we don't know - * what's on the screen, so we have to repaint from scratch. - * - * In the curses library, doing wrefresh(curscr) is okay, but the - * screen flashes when we then apply the refresh() to bring it up - * to date. So, use clearok(). - */ - if (repaint) - clearok(curscr, 1); - return (refresh() == ERR); -} - -/* - * cl_rename -- - * Rename the file. - * - * PUBLIC: int cl_rename __P((SCR *, char *, int)); - */ -int -cl_rename(sp, name, on) - SCR *sp; - char *name; - int on; -{ - GS *gp; - CL_PRIVATE *clp; - char *ttype; - - gp = sp->gp; - clp = CLP(sp); - - ttype = OG_STR(gp, GO_TERM); - - /* - * XXX - * We can only rename windows for xterm. - */ - if (on) { - if (F_ISSET(clp, CL_RENAME_OK) && - !strncmp(ttype, "xterm", sizeof("xterm") - 1)) { - F_SET(clp, CL_RENAME); - (void)printf(XTERM_RENAME, name); - (void)fflush(stdout); - } - } else - if (F_ISSET(clp, CL_RENAME)) { - F_CLR(clp, CL_RENAME); - (void)printf(XTERM_RENAME, ttype); - (void)fflush(stdout); - } - return (0); -} - -/* - * cl_suspend -- - * Suspend a screen. - * - * PUBLIC: int cl_suspend __P((SCR *, int *)); - */ -int -cl_suspend(sp, allowedp) - SCR *sp; - int *allowedp; -{ - struct termios t; - CL_PRIVATE *clp; - GS *gp; - size_t oldy, oldx; - int changed; - - gp = sp->gp; - clp = CLP(sp); - *allowedp = 1; - - /* - * The ex implementation of this function isn't needed by screens not - * supporting ex commands that require full terminal canonical mode - * (e.g. :suspend). - * - * The vi implementation of this function isn't needed by screens not - * supporting vi process suspension, i.e. any screen that isn't backed - * by a UNIX shell. - * - * Setting allowedp to 0 will cause the editor to reject the command. - */ - if (F_ISSET(sp, SC_EX)) { - /* Save the terminal settings, and restore the original ones. */ - if (F_ISSET(clp, CL_STDIN_TTY)) { - (void)tcgetattr(STDIN_FILENO, &t); - (void)tcsetattr(STDIN_FILENO, - TCSASOFT | TCSADRAIN, &clp->orig); - } - - /* Stop the process group. */ - (void)kill(0, SIGTSTP); - - /* Time passes ... */ - - /* Restore terminal settings. */ - if (F_ISSET(clp, CL_STDIN_TTY)) - (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t); - return (0); - } - - /* - * Move to the lower left-hand corner of the screen. - * - * XXX - * Not sure this is necessary in System V implementations, but it - * shouldn't hurt. - */ - getyx(stdscr, oldy, oldx); - (void)move(LINES - 1, 0); - (void)refresh(); - - /* - * Temporarily end the screen. System V introduced a semantic where - * endwin() could be restarted. We use it because restarting curses - * from scratch often fails in System V. 4BSD curses didn't support - * restarting after endwin(), so we have to do what clean up we can - * without calling it. - */ -#ifdef HAVE_BSD_CURSES - /* Save the terminal settings. */ - (void)tcgetattr(STDIN_FILENO, &t); -#endif - - /* Restore the cursor keys to normal mode. */ - (void)keypad(stdscr, FALSE); - - /* Restore the window name. */ - (void)cl_rename(sp, NULL, 0); - -#ifdef HAVE_BSD_CURSES - (void)cl_attr(sp, SA_ALTERNATE, 0); -#else - (void)endwin(); -#endif - /* - * XXX - * Restore the original terminal settings. This is bad -- the - * reset can cause character loss from the tty queue. However, - * we can't call endwin() in BSD curses implementations, and too - * many System V curses implementations don't get it right. - */ - (void)tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->orig); - - /* Stop the process group. */ - (void)kill(0, SIGTSTP); - - /* Time passes ... */ - - /* - * If we received a killer signal, we're done. Leave everything - * unchanged. In addition, the terminal has already been reset - * correctly, so leave it alone. - */ - if (clp->killersig) { - F_CLR(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT); - return (0); - } - -#ifdef HAVE_BSD_CURSES - /* Restore terminal settings. */ - if (F_ISSET(clp, CL_STDIN_TTY)) - (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &t); - - (void)cl_attr(sp, SA_ALTERNATE, 1); -#endif - - /* Set the window name. */ - (void)cl_rename(sp, sp->frp->name, 1); - - /* Put the cursor keys into application mode. */ - (void)keypad(stdscr, TRUE); - - /* Refresh and repaint the screen. */ - (void)move(oldy, oldx); - (void)cl_refresh(sp, 1); - - /* If the screen changed size, set the SIGWINCH bit. */ - if (cl_ssize(sp, 1, NULL, NULL, &changed)) - return (1); - if (changed) - F_SET(CLP(sp), CL_SIGWINCH); - - return (0); -} - -/* - * cl_usage -- - * Print out the curses usage messages. - * - * PUBLIC: void cl_usage __P((void)); - */ -void -cl_usage() -{ -#define USAGE "\ -usage: ex [-eFRrSsv] [-c command] [-t tag] [-w size] [file ...]\n\ -usage: vi [-eFlRrSv] [-c command] [-t tag] [-w size] [file ...]\n" - (void)fprintf(stderr, "%s", USAGE); -#undef USAGE -} - -#ifdef DEBUG -/* - * gdbrefresh -- - * Stub routine so can flush out curses screen changes using gdb. - */ -int -gdbrefresh() -{ - refresh(); - return (0); /* XXX Convince gdb to run it. */ -} -#endif diff --git a/contrib/nvi/cl/cl_main.c b/contrib/nvi/cl/cl_main.c deleted file mode 100644 index 2889f709cbb2..000000000000 --- a/contrib/nvi/cl/cl_main.c +++ /dev/null @@ -1,471 +0,0 @@ -/*- - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * Copyright (c) 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - * - * See the LICENSE file for redistribution information. - */ - -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)cl_main.c 10.36 (Berkeley) 10/14/96"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> - -#include <bitstring.h> -#include <curses.h> -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "../common/common.h" -#ifdef RUNNING_IP -#include "../ip/ip.h" -#endif -#include "cl.h" -#include "pathnames.h" - -GS *__global_list; /* GLOBAL: List of screens. */ -sigset_t __sigblockset; /* GLOBAL: Blocked signals. */ - -static void cl_func_std __P((GS *)); -static CL_PRIVATE *cl_init __P((GS *)); -static GS *gs_init __P((char *)); -static void perr __P((char *, char *)); -static int setsig __P((int, struct sigaction *, void (*)(int))); -static void sig_end __P((GS *)); -static void term_init __P((char *, char *)); - -/* - * main -- - * This is the main loop for the standalone curses editor. - */ -int -main(argc, argv) - int argc; - char *argv[]; -{ - static int reenter; - CL_PRIVATE *clp; - GS *gp; - size_t rows, cols; - int rval; - char *ip_arg, **p_av, **t_av, *ttype; - - /* If loaded at 0 and jumping through a NULL pointer, stop. */ - if (reenter++) - abort(); - - /* Create and initialize the global structure. */ - __global_list = gp = gs_init(argv[0]); - - /* - * Strip out any arguments that vi isn't going to understand. There's - * no way to portably call getopt twice, so arguments parsed here must - * be removed from the argument list. - */ -#ifdef RUNNING_IP - ip_arg = NULL; - for (p_av = t_av = argv;;) { - if (*t_av == NULL) { - *p_av = NULL; - break; - } - if (!strcmp(*t_av, "--")) { - while ((*p_av++ = *t_av++) != NULL); - break; - } - if (!memcmp(*t_av, "-I", sizeof("-I") - 1)) { - if (t_av[0][2] != '\0') { - ip_arg = t_av[0] + 2; - ++t_av; - --argc; - continue; - } - if (t_av[1] != NULL) { - ip_arg = t_av[1]; - t_av += 2; - argc -= 2; - continue; - } - } - *p_av++ = *t_av++; - } - - /* - * If we're being called as an editor library, we're done here, we - * get loaded with the curses screen, we don't share much code. - */ - if (ip_arg != NULL) - exit (ip_main(argc, argv, gp, ip_arg)); -#else - ip_arg = argv[0]; -#endif - - /* Create and initialize the CL_PRIVATE structure. */ - clp = cl_init(gp); - - /* - * Initialize the terminal information. - * - * We have to know what terminal it is from the start, since we may - * have to use termcap/terminfo to find out how big the screen is. - */ - if ((ttype = getenv("TERM")) == NULL) - ttype = "unknown"; - term_init(gp->progname, ttype); - - /* Add the terminal type to the global structure. */ - if ((OG_D_STR(gp, GO_TERM) = - OG_STR(gp, GO_TERM) = strdup(ttype)) == NULL) - perr(gp->progname, NULL); - - /* Figure out how big the screen is. */ - if (cl_ssize(NULL, 0, &rows, &cols, NULL)) - exit (1); - - /* Add the rows and columns to the global structure. */ - OG_VAL(gp, GO_LINES) = OG_D_VAL(gp, GO_LINES) = rows; - OG_VAL(gp, GO_COLUMNS) = OG_D_VAL(gp, GO_COLUMNS) = cols; - - /* Ex wants stdout to be buffered. */ - (void)setvbuf(stdout, NULL, _IOFBF, 0); - - /* Start catching signals. */ - if (sig_init(gp, NULL)) - exit (1); - - /* Run ex/vi. */ - rval = editor(gp, argc, argv); - - /* Clean up signals. */ - sig_end(gp); - - /* Clean up the terminal. */ - (void)cl_quit(gp); - - /* - * XXX - * Reset the O_MESG option. - */ - if (clp->tgw != TGW_UNKNOWN) - (void)cl_omesg(NULL, clp, clp->tgw == TGW_SET); - - /* - * XXX - * Reset the X11 xterm icon/window name. - */ - if (F_ISSET(clp, CL_RENAME)) { - (void)printf(XTERM_RENAME, ttype); - (void)fflush(stdout); - } - - /* If a killer signal arrived, pretend we just got it. */ - if (clp->killersig) { - (void)signal(clp->killersig, SIG_DFL); - (void)kill(getpid(), clp->killersig); - /* NOTREACHED */ - } - - /* Free the global and CL private areas. */ -#if defined(DEBUG) || defined(PURIFY) || defined(LIBRARY) - free(clp); - free(gp); -#endif - - exit (rval); -} - -/* - * gs_init -- - * Create and partially initialize the GS structure. - */ -static GS * -gs_init(name) - char *name; -{ - CL_PRIVATE *clp; - GS *gp; - char *p; - - /* Figure out what our name is. */ - if ((p = strrchr(name, '/')) != NULL) - name = p + 1; - - /* Allocate the global structure. */ - CALLOC_NOMSG(NULL, gp, GS *, 1, sizeof(GS)); - if (gp == NULL) - perr(name, NULL); - - - gp->progname = name; - return (gp); -} - -/* - * cl_init -- - * Create and partially initialize the CL structure. - */ -static CL_PRIVATE * -cl_init(gp) - GS *gp; -{ - CL_PRIVATE *clp; - int fd; - - /* Allocate the CL private structure. */ - CALLOC_NOMSG(NULL, clp, CL_PRIVATE *, 1, sizeof(CL_PRIVATE)); - if (clp == NULL) - perr(gp->progname, NULL); - gp->cl_private = clp; - - /* - * Set the CL_STDIN_TTY flag. It's purpose is to avoid setting - * and resetting the tty if the input isn't from there. We also - * use the same test to determine if we're running a script or - * not. - */ - if (isatty(STDIN_FILENO)) - F_SET(clp, CL_STDIN_TTY); - else - F_SET(gp, G_SCRIPTED); - - /* - * We expect that if we've lost our controlling terminal that the - * open() (but not the tcgetattr()) will fail. - */ - if (F_ISSET(clp, CL_STDIN_TTY)) { - if (tcgetattr(STDIN_FILENO, &clp->orig) == -1) - goto tcfail; - } else if ((fd = open(_PATH_TTY, O_RDONLY, 0)) != -1) { - if (tcgetattr(fd, &clp->orig) == -1) { -tcfail: perr(gp->progname, "tcgetattr"); - exit (1); - } - (void)close(fd); - } - - /* Initialize the list of curses functions. */ - cl_func_std(gp); - - return (clp); -} - -/* - * term_init -- - * Initialize terminal information. - */ -static void -term_init(name, ttype) - char *name, *ttype; -{ - int err; - - /* Set up the terminal database information. */ - setupterm(ttype, STDOUT_FILENO, &err); - switch (err) { - case -1: - (void)fprintf(stderr, - "%s: No terminal database found\n", name); - exit (1); - case 0: - (void)fprintf(stderr, - "%s: %s: unknown terminal type\n", name, ttype); - exit (1); - } -} - -#define GLOBAL_CLP \ - CL_PRIVATE *clp = GCLP(__global_list); -static void -h_hup(signo) - int signo; -{ - GLOBAL_CLP; - - F_SET(clp, CL_SIGHUP); - clp->killersig = SIGHUP; -} - -static void -h_int(signo) - int signo; -{ - GLOBAL_CLP; - - F_SET(clp, CL_SIGINT); -} - -static void -h_term(signo) - int signo; -{ - GLOBAL_CLP; - - F_SET(clp, CL_SIGTERM); - clp->killersig = SIGTERM; -} - -static void -h_winch(signo) - int signo; -{ - GLOBAL_CLP; - - F_SET(clp, CL_SIGWINCH); -} -#undef GLOBAL_CLP - -/* - * sig_init -- - * Initialize signals. - * - * PUBLIC: int sig_init __P((GS *, SCR *)); - */ -int -sig_init(gp, sp) - GS *gp; - SCR *sp; -{ - CL_PRIVATE *clp; - - clp = GCLP(gp); - - if (sp == NULL) { - (void)sigemptyset(&__sigblockset); - if (sigaddset(&__sigblockset, SIGHUP) || - setsig(SIGHUP, &clp->oact[INDX_HUP], h_hup) || - sigaddset(&__sigblockset, SIGINT) || - setsig(SIGINT, &clp->oact[INDX_INT], h_int) || - sigaddset(&__sigblockset, SIGTERM) || - setsig(SIGTERM, &clp->oact[INDX_TERM], h_term) -#ifdef SIGWINCH - || - sigaddset(&__sigblockset, SIGWINCH) || - setsig(SIGWINCH, &clp->oact[INDX_WINCH], h_winch) -#endif - ) { - perr(gp->progname, NULL); - return (1); - } - } else - if (setsig(SIGHUP, NULL, h_hup) || - setsig(SIGINT, NULL, h_int) || - setsig(SIGTERM, NULL, h_term) -#ifdef SIGWINCH - || - setsig(SIGWINCH, NULL, h_winch) -#endif - ) { - msgq(sp, M_SYSERR, "signal-reset"); - } - return (0); -} - -/* - * setsig -- - * Set a signal handler. - */ -static int -setsig(signo, oactp, handler) - int signo; - struct sigaction *oactp; - void (*handler) __P((int)); -{ - struct sigaction act; - - /* - * Use sigaction(2), not signal(3), since we don't always want to - * restart system calls. The example is when waiting for a command - * mode keystroke and SIGWINCH arrives. Besides, you can't portably - * restart system calls (thanks, POSIX!). On the other hand, you - * can't portably NOT restart system calls (thanks, Sun!). SunOS - * used SA_INTERRUPT as their extension to NOT restart read calls. - * We sure hope nobody else used it for anything else. Mom told me - * there'd be days like this. She just never told me that there'd - * be so many. - */ - act.sa_handler = handler; - sigemptyset(&act.sa_mask); - -#ifdef SA_INTERRUPT - act.sa_flags = SA_INTERRUPT; -#else - act.sa_flags = 0; -#endif - return (sigaction(signo, &act, oactp)); -} - -/* - * sig_end -- - * End signal setup. - */ -static void -sig_end(gp) - GS *gp; -{ - CL_PRIVATE *clp; - - clp = GCLP(gp); - (void)sigaction(SIGHUP, NULL, &clp->oact[INDX_HUP]); - (void)sigaction(SIGINT, NULL, &clp->oact[INDX_INT]); - (void)sigaction(SIGTERM, NULL, &clp->oact[INDX_TERM]); -#ifdef SIGWINCH - (void)sigaction(SIGWINCH, NULL, &clp->oact[INDX_WINCH]); -#endif -} - -/* - * cl_func_std -- - * Initialize the standard curses functions. - */ -static void -cl_func_std(gp) - GS *gp; -{ - gp->scr_addstr = cl_addstr; - gp->scr_attr = cl_attr; - gp->scr_baud = cl_baud; - gp->scr_bell = cl_bell; - gp->scr_busy = NULL; - gp->scr_clrtoeol = cl_clrtoeol; - gp->scr_cursor = cl_cursor; - gp->scr_deleteln = cl_deleteln; - gp->scr_event = cl_event; - gp->scr_ex_adjust = cl_ex_adjust; - gp->scr_fmap = cl_fmap; - gp->scr_insertln = cl_insertln; - gp->scr_keyval = cl_keyval; - gp->scr_move = cl_move; - gp->scr_msg = NULL; - gp->scr_optchange = cl_optchange; - gp->scr_refresh = cl_refresh; - gp->scr_rename = cl_rename; - gp->scr_screen = cl_screen; - gp->scr_suspend = cl_suspend; - gp->scr_usage = cl_usage; -} - -/* - * perr -- - * Print system error. - */ -static void -perr(name, msg) - char *name, *msg; -{ - (void)fprintf(stderr, "%s:", name); - if (msg != NULL) - (void)fprintf(stderr, "%s:", msg); - (void)fprintf(stderr, "%s\n", strerror(errno)); - exit(1); -} diff --git a/contrib/nvi/cl/cl_read.c b/contrib/nvi/cl/cl_read.c deleted file mode 100644 index 8a95a77b2438..000000000000 --- a/contrib/nvi/cl/cl_read.c +++ /dev/null @@ -1,334 +0,0 @@ -/*- - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * Copyright (c) 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - * - * See the LICENSE file for redistribution information. - */ - -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)cl_read.c 10.15 (Berkeley) 9/24/96"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif -#include <sys/time.h> - -#include <bitstring.h> -#include <curses.h> -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "../common/common.h" -#include "../ex/script.h" -#include "cl.h" - -static input_t cl_read __P((SCR *, - u_int32_t, CHAR_T *, size_t, int *, struct timeval *)); -static int cl_resize __P((SCR *, size_t, size_t)); - -/* - * cl_event -- - * Return a single event. - * - * PUBLIC: int cl_event __P((SCR *, EVENT *, u_int32_t, int)); - */ -int -cl_event(sp, evp, flags, ms) - SCR *sp; - EVENT *evp; - u_int32_t flags; - int ms; -{ - struct timeval t, *tp; - CL_PRIVATE *clp; - size_t lines, columns; - int changed, nr; - - /* - * Queue signal based events. We never clear SIGHUP or SIGTERM events, - * so that we just keep returning them until the editor dies. - */ - clp = CLP(sp); -retest: if (LF_ISSET(EC_INTERRUPT) || F_ISSET(clp, CL_SIGINT)) { - if (F_ISSET(clp, CL_SIGINT)) { - F_CLR(clp, CL_SIGINT); - evp->e_event = E_INTERRUPT; - } else - evp->e_event = E_TIMEOUT; - return (0); - } - if (F_ISSET(clp, CL_SIGHUP | CL_SIGTERM | CL_SIGWINCH)) { - if (F_ISSET(clp, CL_SIGHUP)) { - evp->e_event = E_SIGHUP; - return (0); - } - if (F_ISSET(clp, CL_SIGTERM)) { - evp->e_event = E_SIGTERM; - return (0); - } - if (F_ISSET(clp, CL_SIGWINCH)) { - F_CLR(clp, CL_SIGWINCH); - if (cl_ssize(sp, 1, &lines, &columns, &changed)) - return (1); - if (changed) { - (void)cl_resize(sp, lines, columns); - evp->e_event = E_WRESIZE; - return (0); - } - /* No real change, ignore the signal. */ - } - } - - /* Set timer. */ - if (ms == 0) - tp = NULL; - else { - t.tv_sec = ms / 1000; - t.tv_usec = (ms % 1000) * 1000; - tp = &t; - } - - /* Read input characters. */ - switch (cl_read(sp, LF_ISSET(EC_QUOTED | EC_RAW), - clp->ibuf, sizeof(clp->ibuf), &nr, tp)) { - case INP_OK: - evp->e_csp = clp->ibuf; - evp->e_len = nr; - evp->e_event = E_STRING; - break; - case INP_EOF: - evp->e_event = E_EOF; - break; - case INP_ERR: - evp->e_event = E_ERR; - break; - case INP_INTR: - goto retest; - case INP_TIMEOUT: - evp->e_event = E_TIMEOUT; - break; - default: - abort(); - } - return (0); -} - -/* - * cl_read -- - * Read characters from the input. - */ -static input_t -cl_read(sp, flags, bp, blen, nrp, tp) - SCR *sp; - u_int32_t flags; - CHAR_T *bp; - size_t blen; - int *nrp; - struct timeval *tp; -{ - struct termios term1, term2; - struct timeval poll; - CL_PRIVATE *clp; - GS *gp; - SCR *tsp; - fd_set rdfd; - input_t rval; - int maxfd, nr, term_reset; - - gp = sp->gp; - clp = CLP(sp); - term_reset = 0; - - /* - * 1: A read from a file or a pipe. In this case, the reads - * never timeout regardless. This means that we can hang - * when trying to complete a map, but we're going to hang - * on the next read anyway. - */ - if (!F_ISSET(clp, CL_STDIN_TTY)) { - switch (nr = read(STDIN_FILENO, bp, blen)) { - case 0: - return (INP_EOF); - case -1: - goto err; - default: - *nrp = nr; - return (INP_OK); - } - /* NOTREACHED */ - } - - /* - * 2: A read with an associated timeout, e.g., trying to complete - * a map sequence. If input exists, we fall into #3. - */ - FD_ZERO(&rdfd); - poll.tv_sec = 0; - poll.tv_usec = 0; - if (tp != NULL) { - FD_SET(STDIN_FILENO, &rdfd); - switch (select(STDIN_FILENO + 1, - &rdfd, NULL, NULL, tp == NULL ? &poll : tp)) { - case 0: - return (INP_TIMEOUT); - case -1: - goto err; - default: - break; - } - } - - /* - * The user can enter a key in the editor to quote a character. If we - * get here and the next key is supposed to be quoted, do what we can. - * Reset the tty so that the user can enter a ^C, ^Q, ^S. There's an - * obvious race here, when the key has already been entered, but there's - * nothing that we can do to fix that problem. - * - * The editor can ask for the next literal character even thought it's - * generally running in line-at-a-time mode. Do what we can. - */ - if (LF_ISSET(EC_QUOTED | EC_RAW) && !tcgetattr(STDIN_FILENO, &term1)) { - term_reset = 1; - if (LF_ISSET(EC_QUOTED)) { - term2 = term1; - term2.c_lflag &= ~ISIG; - term2.c_iflag &= ~(IXON | IXOFF); - (void)tcsetattr(STDIN_FILENO, - TCSASOFT | TCSADRAIN, &term2); - } else - (void)tcsetattr(STDIN_FILENO, - TCSASOFT | TCSADRAIN, &clp->vi_enter); - } - - /* - * 3: Wait for input. - * - * Select on the command input and scripting window file descriptors. - * It's ugly that we wait on scripting file descriptors here, but it's - * the only way to keep from locking out scripting windows. - */ - if (F_ISSET(gp, G_SCRWIN)) { -loop: FD_ZERO(&rdfd); - FD_SET(STDIN_FILENO, &rdfd); - maxfd = STDIN_FILENO; - for (tsp = gp->dq.cqh_first; - tsp != (void *)&gp->dq; tsp = tsp->q.cqe_next) - if (F_ISSET(sp, SC_SCRIPT)) { - FD_SET(sp->script->sh_master, &rdfd); - if (sp->script->sh_master > maxfd) - maxfd = sp->script->sh_master; - } - switch (select(maxfd + 1, &rdfd, NULL, NULL, NULL)) { - case 0: - abort(); - case -1: - goto err; - default: - break; - } - if (!FD_ISSET(STDIN_FILENO, &rdfd)) { - if (sscr_input(sp)) - return (INP_ERR); - goto loop; - } - } - - /* - * 4: Read the input. - * - * !!! - * What's going on here is some scary stuff. Ex runs the terminal in - * canonical mode. So, the <newline> character terminating a line of - * input is returned in the buffer, but a trailing <EOF> character is - * not similarly included. As ex uses 0<EOF> and ^<EOF> as autoindent - * commands, it has to see the trailing <EOF> characters to determine - * the difference between the user entering "0ab" and "0<EOF>ab". We - * leave an extra slot in the buffer, so that we can add a trailing - * <EOF> character if the buffer isn't terminated by a <newline>. We - * lose if the buffer is too small for the line and exactly N characters - * are entered followed by an <EOF> character. - */ -#define ONE_FOR_EOF 1 - switch (nr = read(STDIN_FILENO, bp, blen - ONE_FOR_EOF)) { - case 0: /* EOF. */ - /* - * ^D in canonical mode returns a read of 0, i.e. EOF. EOF is - * a valid command, but we don't want to loop forever because - * the terminal driver is returning EOF because the user has - * disconnected. The editor will almost certainly try to write - * something before this fires, which should kill us, but You - * Never Know. - */ - if (++clp->eof_count < 50) { - bp[0] = clp->orig.c_cc[VEOF]; - *nrp = 1; - rval = INP_OK; - - } else - rval = INP_EOF; - break; - case -1: /* Error or interrupt. */ -err: if (errno == EINTR) - rval = INP_INTR; - else { - rval = INP_ERR; - msgq(sp, M_SYSERR, "input"); - } - break; - default: /* Input characters. */ - if (F_ISSET(sp, SC_EX) && bp[nr - 1] != '\n') - bp[nr++] = clp->orig.c_cc[VEOF]; - *nrp = nr; - clp->eof_count = 0; - rval = INP_OK; - break; - } - - /* Restore the terminal state if it was modified. */ - if (term_reset) - (void)tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &term1); - return (rval); -} - -/* - * cl_resize -- - * Reset the options for a resize event. - */ -static int -cl_resize(sp, lines, columns) - SCR *sp; - size_t lines, columns; -{ - ARGS *argv[2], a, b; - char b1[1024]; - - a.bp = b1; - b.bp = NULL; - a.len = b.len = 0; - argv[0] = &a; - argv[1] = &b; - - (void)snprintf(b1, sizeof(b1), "lines=%lu", (u_long)lines); - a.len = strlen(b1); - if (opts_set(sp, argv, NULL)) - return (1); - (void)snprintf(b1, sizeof(b1), "columns=%lu", (u_long)columns); - a.len = strlen(b1); - if (opts_set(sp, argv, NULL)) - return (1); - return (0); -} diff --git a/contrib/nvi/cl/cl_screen.c b/contrib/nvi/cl/cl_screen.c deleted file mode 100644 index 2ce58e80cc78..000000000000 --- a/contrib/nvi/cl/cl_screen.c +++ /dev/null @@ -1,581 +0,0 @@ -/*- - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * Copyright (c) 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - * - * See the LICENSE file for redistribution information. - */ - -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)cl_screen.c 10.49 (Berkeley) 9/24/96"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/queue.h> - -#include <bitstring.h> -#include <curses.h> -#include <errno.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "../common/common.h" -#include "cl.h" - -static int cl_ex_end __P((GS *)); -static int cl_ex_init __P((SCR *)); -static void cl_freecap __P((CL_PRIVATE *)); -static int cl_vi_end __P((GS *)); -static int cl_vi_init __P((SCR *)); -static int cl_putenv __P((char *, char *, u_long)); - -/* - * cl_screen -- - * Switch screen types. - * - * PUBLIC: int cl_screen __P((SCR *, u_int32_t)); - */ -int -cl_screen(sp, flags) - SCR *sp; - u_int32_t flags; -{ - CL_PRIVATE *clp; - GS *gp; - - gp = sp->gp; - clp = CLP(sp); - - /* See if the current information is incorrect. */ - if (F_ISSET(gp, G_SRESTART)) { - if (cl_quit(gp)) - return (1); - F_CLR(gp, G_SRESTART); - } - - /* See if we're already in the right mode. */ - if (LF_ISSET(SC_EX) && F_ISSET(sp, SC_SCR_EX) || - LF_ISSET(SC_VI) && F_ISSET(sp, SC_SCR_VI)) - return (0); - - /* - * Fake leaving ex mode. - * - * We don't actually exit ex or vi mode unless forced (e.g. by a window - * size change). This is because many curses implementations can't be - * called twice in a single program. Plus, it's faster. If the editor - * "leaves" vi to enter ex, when it exits ex we'll just fall back into - * vi. - */ - if (F_ISSET(sp, SC_SCR_EX)) - F_CLR(sp, SC_SCR_EX); - - /* - * Fake leaving vi mode. - * - * Clear out the rest of the screen if we're in the middle of a split - * screen. Move to the last line in the current screen -- this makes - * terminal scrolling happen naturally. Note: *don't* move past the - * end of the screen, as there are ex commands (e.g., :read ! cat file) - * that don't want to. Don't clear the info line, its contents may be - * valid, e.g. :file|append. - */ - if (F_ISSET(sp, SC_SCR_VI)) { - F_CLR(sp, SC_SCR_VI); - - if (sp->q.cqe_next != (void *)&gp->dq) { - (void)move(RLNO(sp, sp->rows), 0); - clrtobot(); - } - (void)move(RLNO(sp, sp->rows) - 1, 0); - refresh(); - } - - /* Enter the requested mode. */ - if (LF_ISSET(SC_EX)) { - if (cl_ex_init(sp)) - return (1); - F_SET(clp, CL_IN_EX | CL_SCR_EX_INIT); - - /* - * If doing an ex screen for ex mode, move to the last line - * on the screen. - */ - if (F_ISSET(sp, SC_EX) && clp->cup != NULL) - tputs(tgoto(clp->cup, - 0, O_VAL(sp, O_LINES) - 1), 1, cl_putchar); - } else { - if (cl_vi_init(sp)) - return (1); - F_CLR(clp, CL_IN_EX); - F_SET(clp, CL_SCR_VI_INIT); - } - return (0); -} - -/* - * cl_quit -- - * Shutdown the screens. - * - * PUBLIC: int cl_quit __P((GS *)); - */ -int -cl_quit(gp) - GS *gp; -{ - CL_PRIVATE *clp; - int rval; - - rval = 0; - clp = GCLP(gp); - - /* - * If we weren't really running, ignore it. This happens if the - * screen changes size before we've called curses. - */ - if (!F_ISSET(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT)) - return (0); - - /* Clean up the terminal mappings. */ - if (cl_term_end(gp)) - rval = 1; - - /* Really leave vi mode. */ - if (F_ISSET(clp, CL_STDIN_TTY) && - F_ISSET(clp, CL_SCR_VI_INIT) && cl_vi_end(gp)) - rval = 1; - - /* Really leave ex mode. */ - if (F_ISSET(clp, CL_STDIN_TTY) && - F_ISSET(clp, CL_SCR_EX_INIT) && cl_ex_end(gp)) - rval = 1; - - /* - * If we were running ex when we quit, or we're using an implementation - * of curses where endwin() doesn't get this right, restore the original - * terminal modes. - * - * XXX - * We always do this because it's too hard to figure out what curses - * implementations get it wrong. It may discard type-ahead characters - * from the tty queue. - */ - (void)tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->orig); - - F_CLR(clp, CL_SCR_EX_INIT | CL_SCR_VI_INIT); - return (rval); -} - -/* - * cl_vi_init -- - * Initialize the curses vi screen. - */ -static int -cl_vi_init(sp) - SCR *sp; -{ - CL_PRIVATE *clp; - GS *gp; - char *o_cols, *o_lines, *o_term, *ttype; - - gp = sp->gp; - clp = CLP(sp); - - /* If already initialized, just set the terminal modes. */ - if (F_ISSET(clp, CL_SCR_VI_INIT)) - goto fast; - - /* Curses vi always reads from (and writes to) a terminal. */ - if (!F_ISSET(clp, CL_STDIN_TTY) || !isatty(STDOUT_FILENO)) { - msgq(sp, M_ERR, - "016|Vi's standard input and output must be a terminal"); - return (1); - } - - /* We'll need a terminal type. */ - if (opts_empty(sp, O_TERM, 0)) - return (1); - ttype = O_STR(sp, O_TERM); - - /* - * XXX - * Changing the row/column and terminal values is done by putting them - * into the environment, which is then read by curses. What this loses - * in ugliness, it makes up for in stupidity. We can't simply put the - * values into the environment ourselves, because in the presence of a - * kernel mechanism for returning the window size, entering values into - * the environment will screw up future screen resizing events, e.g. if - * the user enters a :shell command and then resizes their window. So, - * if they weren't already in the environment, we make sure to delete - * them immediately after setting them. - * - * XXX - * Putting the TERM variable into the environment is necessary, even - * though we're using newterm() here. We may be using initscr() as - * the underlying function. - */ - o_term = getenv("TERM"); - cl_putenv("TERM", ttype, 0); - o_lines = getenv("LINES"); - cl_putenv("LINES", NULL, (u_long)O_VAL(sp, O_LINES)); - o_cols = getenv("COLUMNS"); - cl_putenv("COLUMNS", NULL, (u_long)O_VAL(sp, O_COLUMNS)); - - /* - * We don't care about the SCREEN reference returned by newterm, we - * never have more than one SCREEN at a time. - * - * XXX - * The SunOS initscr() can't be called twice. Don't even think about - * using it. It fails in subtle ways (e.g. select(2) on fileno(stdin) - * stops working). (The SVID notes that applications should only call - * initscr() once.) - * - * XXX - * The HP/UX newterm doesn't support the NULL first argument, so we - * have to specify the terminal type. - */ - errno = 0; - if (newterm(ttype, stdout, stdin) == NULL) { - if (errno) - msgq(sp, M_SYSERR, "%s", ttype); - else - msgq(sp, M_ERR, "%s: unknown terminal type", ttype); - return (1); - } - - if (o_term == NULL) - unsetenv("TERM"); - if (o_lines == NULL) - unsetenv("LINES"); - if (o_cols == NULL) - unsetenv("COLUMNS"); - - /* - * XXX - * Someone got let out alone without adult supervision -- the SunOS - * newterm resets the signal handlers. There's a race, but it's not - * worth closing. - */ - (void)sig_init(sp->gp, sp); - - /* - * We use raw mode. What we want is 8-bit clean, however, signals - * and flow control should continue to work. Admittedly, it sounds - * like cbreak, but it isn't. Using cbreak() can get you additional - * things like IEXTEN, which turns on flags like DISCARD and LNEXT. - * - * !!! - * If raw isn't turning off echo and newlines, something's wrong. - * However, it shouldn't hurt. - */ - noecho(); /* No character echo. */ - nonl(); /* No CR/NL translation. */ - raw(); /* 8-bit clean. */ - idlok(stdscr, 1); /* Use hardware insert/delete line. */ - - /* Put the cursor keys into application mode. */ - (void)keypad(stdscr, TRUE); - - /* - * XXX - * The screen TI sequence just got sent. See the comment in - * cl_funcs.c:cl_attr(). - */ - clp->ti_te = TI_SENT; - - /* - * XXX - * Historic implementations of curses handled SIGTSTP signals - * in one of three ways. They either: - * - * 1: Set their own handler, regardless. - * 2: Did not set a handler if a handler was already installed. - * 3: Set their own handler, but then called any previously set - * handler after completing their own cleanup. - * - * We don't try and figure out which behavior is in place, we force - * it to SIG_DFL after initializing the curses interface, which means - * that curses isn't going to take the signal. Since curses isn't - * reentrant (i.e., the whole curses SIGTSTP interface is a fantasy), - * we're doing The Right Thing. - */ - (void)signal(SIGTSTP, SIG_DFL); - - /* - * If flow control was on, turn it back on. Turn signals on. ISIG - * turns on VINTR, VQUIT, VDSUSP and VSUSP. The main curses code - * already installed a handler for VINTR. We're going to disable the - * other three. - * - * XXX - * We want to use ^Y as a vi scrolling command. If the user has the - * DSUSP character set to ^Y (common practice) clean it up. As it's - * equally possible that the user has VDSUSP set to 'a', we disable - * it regardless. It doesn't make much sense to suspend vi at read, - * so I don't think anyone will care. Alternatively, we could look - * it up in the table of legal command characters and turn it off if - * it matches one. VDSUSP wasn't in POSIX 1003.1-1990, so we test for - * it. - * - * XXX - * We don't check to see if the user had signals enabled originally. - * If they didn't, it's unclear what we're supposed to do here, but - * it's also pretty unlikely. - */ - if (tcgetattr(STDIN_FILENO, &clp->vi_enter)) { - msgq(sp, M_SYSERR, "tcgetattr"); - goto err; - } - if (clp->orig.c_iflag & IXON) - clp->vi_enter.c_iflag |= IXON; - if (clp->orig.c_iflag & IXOFF) - clp->vi_enter.c_iflag |= IXOFF; - - clp->vi_enter.c_lflag |= ISIG; -#ifdef VDSUSP - clp->vi_enter.c_cc[VDSUSP] = _POSIX_VDISABLE; -#endif - clp->vi_enter.c_cc[VQUIT] = _POSIX_VDISABLE; - clp->vi_enter.c_cc[VSUSP] = _POSIX_VDISABLE; - - /* - * XXX - * OSF/1 doesn't turn off the <discard>, <literal-next> or <status> - * characters when curses switches into raw mode. It should be OK - * to do it explicitly for everyone. - */ -#ifdef VDISCARD - clp->vi_enter.c_cc[VDISCARD] = _POSIX_VDISABLE; -#endif -#ifdef VLNEXT - clp->vi_enter.c_cc[VLNEXT] = _POSIX_VDISABLE; -#endif -#ifdef VSTATUS - clp->vi_enter.c_cc[VSTATUS] = _POSIX_VDISABLE; -#endif - - /* Initialize terminal based information. */ - if (cl_term_init(sp)) - goto err; - -fast: /* Set the terminal modes. */ - if (tcsetattr(STDIN_FILENO, TCSASOFT | TCSADRAIN, &clp->vi_enter)) { - msgq(sp, M_SYSERR, "tcsetattr"); -err: (void)cl_vi_end(sp->gp); - return (1); - } - return (0); -} - -/* - * cl_vi_end -- - * Shutdown the vi screen. - */ -static int -cl_vi_end(gp) - GS *gp; -{ - CL_PRIVATE *clp; - - clp = GCLP(gp); - - /* Restore the cursor keys to normal mode. */ - (void)keypad(stdscr, FALSE); - - /* - * If we were running vi when we quit, scroll the screen up a single - * line so we don't lose any information. - * - * Move to the bottom of the window (some endwin implementations don't - * do this for you). - */ - if (!F_ISSET(clp, CL_IN_EX)) { - (void)move(0, 0); - (void)deleteln(); - (void)move(LINES - 1, 0); - (void)refresh(); - } - - cl_freecap(clp); - - /* End curses window. */ - (void)endwin(); - - /* - * XXX - * The screen TE sequence just got sent. See the comment in - * cl_funcs.c:cl_attr(). - */ - clp->ti_te = TE_SENT; - - return (0); -} - -/* - * cl_ex_init -- - * Initialize the ex screen. - */ -static int -cl_ex_init(sp) - SCR *sp; -{ - CL_PRIVATE *clp; - - clp = CLP(sp); - - /* If already initialized, just set the terminal modes. */ - if (F_ISSET(clp, CL_SCR_EX_INIT)) - goto fast; - - /* If not reading from a file, we're done. */ - if (!F_ISSET(clp, CL_STDIN_TTY)) - return (0); - - /* Get the ex termcap/terminfo strings. */ - (void)cl_getcap(sp, "cup", &clp->cup); - (void)cl_getcap(sp, "smso", &clp->smso); - (void)cl_getcap(sp, "rmso", &clp->rmso); - (void)cl_getcap(sp, "el", &clp->el); - (void)cl_getcap(sp, "cuu1", &clp->cuu1); - - /* Enter_standout_mode and exit_standout_mode are paired. */ - if (clp->smso == NULL || clp->rmso == NULL) { - if (clp->smso != NULL) { - free(clp->smso); - clp->smso = NULL; - } - if (clp->rmso != NULL) { - free(clp->rmso); - clp->rmso = NULL; - } - } - - /* - * Turn on canonical mode, with normal input and output processing. - * Start with the original terminal settings as the user probably - * had them (including any local extensions) set correctly for the - * current terminal. - * - * !!! - * We can't get everything that we need portably; for example, ONLCR, - * mapping <newline> to <carriage-return> on output isn't required - * by POSIX 1003.1b-1993. If this turns out to be a problem, then - * we'll either have to play some games on the mapping, or we'll have - * to make all ex printf's output \r\n instead of \n. - */ - clp->ex_enter = clp->orig; - clp->ex_enter.c_lflag |= ECHO | ECHOE | ECHOK | ICANON | IEXTEN | ISIG; -#ifdef ECHOCTL - clp->ex_enter.c_lflag |= ECHOCTL; -#endif -#ifdef ECHOKE - clp->ex_enter.c_lflag |= ECHOKE; -#endif - clp->ex_enter.c_iflag |= ICRNL; - clp->ex_enter.c_oflag |= OPOST; -#ifdef ONLCR - clp->ex_enter.c_oflag |= ONLCR; -#endif - -fast: if (tcsetattr(STDIN_FILENO, TCSADRAIN | TCSASOFT, &clp->ex_enter)) { - msgq(sp, M_SYSERR, "tcsetattr"); - return (1); - } - return (0); -} - -/* - * cl_ex_end -- - * Shutdown the ex screen. - */ -static int -cl_ex_end(gp) - GS *gp; -{ - CL_PRIVATE *clp; - - clp = GCLP(gp); - - cl_freecap(clp); - - return (0); -} - -/* - * cl_getcap -- - * Retrieve termcap/terminfo strings. - * - * PUBLIC: int cl_getcap __P((SCR *, char *, char **)); - */ -int -cl_getcap(sp, name, elementp) - SCR *sp; - char *name, **elementp; -{ - size_t len; - char *t; - - if ((t = tigetstr(name)) != NULL && - t != (char *)-1 && (len = strlen(t)) != 0) { - MALLOC_RET(sp, *elementp, char *, len + 1); - memmove(*elementp, t, len + 1); - } - return (0); -} - -/* - * cl_freecap -- - * Free any allocated termcap/terminfo strings. - */ -static void -cl_freecap(clp) - CL_PRIVATE *clp; -{ - if (clp->el != NULL) { - free(clp->el); - clp->el = NULL; - } - if (clp->cup != NULL) { - free(clp->cup); - clp->cup = NULL; - } - if (clp->cuu1 != NULL) { - free(clp->cuu1); - clp->cuu1 = NULL; - } - if (clp->rmso != NULL) { - free(clp->rmso); - clp->rmso = NULL; - } - if (clp->smso != NULL) { - free(clp->smso); - clp->smso = NULL; - } -} - -/* - * cl_putenv -- - * Put a value into the environment. - */ -static int -cl_putenv(name, str, value) - char *name, *str; - u_long value; - -{ - char buf[40]; - - if (str == NULL) { - (void)snprintf(buf, sizeof(buf), "%lu", value); - return (setenv(name, buf, 1)); - } else - return (setenv(name, str, 1)); -} diff --git a/contrib/nvi/cl/cl_term.c b/contrib/nvi/cl/cl_term.c deleted file mode 100644 index c36bb3830e9f..000000000000 --- a/contrib/nvi/cl/cl_term.c +++ /dev/null @@ -1,460 +0,0 @@ -/*- - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * Copyright (c) 1993, 1994, 1995, 1996 - * Keith Bostic. All rights reserved. - * - * See the LICENSE file for redistribution information. - */ - -#include "config.h" - -#ifndef lint -static const char sccsid[] = "@(#)cl_term.c 10.22 (Berkeley) 9/15/96"; -#endif /* not lint */ - -#include <sys/types.h> -#include <sys/ioctl.h> -#include <sys/queue.h> -#include <sys/stat.h> - -#include <bitstring.h> -#include <curses.h> -#include <errno.h> -#include <limits.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <termios.h> -#include <unistd.h> - -#include "../common/common.h" -#include "cl.h" - -static int cl_pfmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t)); - -/* - * XXX - * THIS REQUIRES THAT ALL SCREENS SHARE A TERMINAL TYPE. - */ -typedef struct _tklist { - char *ts; /* Key's termcap string. */ - char *output; /* Corresponding vi command. */ - char *name; /* Name. */ - u_char value; /* Special value (for lookup). */ -} TKLIST; -static TKLIST const c_tklist[] = { /* Command mappings. */ - {"kil1", "O", "insert line"}, - {"kdch1", "x", "delete character"}, - {"kcud1", "j", "cursor down"}, - {"kel", "D", "delete to eol"}, - {"kind", "\004", "scroll down"}, /* ^D */ - {"kll", "$", "go to eol"}, - {"kend", "$", "go to eol"}, - {"khome", "^", "go to sol"}, - {"kich1", "i", "insert at cursor"}, - {"kdl1", "dd", "delete line"}, - {"kcub1", "h", "cursor left"}, - {"knp", "\006", "page down"}, /* ^F */ - {"kpp", "\002", "page up"}, /* ^B */ - {"kri", "\025", "scroll up"}, /* ^U */ - {"ked", "dG", "delete to end of screen"}, - {"kcuf1", "l", "cursor right"}, - {"kcuu1", "k", "cursor up"}, - {NULL}, -}; -static TKLIST const m1_tklist[] = { /* Input mappings (lookup). */ - {NULL}, -}; -static TKLIST const m2_tklist[] = { /* Input mappings (set or delete). */ - {"kcud1", "\033ja", "cursor down"}, /* ^[ja */ - {"kcub1", "\033ha", "cursor left"}, /* ^[ha */ - {"kcuu1", "\033ka", "cursor up"}, /* ^[ka */ - {"kcuf1", "\033la", "cursor right"}, /* ^[la */ - {NULL}, -}; - -/* - * cl_term_init -- - * Initialize the special keys defined by the termcap/terminfo entry. - * - * PUBLIC: int cl_term_init __P((SCR *)); - */ -int -cl_term_init(sp) - SCR *sp; -{ - KEYLIST *kp; - SEQ *qp; - TKLIST const *tkp; - char *t; - - /* Command mappings. */ - for (tkp = c_tklist; tkp->name != NULL; ++tkp) { - if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1) - continue; - if (seq_set(sp, tkp->name, strlen(tkp->name), t, strlen(t), - tkp->output, strlen(tkp->output), SEQ_COMMAND, - SEQ_NOOVERWRITE | SEQ_SCREEN)) - return (1); - } - - /* Input mappings needing to be looked up. */ - for (tkp = m1_tklist; tkp->name != NULL; ++tkp) { - if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1) - continue; - for (kp = keylist;; ++kp) - if (kp->value == tkp->value) - break; - if (kp == NULL) - continue; - if (seq_set(sp, tkp->name, strlen(tkp->name), t, strlen(t), - &kp->ch, 1, SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN)) - return (1); - } - - /* Input mappings that are already set or are text deletions. */ - for (tkp = m2_tklist; tkp->name != NULL; ++tkp) { - if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1) - continue; - /* - * !!! - * Some terminals' <cursor_left> keys send single <backspace> - * characters. This is okay in command mapping, but not okay - * in input mapping. That combination is the only one we'll - * ever see, hopefully, so kluge it here for now. - */ - if (!strcmp(t, "\b")) - continue; - if (tkp->output == NULL) { - if (seq_set(sp, tkp->name, strlen(tkp->name), - t, strlen(t), NULL, 0, - SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN)) - return (1); - } else - if (seq_set(sp, tkp->name, strlen(tkp->name), - t, strlen(t), tkp->output, strlen(tkp->output), - SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN)) - return (1); - } - - /* - * Rework any function key mappings that were set before the - * screen was initialized. - */ - for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) - if (F_ISSET(qp, SEQ_FUNCMAP)) - (void)cl_pfmap(sp, qp->stype, - qp->input, qp->ilen, qp->output, qp->olen); - return (0); -} - -/* - * cl_term_end -- - * End the special keys defined by the termcap/terminfo entry. - * - * PUBLIC: int cl_term_end __P((GS *)); - */ -int -cl_term_end(gp) - GS *gp; -{ - SEQ *qp, *nqp; - - /* Delete screen specific mappings. */ - for (qp = gp->seqq.lh_first; qp != NULL; qp = nqp) { - nqp = qp->q.le_next; - if (F_ISSET(qp, SEQ_SCREEN)) - (void)seq_mdel(qp); - } - return (0); -} - -/* - * cl_fmap -- - * Map a function key. - * - * PUBLIC: int cl_fmap __P((SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t)); - */ -int -cl_fmap(sp, stype, from, flen, to, tlen) - SCR *sp; - seq_t stype; - CHAR_T *from, *to; - size_t flen, tlen; -{ - /* Ignore until the screen is running, do the real work then. */ - if (F_ISSET(sp, SC_VI) && !F_ISSET(sp, SC_SCR_VI)) - return (0); - if (F_ISSET(sp, SC_EX) && !F_ISSET(sp, SC_SCR_EX)) - return (0); - - return (cl_pfmap(sp, stype, from, flen, to, tlen)); -} - -/* - * cl_pfmap -- - * Map a function key (private version). - */ -static int -cl_pfmap(sp, stype, from, flen, to, tlen) - SCR *sp; - seq_t stype; - CHAR_T *from, *to; - size_t flen, tlen; -{ - size_t nlen; - char *p, keyname[64]; - - (void)snprintf(keyname, sizeof(keyname), "kf%d", atoi(from + 1)); - if ((p = tigetstr(keyname)) == NULL || - p == (char *)-1 || strlen(p) == 0) - p = NULL; - if (p == NULL) { - msgq_str(sp, M_ERR, from, "233|This terminal has no %s key"); - return (1); - } - - nlen = snprintf(keyname, - sizeof(keyname), "function key %d", atoi(from + 1)); - return (seq_set(sp, keyname, nlen, - p, strlen(p), to, tlen, stype, SEQ_NOOVERWRITE | SEQ_SCREEN)); -} - -/* - * cl_optchange -- - * Curses screen specific "option changed" routine. - * - * PUBLIC: int cl_optchange __P((SCR *, int, char *, u_long *)); - */ -int -cl_optchange(sp, opt, str, valp) - SCR *sp; - int opt; - char *str; - u_long *valp; -{ - CL_PRIVATE *clp; - - clp = CLP(sp); - - switch (opt) { - case O_COLUMNS: - case O_LINES: - case O_TERM: - /* - * Changing the columns, lines or terminal require that - * we restart the screen. - */ - F_SET(sp->gp, G_SRESTART); - F_CLR(sp, SC_SCR_EX | SC_SCR_VI); - break; - case O_MESG: - (void)cl_omesg(sp, clp, !*valp); - break; - case O_WINDOWNAME: - if (*valp) { - F_CLR(clp, CL_RENAME_OK); - - (void)cl_rename(sp, NULL, 0); - } else { - F_SET(clp, CL_RENAME_OK); - - /* - * If the screen is live, i.e. we're not reading the - * .exrc file, update the window. - */ - if (sp->frp != NULL && sp->frp->name != NULL) - (void)cl_rename(sp, sp->frp->name, 1); - } - break; - } - return (0); -} - -/* - * cl_omesg -- - * Turn the tty write permission on or off. - * - * PUBLIC: int cl_omesg __P((SCR *, CL_PRIVATE *, int)); - */ -int -cl_omesg(sp, clp, on) - SCR *sp; - CL_PRIVATE *clp; - int on; -{ - struct stat sb; - char *tty; - - /* Find the tty, get the current permissions. */ - if ((tty = ttyname(STDERR_FILENO)) == NULL) { - if (sp != NULL) - msgq(sp, M_SYSERR, "stderr"); - return (1); - } - if (stat(tty, &sb) < 0) { - if (sp != NULL) - msgq(sp, M_SYSERR, "%s", tty); - return (1); - } - - /* Save the original status if it's unknown. */ - if (clp->tgw == TGW_UNKNOWN) - clp->tgw = sb.st_mode & S_IWGRP ? TGW_SET : TGW_UNSET; - - /* Toggle the permissions. */ - if (on) { - if (chmod(tty, sb.st_mode | S_IWGRP) < 0) { - if (sp != NULL) - msgq(sp, M_SYSERR, - "046|messages not turned on: %s", tty); - return (1); - } - } else - if (chmod(tty, sb.st_mode & ~S_IWGRP) < 0) { - if (sp != NULL) - msgq(sp, M_SYSERR, - "045|messages not turned off: %s", tty); - return (1); - } - return (0); -} - -/* - * cl_ssize -- - * Return the terminal size. - * - * PUBLIC: int cl_ssize __P((SCR *, int, size_t *, size_t *, int *)); - */ -int -cl_ssize(sp, sigwinch, rowp, colp, changedp) - SCR *sp; - int sigwinch; - size_t *rowp, *colp; - int *changedp; -{ -#ifdef TIOCGWINSZ - struct winsize win; -#endif - size_t col, row; - int rval; - char *p; - - /* Assume it's changed. */ - if (changedp != NULL) - *changedp = 1; - - /* - * !!! - * sp may be NULL. - * - * Get the screen rows and columns. If the values are wrong, it's - * not a big deal -- as soon as the user sets them explicitly the - * environment will be set and the screen package will use the new - * values. - * - * Try TIOCGWINSZ. - */ - row = col = 0; -#ifdef TIOCGWINSZ - if (ioctl(STDERR_FILENO, TIOCGWINSZ, &win) != -1) { - row = win.ws_row; - col = win.ws_col; - } -#endif - /* If here because of suspend or a signal, only trust TIOCGWINSZ. */ - if (sigwinch) { - /* - * Somebody didn't get TIOCGWINSZ right, or has suspend - * without window resizing support. The user just lost, - * but there's nothing we can do. - */ - if (row == 0 || col == 0) { - if (changedp != NULL) - *changedp = 0; - return (0); - } - - /* - * SunOS systems deliver SIGWINCH when windows are uncovered - * as well as when they change size. In addition, we call - * here when continuing after being suspended since the window - * may have changed size. Since we don't want to background - * all of the screens just because the window was uncovered, - * ignore the signal if there's no change. - */ - if (sp != NULL && - row == O_VAL(sp, O_LINES) && col == O_VAL(sp, O_COLUMNS)) { - if (changedp != NULL) - *changedp = 0; - return (0); - } - - if (rowp != NULL) - *rowp = row; - if (colp != NULL) - *colp = col; - return (0); - } - - /* - * !!! - * If TIOCGWINSZ failed, or had entries of 0, try termcap. This - * routine is called before any termcap or terminal information - * has been set up. If there's no TERM environmental variable set, - * let it go, at least ex can run. - */ - if (row == 0 || col == 0) { - if ((p = getenv("TERM")) == NULL) - goto noterm; - if (row == 0) - if ((rval = tigetnum("lines")) < 0) - msgq(sp, M_SYSERR, "tigetnum: lines"); - else - row = rval; - if (col == 0) - if ((rval = tigetnum("cols")) < 0) - msgq(sp, M_SYSERR, "tigetnum: cols"); - else - col = rval; - } - - /* If nothing else, well, it's probably a VT100. */ -noterm: if (row == 0) - row = 24; - if (col == 0) - col = 80; - - /* - * !!! - * POSIX 1003.2 requires the environment to override everything. - * Often, people can get nvi to stop messing up their screen by - * deleting the LINES and COLUMNS environment variables from their - * dot-files. - */ - if ((p = getenv("LINES")) != NULL) - row = strtol(p, NULL, 10); - if ((p = getenv("COLUMNS")) != NULL) - col = strtol(p, NULL, 10); - - if (rowp != NULL) - *rowp = row; - if (colp != NULL) - *colp = col; - return (0); -} - -/* - * cl_putchar -- - * Function version of putchar, for tputs. - * - * PUBLIC: int cl_putchar __P((int)); - */ -int -cl_putchar(ch) - int ch; -{ - return (putchar(ch)); -} |
