17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
523a1cceaSRoger A. Faulkner * Common Development and Distribution License (the "License").
623a1cceaSRoger A. Faulkner * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
2123a1cceaSRoger A. Faulkner
22f6db9f27Scf /*
2323a1cceaSRoger A. Faulkner * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24f6db9f27Scf */
25f6db9f27Scf
267c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
277c478bd9Sstevel@tonic-gate /* All Rights Reserved */
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */
317c478bd9Sstevel@tonic-gate
327c478bd9Sstevel@tonic-gate #include "ex.h"
337c478bd9Sstevel@tonic-gate #include "ex_tty.h"
347c478bd9Sstevel@tonic-gate #include "ex_vis.h"
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate /*
377c478bd9Sstevel@tonic-gate * Input routines for open/visual.
387c478bd9Sstevel@tonic-gate * We handle upper case only terminals in visual and reading from the
397c478bd9Sstevel@tonic-gate * echo area here as well as notification on large changes
407c478bd9Sstevel@tonic-gate * which appears in the echo area.
417c478bd9Sstevel@tonic-gate */
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate /*
447c478bd9Sstevel@tonic-gate * Return the key.
457c478bd9Sstevel@tonic-gate */
46f6db9f27Scf void
ungetkey(int c)47f6db9f27Scf ungetkey(int c)
487c478bd9Sstevel@tonic-gate {
497c478bd9Sstevel@tonic-gate
507c478bd9Sstevel@tonic-gate if (Peekkey != ATTN)
517c478bd9Sstevel@tonic-gate Peekkey = c;
527c478bd9Sstevel@tonic-gate }
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate /*
557c478bd9Sstevel@tonic-gate * Return a keystroke, but never a ^@.
567c478bd9Sstevel@tonic-gate */
57f6db9f27Scf int
getkey(void)58f6db9f27Scf getkey(void)
597c478bd9Sstevel@tonic-gate {
60f6db9f27Scf int c; /* char --> int */
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate do {
637c478bd9Sstevel@tonic-gate c = getbr();
647c478bd9Sstevel@tonic-gate if (c==0)
65f6db9f27Scf (void) beep();
667c478bd9Sstevel@tonic-gate } while (c == 0);
677c478bd9Sstevel@tonic-gate return (c);
687c478bd9Sstevel@tonic-gate }
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate /*
717c478bd9Sstevel@tonic-gate * Tell whether next keystroke would be a ^@.
727c478bd9Sstevel@tonic-gate */
73f6db9f27Scf int
peekbr(void)74f6db9f27Scf peekbr(void)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate Peekkey = getbr();
787c478bd9Sstevel@tonic-gate return (Peekkey == 0);
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate short precbksl;
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate /*
847c478bd9Sstevel@tonic-gate * Get a keystroke, including a ^@.
857c478bd9Sstevel@tonic-gate * If an key was returned with ungetkey, that
867c478bd9Sstevel@tonic-gate * comes back first. Next comes unread input (e.g.
877c478bd9Sstevel@tonic-gate * from repeating commands with .), and finally new
887c478bd9Sstevel@tonic-gate * keystrokes.
897c478bd9Sstevel@tonic-gate *
907c478bd9Sstevel@tonic-gate * The hard work here is in mapping of \ escaped
917c478bd9Sstevel@tonic-gate * characters on upper case only terminals.
927c478bd9Sstevel@tonic-gate */
93f6db9f27Scf int
getbr(void)94f6db9f27Scf getbr(void)
957c478bd9Sstevel@tonic-gate {
967c478bd9Sstevel@tonic-gate unsigned char ch;
97f6db9f27Scf int c, d;
98f6db9f27Scf unsigned char *colp;
997c478bd9Sstevel@tonic-gate int cnt;
1007c478bd9Sstevel@tonic-gate static unsigned char Peek2key;
1017c478bd9Sstevel@tonic-gate extern short slevel, ttyindes;
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate getATTN:
1047c478bd9Sstevel@tonic-gate if (Peekkey) {
1057c478bd9Sstevel@tonic-gate c = Peekkey;
1067c478bd9Sstevel@tonic-gate Peekkey = 0;
1077c478bd9Sstevel@tonic-gate return (c);
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate if (Peek2key) {
1107c478bd9Sstevel@tonic-gate c = Peek2key;
1117c478bd9Sstevel@tonic-gate Peek2key = 0;
1127c478bd9Sstevel@tonic-gate return (c);
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate if (vglobp) {
1157c478bd9Sstevel@tonic-gate if (*vglobp)
1167c478bd9Sstevel@tonic-gate return (lastvgk = *vglobp++);
1177c478bd9Sstevel@tonic-gate lastvgk = 0;
1187c478bd9Sstevel@tonic-gate return (ESCAPE);
1197c478bd9Sstevel@tonic-gate }
1207c478bd9Sstevel@tonic-gate if (vmacp) {
1217c478bd9Sstevel@tonic-gate if (*vmacp)
1227c478bd9Sstevel@tonic-gate return(*vmacp++);
1237c478bd9Sstevel@tonic-gate /* End of a macro or set of nested macros */
1247c478bd9Sstevel@tonic-gate vmacp = 0;
1257c478bd9Sstevel@tonic-gate if (inopen == -1) /* don't mess up undo for esc esc */
1267c478bd9Sstevel@tonic-gate vundkind = VMANY;
1277c478bd9Sstevel@tonic-gate inopen = 1; /* restore old setting now that macro done */
1287c478bd9Sstevel@tonic-gate vch_mac = VC_NOTINMAC;
1297c478bd9Sstevel@tonic-gate }
1307c478bd9Sstevel@tonic-gate flusho();
1317c478bd9Sstevel@tonic-gate again:
1327c478bd9Sstevel@tonic-gate if ((c=read(slevel == 0 ? 0 : ttyindes, &ch, 1)) != 1) {
1337c478bd9Sstevel@tonic-gate if (errno == EINTR)
1347c478bd9Sstevel@tonic-gate goto getATTN;
1357c478bd9Sstevel@tonic-gate else if (errno == EIO)
1367c478bd9Sstevel@tonic-gate kill(getpid(), SIGHUP);
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate error(gettext("Input read error"));
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate c = ch;
1417c478bd9Sstevel@tonic-gate if (beehive_glitch && slevel==0 && c == ESCAPE) {
1427c478bd9Sstevel@tonic-gate if (read(0, &Peek2key, 1) != 1)
1437c478bd9Sstevel@tonic-gate goto getATTN;
1447c478bd9Sstevel@tonic-gate switch (Peek2key) {
1457c478bd9Sstevel@tonic-gate case 'C': /* SPOW mode sometimes sends \EC for space */
1467c478bd9Sstevel@tonic-gate c = ' ';
1477c478bd9Sstevel@tonic-gate Peek2key = 0;
1487c478bd9Sstevel@tonic-gate break;
1497c478bd9Sstevel@tonic-gate case 'q': /* f2 -> ^C */
1507c478bd9Sstevel@tonic-gate c = CTRL('c');
1517c478bd9Sstevel@tonic-gate Peek2key = 0;
1527c478bd9Sstevel@tonic-gate break;
1537c478bd9Sstevel@tonic-gate case 'p': /* f1 -> esc */
1547c478bd9Sstevel@tonic-gate Peek2key = 0;
1557c478bd9Sstevel@tonic-gate break;
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate /*
1607c478bd9Sstevel@tonic-gate * The algorithm here is that of the UNIX kernel.
1617c478bd9Sstevel@tonic-gate * See the description in the programmers manual.
1627c478bd9Sstevel@tonic-gate */
1637c478bd9Sstevel@tonic-gate if (UPPERCASE) {
1647c478bd9Sstevel@tonic-gate if (isupper(c))
1657c478bd9Sstevel@tonic-gate c = tolower(c);
1667c478bd9Sstevel@tonic-gate if (c == '\\') {
1677c478bd9Sstevel@tonic-gate if (precbksl < 2)
1687c478bd9Sstevel@tonic-gate precbksl++;
1697c478bd9Sstevel@tonic-gate if (precbksl == 1)
1707c478bd9Sstevel@tonic-gate goto again;
1717c478bd9Sstevel@tonic-gate } else if (precbksl) {
1727c478bd9Sstevel@tonic-gate d = 0;
1737c478bd9Sstevel@tonic-gate if (islower(c))
1747c478bd9Sstevel@tonic-gate d = toupper(c);
1757c478bd9Sstevel@tonic-gate else {
1767c478bd9Sstevel@tonic-gate colp = (unsigned char *)"({)}!|^~'~";
1777c478bd9Sstevel@tonic-gate while (d = *colp++)
1787c478bd9Sstevel@tonic-gate if (d == c) {
1797c478bd9Sstevel@tonic-gate d = *colp++;
1807c478bd9Sstevel@tonic-gate break;
1817c478bd9Sstevel@tonic-gate } else
1827c478bd9Sstevel@tonic-gate colp++;
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate if (precbksl == 2) {
1857c478bd9Sstevel@tonic-gate if (!d) {
1867c478bd9Sstevel@tonic-gate Peekkey = c;
1877c478bd9Sstevel@tonic-gate precbksl = 0;
1887c478bd9Sstevel@tonic-gate c = '\\';
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate } else if (d)
1917c478bd9Sstevel@tonic-gate c = d;
1927c478bd9Sstevel@tonic-gate else {
1937c478bd9Sstevel@tonic-gate Peekkey = c;
1947c478bd9Sstevel@tonic-gate precbksl = 0;
1957c478bd9Sstevel@tonic-gate c = '\\';
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate }
1987c478bd9Sstevel@tonic-gate if (c != '\\')
1997c478bd9Sstevel@tonic-gate precbksl = 0;
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate #ifdef TRACE
2027c478bd9Sstevel@tonic-gate if (trace) {
2037c478bd9Sstevel@tonic-gate if (!techoin) {
2047c478bd9Sstevel@tonic-gate tfixnl();
2057c478bd9Sstevel@tonic-gate techoin = 1;
2067c478bd9Sstevel@tonic-gate fprintf(trace, "*** Input: ");
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate tracec(c);
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate #endif
2117c478bd9Sstevel@tonic-gate lastvgk = 0;
2127c478bd9Sstevel@tonic-gate return (c);
2137c478bd9Sstevel@tonic-gate }
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate /*
2167c478bd9Sstevel@tonic-gate * Get a key, but if a delete, quit or attention
2177c478bd9Sstevel@tonic-gate * is typed return 0 so we will abort a partial command.
2187c478bd9Sstevel@tonic-gate */
219f6db9f27Scf int
getesc(void)220f6db9f27Scf getesc(void)
2217c478bd9Sstevel@tonic-gate {
222f6db9f27Scf int c;
2237c478bd9Sstevel@tonic-gate
2247c478bd9Sstevel@tonic-gate c = getkey();
2257c478bd9Sstevel@tonic-gate switch (c) {
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate case CTRL('v'):
2287c478bd9Sstevel@tonic-gate case CTRL('q'):
2297c478bd9Sstevel@tonic-gate c = getkey();
2307c478bd9Sstevel@tonic-gate return (c);
2317c478bd9Sstevel@tonic-gate
2327c478bd9Sstevel@tonic-gate case ATTN:
2337c478bd9Sstevel@tonic-gate case QUIT:
2347c478bd9Sstevel@tonic-gate ungetkey(c);
2357c478bd9Sstevel@tonic-gate return (0);
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate case ESCAPE:
2387c478bd9Sstevel@tonic-gate return (0);
2397c478bd9Sstevel@tonic-gate }
2407c478bd9Sstevel@tonic-gate return (c);
2417c478bd9Sstevel@tonic-gate }
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate /*
2447c478bd9Sstevel@tonic-gate * Peek at the next keystroke.
2457c478bd9Sstevel@tonic-gate */
246f6db9f27Scf int
peekkey(void)247f6db9f27Scf peekkey(void)
2487c478bd9Sstevel@tonic-gate {
2497c478bd9Sstevel@tonic-gate
2507c478bd9Sstevel@tonic-gate Peekkey = getkey();
2517c478bd9Sstevel@tonic-gate return (Peekkey);
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate
2547c478bd9Sstevel@tonic-gate /*
2557c478bd9Sstevel@tonic-gate * Read a line from the echo area, with single character prompt c.
2567c478bd9Sstevel@tonic-gate * A return value of 1 means the user blewit or blewit away.
2577c478bd9Sstevel@tonic-gate */
258f6db9f27Scf int
readecho(c)2597c478bd9Sstevel@tonic-gate readecho(c)
2607c478bd9Sstevel@tonic-gate unsigned char c;
2617c478bd9Sstevel@tonic-gate {
262f6db9f27Scf unsigned char *sc = cursor;
263f6db9f27Scf int (*OP)();
2647c478bd9Sstevel@tonic-gate bool waste;
265f6db9f27Scf int OPeek;
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate if (WBOT == WECHO)
2687c478bd9Sstevel@tonic-gate vclean();
2697c478bd9Sstevel@tonic-gate else
2707c478bd9Sstevel@tonic-gate vclrech(0);
2717c478bd9Sstevel@tonic-gate splitw++;
2727c478bd9Sstevel@tonic-gate vgoto(WECHO, 0);
2737c478bd9Sstevel@tonic-gate putchar(c);
2747c478bd9Sstevel@tonic-gate vclreol();
2757c478bd9Sstevel@tonic-gate vgoto(WECHO, 1);
2767c478bd9Sstevel@tonic-gate cursor = linebuf; linebuf[0] = 0; genbuf[0] = c;
2777c478bd9Sstevel@tonic-gate ixlatctl(1);
2787c478bd9Sstevel@tonic-gate if (peekbr()) {
2797c478bd9Sstevel@tonic-gate if (!INS[0] || (unsigned char)INS[128] == 0200) {
2807c478bd9Sstevel@tonic-gate INS[128] = 0;
2817c478bd9Sstevel@tonic-gate goto blewit;
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate vglobp = INS;
2847c478bd9Sstevel@tonic-gate }
2857c478bd9Sstevel@tonic-gate OP = Pline; Pline = normline;
2867c478bd9Sstevel@tonic-gate (void)vgetline(0, genbuf + 1, &waste, c);
2877c478bd9Sstevel@tonic-gate doomed = 0; /* don't care about doomed characters in echo line */
2887c478bd9Sstevel@tonic-gate ixlatctl(0);
2897c478bd9Sstevel@tonic-gate if (Outchar == termchar)
2907c478bd9Sstevel@tonic-gate putchar('\n');
2917c478bd9Sstevel@tonic-gate vscrap();
2927c478bd9Sstevel@tonic-gate Pline = OP;
2937c478bd9Sstevel@tonic-gate if (Peekkey != ATTN && Peekkey != QUIT && Peekkey != CTRL('h')) {
2947c478bd9Sstevel@tonic-gate cursor = sc;
2957c478bd9Sstevel@tonic-gate vclreol();
2967c478bd9Sstevel@tonic-gate return (0);
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate blewit:
2997c478bd9Sstevel@tonic-gate OPeek = Peekkey==CTRL('h') ? 0 : Peekkey; Peekkey = 0;
3007c478bd9Sstevel@tonic-gate splitw = 0;
3017c478bd9Sstevel@tonic-gate vclean();
3027c478bd9Sstevel@tonic-gate vshow(dot, NOLINE);
3037c478bd9Sstevel@tonic-gate vnline(sc);
3047c478bd9Sstevel@tonic-gate Peekkey = OPeek;
3057c478bd9Sstevel@tonic-gate return (1);
3067c478bd9Sstevel@tonic-gate }
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate /*
3097c478bd9Sstevel@tonic-gate * A complete command has been defined for
3107c478bd9Sstevel@tonic-gate * the purposes of repeat, so copy it from
3117c478bd9Sstevel@tonic-gate * the working to the previous command buffer.
3127c478bd9Sstevel@tonic-gate */
313f6db9f27Scf void
setLAST(void)314f6db9f27Scf setLAST(void)
3157c478bd9Sstevel@tonic-gate {
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gate if (vglobp || vmacp)
3187c478bd9Sstevel@tonic-gate return;
3197c478bd9Sstevel@tonic-gate lastreg = vreg;
3207c478bd9Sstevel@tonic-gate lasthad = Xhadcnt;
3217c478bd9Sstevel@tonic-gate lastcnt = Xcnt;
3227c478bd9Sstevel@tonic-gate *lastcp = 0;
3237c478bd9Sstevel@tonic-gate CP(lastcmd, workcmd);
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate
3267c478bd9Sstevel@tonic-gate /*
3277c478bd9Sstevel@tonic-gate * Gather up some more text from an insert.
3287c478bd9Sstevel@tonic-gate * If the insertion buffer oveflows, then destroy
3297c478bd9Sstevel@tonic-gate * the repeatability of the insert.
3307c478bd9Sstevel@tonic-gate */
331f6db9f27Scf void
addtext(unsigned char * cp)332f6db9f27Scf addtext(unsigned char *cp)
3337c478bd9Sstevel@tonic-gate {
3347c478bd9Sstevel@tonic-gate
3357c478bd9Sstevel@tonic-gate if (vglobp)
3367c478bd9Sstevel@tonic-gate return;
3377c478bd9Sstevel@tonic-gate addto(INS, cp);
3387c478bd9Sstevel@tonic-gate if ((unsigned char)INS[128] == 0200)
3397c478bd9Sstevel@tonic-gate lastcmd[0] = 0;
3407c478bd9Sstevel@tonic-gate }
3417c478bd9Sstevel@tonic-gate
342f6db9f27Scf void
setDEL(void)343f6db9f27Scf setDEL(void)
3447c478bd9Sstevel@tonic-gate {
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate setBUF(DEL);
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate /*
3507c478bd9Sstevel@tonic-gate * Put text from cursor upto wcursor in BUF.
3517c478bd9Sstevel@tonic-gate */
352f6db9f27Scf void
setBUF(unsigned char * BUF)353f6db9f27Scf setBUF(unsigned char *BUF)
3547c478bd9Sstevel@tonic-gate {
355f6db9f27Scf int c;
356f6db9f27Scf unsigned char *wp = wcursor;
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate c = *wp;
3597c478bd9Sstevel@tonic-gate *wp = 0;
3607c478bd9Sstevel@tonic-gate BUF[0] = 0;
3617c478bd9Sstevel@tonic-gate BUF[128] = 0;
3627c478bd9Sstevel@tonic-gate addto(BUF, cursor);
3637c478bd9Sstevel@tonic-gate *wp = c;
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate
366f6db9f27Scf void
addto(unsigned char * buf,unsigned char * str)367f6db9f27Scf addto(unsigned char *buf, unsigned char *str)
3687c478bd9Sstevel@tonic-gate {
3697c478bd9Sstevel@tonic-gate
3707c478bd9Sstevel@tonic-gate if ((unsigned char)buf[128] == 0200)
3717c478bd9Sstevel@tonic-gate return;
3727c478bd9Sstevel@tonic-gate if (strlen(buf) + strlen(str) + 1 >= VBSIZE) {
3737c478bd9Sstevel@tonic-gate buf[128] = 0200;
3747c478bd9Sstevel@tonic-gate return;
3757c478bd9Sstevel@tonic-gate }
3767c478bd9Sstevel@tonic-gate (void)strcat(buf, str);
3777c478bd9Sstevel@tonic-gate buf[128] = 0;
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate
3807c478bd9Sstevel@tonic-gate /*
3817c478bd9Sstevel@tonic-gate * Verbalize command name and embed it in message.
3827c478bd9Sstevel@tonic-gate */
3837c478bd9Sstevel@tonic-gate char *
verbalize(cnt,cmdstr,sgn)3847c478bd9Sstevel@tonic-gate verbalize(cnt, cmdstr, sgn)
3857c478bd9Sstevel@tonic-gate int cnt;
3867c478bd9Sstevel@tonic-gate char *cmdstr, *sgn;
3877c478bd9Sstevel@tonic-gate {
3887c478bd9Sstevel@tonic-gate if (cmdstr[0] == '\0')
3897c478bd9Sstevel@tonic-gate cmdstr = (char *)Command;
3907c478bd9Sstevel@tonic-gate if (sgn[0] == '\0') {
3917c478bd9Sstevel@tonic-gate switch (cmdstr[0]) {
3927c478bd9Sstevel@tonic-gate case 'c':
3937c478bd9Sstevel@tonic-gate if (cmdstr[1] == 'h') {
394f6db9f27Scf viprintf((cnt == 1) ?
395f6db9f27Scf gettext("1 line changed") :
396f6db9f27Scf gettext("%d lines changed"), cnt);
3977c478bd9Sstevel@tonic-gate break;
3987c478bd9Sstevel@tonic-gate } else if (cmdstr[1] != 'o') {
3997c478bd9Sstevel@tonic-gate goto Default;
4007c478bd9Sstevel@tonic-gate }
4019097ca5cSToomas Soome /* FALLTHROUGH */
4027c478bd9Sstevel@tonic-gate case 't':
4037c478bd9Sstevel@tonic-gate if (cmdstr[1] != '\0')
4047c478bd9Sstevel@tonic-gate goto Default;
405f6db9f27Scf viprintf((cnt == 1) ? gettext("1 line copied") :
4067c478bd9Sstevel@tonic-gate gettext("%d lines copied"), cnt);
4077c478bd9Sstevel@tonic-gate break;
4087c478bd9Sstevel@tonic-gate case 'd':
409f6db9f27Scf viprintf((cnt == 1) ? gettext("1 line deleted") :
4107c478bd9Sstevel@tonic-gate gettext("%d lines deleted"), cnt);
4117c478bd9Sstevel@tonic-gate break;
4127c478bd9Sstevel@tonic-gate case 'j':
413f6db9f27Scf viprintf((cnt == 1) ? gettext("1 line joined") :
4147c478bd9Sstevel@tonic-gate gettext("%d lines joined"), cnt);
4157c478bd9Sstevel@tonic-gate break;
4167c478bd9Sstevel@tonic-gate case 'm':
417f6db9f27Scf viprintf((cnt == 1) ? gettext("1 line moved") :
4187c478bd9Sstevel@tonic-gate gettext("%d lines moved"), cnt);
4197c478bd9Sstevel@tonic-gate break;
4207c478bd9Sstevel@tonic-gate case 'p':
421f6db9f27Scf viprintf((cnt == 1) ? gettext("1 line put") :
4227c478bd9Sstevel@tonic-gate gettext("%d lines put"), cnt);
4237c478bd9Sstevel@tonic-gate break;
4247c478bd9Sstevel@tonic-gate case 'y':
425f6db9f27Scf viprintf((cnt == 1) ? gettext("1 line yanked") :
4267c478bd9Sstevel@tonic-gate gettext("%d lines yanked"), cnt);
4277c478bd9Sstevel@tonic-gate break;
4287c478bd9Sstevel@tonic-gate case '>':
429f6db9f27Scf viprintf((cnt == 1) ? gettext("1 line >>ed") :
4307c478bd9Sstevel@tonic-gate gettext("%d lines >>ed"), cnt);
4317c478bd9Sstevel@tonic-gate break;
4327c478bd9Sstevel@tonic-gate case '=':
433f6db9f27Scf viprintf((cnt == 1) ? gettext("1 line =ed") :
4347c478bd9Sstevel@tonic-gate gettext("%d lines =ed"), cnt);
4357c478bd9Sstevel@tonic-gate break;
4367c478bd9Sstevel@tonic-gate case '<':
437f6db9f27Scf viprintf((cnt == 1) ? gettext("1 line <<ed") :
4387c478bd9Sstevel@tonic-gate gettext("%d lines <<ed"), cnt);
4397c478bd9Sstevel@tonic-gate break;
4407c478bd9Sstevel@tonic-gate default:
4417c478bd9Sstevel@tonic-gate Default:
442f6db9f27Scf viprintf((cnt == 1) ? gettext("1 line") :
4437c478bd9Sstevel@tonic-gate gettext("%d lines"), cnt);
4447c478bd9Sstevel@tonic-gate break;
4457c478bd9Sstevel@tonic-gate }
4467c478bd9Sstevel@tonic-gate } else if (sgn[0] == 'm') {
447f6db9f27Scf viprintf((cnt == 1) ? gettext("1 more line") :
4487c478bd9Sstevel@tonic-gate gettext("%d more lines"), cnt);
4497c478bd9Sstevel@tonic-gate } else {
450f6db9f27Scf viprintf((cnt == 1) ? gettext("1 fewer line") :
4517c478bd9Sstevel@tonic-gate gettext("%d fewer lines"), cnt);
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate return (NULL);
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate
4567c478bd9Sstevel@tonic-gate /*
4577c478bd9Sstevel@tonic-gate * Note a change affecting a lot of lines, or non-visible
4587c478bd9Sstevel@tonic-gate * lines. If the parameter must is set, then we only want
4597c478bd9Sstevel@tonic-gate * to do this for open modes now; return and save for later
4607c478bd9Sstevel@tonic-gate * notification in visual.
4617c478bd9Sstevel@tonic-gate */
462f6db9f27Scf int
noteit(must)4637c478bd9Sstevel@tonic-gate noteit(must)
4647c478bd9Sstevel@tonic-gate bool must;
4657c478bd9Sstevel@tonic-gate {
466f6db9f27Scf int sdl = destline, sdc = destcol;
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate if (notecnt < 1 || !must && state == VISUAL)
4697c478bd9Sstevel@tonic-gate return (0);
4707c478bd9Sstevel@tonic-gate splitw++;
4717c478bd9Sstevel@tonic-gate if (WBOT == WECHO)
4727c478bd9Sstevel@tonic-gate vmoveitup(1, 1);
4737c478bd9Sstevel@tonic-gate vigoto(WECHO, 0);
4747c478bd9Sstevel@tonic-gate
4757c478bd9Sstevel@tonic-gate verbalize(notecnt, notenam, notesgn);
4767c478bd9Sstevel@tonic-gate vclreol();
4777c478bd9Sstevel@tonic-gate notecnt = 0;
4787c478bd9Sstevel@tonic-gate if (state != VISUAL)
4797c478bd9Sstevel@tonic-gate vcnt = vcline = 0;
4807c478bd9Sstevel@tonic-gate splitw = 0;
4817c478bd9Sstevel@tonic-gate if (state == ONEOPEN || state == CRTOPEN)
4827c478bd9Sstevel@tonic-gate vup1();
4837c478bd9Sstevel@tonic-gate destline = sdl; destcol = sdc;
4847c478bd9Sstevel@tonic-gate return (1);
4857c478bd9Sstevel@tonic-gate }
4867c478bd9Sstevel@tonic-gate
4877c478bd9Sstevel@tonic-gate /*
4887c478bd9Sstevel@tonic-gate * Ring or beep.
4897c478bd9Sstevel@tonic-gate * If possible, flash screen.
4907c478bd9Sstevel@tonic-gate */
491f6db9f27Scf int
beep(void)492f6db9f27Scf beep(void)
4937c478bd9Sstevel@tonic-gate {
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate if (flash_screen && value(vi_FLASH))
4967c478bd9Sstevel@tonic-gate vputp(flash_screen, 0);
4977c478bd9Sstevel@tonic-gate else if (bell)
4987c478bd9Sstevel@tonic-gate vputp(bell, 0);
499f6db9f27Scf return (0);
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate
5027c478bd9Sstevel@tonic-gate /*
5037c478bd9Sstevel@tonic-gate * Map the command input character c,
5047c478bd9Sstevel@tonic-gate * for keypads and labelled keys which do cursor
5057c478bd9Sstevel@tonic-gate * motions. I.e. on an adm3a we might map ^K to ^P.
5067c478bd9Sstevel@tonic-gate * DM1520 for example has a lot of mappable characters.
5077c478bd9Sstevel@tonic-gate */
5087c478bd9Sstevel@tonic-gate
509f6db9f27Scf int
map(c,maps,commch)510f6db9f27Scf map(c, maps, commch)
511f6db9f27Scf int c;
512f6db9f27Scf struct maps *maps;
513f6db9f27Scf unsigned char commch; /* indicate if in append/insert/replace mode */
5147c478bd9Sstevel@tonic-gate {
515f6db9f27Scf int d;
516f6db9f27Scf unsigned char *p, *q;
5177c478bd9Sstevel@tonic-gate unsigned char b[10]; /* Assumption: no keypad sends string longer than 10 */
5187c478bd9Sstevel@tonic-gate unsigned char *st;
5197c478bd9Sstevel@tonic-gate
5207c478bd9Sstevel@tonic-gate /*
5217c478bd9Sstevel@tonic-gate * Mapping for special keys on the terminal only.
5227c478bd9Sstevel@tonic-gate * BUG: if there's a long sequence and it matches
5237c478bd9Sstevel@tonic-gate * some chars and then misses, we lose some chars.
5247c478bd9Sstevel@tonic-gate *
5257c478bd9Sstevel@tonic-gate * For this to work, some conditions must be met.
5267c478bd9Sstevel@tonic-gate * 1) Keypad sends SHORT (2 or 3 char) strings
5277c478bd9Sstevel@tonic-gate * 2) All strings sent are same length & similar
5287c478bd9Sstevel@tonic-gate * 3) The user is unlikely to type the first few chars of
5297c478bd9Sstevel@tonic-gate * one of these strings very fast.
5307c478bd9Sstevel@tonic-gate * Note: some code has been fixed up since the above was laid out,
5317c478bd9Sstevel@tonic-gate * so conditions 1 & 2 are probably not required anymore.
5327c478bd9Sstevel@tonic-gate * However, this hasn't been tested with any first char
5337c478bd9Sstevel@tonic-gate * that means anything else except escape.
5347c478bd9Sstevel@tonic-gate */
5357c478bd9Sstevel@tonic-gate #ifdef MDEBUG
5367c478bd9Sstevel@tonic-gate if (trace)
5377c478bd9Sstevel@tonic-gate fprintf(trace,"map(%c): ",c);
5387c478bd9Sstevel@tonic-gate #endif
5397c478bd9Sstevel@tonic-gate /*
5407c478bd9Sstevel@tonic-gate * If c==0, the char came from getesc typing escape. Pass it through
5417c478bd9Sstevel@tonic-gate * unchanged. 0 messes up the following code anyway.
5427c478bd9Sstevel@tonic-gate */
5437c478bd9Sstevel@tonic-gate if (c==0)
5447c478bd9Sstevel@tonic-gate return(0);
5457c478bd9Sstevel@tonic-gate
5467c478bd9Sstevel@tonic-gate b[0] = c;
5477c478bd9Sstevel@tonic-gate b[1] = 0;
5487c478bd9Sstevel@tonic-gate for (d=0; d < MAXNOMACS && maps[d].mapto; d++) {
5497c478bd9Sstevel@tonic-gate #ifdef MDEBUG
5507c478bd9Sstevel@tonic-gate if (trace)
5517c478bd9Sstevel@tonic-gate fprintf(trace,"\ntry '%s', ",maps[d].cap);
5527c478bd9Sstevel@tonic-gate #endif
5537c478bd9Sstevel@tonic-gate if (p = maps[d].cap) {
5547c478bd9Sstevel@tonic-gate for (q=b; *p; p++, q++) {
5557c478bd9Sstevel@tonic-gate #ifdef MDEBUG
5567c478bd9Sstevel@tonic-gate if (trace)
5577c478bd9Sstevel@tonic-gate fprintf(trace,"q->b[%d], ",q-b);
5587c478bd9Sstevel@tonic-gate #endif
5597c478bd9Sstevel@tonic-gate if (*q==0) {
5607c478bd9Sstevel@tonic-gate /*
5617c478bd9Sstevel@tonic-gate * Is there another char waiting?
5627c478bd9Sstevel@tonic-gate *
5637c478bd9Sstevel@tonic-gate * This test is oversimplified, but
5647c478bd9Sstevel@tonic-gate * should work mostly. It handles the
5657c478bd9Sstevel@tonic-gate * case where we get an ESCAPE that
5667c478bd9Sstevel@tonic-gate * wasn't part of a keypad string.
5677c478bd9Sstevel@tonic-gate */
5687c478bd9Sstevel@tonic-gate if ((c=='#' ? peekkey() : fastpeekkey()) == 0) {
5697c478bd9Sstevel@tonic-gate #ifdef MDEBUG
5707c478bd9Sstevel@tonic-gate if (trace)
5717c478bd9Sstevel@tonic-gate fprintf(trace,"fpk=0: will return '%c'",c);
5727c478bd9Sstevel@tonic-gate #endif
5737c478bd9Sstevel@tonic-gate /*
5747c478bd9Sstevel@tonic-gate * Nothing waiting. Push back
5757c478bd9Sstevel@tonic-gate * what we peeked at & return
5767c478bd9Sstevel@tonic-gate * failure (c).
5777c478bd9Sstevel@tonic-gate *
5787c478bd9Sstevel@tonic-gate * We want to be able to undo
5797c478bd9Sstevel@tonic-gate * commands, but it's nonsense
5807c478bd9Sstevel@tonic-gate * to undo part of an insertion
5817c478bd9Sstevel@tonic-gate * so if in input mode don't.
5827c478bd9Sstevel@tonic-gate */
5837c478bd9Sstevel@tonic-gate #ifdef MDEBUG
5847c478bd9Sstevel@tonic-gate if (trace)
5857c478bd9Sstevel@tonic-gate fprintf(trace, "Call macpush, b %d %d %d\n", b[0], b[1], b[2]);
5867c478bd9Sstevel@tonic-gate #endif
5877c478bd9Sstevel@tonic-gate macpush(&b[1],maps == arrows);
5887c478bd9Sstevel@tonic-gate #ifdef MDEBUG
5897c478bd9Sstevel@tonic-gate if (trace)
590*55fea89dSDan Cross fprintf(trace, "return %d\n", c);
5917c478bd9Sstevel@tonic-gate #endif
5927c478bd9Sstevel@tonic-gate return(c);
5937c478bd9Sstevel@tonic-gate }
5947c478bd9Sstevel@tonic-gate *q = getkey();
5957c478bd9Sstevel@tonic-gate q[1] = 0;
5967c478bd9Sstevel@tonic-gate }
5977c478bd9Sstevel@tonic-gate if (*p != *q)
5987c478bd9Sstevel@tonic-gate goto contin;
5997c478bd9Sstevel@tonic-gate }
6007c478bd9Sstevel@tonic-gate macpush(maps[d].mapto,maps == arrows);
6017c478bd9Sstevel@tonic-gate /*
6027c478bd9Sstevel@tonic-gate * For all macros performed within insert,
6037c478bd9Sstevel@tonic-gate * append, or replacement mode, we must end
6047c478bd9Sstevel@tonic-gate * up returning back to that mode when we
6057c478bd9Sstevel@tonic-gate * return (except that append will become
6067c478bd9Sstevel@tonic-gate * insert for <home> key, so cursor is not
6077c478bd9Sstevel@tonic-gate * in second column).
6087c478bd9Sstevel@tonic-gate *
6097c478bd9Sstevel@tonic-gate * In order to preserve backward movement
6107c478bd9Sstevel@tonic-gate * when leaving insert mode, an 'l' must be
6117c478bd9Sstevel@tonic-gate * done to compensate for the left done by
6127c478bd9Sstevel@tonic-gate * the <esc> (except when cursor is already
6137c478bd9Sstevel@tonic-gate * in the first column: i.e., outcol = 0).
6147c478bd9Sstevel@tonic-gate */
615*55fea89dSDan Cross if ((maps == immacs)
6167c478bd9Sstevel@tonic-gate && strcmp(maps[d].descr, maps[d].cap)) {
6177c478bd9Sstevel@tonic-gate switch (commch) {
6187c478bd9Sstevel@tonic-gate case 'R':
6197c478bd9Sstevel@tonic-gate if (!strcmp(maps[d].descr, "home"))
6207c478bd9Sstevel@tonic-gate st = (unsigned char *)"R";
6217c478bd9Sstevel@tonic-gate else
6227c478bd9Sstevel@tonic-gate if (outcol == 0)
6237c478bd9Sstevel@tonic-gate st = (unsigned char *)"R";
6247c478bd9Sstevel@tonic-gate else
625*55fea89dSDan Cross st = (unsigned char *)"lR";
6267c478bd9Sstevel@tonic-gate break;
6277c478bd9Sstevel@tonic-gate case 'i':
6287c478bd9Sstevel@tonic-gate if (!strcmp(maps[d].descr, "home"))
6297c478bd9Sstevel@tonic-gate st = (unsigned char *)"i";
6307c478bd9Sstevel@tonic-gate else
6317c478bd9Sstevel@tonic-gate if (outcol == 0)
6327c478bd9Sstevel@tonic-gate st = (unsigned char *)"i";
6337c478bd9Sstevel@tonic-gate else
634*55fea89dSDan Cross st = (unsigned char *)"li";
6357c478bd9Sstevel@tonic-gate break;
6367c478bd9Sstevel@tonic-gate case 'a':
6377c478bd9Sstevel@tonic-gate if (!strcmp(maps[d].descr, "home"))
6387c478bd9Sstevel@tonic-gate st = (unsigned char *)"i";
6397c478bd9Sstevel@tonic-gate else
6407c478bd9Sstevel@tonic-gate st = (unsigned char *)"a";
6417c478bd9Sstevel@tonic-gate break;
6427c478bd9Sstevel@tonic-gate default:
6437c478bd9Sstevel@tonic-gate st = (unsigned char *)"i";
6447c478bd9Sstevel@tonic-gate }
645*55fea89dSDan Cross if(strlen(vmacbuf) + strlen(st) > BUFSIZE)
6467c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ?
6477c478bd9Sstevel@tonic-gate gettext("Macro too long") : gettext("Macro too long - maybe recursive?"));
6487c478bd9Sstevel@tonic-gate else
649*55fea89dSDan Cross /*
6507c478bd9Sstevel@tonic-gate * Macros such as function keys are
6517c478bd9Sstevel@tonic-gate * performed by leaving the insert,
652*55fea89dSDan Cross * replace, or append mode, executing
6537c478bd9Sstevel@tonic-gate * the proper cursor movement commands
6547c478bd9Sstevel@tonic-gate * and returning to the mode we are
6557c478bd9Sstevel@tonic-gate * currently in (commch).
6567c478bd9Sstevel@tonic-gate */
6577c478bd9Sstevel@tonic-gate strcat(vmacbuf, st);
6587c478bd9Sstevel@tonic-gate }
6597c478bd9Sstevel@tonic-gate c = getkey();
6607c478bd9Sstevel@tonic-gate #ifdef MDEBUG
6617c478bd9Sstevel@tonic-gate if (trace)
6627c478bd9Sstevel@tonic-gate fprintf(trace,"Success: push(%s), return %c",maps[d].mapto, c);
6637c478bd9Sstevel@tonic-gate #endif
6647c478bd9Sstevel@tonic-gate return(c); /* first char of map string */
6657c478bd9Sstevel@tonic-gate contin:;
6667c478bd9Sstevel@tonic-gate }
6677c478bd9Sstevel@tonic-gate }
6687c478bd9Sstevel@tonic-gate #ifdef MDEBUG
6697c478bd9Sstevel@tonic-gate if (trace)
6707c478bd9Sstevel@tonic-gate fprintf(trace,"Fail: push(%s), return %c", &b[1], c);
6717c478bd9Sstevel@tonic-gate #endif
6727c478bd9Sstevel@tonic-gate macpush(&b[1],0);
6737c478bd9Sstevel@tonic-gate return(c);
6747c478bd9Sstevel@tonic-gate }
6757c478bd9Sstevel@tonic-gate
6767c478bd9Sstevel@tonic-gate /*
6777c478bd9Sstevel@tonic-gate * Push st onto the front of vmacp. This is tricky because we have to
6787c478bd9Sstevel@tonic-gate * worry about where vmacp was previously pointing. We also have to
6797c478bd9Sstevel@tonic-gate * check for overflow (which is typically from a recursive macro)
6807c478bd9Sstevel@tonic-gate * Finally we have to set a flag so the whole thing can be undone.
6817c478bd9Sstevel@tonic-gate * canundo is 1 iff we want to be able to undo the macro. This
6827c478bd9Sstevel@tonic-gate * is false for, for example, pushing back lookahead from fastpeekkey(),
6837c478bd9Sstevel@tonic-gate * since otherwise two fast escapes can clobber our undo.
6847c478bd9Sstevel@tonic-gate */
685f6db9f27Scf void
macpush(unsigned char * st,int canundo)686f6db9f27Scf macpush(unsigned char *st, int canundo)
6877c478bd9Sstevel@tonic-gate {
6887c478bd9Sstevel@tonic-gate unsigned char tmpbuf[BUFSIZE];
6897c478bd9Sstevel@tonic-gate
6907c478bd9Sstevel@tonic-gate if (st==0 || *st==0)
6917c478bd9Sstevel@tonic-gate return;
6927c478bd9Sstevel@tonic-gate #ifdef MDEBUG
6937c478bd9Sstevel@tonic-gate if (trace)
6947c478bd9Sstevel@tonic-gate fprintf(trace, "macpush(%s), canundo=%d\n",st,canundo);
6957c478bd9Sstevel@tonic-gate #endif
6967c478bd9Sstevel@tonic-gate if ((vmacp ? strlen(vmacp) : 0) + strlen(st) > BUFSIZE)
6977c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Macro too long") :
6987c478bd9Sstevel@tonic-gate gettext("Macro too long - maybe recursive?"));
6997c478bd9Sstevel@tonic-gate if (vmacp) {
7007c478bd9Sstevel@tonic-gate strcpy(tmpbuf, vmacp);
7017c478bd9Sstevel@tonic-gate if (!FIXUNDO)
7027c478bd9Sstevel@tonic-gate canundo = 0; /* can't undo inside a macro anyway */
7037c478bd9Sstevel@tonic-gate }
7047c478bd9Sstevel@tonic-gate strcpy(vmacbuf, st);
7057c478bd9Sstevel@tonic-gate if (vmacp)
7067c478bd9Sstevel@tonic-gate strcat(vmacbuf, tmpbuf);
7077c478bd9Sstevel@tonic-gate vmacp = vmacbuf;
7087c478bd9Sstevel@tonic-gate /* arrange to be able to undo the whole macro */
7097c478bd9Sstevel@tonic-gate if (canundo) {
7107c478bd9Sstevel@tonic-gate #ifdef notdef
7117c478bd9Sstevel@tonic-gate otchng = tchng;
7127c478bd9Sstevel@tonic-gate vsave();
7137c478bd9Sstevel@tonic-gate saveall();
7147c478bd9Sstevel@tonic-gate inopen = -1; /* no need to save since it had to be 1 or -1 before */
7157c478bd9Sstevel@tonic-gate vundkind = VMANY;
7167c478bd9Sstevel@tonic-gate #endif
7177c478bd9Sstevel@tonic-gate vch_mac = VC_NOCHANGE;
7187c478bd9Sstevel@tonic-gate }
7197c478bd9Sstevel@tonic-gate }
7207c478bd9Sstevel@tonic-gate
7217c478bd9Sstevel@tonic-gate #ifdef UNDOTRACE
visdump(s)7227c478bd9Sstevel@tonic-gate visdump(s)
7237c478bd9Sstevel@tonic-gate unsigned char *s;
7247c478bd9Sstevel@tonic-gate {
725f6db9f27Scf int i;
7267c478bd9Sstevel@tonic-gate
7277c478bd9Sstevel@tonic-gate if (!trace) return;
7287c478bd9Sstevel@tonic-gate
7297c478bd9Sstevel@tonic-gate fprintf(trace, "\n%s: basWTOP=%d, basWLINES=%d, WTOP=%d, WBOT=%d, WLINES=%d, WCOLS=%d, WECHO=%d\n",
7307c478bd9Sstevel@tonic-gate s, basWTOP, basWLINES, WTOP, WBOT, WLINES, WCOLS, WECHO);
7317c478bd9Sstevel@tonic-gate fprintf(trace, " vcnt=%d, vcline=%d, cursor=%d, wcursor=%d, wdot=%d\n",
7327c478bd9Sstevel@tonic-gate vcnt, vcline, cursor-linebuf, wcursor-linebuf, wdot-zero);
7337c478bd9Sstevel@tonic-gate for (i=0; i<TUBELINES; i++)
7347c478bd9Sstevel@tonic-gate if (vtube[i] && *vtube[i])
7357c478bd9Sstevel@tonic-gate fprintf(trace, "%d: '%s'\n", i, vtube[i]);
7367c478bd9Sstevel@tonic-gate tvliny();
7377c478bd9Sstevel@tonic-gate }
7387c478bd9Sstevel@tonic-gate
vudump(s)7397c478bd9Sstevel@tonic-gate vudump(s)
7407c478bd9Sstevel@tonic-gate unsigned char *s;
7417c478bd9Sstevel@tonic-gate {
742f6db9f27Scf line *p;
7437c478bd9Sstevel@tonic-gate unsigned char savelb[1024];
7447c478bd9Sstevel@tonic-gate
7457c478bd9Sstevel@tonic-gate if (!trace) return;
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate fprintf(trace, "\n%s: undkind=%d, vundkind=%d, unddel=%d, undap1=%d, undap2=%d,\n",
7487c478bd9Sstevel@tonic-gate s, undkind, vundkind, lineno(unddel), lineno(undap1), lineno(undap2));
7497c478bd9Sstevel@tonic-gate fprintf(trace, " undadot=%d, dot=%d, dol=%d, unddol=%d, truedol=%d\n",
7507c478bd9Sstevel@tonic-gate lineno(undadot), lineno(dot), lineno(dol), lineno(unddol), lineno(truedol));
7517c478bd9Sstevel@tonic-gate fprintf(trace, " [\n");
7527c478bd9Sstevel@tonic-gate CP(savelb, linebuf);
7537c478bd9Sstevel@tonic-gate fprintf(trace, "linebuf = '%s'\n", linebuf);
7547c478bd9Sstevel@tonic-gate for (p=zero+1; p<=truedol; p++) {
7557c478bd9Sstevel@tonic-gate fprintf(trace, "%o ", *p);
75623a1cceaSRoger A. Faulkner getaline(*p);
7577c478bd9Sstevel@tonic-gate fprintf(trace, "'%s'\n", linebuf);
7587c478bd9Sstevel@tonic-gate }
7597c478bd9Sstevel@tonic-gate fprintf(trace, "]\n");
7607c478bd9Sstevel@tonic-gate CP(linebuf, savelb);
7617c478bd9Sstevel@tonic-gate }
7627c478bd9Sstevel@tonic-gate #endif
7637c478bd9Sstevel@tonic-gate
7647c478bd9Sstevel@tonic-gate /*
7657c478bd9Sstevel@tonic-gate * Get a count from the keyed input stream.
7667c478bd9Sstevel@tonic-gate * A zero count is indistinguishable from no count.
7677c478bd9Sstevel@tonic-gate */
768f6db9f27Scf int
vgetcnt(void)769f6db9f27Scf vgetcnt(void)
7707c478bd9Sstevel@tonic-gate {
771f6db9f27Scf int c, cnt;
7727c478bd9Sstevel@tonic-gate
7737c478bd9Sstevel@tonic-gate cnt = 0;
7747c478bd9Sstevel@tonic-gate for (;;) {
7757c478bd9Sstevel@tonic-gate c = getkey();
7767c478bd9Sstevel@tonic-gate if (!isdigit(c))
7777c478bd9Sstevel@tonic-gate break;
7787c478bd9Sstevel@tonic-gate cnt *= 10, cnt += c - '0';
7797c478bd9Sstevel@tonic-gate }
7807c478bd9Sstevel@tonic-gate ungetkey(c);
7817c478bd9Sstevel@tonic-gate Xhadcnt = 1;
7827c478bd9Sstevel@tonic-gate Xcnt = cnt;
7837c478bd9Sstevel@tonic-gate return(cnt);
7847c478bd9Sstevel@tonic-gate }
7857c478bd9Sstevel@tonic-gate
7867c478bd9Sstevel@tonic-gate /*
7877c478bd9Sstevel@tonic-gate * fastpeekkey is just like peekkey but insists the character come in
7887c478bd9Sstevel@tonic-gate * fast (within 1 second). This will succeed if it is the 2nd char of
7897c478bd9Sstevel@tonic-gate * a machine generated sequence (such as a function pad from an escape
7907c478bd9Sstevel@tonic-gate * flavor terminal) but fail for a human hitting escape then waiting.
7917c478bd9Sstevel@tonic-gate */
792f6db9f27Scf int
fastpeekkey(void)793f6db9f27Scf fastpeekkey(void)
7947c478bd9Sstevel@tonic-gate {
7957c478bd9Sstevel@tonic-gate void trapalarm();
796f6db9f27Scf int c;
7977c478bd9Sstevel@tonic-gate
7987c478bd9Sstevel@tonic-gate /*
7997c478bd9Sstevel@tonic-gate * If the user has set notimeout, we wait forever for a key.
8007c478bd9Sstevel@tonic-gate * If we are in a macro we do too, but since it's already
8017c478bd9Sstevel@tonic-gate * buffered internally it will return immediately.
8027c478bd9Sstevel@tonic-gate * In other cases we force this to die in 1 second.
8037c478bd9Sstevel@tonic-gate * This is pretty reliable (VMUNIX rounds it to .5 - 1.5 secs,
8047c478bd9Sstevel@tonic-gate * but UNIX truncates it to 0 - 1 secs) but due to system delays
8057c478bd9Sstevel@tonic-gate * there are times when arrow keys or very fast typing get counted
8067c478bd9Sstevel@tonic-gate * as separate. notimeout is provided for people who dislike such
8077c478bd9Sstevel@tonic-gate * nondeterminism.
8087c478bd9Sstevel@tonic-gate */
8097c478bd9Sstevel@tonic-gate CATCH
8107c478bd9Sstevel@tonic-gate if (value(vi_TIMEOUT) && inopen >= 0) {
8117c478bd9Sstevel@tonic-gate signal(SIGALRM, trapalarm);
8127c478bd9Sstevel@tonic-gate setalarm();
8137c478bd9Sstevel@tonic-gate }
8147c478bd9Sstevel@tonic-gate c = peekkey();
8157c478bd9Sstevel@tonic-gate cancelalarm();
8167c478bd9Sstevel@tonic-gate ONERR
8177c478bd9Sstevel@tonic-gate c = 0;
8187c478bd9Sstevel@tonic-gate ENDCATCH
8197c478bd9Sstevel@tonic-gate /* Should have an alternative method based on select for 4.2BSD */
8207c478bd9Sstevel@tonic-gate return(c);
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate
8237c478bd9Sstevel@tonic-gate static int ftfd;
8247c478bd9Sstevel@tonic-gate struct requestbuf {
8257c478bd9Sstevel@tonic-gate short time;
8267c478bd9Sstevel@tonic-gate short signo;
8277c478bd9Sstevel@tonic-gate };
8287c478bd9Sstevel@tonic-gate
8297c478bd9Sstevel@tonic-gate /*
8307c478bd9Sstevel@tonic-gate * Arrange for SIGALRM to come in shortly, so we don't
8317c478bd9Sstevel@tonic-gate * hang very long if the user didn't type anything. There are
8327c478bd9Sstevel@tonic-gate * various ways to do this on different systems.
8337c478bd9Sstevel@tonic-gate */
834f6db9f27Scf void
setalarm(void)835f6db9f27Scf setalarm(void)
8367c478bd9Sstevel@tonic-gate {
8377c478bd9Sstevel@tonic-gate unsigned char ftname[20];
8387c478bd9Sstevel@tonic-gate struct requestbuf rb;
8397c478bd9Sstevel@tonic-gate
8407c478bd9Sstevel@tonic-gate #ifdef FTIOCSET
8417c478bd9Sstevel@tonic-gate /*
8427c478bd9Sstevel@tonic-gate * Use nonstandard "fast timer" to get better than
8437c478bd9Sstevel@tonic-gate * one second resolution. We must wait at least
8447c478bd9Sstevel@tonic-gate * 1/15th of a second because some keypads don't
8457c478bd9Sstevel@tonic-gate * transmit faster than this.
8467c478bd9Sstevel@tonic-gate */
8477c478bd9Sstevel@tonic-gate
8487c478bd9Sstevel@tonic-gate /* Open ft psuedo-device - we need our own copy. */
8497c478bd9Sstevel@tonic-gate if (ftfd == 0) {
8507c478bd9Sstevel@tonic-gate strcpy(ftname, "/dev/ft0");
8517c478bd9Sstevel@tonic-gate while (ftfd <= 0 && ftname[7] <= '~') {
8527c478bd9Sstevel@tonic-gate ftfd = open(ftname, 0);
8537c478bd9Sstevel@tonic-gate if (ftfd <= 0)
8547c478bd9Sstevel@tonic-gate ftname[7] ++;
8557c478bd9Sstevel@tonic-gate }
8567c478bd9Sstevel@tonic-gate }
8577c478bd9Sstevel@tonic-gate if (ftfd <= 0) { /* Couldn't open a /dev/ft? */
8587c478bd9Sstevel@tonic-gate alarm(1);
8597c478bd9Sstevel@tonic-gate } else {
8607c478bd9Sstevel@tonic-gate rb.time = 6; /* 6 ticks = 100 ms > 67 ms. */
8617c478bd9Sstevel@tonic-gate rb.signo = SIGALRM;
8627c478bd9Sstevel@tonic-gate ioctl(ftfd, FTIOCSET, &rb);
8637c478bd9Sstevel@tonic-gate }
8647c478bd9Sstevel@tonic-gate #else
8657c478bd9Sstevel@tonic-gate /*
8667c478bd9Sstevel@tonic-gate * No special capabilities, so we use alarm, with 1 sec. resolution.
8677c478bd9Sstevel@tonic-gate */
8687c478bd9Sstevel@tonic-gate alarm(1);
8697c478bd9Sstevel@tonic-gate #endif
8707c478bd9Sstevel@tonic-gate }
8717c478bd9Sstevel@tonic-gate
8727c478bd9Sstevel@tonic-gate /*
8737c478bd9Sstevel@tonic-gate * Get rid of any impending incoming SIGALRM.
8747c478bd9Sstevel@tonic-gate */
875f6db9f27Scf void
cancelalarm(void)876f6db9f27Scf cancelalarm(void)
8777c478bd9Sstevel@tonic-gate {
8787c478bd9Sstevel@tonic-gate struct requestbuf rb;
8797c478bd9Sstevel@tonic-gate #ifdef FTIOCSET
8807c478bd9Sstevel@tonic-gate if (ftfd > 0) {
8817c478bd9Sstevel@tonic-gate rb.time = 0;
8827c478bd9Sstevel@tonic-gate rb.signo = SIGALRM;
8837c478bd9Sstevel@tonic-gate ioctl(ftfd, FTIOCCANCEL, &rb);
8847c478bd9Sstevel@tonic-gate }
8857c478bd9Sstevel@tonic-gate #endif
8867c478bd9Sstevel@tonic-gate alarm(0); /* Have to do this whether or not FTIOCSET */
8877c478bd9Sstevel@tonic-gate }
8887c478bd9Sstevel@tonic-gate
trapalarm()8897c478bd9Sstevel@tonic-gate void trapalarm() {
8907c478bd9Sstevel@tonic-gate alarm(0);
8917c478bd9Sstevel@tonic-gate longjmp(vreslab,1);
8927c478bd9Sstevel@tonic-gate }
893