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