BSD 4_4_Lite2 release
[unix-history] / usr / src / contrib / nvi.1.43 / svi / svi_term.c
CommitLineData
fd88f5c5
C
1/*-
2 * Copyright (c) 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35static char sccsid[] = "@(#)svi_term.c 9.1 (Berkeley) 11/9/94";
36#endif /* not lint */
37
38#include <sys/types.h>
39#include <sys/queue.h>
40#include <sys/time.h>
41
42#include <bitstring.h>
43#include <errno.h>
44#include <limits.h>
45#include <signal.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <termios.h>
50#include <unistd.h>
51
52#include "compat.h"
53#include <curses.h>
54#include <db.h>
55#include <regex.h>
56
57#include "vi.h"
58#include "../vi/vcmd.h"
59#include "excmd.h"
60#include "svi_screen.h"
61
62/*
63 * XXX
64 * THIS REQUIRES THAT ALL SCREENS SHARE A TERMINAL TYPE.
65 */
66typedef struct _tklist {
67 char *ts; /* Key's termcap string. */
68 char *output; /* Corresponding vi command. */
69 char *name; /* Name. */
70 u_char value; /* Special value (for lookup). */
71} TKLIST;
72static TKLIST const c_tklist[] = { /* Command mappings. */
73#ifdef SYSV_CURSES
74 {"kil1", "O", "insert line"},
75 {"kdch1", "x", "delete character"},
76 {"kcud1", "j", "cursor down"},
77 {"kel", "D", "delete to eol"},
78 {"kind", "\004", "scroll down"},
79 {"kll", "$", "go to eol"},
80 {"khome", "^", "go to sol"},
81 {"kich1", "i", "insert at cursor"},
82 {"kdl1", "dd", "delete line"},
83 {"kcub1", "h", "cursor left"},
84 {"knp", "\006", "page down"},
85 {"kpp", "\002", "page up"},
86 {"kri", "\025", "scroll up"},
87 {"ked", "dG", "delete to end of screen"},
88 {"kcuf1", "l", "cursor right"},
89 {"kcuu1", "k", "cursor up"},
90#else
91 {"kA", "O", "insert line"},
92 {"kD", "x", "delete character"},
93 {"kd", "j", "cursor down"},
94 {"kE", "D", "delete to eol"},
95 {"kF", "\004", "scroll down"},
96 {"kH", "$", "go to eol"},
97 {"kh", "^", "go to sol"},
98 {"kI", "i", "insert at cursor"},
99 {"kL", "dd", "delete line"},
100 {"kl", "h", "cursor left"},
101 {"kN", "\006", "page down"},
102 {"kP", "\002", "page up"},
103 {"kR", "\025", "scroll up"},
104 {"kS", "dG", "delete to end of screen"},
105 {"kr", "l", "cursor right"},
106 {"ku", "k", "cursor up"},
107#endif
108 {NULL},
109};
110static TKLIST const m1_tklist[] = { /* Input mappings (lookup). */
111 {NULL},
112};
113static TKLIST const m2_tklist[] = { /* Input mappings (set or delete). */
114#ifdef SYSV_CURSES
115 {"kcud1", "\033ja", "cursor down"},
116 {"kcub1", "\033ha", "cursor left"},
117 {"kcuu1", "\033ka", "cursor up"},
118 {"kcuf1", "\033la", "cursor right"},
119#else
120 {"kd", "\033ja", "cursor down"},
121 {"kl", "\033ha", "cursor left"},
122 {"ku", "\033ka", "cursor up"},
123 {"kr", "\033la", "cursor right"},
124#endif
125 {NULL},
126};
127
128/*
129 * svi_term_init --
130 * Initialize the special keys defined by the termcap/terminfo entry.
131 */
132int
133svi_term_init(sp)
134 SCR *sp;
135{
136 KEYLIST *kp;
137 SEQ *qp;
138 TKLIST const *tkp;
139 size_t len;
140 char *sbp, *s, *t, sbuf[1024];
141
142 /* Command mappings. */
143 for (tkp = c_tklist; tkp->name != NULL; ++tkp) {
144#ifdef SYSV_CURSES
145 if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
146 continue;
147#else
148 sbp = sbuf;
149 if ((t = tgetstr(tkp->ts, &sbp)) == NULL)
150 continue;
151#endif
152 if (seq_set(sp, tkp->name, strlen(tkp->name), t, strlen(t),
153 tkp->output, strlen(tkp->output), SEQ_COMMAND,
154 SEQ_NOOVERWRITE | SEQ_SCREEN))
155 return (1);
156 }
157
158 /* Input mappings needing to be looked up. */
159 for (tkp = m1_tklist; tkp->name != NULL; ++tkp) {
160#ifdef SYSV_CURSES
161 if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
162 continue;
163#else
164 sbp = sbuf;
165 if ((t = tgetstr(tkp->ts, &sbp)) == NULL)
166 continue;
167#endif
168 for (kp = keylist;; ++kp)
169 if (kp->value == tkp->value)
170 break;
171 if (kp == NULL)
172 continue;
173 if (seq_set(sp, tkp->name, strlen(tkp->name), t, strlen(t),
174 &kp->ch, 1, SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
175 return (1);
176 }
177
178 /* Input mappings that are already set or are text deletions. */
179 for (tkp = m2_tklist; tkp->name != NULL; ++tkp) {
180#ifdef SYSV_CURSES
181 if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
182 continue;
183#else
184 sbp = sbuf;
185 if ((t = tgetstr(tkp->ts, &sbp)) == NULL)
186 continue;
187#endif
188 /*
189 * !!!
190 * Some terminals' <cursor_left> keys send single <backspace>
191 * characters. This is okay in command mapping, but not okay
192 * in input mapping. That combination is the only one we'll
193 * ever see, hopefully, so kluge it here for now.
194 */
195 if (!strcmp(t, "\b"))
196 continue;
197 if (tkp->output == NULL) {
198 if (seq_set(sp, tkp->name, strlen(tkp->name),
199 t, strlen(t), NULL, 0,
200 SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
201 return (1);
202 } else
203 if (seq_set(sp, tkp->name, strlen(tkp->name),
204 t, strlen(t), tkp->output, strlen(tkp->output),
205 SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
206 return (1);
207 }
208
209 /* Rework any function key mappings. */
210 for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = qp->q.le_next) {
211 if (!F_ISSET(qp, SEQ_FUNCMAP))
212 continue;
213 (void)svi_fmap(sp, qp->stype,
214 qp->input, qp->ilen, qp->output, qp->olen);
215 }
216
217 /* Set up the visual bell information. */
218 t = sbuf;
219 if (tgetstr("vb", &t) != NULL && (len = t - sbuf) != 0) {
220 MALLOC_RET(sp, s, char *, len);
221 memmove(s, sbuf, len);
222 if (SVP(sp)->VB != NULL)
223 free(SVP(sp)->VB);
224 SVP(sp)->VB = s;
225 return (0);
226 }
227
228 return (0);
229}
230
231/*
232 * svi_term_end --
233 * End the special keys defined by the termcap/terminfo entry.
234 */
235int
236svi_term_end(sp)
237 SCR *sp;
238{
239 SEQ *qp, *nqp;
240
241 /* Delete screen specific mappings. */
242 for (qp = sp->gp->seqq.lh_first; qp != NULL; qp = nqp) {
243 nqp = qp->q.le_next;
244 if (!F_ISSET(qp, SEQ_SCREEN))
245 continue;
246 (void)seq_mdel(qp);
247 }
248 return (0);
249}
250
251/*
252 * svi_fmap --
253 * Map a function key.
254 */
255int
256svi_fmap(sp, stype, from, flen, to, tlen)
257 SCR *sp;
258 enum seqtype stype;
259 CHAR_T *from, *to;
260 size_t flen, tlen;
261{
262 size_t nlen;
263 int nf;
264 char *p, *t, keyname[64];
265
266 /* If the terminal isn't initialized, there's nothing to do. */
267 if (!F_ISSET(SVP(sp), SVI_CURSES_INIT))
268 return (0);
269
270#ifdef SYSV_CURSES
271 (void)snprintf(keyname, sizeof(keyname), "kf%d", atoi(from + 1));
272 if ((t = tigetstr(keyname)) == NULL || t == (char *)-1)
273 t = NULL;
274#else
275 /*
276 * !!!
277 * Historically, the 4BSD termcap code didn't support functions keys
278 * greater than 9. This was silently enforced -- asking for key k12
279 * returned the value for k1. We try and get around this by using
280 * the tables specified in the terminfo(TI_ENV) man page from the 3rd
281 * Edition SVID. This assumes that the implementors of any System V
282 * compatibility code or an extended termcap used those codes.
283 */
284 { int n; char *sbp, sbuf[1024];
285 static const char codes[] = {
286/* 0-10 */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ';',
287/* 11-19 */ '1', '2', '3', '4', '5', '6', '7', '8', '9',
288/* 20-63 */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
289 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
290 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
291 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
292 };
293 if ((n = atoi(from + 1)) > 63) {
294 p = msg_print(sp, from, &nf);
295 msgq(sp, M_ERR,
296 "228|Termcap has no code for the %s function key", p);
297 if (nf)
298 FREE_SPACE(sp, p, 0);
299 return (1);
300 }
301 (void)snprintf(keyname, sizeof(keyname),
302 "%c%c", n <= 10 ? 'k' : 'F', codes[n]);
303 sbp = sbuf;
304 t = tgetstr(keyname, &sbp);
305 }
306#endif
307 if (t == NULL) {
308 p = msg_print(sp, from, &nf);
309 msgq(sp, M_ERR, "229|This terminal has no %s key", p);
310 if (nf)
311 FREE_SPACE(sp, p, 0);
312 return (1);
313 }
314
315 nlen = snprintf(keyname,
316 sizeof(keyname), "function key %d", atoi(from + 1));
317 return (seq_set(sp, keyname, nlen, t, strlen(t),
318 to, tlen, stype, SEQ_NOOVERWRITE | SEQ_SCREEN | SEQ_USERDEF));
319}