10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*13093SRoger.Faulkner@Oracle.COM * Common Development and Distribution License (the "License").
6*13093SRoger.Faulkner@Oracle.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
21*13093SRoger.Faulkner@Oracle.COM
22802Scf46844 /*
23*13093SRoger.Faulkner@Oracle.COM * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24802Scf46844 */
25802Scf46844
260Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
270Sstevel@tonic-gate /* All Rights Reserved */
280Sstevel@tonic-gate
290Sstevel@tonic-gate
300Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */
310Sstevel@tonic-gate
320Sstevel@tonic-gate #include "ex.h"
330Sstevel@tonic-gate #include "ex_tty.h"
340Sstevel@tonic-gate #include "ex_vis.h"
350Sstevel@tonic-gate
360Sstevel@tonic-gate /*
370Sstevel@tonic-gate * Input routines for open/visual.
380Sstevel@tonic-gate * We handle upper case only terminals in visual and reading from the
390Sstevel@tonic-gate * echo area here as well as notification on large changes
400Sstevel@tonic-gate * which appears in the echo area.
410Sstevel@tonic-gate */
420Sstevel@tonic-gate
430Sstevel@tonic-gate /*
440Sstevel@tonic-gate * Return the key.
450Sstevel@tonic-gate */
46802Scf46844 void
ungetkey(int c)47802Scf46844 ungetkey(int c)
480Sstevel@tonic-gate {
490Sstevel@tonic-gate
500Sstevel@tonic-gate if (Peekkey != ATTN)
510Sstevel@tonic-gate Peekkey = c;
520Sstevel@tonic-gate }
530Sstevel@tonic-gate
540Sstevel@tonic-gate /*
550Sstevel@tonic-gate * Return a keystroke, but never a ^@.
560Sstevel@tonic-gate */
57802Scf46844 int
getkey(void)58802Scf46844 getkey(void)
590Sstevel@tonic-gate {
60802Scf46844 int c; /* char --> int */
610Sstevel@tonic-gate
620Sstevel@tonic-gate do {
630Sstevel@tonic-gate c = getbr();
640Sstevel@tonic-gate if (c==0)
65802Scf46844 (void) beep();
660Sstevel@tonic-gate } while (c == 0);
670Sstevel@tonic-gate return (c);
680Sstevel@tonic-gate }
690Sstevel@tonic-gate
700Sstevel@tonic-gate /*
710Sstevel@tonic-gate * Tell whether next keystroke would be a ^@.
720Sstevel@tonic-gate */
73802Scf46844 int
peekbr(void)74802Scf46844 peekbr(void)
750Sstevel@tonic-gate {
760Sstevel@tonic-gate
770Sstevel@tonic-gate Peekkey = getbr();
780Sstevel@tonic-gate return (Peekkey == 0);
790Sstevel@tonic-gate }
800Sstevel@tonic-gate
810Sstevel@tonic-gate short precbksl;
820Sstevel@tonic-gate
830Sstevel@tonic-gate /*
840Sstevel@tonic-gate * Get a keystroke, including a ^@.
850Sstevel@tonic-gate * If an key was returned with ungetkey, that
860Sstevel@tonic-gate * comes back first. Next comes unread input (e.g.
870Sstevel@tonic-gate * from repeating commands with .), and finally new
880Sstevel@tonic-gate * keystrokes.
890Sstevel@tonic-gate *
900Sstevel@tonic-gate * The hard work here is in mapping of \ escaped
910Sstevel@tonic-gate * characters on upper case only terminals.
920Sstevel@tonic-gate */
93802Scf46844 int
getbr(void)94802Scf46844 getbr(void)
950Sstevel@tonic-gate {
960Sstevel@tonic-gate unsigned char ch;
97802Scf46844 int c, d;
98802Scf46844 unsigned char *colp;
990Sstevel@tonic-gate int cnt;
1000Sstevel@tonic-gate static unsigned char Peek2key;
1010Sstevel@tonic-gate extern short slevel, ttyindes;
1020Sstevel@tonic-gate
1030Sstevel@tonic-gate getATTN:
1040Sstevel@tonic-gate if (Peekkey) {
1050Sstevel@tonic-gate c = Peekkey;
1060Sstevel@tonic-gate Peekkey = 0;
1070Sstevel@tonic-gate return (c);
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate if (Peek2key) {
1100Sstevel@tonic-gate c = Peek2key;
1110Sstevel@tonic-gate Peek2key = 0;
1120Sstevel@tonic-gate return (c);
1130Sstevel@tonic-gate }
1140Sstevel@tonic-gate if (vglobp) {
1150Sstevel@tonic-gate if (*vglobp)
1160Sstevel@tonic-gate return (lastvgk = *vglobp++);
1170Sstevel@tonic-gate lastvgk = 0;
1180Sstevel@tonic-gate return (ESCAPE);
1190Sstevel@tonic-gate }
1200Sstevel@tonic-gate if (vmacp) {
1210Sstevel@tonic-gate if (*vmacp)
1220Sstevel@tonic-gate return(*vmacp++);
1230Sstevel@tonic-gate /* End of a macro or set of nested macros */
1240Sstevel@tonic-gate vmacp = 0;
1250Sstevel@tonic-gate if (inopen == -1) /* don't mess up undo for esc esc */
1260Sstevel@tonic-gate vundkind = VMANY;
1270Sstevel@tonic-gate inopen = 1; /* restore old setting now that macro done */
1280Sstevel@tonic-gate vch_mac = VC_NOTINMAC;
1290Sstevel@tonic-gate }
1300Sstevel@tonic-gate flusho();
1310Sstevel@tonic-gate again:
1320Sstevel@tonic-gate if ((c=read(slevel == 0 ? 0 : ttyindes, &ch, 1)) != 1) {
1330Sstevel@tonic-gate if (errno == EINTR)
1340Sstevel@tonic-gate goto getATTN;
1350Sstevel@tonic-gate else if (errno == EIO)
1360Sstevel@tonic-gate kill(getpid(), SIGHUP);
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate error(gettext("Input read error"));
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate c = ch;
1410Sstevel@tonic-gate if (beehive_glitch && slevel==0 && c == ESCAPE) {
1420Sstevel@tonic-gate if (read(0, &Peek2key, 1) != 1)
1430Sstevel@tonic-gate goto getATTN;
1440Sstevel@tonic-gate switch (Peek2key) {
1450Sstevel@tonic-gate case 'C': /* SPOW mode sometimes sends \EC for space */
1460Sstevel@tonic-gate c = ' ';
1470Sstevel@tonic-gate Peek2key = 0;
1480Sstevel@tonic-gate break;
1490Sstevel@tonic-gate case 'q': /* f2 -> ^C */
1500Sstevel@tonic-gate c = CTRL('c');
1510Sstevel@tonic-gate Peek2key = 0;
1520Sstevel@tonic-gate break;
1530Sstevel@tonic-gate case 'p': /* f1 -> esc */
1540Sstevel@tonic-gate Peek2key = 0;
1550Sstevel@tonic-gate break;
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate }
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate /*
1600Sstevel@tonic-gate * The algorithm here is that of the UNIX kernel.
1610Sstevel@tonic-gate * See the description in the programmers manual.
1620Sstevel@tonic-gate */
1630Sstevel@tonic-gate if (UPPERCASE) {
1640Sstevel@tonic-gate if (isupper(c))
1650Sstevel@tonic-gate c = tolower(c);
1660Sstevel@tonic-gate if (c == '\\') {
1670Sstevel@tonic-gate if (precbksl < 2)
1680Sstevel@tonic-gate precbksl++;
1690Sstevel@tonic-gate if (precbksl == 1)
1700Sstevel@tonic-gate goto again;
1710Sstevel@tonic-gate } else if (precbksl) {
1720Sstevel@tonic-gate d = 0;
1730Sstevel@tonic-gate if (islower(c))
1740Sstevel@tonic-gate d = toupper(c);
1750Sstevel@tonic-gate else {
1760Sstevel@tonic-gate colp = (unsigned char *)"({)}!|^~'~";
1770Sstevel@tonic-gate while (d = *colp++)
1780Sstevel@tonic-gate if (d == c) {
1790Sstevel@tonic-gate d = *colp++;
1800Sstevel@tonic-gate break;
1810Sstevel@tonic-gate } else
1820Sstevel@tonic-gate colp++;
1830Sstevel@tonic-gate }
1840Sstevel@tonic-gate if (precbksl == 2) {
1850Sstevel@tonic-gate if (!d) {
1860Sstevel@tonic-gate Peekkey = c;
1870Sstevel@tonic-gate precbksl = 0;
1880Sstevel@tonic-gate c = '\\';
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate } else if (d)
1910Sstevel@tonic-gate c = d;
1920Sstevel@tonic-gate else {
1930Sstevel@tonic-gate Peekkey = c;
1940Sstevel@tonic-gate precbksl = 0;
1950Sstevel@tonic-gate c = '\\';
1960Sstevel@tonic-gate }
1970Sstevel@tonic-gate }
1980Sstevel@tonic-gate if (c != '\\')
1990Sstevel@tonic-gate precbksl = 0;
2000Sstevel@tonic-gate }
2010Sstevel@tonic-gate #ifdef TRACE
2020Sstevel@tonic-gate if (trace) {
2030Sstevel@tonic-gate if (!techoin) {
2040Sstevel@tonic-gate tfixnl();
2050Sstevel@tonic-gate techoin = 1;
2060Sstevel@tonic-gate fprintf(trace, "*** Input: ");
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate tracec(c);
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate #endif
2110Sstevel@tonic-gate lastvgk = 0;
2120Sstevel@tonic-gate return (c);
2130Sstevel@tonic-gate }
2140Sstevel@tonic-gate
2150Sstevel@tonic-gate /*
2160Sstevel@tonic-gate * Get a key, but if a delete, quit or attention
2170Sstevel@tonic-gate * is typed return 0 so we will abort a partial command.
2180Sstevel@tonic-gate */
219802Scf46844 int
getesc(void)220802Scf46844 getesc(void)
2210Sstevel@tonic-gate {
222802Scf46844 int c;
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate c = getkey();
2250Sstevel@tonic-gate switch (c) {
2260Sstevel@tonic-gate
2270Sstevel@tonic-gate case CTRL('v'):
2280Sstevel@tonic-gate case CTRL('q'):
2290Sstevel@tonic-gate c = getkey();
2300Sstevel@tonic-gate return (c);
2310Sstevel@tonic-gate
2320Sstevel@tonic-gate case ATTN:
2330Sstevel@tonic-gate case QUIT:
2340Sstevel@tonic-gate ungetkey(c);
2350Sstevel@tonic-gate return (0);
2360Sstevel@tonic-gate
2370Sstevel@tonic-gate case ESCAPE:
2380Sstevel@tonic-gate return (0);
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate return (c);
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate /*
2440Sstevel@tonic-gate * Peek at the next keystroke.
2450Sstevel@tonic-gate */
246802Scf46844 int
peekkey(void)247802Scf46844 peekkey(void)
2480Sstevel@tonic-gate {
2490Sstevel@tonic-gate
2500Sstevel@tonic-gate Peekkey = getkey();
2510Sstevel@tonic-gate return (Peekkey);
2520Sstevel@tonic-gate }
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate /*
2550Sstevel@tonic-gate * Read a line from the echo area, with single character prompt c.
2560Sstevel@tonic-gate * A return value of 1 means the user blewit or blewit away.
2570Sstevel@tonic-gate */
258802Scf46844 int
readecho(c)2590Sstevel@tonic-gate readecho(c)
2600Sstevel@tonic-gate unsigned char c;
2610Sstevel@tonic-gate {
262802Scf46844 unsigned char *sc = cursor;
263802Scf46844 int (*OP)();
2640Sstevel@tonic-gate bool waste;
265802Scf46844 int OPeek;
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate if (WBOT == WECHO)
2680Sstevel@tonic-gate vclean();
2690Sstevel@tonic-gate else
2700Sstevel@tonic-gate vclrech(0);
2710Sstevel@tonic-gate splitw++;
2720Sstevel@tonic-gate vgoto(WECHO, 0);
2730Sstevel@tonic-gate putchar(c);
2740Sstevel@tonic-gate vclreol();
2750Sstevel@tonic-gate vgoto(WECHO, 1);
2760Sstevel@tonic-gate cursor = linebuf; linebuf[0] = 0; genbuf[0] = c;
2770Sstevel@tonic-gate ixlatctl(1);
2780Sstevel@tonic-gate if (peekbr()) {
2790Sstevel@tonic-gate if (!INS[0] || (unsigned char)INS[128] == 0200) {
2800Sstevel@tonic-gate INS[128] = 0;
2810Sstevel@tonic-gate goto blewit;
2820Sstevel@tonic-gate }
2830Sstevel@tonic-gate vglobp = INS;
2840Sstevel@tonic-gate }
2850Sstevel@tonic-gate OP = Pline; Pline = normline;
2860Sstevel@tonic-gate (void)vgetline(0, genbuf + 1, &waste, c);
2870Sstevel@tonic-gate doomed = 0; /* don't care about doomed characters in echo line */
2880Sstevel@tonic-gate ixlatctl(0);
2890Sstevel@tonic-gate if (Outchar == termchar)
2900Sstevel@tonic-gate putchar('\n');
2910Sstevel@tonic-gate vscrap();
2920Sstevel@tonic-gate Pline = OP;
2930Sstevel@tonic-gate if (Peekkey != ATTN && Peekkey != QUIT && Peekkey != CTRL('h')) {
2940Sstevel@tonic-gate cursor = sc;
2950Sstevel@tonic-gate vclreol();
2960Sstevel@tonic-gate return (0);
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate blewit:
2990Sstevel@tonic-gate OPeek = Peekkey==CTRL('h') ? 0 : Peekkey; Peekkey = 0;
3000Sstevel@tonic-gate splitw = 0;
3010Sstevel@tonic-gate vclean();
3020Sstevel@tonic-gate vshow(dot, NOLINE);
3030Sstevel@tonic-gate vnline(sc);
3040Sstevel@tonic-gate Peekkey = OPeek;
3050Sstevel@tonic-gate return (1);
3060Sstevel@tonic-gate }
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate /*
3090Sstevel@tonic-gate * A complete command has been defined for
3100Sstevel@tonic-gate * the purposes of repeat, so copy it from
3110Sstevel@tonic-gate * the working to the previous command buffer.
3120Sstevel@tonic-gate */
313802Scf46844 void
setLAST(void)314802Scf46844 setLAST(void)
3150Sstevel@tonic-gate {
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate if (vglobp || vmacp)
3180Sstevel@tonic-gate return;
3190Sstevel@tonic-gate lastreg = vreg;
3200Sstevel@tonic-gate lasthad = Xhadcnt;
3210Sstevel@tonic-gate lastcnt = Xcnt;
3220Sstevel@tonic-gate *lastcp = 0;
3230Sstevel@tonic-gate CP(lastcmd, workcmd);
3240Sstevel@tonic-gate }
3250Sstevel@tonic-gate
3260Sstevel@tonic-gate /*
3270Sstevel@tonic-gate * Gather up some more text from an insert.
3280Sstevel@tonic-gate * If the insertion buffer oveflows, then destroy
3290Sstevel@tonic-gate * the repeatability of the insert.
3300Sstevel@tonic-gate */
331802Scf46844 void
addtext(unsigned char * cp)332802Scf46844 addtext(unsigned char *cp)
3330Sstevel@tonic-gate {
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate if (vglobp)
3360Sstevel@tonic-gate return;
3370Sstevel@tonic-gate addto(INS, cp);
3380Sstevel@tonic-gate if ((unsigned char)INS[128] == 0200)
3390Sstevel@tonic-gate lastcmd[0] = 0;
3400Sstevel@tonic-gate }
3410Sstevel@tonic-gate
342802Scf46844 void
setDEL(void)343802Scf46844 setDEL(void)
3440Sstevel@tonic-gate {
3450Sstevel@tonic-gate
3460Sstevel@tonic-gate setBUF(DEL);
3470Sstevel@tonic-gate }
3480Sstevel@tonic-gate
3490Sstevel@tonic-gate /*
3500Sstevel@tonic-gate * Put text from cursor upto wcursor in BUF.
3510Sstevel@tonic-gate */
352802Scf46844 void
setBUF(unsigned char * BUF)353802Scf46844 setBUF(unsigned char *BUF)
3540Sstevel@tonic-gate {
355802Scf46844 int c;
356802Scf46844 unsigned char *wp = wcursor;
3570Sstevel@tonic-gate
3580Sstevel@tonic-gate c = *wp;
3590Sstevel@tonic-gate *wp = 0;
3600Sstevel@tonic-gate BUF[0] = 0;
3610Sstevel@tonic-gate BUF[128] = 0;
3620Sstevel@tonic-gate addto(BUF, cursor);
3630Sstevel@tonic-gate *wp = c;
3640Sstevel@tonic-gate }
3650Sstevel@tonic-gate
366802Scf46844 void
addto(unsigned char * buf,unsigned char * str)367802Scf46844 addto(unsigned char *buf, unsigned char *str)
3680Sstevel@tonic-gate {
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate if ((unsigned char)buf[128] == 0200)
3710Sstevel@tonic-gate return;
3720Sstevel@tonic-gate if (strlen(buf) + strlen(str) + 1 >= VBSIZE) {
3730Sstevel@tonic-gate buf[128] = 0200;
3740Sstevel@tonic-gate return;
3750Sstevel@tonic-gate }
3760Sstevel@tonic-gate (void)strcat(buf, str);
3770Sstevel@tonic-gate buf[128] = 0;
3780Sstevel@tonic-gate }
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate /*
3810Sstevel@tonic-gate * Verbalize command name and embed it in message.
3820Sstevel@tonic-gate */
3830Sstevel@tonic-gate char *
verbalize(cnt,cmdstr,sgn)3840Sstevel@tonic-gate verbalize(cnt, cmdstr, sgn)
3850Sstevel@tonic-gate int cnt;
3860Sstevel@tonic-gate char *cmdstr, *sgn;
3870Sstevel@tonic-gate {
3880Sstevel@tonic-gate if (cmdstr[0] == '\0')
3890Sstevel@tonic-gate cmdstr = (char *)Command;
3900Sstevel@tonic-gate if (sgn[0] == '\0') {
3910Sstevel@tonic-gate switch (cmdstr[0]) {
3920Sstevel@tonic-gate case 'c':
3930Sstevel@tonic-gate if (cmdstr[1] == 'h') {
394802Scf46844 viprintf((cnt == 1) ?
395802Scf46844 gettext("1 line changed") :
396802Scf46844 gettext("%d lines changed"), cnt);
3970Sstevel@tonic-gate break;
3980Sstevel@tonic-gate } else if (cmdstr[1] != 'o') {
3990Sstevel@tonic-gate goto Default;
4000Sstevel@tonic-gate }
4010Sstevel@tonic-gate case 't':
4020Sstevel@tonic-gate if (cmdstr[1] != '\0')
4030Sstevel@tonic-gate goto Default;
404802Scf46844 viprintf((cnt == 1) ? gettext("1 line copied") :
4050Sstevel@tonic-gate gettext("%d lines copied"), cnt);
4060Sstevel@tonic-gate break;
4070Sstevel@tonic-gate case 'd':
408802Scf46844 viprintf((cnt == 1) ? gettext("1 line deleted") :
4090Sstevel@tonic-gate gettext("%d lines deleted"), cnt);
4100Sstevel@tonic-gate break;
4110Sstevel@tonic-gate case 'j':
412802Scf46844 viprintf((cnt == 1) ? gettext("1 line joined") :
4130Sstevel@tonic-gate gettext("%d lines joined"), cnt);
4140Sstevel@tonic-gate break;
4150Sstevel@tonic-gate case 'm':
416802Scf46844 viprintf((cnt == 1) ? gettext("1 line moved") :
4170Sstevel@tonic-gate gettext("%d lines moved"), cnt);
4180Sstevel@tonic-gate break;
4190Sstevel@tonic-gate case 'p':
420802Scf46844 viprintf((cnt == 1) ? gettext("1 line put") :
4210Sstevel@tonic-gate gettext("%d lines put"), cnt);
4220Sstevel@tonic-gate break;
4230Sstevel@tonic-gate case 'y':
424802Scf46844 viprintf((cnt == 1) ? gettext("1 line yanked") :
4250Sstevel@tonic-gate gettext("%d lines yanked"), cnt);
4260Sstevel@tonic-gate break;
4270Sstevel@tonic-gate case '>':
428802Scf46844 viprintf((cnt == 1) ? gettext("1 line >>ed") :
4290Sstevel@tonic-gate gettext("%d lines >>ed"), cnt);
4300Sstevel@tonic-gate break;
4310Sstevel@tonic-gate case '=':
432802Scf46844 viprintf((cnt == 1) ? gettext("1 line =ed") :
4330Sstevel@tonic-gate gettext("%d lines =ed"), cnt);
4340Sstevel@tonic-gate break;
4350Sstevel@tonic-gate case '<':
436802Scf46844 viprintf((cnt == 1) ? gettext("1 line <<ed") :
4370Sstevel@tonic-gate gettext("%d lines <<ed"), cnt);
4380Sstevel@tonic-gate break;
4390Sstevel@tonic-gate default:
4400Sstevel@tonic-gate Default:
441802Scf46844 viprintf((cnt == 1) ? gettext("1 line") :
4420Sstevel@tonic-gate gettext("%d lines"), cnt);
4430Sstevel@tonic-gate break;
4440Sstevel@tonic-gate }
4450Sstevel@tonic-gate } else if (sgn[0] == 'm') {
446802Scf46844 viprintf((cnt == 1) ? gettext("1 more line") :
4470Sstevel@tonic-gate gettext("%d more lines"), cnt);
4480Sstevel@tonic-gate } else {
449802Scf46844 viprintf((cnt == 1) ? gettext("1 fewer line") :
4500Sstevel@tonic-gate gettext("%d fewer lines"), cnt);
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate return (NULL);
4530Sstevel@tonic-gate }
4540Sstevel@tonic-gate
4550Sstevel@tonic-gate /*
4560Sstevel@tonic-gate * Note a change affecting a lot of lines, or non-visible
4570Sstevel@tonic-gate * lines. If the parameter must is set, then we only want
4580Sstevel@tonic-gate * to do this for open modes now; return and save for later
4590Sstevel@tonic-gate * notification in visual.
4600Sstevel@tonic-gate */
461802Scf46844 int
noteit(must)4620Sstevel@tonic-gate noteit(must)
4630Sstevel@tonic-gate bool must;
4640Sstevel@tonic-gate {
465802Scf46844 int sdl = destline, sdc = destcol;
4660Sstevel@tonic-gate
4670Sstevel@tonic-gate if (notecnt < 1 || !must && state == VISUAL)
4680Sstevel@tonic-gate return (0);
4690Sstevel@tonic-gate splitw++;
4700Sstevel@tonic-gate if (WBOT == WECHO)
4710Sstevel@tonic-gate vmoveitup(1, 1);
4720Sstevel@tonic-gate vigoto(WECHO, 0);
4730Sstevel@tonic-gate
4740Sstevel@tonic-gate verbalize(notecnt, notenam, notesgn);
4750Sstevel@tonic-gate vclreol();
4760Sstevel@tonic-gate notecnt = 0;
4770Sstevel@tonic-gate if (state != VISUAL)
4780Sstevel@tonic-gate vcnt = vcline = 0;
4790Sstevel@tonic-gate splitw = 0;
4800Sstevel@tonic-gate if (state == ONEOPEN || state == CRTOPEN)
4810Sstevel@tonic-gate vup1();
4820Sstevel@tonic-gate destline = sdl; destcol = sdc;
4830Sstevel@tonic-gate return (1);
4840Sstevel@tonic-gate }
4850Sstevel@tonic-gate
4860Sstevel@tonic-gate /*
4870Sstevel@tonic-gate * Ring or beep.
4880Sstevel@tonic-gate * If possible, flash screen.
4890Sstevel@tonic-gate */
490802Scf46844 int
beep(void)491802Scf46844 beep(void)
4920Sstevel@tonic-gate {
4930Sstevel@tonic-gate
4940Sstevel@tonic-gate if (flash_screen && value(vi_FLASH))
4950Sstevel@tonic-gate vputp(flash_screen, 0);
4960Sstevel@tonic-gate else if (bell)
4970Sstevel@tonic-gate vputp(bell, 0);
498802Scf46844 return (0);
4990Sstevel@tonic-gate }
5000Sstevel@tonic-gate
5010Sstevel@tonic-gate /*
5020Sstevel@tonic-gate * Map the command input character c,
5030Sstevel@tonic-gate * for keypads and labelled keys which do cursor
5040Sstevel@tonic-gate * motions. I.e. on an adm3a we might map ^K to ^P.
5050Sstevel@tonic-gate * DM1520 for example has a lot of mappable characters.
5060Sstevel@tonic-gate */
5070Sstevel@tonic-gate
508802Scf46844 int
map(c,maps,commch)509802Scf46844 map(c, maps, commch)
510802Scf46844 int c;
511802Scf46844 struct maps *maps;
512802Scf46844 unsigned char commch; /* indicate if in append/insert/replace mode */
5130Sstevel@tonic-gate {
514802Scf46844 int d;
515802Scf46844 unsigned char *p, *q;
5160Sstevel@tonic-gate unsigned char b[10]; /* Assumption: no keypad sends string longer than 10 */
5170Sstevel@tonic-gate unsigned char *st;
5180Sstevel@tonic-gate
5190Sstevel@tonic-gate /*
5200Sstevel@tonic-gate * Mapping for special keys on the terminal only.
5210Sstevel@tonic-gate * BUG: if there's a long sequence and it matches
5220Sstevel@tonic-gate * some chars and then misses, we lose some chars.
5230Sstevel@tonic-gate *
5240Sstevel@tonic-gate * For this to work, some conditions must be met.
5250Sstevel@tonic-gate * 1) Keypad sends SHORT (2 or 3 char) strings
5260Sstevel@tonic-gate * 2) All strings sent are same length & similar
5270Sstevel@tonic-gate * 3) The user is unlikely to type the first few chars of
5280Sstevel@tonic-gate * one of these strings very fast.
5290Sstevel@tonic-gate * Note: some code has been fixed up since the above was laid out,
5300Sstevel@tonic-gate * so conditions 1 & 2 are probably not required anymore.
5310Sstevel@tonic-gate * However, this hasn't been tested with any first char
5320Sstevel@tonic-gate * that means anything else except escape.
5330Sstevel@tonic-gate */
5340Sstevel@tonic-gate #ifdef MDEBUG
5350Sstevel@tonic-gate if (trace)
5360Sstevel@tonic-gate fprintf(trace,"map(%c): ",c);
5370Sstevel@tonic-gate #endif
5380Sstevel@tonic-gate /*
5390Sstevel@tonic-gate * If c==0, the char came from getesc typing escape. Pass it through
5400Sstevel@tonic-gate * unchanged. 0 messes up the following code anyway.
5410Sstevel@tonic-gate */
5420Sstevel@tonic-gate if (c==0)
5430Sstevel@tonic-gate return(0);
5440Sstevel@tonic-gate
5450Sstevel@tonic-gate b[0] = c;
5460Sstevel@tonic-gate b[1] = 0;
5470Sstevel@tonic-gate for (d=0; d < MAXNOMACS && maps[d].mapto; d++) {
5480Sstevel@tonic-gate #ifdef MDEBUG
5490Sstevel@tonic-gate if (trace)
5500Sstevel@tonic-gate fprintf(trace,"\ntry '%s', ",maps[d].cap);
5510Sstevel@tonic-gate #endif
5520Sstevel@tonic-gate if (p = maps[d].cap) {
5530Sstevel@tonic-gate for (q=b; *p; p++, q++) {
5540Sstevel@tonic-gate #ifdef MDEBUG
5550Sstevel@tonic-gate if (trace)
5560Sstevel@tonic-gate fprintf(trace,"q->b[%d], ",q-b);
5570Sstevel@tonic-gate #endif
5580Sstevel@tonic-gate if (*q==0) {
5590Sstevel@tonic-gate /*
5600Sstevel@tonic-gate * Is there another char waiting?
5610Sstevel@tonic-gate *
5620Sstevel@tonic-gate * This test is oversimplified, but
5630Sstevel@tonic-gate * should work mostly. It handles the
5640Sstevel@tonic-gate * case where we get an ESCAPE that
5650Sstevel@tonic-gate * wasn't part of a keypad string.
5660Sstevel@tonic-gate */
5670Sstevel@tonic-gate if ((c=='#' ? peekkey() : fastpeekkey()) == 0) {
5680Sstevel@tonic-gate #ifdef MDEBUG
5690Sstevel@tonic-gate if (trace)
5700Sstevel@tonic-gate fprintf(trace,"fpk=0: will return '%c'",c);
5710Sstevel@tonic-gate #endif
5720Sstevel@tonic-gate /*
5730Sstevel@tonic-gate * Nothing waiting. Push back
5740Sstevel@tonic-gate * what we peeked at & return
5750Sstevel@tonic-gate * failure (c).
5760Sstevel@tonic-gate *
5770Sstevel@tonic-gate * We want to be able to undo
5780Sstevel@tonic-gate * commands, but it's nonsense
5790Sstevel@tonic-gate * to undo part of an insertion
5800Sstevel@tonic-gate * so if in input mode don't.
5810Sstevel@tonic-gate */
5820Sstevel@tonic-gate #ifdef MDEBUG
5830Sstevel@tonic-gate if (trace)
5840Sstevel@tonic-gate fprintf(trace, "Call macpush, b %d %d %d\n", b[0], b[1], b[2]);
5850Sstevel@tonic-gate #endif
5860Sstevel@tonic-gate macpush(&b[1],maps == arrows);
5870Sstevel@tonic-gate #ifdef MDEBUG
5880Sstevel@tonic-gate if (trace)
5890Sstevel@tonic-gate fprintf(trace, "return %d\n", c);
5900Sstevel@tonic-gate #endif
5910Sstevel@tonic-gate return(c);
5920Sstevel@tonic-gate }
5930Sstevel@tonic-gate *q = getkey();
5940Sstevel@tonic-gate q[1] = 0;
5950Sstevel@tonic-gate }
5960Sstevel@tonic-gate if (*p != *q)
5970Sstevel@tonic-gate goto contin;
5980Sstevel@tonic-gate }
5990Sstevel@tonic-gate macpush(maps[d].mapto,maps == arrows);
6000Sstevel@tonic-gate /*
6010Sstevel@tonic-gate * For all macros performed within insert,
6020Sstevel@tonic-gate * append, or replacement mode, we must end
6030Sstevel@tonic-gate * up returning back to that mode when we
6040Sstevel@tonic-gate * return (except that append will become
6050Sstevel@tonic-gate * insert for <home> key, so cursor is not
6060Sstevel@tonic-gate * in second column).
6070Sstevel@tonic-gate *
6080Sstevel@tonic-gate * In order to preserve backward movement
6090Sstevel@tonic-gate * when leaving insert mode, an 'l' must be
6100Sstevel@tonic-gate * done to compensate for the left done by
6110Sstevel@tonic-gate * the <esc> (except when cursor is already
6120Sstevel@tonic-gate * in the first column: i.e., outcol = 0).
6130Sstevel@tonic-gate */
6140Sstevel@tonic-gate if ((maps == immacs)
6150Sstevel@tonic-gate && strcmp(maps[d].descr, maps[d].cap)) {
6160Sstevel@tonic-gate switch (commch) {
6170Sstevel@tonic-gate case 'R':
6180Sstevel@tonic-gate if (!strcmp(maps[d].descr, "home"))
6190Sstevel@tonic-gate st = (unsigned char *)"R";
6200Sstevel@tonic-gate else
6210Sstevel@tonic-gate if (outcol == 0)
6220Sstevel@tonic-gate st = (unsigned char *)"R";
6230Sstevel@tonic-gate else
6240Sstevel@tonic-gate st = (unsigned char *)"lR";
6250Sstevel@tonic-gate break;
6260Sstevel@tonic-gate case 'i':
6270Sstevel@tonic-gate if (!strcmp(maps[d].descr, "home"))
6280Sstevel@tonic-gate st = (unsigned char *)"i";
6290Sstevel@tonic-gate else
6300Sstevel@tonic-gate if (outcol == 0)
6310Sstevel@tonic-gate st = (unsigned char *)"i";
6320Sstevel@tonic-gate else
6330Sstevel@tonic-gate st = (unsigned char *)"li";
6340Sstevel@tonic-gate break;
6350Sstevel@tonic-gate case 'a':
6360Sstevel@tonic-gate if (!strcmp(maps[d].descr, "home"))
6370Sstevel@tonic-gate st = (unsigned char *)"i";
6380Sstevel@tonic-gate else
6390Sstevel@tonic-gate st = (unsigned char *)"a";
6400Sstevel@tonic-gate break;
6410Sstevel@tonic-gate default:
6420Sstevel@tonic-gate st = (unsigned char *)"i";
6430Sstevel@tonic-gate }
6440Sstevel@tonic-gate if(strlen(vmacbuf) + strlen(st) > BUFSIZE)
6450Sstevel@tonic-gate error(value(vi_TERSE) ?
6460Sstevel@tonic-gate gettext("Macro too long") : gettext("Macro too long - maybe recursive?"));
6470Sstevel@tonic-gate else
6480Sstevel@tonic-gate /*
6490Sstevel@tonic-gate * Macros such as function keys are
6500Sstevel@tonic-gate * performed by leaving the insert,
6510Sstevel@tonic-gate * replace, or append mode, executing
6520Sstevel@tonic-gate * the proper cursor movement commands
6530Sstevel@tonic-gate * and returning to the mode we are
6540Sstevel@tonic-gate * currently in (commch).
6550Sstevel@tonic-gate */
6560Sstevel@tonic-gate strcat(vmacbuf, st);
6570Sstevel@tonic-gate }
6580Sstevel@tonic-gate c = getkey();
6590Sstevel@tonic-gate #ifdef MDEBUG
6600Sstevel@tonic-gate if (trace)
6610Sstevel@tonic-gate fprintf(trace,"Success: push(%s), return %c",maps[d].mapto, c);
6620Sstevel@tonic-gate #endif
6630Sstevel@tonic-gate return(c); /* first char of map string */
6640Sstevel@tonic-gate contin:;
6650Sstevel@tonic-gate }
6660Sstevel@tonic-gate }
6670Sstevel@tonic-gate #ifdef MDEBUG
6680Sstevel@tonic-gate if (trace)
6690Sstevel@tonic-gate fprintf(trace,"Fail: push(%s), return %c", &b[1], c);
6700Sstevel@tonic-gate #endif
6710Sstevel@tonic-gate macpush(&b[1],0);
6720Sstevel@tonic-gate return(c);
6730Sstevel@tonic-gate }
6740Sstevel@tonic-gate
6750Sstevel@tonic-gate /*
6760Sstevel@tonic-gate * Push st onto the front of vmacp. This is tricky because we have to
6770Sstevel@tonic-gate * worry about where vmacp was previously pointing. We also have to
6780Sstevel@tonic-gate * check for overflow (which is typically from a recursive macro)
6790Sstevel@tonic-gate * Finally we have to set a flag so the whole thing can be undone.
6800Sstevel@tonic-gate * canundo is 1 iff we want to be able to undo the macro. This
6810Sstevel@tonic-gate * is false for, for example, pushing back lookahead from fastpeekkey(),
6820Sstevel@tonic-gate * since otherwise two fast escapes can clobber our undo.
6830Sstevel@tonic-gate */
684802Scf46844 void
macpush(unsigned char * st,int canundo)685802Scf46844 macpush(unsigned char *st, int canundo)
6860Sstevel@tonic-gate {
6870Sstevel@tonic-gate unsigned char tmpbuf[BUFSIZE];
6880Sstevel@tonic-gate
6890Sstevel@tonic-gate if (st==0 || *st==0)
6900Sstevel@tonic-gate return;
6910Sstevel@tonic-gate #ifdef MDEBUG
6920Sstevel@tonic-gate if (trace)
6930Sstevel@tonic-gate fprintf(trace, "macpush(%s), canundo=%d\n",st,canundo);
6940Sstevel@tonic-gate #endif
6950Sstevel@tonic-gate if ((vmacp ? strlen(vmacp) : 0) + strlen(st) > BUFSIZE)
6960Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Macro too long") :
6970Sstevel@tonic-gate gettext("Macro too long - maybe recursive?"));
6980Sstevel@tonic-gate if (vmacp) {
6990Sstevel@tonic-gate strcpy(tmpbuf, vmacp);
7000Sstevel@tonic-gate if (!FIXUNDO)
7010Sstevel@tonic-gate canundo = 0; /* can't undo inside a macro anyway */
7020Sstevel@tonic-gate }
7030Sstevel@tonic-gate strcpy(vmacbuf, st);
7040Sstevel@tonic-gate if (vmacp)
7050Sstevel@tonic-gate strcat(vmacbuf, tmpbuf);
7060Sstevel@tonic-gate vmacp = vmacbuf;
7070Sstevel@tonic-gate /* arrange to be able to undo the whole macro */
7080Sstevel@tonic-gate if (canundo) {
7090Sstevel@tonic-gate #ifdef notdef
7100Sstevel@tonic-gate otchng = tchng;
7110Sstevel@tonic-gate vsave();
7120Sstevel@tonic-gate saveall();
7130Sstevel@tonic-gate inopen = -1; /* no need to save since it had to be 1 or -1 before */
7140Sstevel@tonic-gate vundkind = VMANY;
7150Sstevel@tonic-gate #endif
7160Sstevel@tonic-gate vch_mac = VC_NOCHANGE;
7170Sstevel@tonic-gate }
7180Sstevel@tonic-gate }
7190Sstevel@tonic-gate
7200Sstevel@tonic-gate #ifdef UNDOTRACE
visdump(s)7210Sstevel@tonic-gate visdump(s)
7220Sstevel@tonic-gate unsigned char *s;
7230Sstevel@tonic-gate {
724802Scf46844 int i;
7250Sstevel@tonic-gate
7260Sstevel@tonic-gate if (!trace) return;
7270Sstevel@tonic-gate
7280Sstevel@tonic-gate fprintf(trace, "\n%s: basWTOP=%d, basWLINES=%d, WTOP=%d, WBOT=%d, WLINES=%d, WCOLS=%d, WECHO=%d\n",
7290Sstevel@tonic-gate s, basWTOP, basWLINES, WTOP, WBOT, WLINES, WCOLS, WECHO);
7300Sstevel@tonic-gate fprintf(trace, " vcnt=%d, vcline=%d, cursor=%d, wcursor=%d, wdot=%d\n",
7310Sstevel@tonic-gate vcnt, vcline, cursor-linebuf, wcursor-linebuf, wdot-zero);
7320Sstevel@tonic-gate for (i=0; i<TUBELINES; i++)
7330Sstevel@tonic-gate if (vtube[i] && *vtube[i])
7340Sstevel@tonic-gate fprintf(trace, "%d: '%s'\n", i, vtube[i]);
7350Sstevel@tonic-gate tvliny();
7360Sstevel@tonic-gate }
7370Sstevel@tonic-gate
vudump(s)7380Sstevel@tonic-gate vudump(s)
7390Sstevel@tonic-gate unsigned char *s;
7400Sstevel@tonic-gate {
741802Scf46844 line *p;
7420Sstevel@tonic-gate unsigned char savelb[1024];
7430Sstevel@tonic-gate
7440Sstevel@tonic-gate if (!trace) return;
7450Sstevel@tonic-gate
7460Sstevel@tonic-gate fprintf(trace, "\n%s: undkind=%d, vundkind=%d, unddel=%d, undap1=%d, undap2=%d,\n",
7470Sstevel@tonic-gate s, undkind, vundkind, lineno(unddel), lineno(undap1), lineno(undap2));
7480Sstevel@tonic-gate fprintf(trace, " undadot=%d, dot=%d, dol=%d, unddol=%d, truedol=%d\n",
7490Sstevel@tonic-gate lineno(undadot), lineno(dot), lineno(dol), lineno(unddol), lineno(truedol));
7500Sstevel@tonic-gate fprintf(trace, " [\n");
7510Sstevel@tonic-gate CP(savelb, linebuf);
7520Sstevel@tonic-gate fprintf(trace, "linebuf = '%s'\n", linebuf);
7530Sstevel@tonic-gate for (p=zero+1; p<=truedol; p++) {
7540Sstevel@tonic-gate fprintf(trace, "%o ", *p);
755*13093SRoger.Faulkner@Oracle.COM getaline(*p);
7560Sstevel@tonic-gate fprintf(trace, "'%s'\n", linebuf);
7570Sstevel@tonic-gate }
7580Sstevel@tonic-gate fprintf(trace, "]\n");
7590Sstevel@tonic-gate CP(linebuf, savelb);
7600Sstevel@tonic-gate }
7610Sstevel@tonic-gate #endif
7620Sstevel@tonic-gate
7630Sstevel@tonic-gate /*
7640Sstevel@tonic-gate * Get a count from the keyed input stream.
7650Sstevel@tonic-gate * A zero count is indistinguishable from no count.
7660Sstevel@tonic-gate */
767802Scf46844 int
vgetcnt(void)768802Scf46844 vgetcnt(void)
7690Sstevel@tonic-gate {
770802Scf46844 int c, cnt;
7710Sstevel@tonic-gate
7720Sstevel@tonic-gate cnt = 0;
7730Sstevel@tonic-gate for (;;) {
7740Sstevel@tonic-gate c = getkey();
7750Sstevel@tonic-gate if (!isdigit(c))
7760Sstevel@tonic-gate break;
7770Sstevel@tonic-gate cnt *= 10, cnt += c - '0';
7780Sstevel@tonic-gate }
7790Sstevel@tonic-gate ungetkey(c);
7800Sstevel@tonic-gate Xhadcnt = 1;
7810Sstevel@tonic-gate Xcnt = cnt;
7820Sstevel@tonic-gate return(cnt);
7830Sstevel@tonic-gate }
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate /*
7860Sstevel@tonic-gate * fastpeekkey is just like peekkey but insists the character come in
7870Sstevel@tonic-gate * fast (within 1 second). This will succeed if it is the 2nd char of
7880Sstevel@tonic-gate * a machine generated sequence (such as a function pad from an escape
7890Sstevel@tonic-gate * flavor terminal) but fail for a human hitting escape then waiting.
7900Sstevel@tonic-gate */
791802Scf46844 int
fastpeekkey(void)792802Scf46844 fastpeekkey(void)
7930Sstevel@tonic-gate {
7940Sstevel@tonic-gate void trapalarm();
795802Scf46844 int c;
7960Sstevel@tonic-gate
7970Sstevel@tonic-gate /*
7980Sstevel@tonic-gate * If the user has set notimeout, we wait forever for a key.
7990Sstevel@tonic-gate * If we are in a macro we do too, but since it's already
8000Sstevel@tonic-gate * buffered internally it will return immediately.
8010Sstevel@tonic-gate * In other cases we force this to die in 1 second.
8020Sstevel@tonic-gate * This is pretty reliable (VMUNIX rounds it to .5 - 1.5 secs,
8030Sstevel@tonic-gate * but UNIX truncates it to 0 - 1 secs) but due to system delays
8040Sstevel@tonic-gate * there are times when arrow keys or very fast typing get counted
8050Sstevel@tonic-gate * as separate. notimeout is provided for people who dislike such
8060Sstevel@tonic-gate * nondeterminism.
8070Sstevel@tonic-gate */
8080Sstevel@tonic-gate CATCH
8090Sstevel@tonic-gate if (value(vi_TIMEOUT) && inopen >= 0) {
8100Sstevel@tonic-gate signal(SIGALRM, trapalarm);
8110Sstevel@tonic-gate setalarm();
8120Sstevel@tonic-gate }
8130Sstevel@tonic-gate c = peekkey();
8140Sstevel@tonic-gate cancelalarm();
8150Sstevel@tonic-gate ONERR
8160Sstevel@tonic-gate c = 0;
8170Sstevel@tonic-gate ENDCATCH
8180Sstevel@tonic-gate /* Should have an alternative method based on select for 4.2BSD */
8190Sstevel@tonic-gate return(c);
8200Sstevel@tonic-gate }
8210Sstevel@tonic-gate
8220Sstevel@tonic-gate static int ftfd;
8230Sstevel@tonic-gate struct requestbuf {
8240Sstevel@tonic-gate short time;
8250Sstevel@tonic-gate short signo;
8260Sstevel@tonic-gate };
8270Sstevel@tonic-gate
8280Sstevel@tonic-gate /*
8290Sstevel@tonic-gate * Arrange for SIGALRM to come in shortly, so we don't
8300Sstevel@tonic-gate * hang very long if the user didn't type anything. There are
8310Sstevel@tonic-gate * various ways to do this on different systems.
8320Sstevel@tonic-gate */
833802Scf46844 void
setalarm(void)834802Scf46844 setalarm(void)
8350Sstevel@tonic-gate {
8360Sstevel@tonic-gate unsigned char ftname[20];
8370Sstevel@tonic-gate struct requestbuf rb;
8380Sstevel@tonic-gate
8390Sstevel@tonic-gate #ifdef FTIOCSET
8400Sstevel@tonic-gate /*
8410Sstevel@tonic-gate * Use nonstandard "fast timer" to get better than
8420Sstevel@tonic-gate * one second resolution. We must wait at least
8430Sstevel@tonic-gate * 1/15th of a second because some keypads don't
8440Sstevel@tonic-gate * transmit faster than this.
8450Sstevel@tonic-gate */
8460Sstevel@tonic-gate
8470Sstevel@tonic-gate /* Open ft psuedo-device - we need our own copy. */
8480Sstevel@tonic-gate if (ftfd == 0) {
8490Sstevel@tonic-gate strcpy(ftname, "/dev/ft0");
8500Sstevel@tonic-gate while (ftfd <= 0 && ftname[7] <= '~') {
8510Sstevel@tonic-gate ftfd = open(ftname, 0);
8520Sstevel@tonic-gate if (ftfd <= 0)
8530Sstevel@tonic-gate ftname[7] ++;
8540Sstevel@tonic-gate }
8550Sstevel@tonic-gate }
8560Sstevel@tonic-gate if (ftfd <= 0) { /* Couldn't open a /dev/ft? */
8570Sstevel@tonic-gate alarm(1);
8580Sstevel@tonic-gate } else {
8590Sstevel@tonic-gate rb.time = 6; /* 6 ticks = 100 ms > 67 ms. */
8600Sstevel@tonic-gate rb.signo = SIGALRM;
8610Sstevel@tonic-gate ioctl(ftfd, FTIOCSET, &rb);
8620Sstevel@tonic-gate }
8630Sstevel@tonic-gate #else
8640Sstevel@tonic-gate /*
8650Sstevel@tonic-gate * No special capabilities, so we use alarm, with 1 sec. resolution.
8660Sstevel@tonic-gate */
8670Sstevel@tonic-gate alarm(1);
8680Sstevel@tonic-gate #endif
8690Sstevel@tonic-gate }
8700Sstevel@tonic-gate
8710Sstevel@tonic-gate /*
8720Sstevel@tonic-gate * Get rid of any impending incoming SIGALRM.
8730Sstevel@tonic-gate */
874802Scf46844 void
cancelalarm(void)875802Scf46844 cancelalarm(void)
8760Sstevel@tonic-gate {
8770Sstevel@tonic-gate struct requestbuf rb;
8780Sstevel@tonic-gate #ifdef FTIOCSET
8790Sstevel@tonic-gate if (ftfd > 0) {
8800Sstevel@tonic-gate rb.time = 0;
8810Sstevel@tonic-gate rb.signo = SIGALRM;
8820Sstevel@tonic-gate ioctl(ftfd, FTIOCCANCEL, &rb);
8830Sstevel@tonic-gate }
8840Sstevel@tonic-gate #endif
8850Sstevel@tonic-gate alarm(0); /* Have to do this whether or not FTIOCSET */
8860Sstevel@tonic-gate }
8870Sstevel@tonic-gate
trapalarm()8880Sstevel@tonic-gate void trapalarm() {
8890Sstevel@tonic-gate alarm(0);
8900Sstevel@tonic-gate longjmp(vreslab,1);
8910Sstevel@tonic-gate }
892