diff options
Diffstat (limited to 'usr.bin/vi/svi/svi_term.c')
-rw-r--r-- | usr.bin/vi/svi/svi_term.c | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/usr.bin/vi/svi/svi_term.c b/usr.bin/vi/svi/svi_term.c new file mode 100644 index 000000000000..baedfa7f931f --- /dev/null +++ b/usr.bin/vi/svi/svi_term.c @@ -0,0 +1,310 @@ +/*- + * Copyright (c) 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)svi_term.c 8.5 (Berkeley) 8/14/94"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/queue.h> +#include <sys/time.h> + +#include <bitstring.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 "compat.h" +#include <curses.h> +#include <db.h> +#include <regex.h> + +#include "vi.h" +#include "../vi/vcmd.h" +#include "excmd.h" +#include "svi_screen.h" + +/* + * 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. */ +#ifdef SYSV_CURSES + {"kil1", "O", "insert line"}, + {"kdch1", "x", "delete character"}, + {"kcud1", "j", "cursor down"}, + {"kel", "D", "delete to eol"}, + {"kind", "\004", "scroll down"}, + {"kll", "$", "go to eol"}, + {"khome", "^", "go to sol"}, + {"kich1", "i", "insert at cursor"}, + {"kdl1", "dd", "delete line"}, + {"kcub1", "h", "cursor left"}, + {"knp", "\006", "page down"}, + {"kpp", "\002", "page up"}, + {"kri", "\025", "scroll up"}, + {"ked", "dG", "delete to end of screen"}, + {"kcuf1", "l", "cursor right"}, + {"kcuu1", "k", "cursor up"}, +#else + {"kA", "O", "insert line"}, + {"kD", "x", "delete character"}, + {"kd", "j", "cursor down"}, + {"kE", "D", "delete to eol"}, + {"kF", "\004", "scroll down"}, + {"kH", "$", "go to eol"}, + {"kh", "^", "go to sol"}, + {"kI", "i", "insert at cursor"}, + {"kL", "dd", "delete line"}, + {"kl", "h", "cursor left"}, + {"kN", "\006", "page down"}, + {"kP", "\002", "page up"}, + {"kR", "\025", "scroll up"}, + {"kS", "dG", "delete to end of screen"}, + {"kr", "l", "cursor right"}, + {"ku", "k", "cursor up"}, +#endif + {NULL}, +}; +static TKLIST const m1_tklist[] = { /* Input mappings (lookup). */ + {NULL}, +}; +static TKLIST const m2_tklist[] = { /* Input mappings (set or delete). */ +#ifdef SYSV_CURSES + {"kcud1", "\033ja", "cursor down"}, + {"kcub1", "\033ha", "cursor left"}, + {"kcuu1", "\033ka", "cursor up"}, + {"kcuf1", "\033la", "cursor right"}, +#else + {"kd", "\033ja", "cursor down"}, + {"kl", "\033ha", "cursor left"}, + {"ku", "\033ka", "cursor up"}, + {"kr", "\033la", "cursor right"}, +#endif + {NULL}, +}; + +/* + * svi_term_init -- + * Initialize the special keys defined by the termcap/terminfo entry. + */ +int +svi_term_init(sp) + SCR *sp; +{ + KEYLIST *kp; + SEQ *qp; + TKLIST const *tkp; + size_t len; + char *sbp, *s, *t, sbuf[1024]; + + /* Command mappings. */ + for (tkp = c_tklist; tkp->name != NULL; ++tkp) { +#ifdef SYSV_CURSES + if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1) + continue; +#else + sbp = sbuf; + if ((t = tgetstr(tkp->ts, &sbp)) == NULL) + continue; +#endif + if (seq_set(sp, tkp->name, strlen(tkp->name), t, strlen(t), + tkp->output, strlen(tkp->output), SEQ_COMMAND, SEQ_SCREEN)) + return (1); + } + + /* Input mappings needing to be looked up. */ + for (tkp = m1_tklist; tkp->name != NULL; ++tkp) { +#ifdef SYSV_CURSES + if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1) + continue; +#else + sbp = sbuf; + if ((t = tgetstr(tkp->ts, &sbp)) == NULL) + continue; +#endif + 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_SCREEN)) + return (1); + } + + /* Input mappings that are already set or are text deletions. */ + for (tkp = m2_tklist; tkp->name != NULL; ++tkp) { +#ifdef SYSV_CURSES + if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1) + continue; +#else + sbp = sbuf; + if ((t = tgetstr(tkp->ts, &sbp)) == NULL) + continue; +#endif + /* + * !!! + * 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_SCREEN)) + return (1); + } else + if (seq_set(sp, tkp->name, strlen(tkp->name), + t, strlen(t), tkp->output, strlen(tkp->output), + SEQ_INPUT, SEQ_SCREEN)) + return (1); + } + + /* Rework any function key mappings. */ + for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) { + if (!F_ISSET(qp, SEQ_FUNCMAP)) + continue; + (void)svi_fmap(sp, qp->stype, + qp->input, qp->ilen, qp->output, qp->olen); + } + + /* Set up the visual bell information. */ + t = sbuf; + if (tgetstr("vb", &t) != NULL && (len = t - sbuf) != 0) { + MALLOC_RET(sp, s, char *, len); + memmove(s, sbuf, len); + if (SVP(sp)->VB != NULL) + free(SVP(sp)->VB); + SVP(sp)->VB = s; + return (0); + } + + return (0); +} + +/* + * svi_term_end -- + * End the special keys defined by the termcap/terminfo entry. + */ +int +svi_term_end(sp) + SCR *sp; +{ + SEQ *qp, *nqp; + + /* Delete screen specific mappings. */ + for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = nqp) { + nqp = qp->q.le_next; + if (!F_ISSET(qp, SEQ_SCREEN)) + continue; + (void)seq_mdel(qp); + } + return (0); +} + +/* + * svi_fmap -- + * Map a function key. + */ +int +svi_fmap(sp, stype, from, flen, to, tlen) + SCR *sp; + enum seqtype stype; + CHAR_T *from, *to; + size_t flen, tlen; +{ + char *t, keyname[64]; + size_t nlen; + + /* If the terminal isn't initialized, there's nothing to do. */ + if (!F_ISSET(SVP(sp), SVI_CURSES_INIT)) + return (0); + +#ifdef SYSV_CURSES + (void)snprintf(keyname, sizeof(keyname), "kf%d", atoi(from + 1)); + if ((t = tigetstr(keyname)) == NULL || t == (char *)-1) + t = NULL; +#else + /* + * !!! + * Historically, the 4BSD termcap code didn't support functions keys + * greater than 9. This was silently enforced -- asking for key k12 + * returned 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 that the implementors of any System V + * compatibility code or an extended termcap used those codes. + */ + { int n; char *sbp, sbuf[1024]; + 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', + }; + if ((n = atoi(from + 1)) > 63) { + msgq(sp, M_ERR, + "Termcap has no code for the %s function key", + from); + return (1); + } + (void)snprintf(keyname, sizeof(keyname), + "%c%c", n <= 10 ? 'k' : 'F', codes[n]); + sbp = sbuf; + t = tgetstr(keyname, &sbp); + } +#endif + if (t == NULL) { + msgq(sp, M_ERR, "This terminal has no %s key", from); + return (1); + } + nlen = snprintf(keyname, + sizeof(keyname), "function key %d", atoi(from + 1)); + return (seq_set(sp, keyname, nlen, t, strlen(t), + to, tlen, stype, SEQ_SCREEN | SEQ_USERDEF)); +} |