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 5*23a1cceaSRoger A. Faulkner * Common Development and Distribution License (the "License"). 6*23a1cceaSRoger 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 */ 21*23a1cceaSRoger A. Faulkner 22f6db9f27Scf46844 /* 23*23a1cceaSRoger A. Faulkner * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 24f6db9f27Scf46844 */ 25f6db9f27Scf46844 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 */ 46f6db9f27Scf46844 void 47f6db9f27Scf46844 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 */ 57f6db9f27Scf46844 int 58f6db9f27Scf46844 getkey(void) 597c478bd9Sstevel@tonic-gate { 60f6db9f27Scf46844 int c; /* char --> int */ 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate do { 637c478bd9Sstevel@tonic-gate c = getbr(); 647c478bd9Sstevel@tonic-gate if (c==0) 65f6db9f27Scf46844 (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 */ 73f6db9f27Scf46844 int 74f6db9f27Scf46844 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 */ 93f6db9f27Scf46844 int 94f6db9f27Scf46844 getbr(void) 957c478bd9Sstevel@tonic-gate { 967c478bd9Sstevel@tonic-gate unsigned char ch; 97f6db9f27Scf46844 int c, d; 98f6db9f27Scf46844 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 */ 219f6db9f27Scf46844 int 220f6db9f27Scf46844 getesc(void) 2217c478bd9Sstevel@tonic-gate { 222f6db9f27Scf46844 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 */ 246f6db9f27Scf46844 int 247f6db9f27Scf46844 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 */ 258f6db9f27Scf46844 int 2597c478bd9Sstevel@tonic-gate readecho(c) 2607c478bd9Sstevel@tonic-gate unsigned char c; 2617c478bd9Sstevel@tonic-gate { 262f6db9f27Scf46844 unsigned char *sc = cursor; 263f6db9f27Scf46844 int (*OP)(); 2647c478bd9Sstevel@tonic-gate bool waste; 265f6db9f27Scf46844 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 */ 313f6db9f27Scf46844 void 314f6db9f27Scf46844 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 */ 331f6db9f27Scf46844 void 332f6db9f27Scf46844 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 342f6db9f27Scf46844 void 343f6db9f27Scf46844 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 */ 352f6db9f27Scf46844 void 353f6db9f27Scf46844 setBUF(unsigned char *BUF) 3547c478bd9Sstevel@tonic-gate { 355f6db9f27Scf46844 int c; 356f6db9f27Scf46844 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 366f6db9f27Scf46844 void 367f6db9f27Scf46844 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 * 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') { 394f6db9f27Scf46844 viprintf((cnt == 1) ? 395f6db9f27Scf46844 gettext("1 line changed") : 3967c478bd9Sstevel@tonic-gate 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 } 4017c478bd9Sstevel@tonic-gate case 't': 4027c478bd9Sstevel@tonic-gate if (cmdstr[1] != '\0') 4037c478bd9Sstevel@tonic-gate goto Default; 404f6db9f27Scf46844 viprintf((cnt == 1) ? gettext("1 line copied") : 4057c478bd9Sstevel@tonic-gate gettext("%d lines copied"), cnt); 4067c478bd9Sstevel@tonic-gate break; 4077c478bd9Sstevel@tonic-gate case 'd': 408f6db9f27Scf46844 viprintf((cnt == 1) ? gettext("1 line deleted") : 4097c478bd9Sstevel@tonic-gate gettext("%d lines deleted"), cnt); 4107c478bd9Sstevel@tonic-gate break; 4117c478bd9Sstevel@tonic-gate case 'j': 412f6db9f27Scf46844 viprintf((cnt == 1) ? gettext("1 line joined") : 4137c478bd9Sstevel@tonic-gate gettext("%d lines joined"), cnt); 4147c478bd9Sstevel@tonic-gate break; 4157c478bd9Sstevel@tonic-gate case 'm': 416f6db9f27Scf46844 viprintf((cnt == 1) ? gettext("1 line moved") : 4177c478bd9Sstevel@tonic-gate gettext("%d lines moved"), cnt); 4187c478bd9Sstevel@tonic-gate break; 4197c478bd9Sstevel@tonic-gate case 'p': 420f6db9f27Scf46844 viprintf((cnt == 1) ? gettext("1 line put") : 4217c478bd9Sstevel@tonic-gate gettext("%d lines put"), cnt); 4227c478bd9Sstevel@tonic-gate break; 4237c478bd9Sstevel@tonic-gate case 'y': 424f6db9f27Scf46844 viprintf((cnt == 1) ? gettext("1 line yanked") : 4257c478bd9Sstevel@tonic-gate gettext("%d lines yanked"), cnt); 4267c478bd9Sstevel@tonic-gate break; 4277c478bd9Sstevel@tonic-gate case '>': 428f6db9f27Scf46844 viprintf((cnt == 1) ? gettext("1 line >>ed") : 4297c478bd9Sstevel@tonic-gate gettext("%d lines >>ed"), cnt); 4307c478bd9Sstevel@tonic-gate break; 4317c478bd9Sstevel@tonic-gate case '=': 432f6db9f27Scf46844 viprintf((cnt == 1) ? gettext("1 line =ed") : 4337c478bd9Sstevel@tonic-gate gettext("%d lines =ed"), cnt); 4347c478bd9Sstevel@tonic-gate break; 4357c478bd9Sstevel@tonic-gate case '<': 436f6db9f27Scf46844 viprintf((cnt == 1) ? gettext("1 line <<ed") : 4377c478bd9Sstevel@tonic-gate gettext("%d lines <<ed"), cnt); 4387c478bd9Sstevel@tonic-gate break; 4397c478bd9Sstevel@tonic-gate default: 4407c478bd9Sstevel@tonic-gate Default: 441f6db9f27Scf46844 viprintf((cnt == 1) ? gettext("1 line") : 4427c478bd9Sstevel@tonic-gate gettext("%d lines"), cnt); 4437c478bd9Sstevel@tonic-gate break; 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate } else if (sgn[0] == 'm') { 446f6db9f27Scf46844 viprintf((cnt == 1) ? gettext("1 more line") : 4477c478bd9Sstevel@tonic-gate gettext("%d more lines"), cnt); 4487c478bd9Sstevel@tonic-gate } else { 449f6db9f27Scf46844 viprintf((cnt == 1) ? gettext("1 fewer line") : 4507c478bd9Sstevel@tonic-gate gettext("%d fewer lines"), cnt); 4517c478bd9Sstevel@tonic-gate } 4527c478bd9Sstevel@tonic-gate return (NULL); 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate /* 4567c478bd9Sstevel@tonic-gate * Note a change affecting a lot of lines, or non-visible 4577c478bd9Sstevel@tonic-gate * lines. If the parameter must is set, then we only want 4587c478bd9Sstevel@tonic-gate * to do this for open modes now; return and save for later 4597c478bd9Sstevel@tonic-gate * notification in visual. 4607c478bd9Sstevel@tonic-gate */ 461f6db9f27Scf46844 int 4627c478bd9Sstevel@tonic-gate noteit(must) 4637c478bd9Sstevel@tonic-gate bool must; 4647c478bd9Sstevel@tonic-gate { 465f6db9f27Scf46844 int sdl = destline, sdc = destcol; 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate if (notecnt < 1 || !must && state == VISUAL) 4687c478bd9Sstevel@tonic-gate return (0); 4697c478bd9Sstevel@tonic-gate splitw++; 4707c478bd9Sstevel@tonic-gate if (WBOT == WECHO) 4717c478bd9Sstevel@tonic-gate vmoveitup(1, 1); 4727c478bd9Sstevel@tonic-gate vigoto(WECHO, 0); 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate verbalize(notecnt, notenam, notesgn); 4757c478bd9Sstevel@tonic-gate vclreol(); 4767c478bd9Sstevel@tonic-gate notecnt = 0; 4777c478bd9Sstevel@tonic-gate if (state != VISUAL) 4787c478bd9Sstevel@tonic-gate vcnt = vcline = 0; 4797c478bd9Sstevel@tonic-gate splitw = 0; 4807c478bd9Sstevel@tonic-gate if (state == ONEOPEN || state == CRTOPEN) 4817c478bd9Sstevel@tonic-gate vup1(); 4827c478bd9Sstevel@tonic-gate destline = sdl; destcol = sdc; 4837c478bd9Sstevel@tonic-gate return (1); 4847c478bd9Sstevel@tonic-gate } 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate /* 4877c478bd9Sstevel@tonic-gate * Ring or beep. 4887c478bd9Sstevel@tonic-gate * If possible, flash screen. 4897c478bd9Sstevel@tonic-gate */ 490f6db9f27Scf46844 int 491f6db9f27Scf46844 beep(void) 4927c478bd9Sstevel@tonic-gate { 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate if (flash_screen && value(vi_FLASH)) 4957c478bd9Sstevel@tonic-gate vputp(flash_screen, 0); 4967c478bd9Sstevel@tonic-gate else if (bell) 4977c478bd9Sstevel@tonic-gate vputp(bell, 0); 498f6db9f27Scf46844 return (0); 4997c478bd9Sstevel@tonic-gate } 5007c478bd9Sstevel@tonic-gate 5017c478bd9Sstevel@tonic-gate /* 5027c478bd9Sstevel@tonic-gate * Map the command input character c, 5037c478bd9Sstevel@tonic-gate * for keypads and labelled keys which do cursor 5047c478bd9Sstevel@tonic-gate * motions. I.e. on an adm3a we might map ^K to ^P. 5057c478bd9Sstevel@tonic-gate * DM1520 for example has a lot of mappable characters. 5067c478bd9Sstevel@tonic-gate */ 5077c478bd9Sstevel@tonic-gate 508f6db9f27Scf46844 int 5097c478bd9Sstevel@tonic-gate map(c, maps, commch) 510f6db9f27Scf46844 int c; 511f6db9f27Scf46844 struct maps *maps; 5127c478bd9Sstevel@tonic-gate unsigned char commch; /* indicate if in append/insert/replace mode */ 5137c478bd9Sstevel@tonic-gate { 514f6db9f27Scf46844 int d; 515f6db9f27Scf46844 unsigned char *p, *q; 5167c478bd9Sstevel@tonic-gate unsigned char b[10]; /* Assumption: no keypad sends string longer than 10 */ 5177c478bd9Sstevel@tonic-gate unsigned char *st; 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate /* 5207c478bd9Sstevel@tonic-gate * Mapping for special keys on the terminal only. 5217c478bd9Sstevel@tonic-gate * BUG: if there's a long sequence and it matches 5227c478bd9Sstevel@tonic-gate * some chars and then misses, we lose some chars. 5237c478bd9Sstevel@tonic-gate * 5247c478bd9Sstevel@tonic-gate * For this to work, some conditions must be met. 5257c478bd9Sstevel@tonic-gate * 1) Keypad sends SHORT (2 or 3 char) strings 5267c478bd9Sstevel@tonic-gate * 2) All strings sent are same length & similar 5277c478bd9Sstevel@tonic-gate * 3) The user is unlikely to type the first few chars of 5287c478bd9Sstevel@tonic-gate * one of these strings very fast. 5297c478bd9Sstevel@tonic-gate * Note: some code has been fixed up since the above was laid out, 5307c478bd9Sstevel@tonic-gate * so conditions 1 & 2 are probably not required anymore. 5317c478bd9Sstevel@tonic-gate * However, this hasn't been tested with any first char 5327c478bd9Sstevel@tonic-gate * that means anything else except escape. 5337c478bd9Sstevel@tonic-gate */ 5347c478bd9Sstevel@tonic-gate #ifdef MDEBUG 5357c478bd9Sstevel@tonic-gate if (trace) 5367c478bd9Sstevel@tonic-gate fprintf(trace,"map(%c): ",c); 5377c478bd9Sstevel@tonic-gate #endif 5387c478bd9Sstevel@tonic-gate /* 5397c478bd9Sstevel@tonic-gate * If c==0, the char came from getesc typing escape. Pass it through 5407c478bd9Sstevel@tonic-gate * unchanged. 0 messes up the following code anyway. 5417c478bd9Sstevel@tonic-gate */ 5427c478bd9Sstevel@tonic-gate if (c==0) 5437c478bd9Sstevel@tonic-gate return(0); 5447c478bd9Sstevel@tonic-gate 5457c478bd9Sstevel@tonic-gate b[0] = c; 5467c478bd9Sstevel@tonic-gate b[1] = 0; 5477c478bd9Sstevel@tonic-gate for (d=0; d < MAXNOMACS && maps[d].mapto; d++) { 5487c478bd9Sstevel@tonic-gate #ifdef MDEBUG 5497c478bd9Sstevel@tonic-gate if (trace) 5507c478bd9Sstevel@tonic-gate fprintf(trace,"\ntry '%s', ",maps[d].cap); 5517c478bd9Sstevel@tonic-gate #endif 5527c478bd9Sstevel@tonic-gate if (p = maps[d].cap) { 5537c478bd9Sstevel@tonic-gate for (q=b; *p; p++, q++) { 5547c478bd9Sstevel@tonic-gate #ifdef MDEBUG 5557c478bd9Sstevel@tonic-gate if (trace) 5567c478bd9Sstevel@tonic-gate fprintf(trace,"q->b[%d], ",q-b); 5577c478bd9Sstevel@tonic-gate #endif 5587c478bd9Sstevel@tonic-gate if (*q==0) { 5597c478bd9Sstevel@tonic-gate /* 5607c478bd9Sstevel@tonic-gate * Is there another char waiting? 5617c478bd9Sstevel@tonic-gate * 5627c478bd9Sstevel@tonic-gate * This test is oversimplified, but 5637c478bd9Sstevel@tonic-gate * should work mostly. It handles the 5647c478bd9Sstevel@tonic-gate * case where we get an ESCAPE that 5657c478bd9Sstevel@tonic-gate * wasn't part of a keypad string. 5667c478bd9Sstevel@tonic-gate */ 5677c478bd9Sstevel@tonic-gate if ((c=='#' ? peekkey() : fastpeekkey()) == 0) { 5687c478bd9Sstevel@tonic-gate #ifdef MDEBUG 5697c478bd9Sstevel@tonic-gate if (trace) 5707c478bd9Sstevel@tonic-gate fprintf(trace,"fpk=0: will return '%c'",c); 5717c478bd9Sstevel@tonic-gate #endif 5727c478bd9Sstevel@tonic-gate /* 5737c478bd9Sstevel@tonic-gate * Nothing waiting. Push back 5747c478bd9Sstevel@tonic-gate * what we peeked at & return 5757c478bd9Sstevel@tonic-gate * failure (c). 5767c478bd9Sstevel@tonic-gate * 5777c478bd9Sstevel@tonic-gate * We want to be able to undo 5787c478bd9Sstevel@tonic-gate * commands, but it's nonsense 5797c478bd9Sstevel@tonic-gate * to undo part of an insertion 5807c478bd9Sstevel@tonic-gate * so if in input mode don't. 5817c478bd9Sstevel@tonic-gate */ 5827c478bd9Sstevel@tonic-gate #ifdef MDEBUG 5837c478bd9Sstevel@tonic-gate if (trace) 5847c478bd9Sstevel@tonic-gate fprintf(trace, "Call macpush, b %d %d %d\n", b[0], b[1], b[2]); 5857c478bd9Sstevel@tonic-gate #endif 5867c478bd9Sstevel@tonic-gate macpush(&b[1],maps == arrows); 5877c478bd9Sstevel@tonic-gate #ifdef MDEBUG 5887c478bd9Sstevel@tonic-gate if (trace) 5897c478bd9Sstevel@tonic-gate fprintf(trace, "return %d\n", c); 5907c478bd9Sstevel@tonic-gate #endif 5917c478bd9Sstevel@tonic-gate return(c); 5927c478bd9Sstevel@tonic-gate } 5937c478bd9Sstevel@tonic-gate *q = getkey(); 5947c478bd9Sstevel@tonic-gate q[1] = 0; 5957c478bd9Sstevel@tonic-gate } 5967c478bd9Sstevel@tonic-gate if (*p != *q) 5977c478bd9Sstevel@tonic-gate goto contin; 5987c478bd9Sstevel@tonic-gate } 5997c478bd9Sstevel@tonic-gate macpush(maps[d].mapto,maps == arrows); 6007c478bd9Sstevel@tonic-gate /* 6017c478bd9Sstevel@tonic-gate * For all macros performed within insert, 6027c478bd9Sstevel@tonic-gate * append, or replacement mode, we must end 6037c478bd9Sstevel@tonic-gate * up returning back to that mode when we 6047c478bd9Sstevel@tonic-gate * return (except that append will become 6057c478bd9Sstevel@tonic-gate * insert for <home> key, so cursor is not 6067c478bd9Sstevel@tonic-gate * in second column). 6077c478bd9Sstevel@tonic-gate * 6087c478bd9Sstevel@tonic-gate * In order to preserve backward movement 6097c478bd9Sstevel@tonic-gate * when leaving insert mode, an 'l' must be 6107c478bd9Sstevel@tonic-gate * done to compensate for the left done by 6117c478bd9Sstevel@tonic-gate * the <esc> (except when cursor is already 6127c478bd9Sstevel@tonic-gate * in the first column: i.e., outcol = 0). 6137c478bd9Sstevel@tonic-gate */ 6147c478bd9Sstevel@tonic-gate if ((maps == immacs) 6157c478bd9Sstevel@tonic-gate && strcmp(maps[d].descr, maps[d].cap)) { 6167c478bd9Sstevel@tonic-gate switch (commch) { 6177c478bd9Sstevel@tonic-gate case 'R': 6187c478bd9Sstevel@tonic-gate if (!strcmp(maps[d].descr, "home")) 6197c478bd9Sstevel@tonic-gate st = (unsigned char *)"R"; 6207c478bd9Sstevel@tonic-gate else 6217c478bd9Sstevel@tonic-gate if (outcol == 0) 6227c478bd9Sstevel@tonic-gate st = (unsigned char *)"R"; 6237c478bd9Sstevel@tonic-gate else 6247c478bd9Sstevel@tonic-gate st = (unsigned char *)"lR"; 6257c478bd9Sstevel@tonic-gate break; 6267c478bd9Sstevel@tonic-gate case 'i': 6277c478bd9Sstevel@tonic-gate if (!strcmp(maps[d].descr, "home")) 6287c478bd9Sstevel@tonic-gate st = (unsigned char *)"i"; 6297c478bd9Sstevel@tonic-gate else 6307c478bd9Sstevel@tonic-gate if (outcol == 0) 6317c478bd9Sstevel@tonic-gate st = (unsigned char *)"i"; 6327c478bd9Sstevel@tonic-gate else 6337c478bd9Sstevel@tonic-gate st = (unsigned char *)"li"; 6347c478bd9Sstevel@tonic-gate break; 6357c478bd9Sstevel@tonic-gate case 'a': 6367c478bd9Sstevel@tonic-gate if (!strcmp(maps[d].descr, "home")) 6377c478bd9Sstevel@tonic-gate st = (unsigned char *)"i"; 6387c478bd9Sstevel@tonic-gate else 6397c478bd9Sstevel@tonic-gate st = (unsigned char *)"a"; 6407c478bd9Sstevel@tonic-gate break; 6417c478bd9Sstevel@tonic-gate default: 6427c478bd9Sstevel@tonic-gate st = (unsigned char *)"i"; 6437c478bd9Sstevel@tonic-gate } 6447c478bd9Sstevel@tonic-gate if(strlen(vmacbuf) + strlen(st) > BUFSIZE) 6457c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? 6467c478bd9Sstevel@tonic-gate gettext("Macro too long") : gettext("Macro too long - maybe recursive?")); 6477c478bd9Sstevel@tonic-gate else 6487c478bd9Sstevel@tonic-gate /* 6497c478bd9Sstevel@tonic-gate * Macros such as function keys are 6507c478bd9Sstevel@tonic-gate * performed by leaving the insert, 6517c478bd9Sstevel@tonic-gate * replace, or append mode, executing 6527c478bd9Sstevel@tonic-gate * the proper cursor movement commands 6537c478bd9Sstevel@tonic-gate * and returning to the mode we are 6547c478bd9Sstevel@tonic-gate * currently in (commch). 6557c478bd9Sstevel@tonic-gate */ 6567c478bd9Sstevel@tonic-gate strcat(vmacbuf, st); 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate c = getkey(); 6597c478bd9Sstevel@tonic-gate #ifdef MDEBUG 6607c478bd9Sstevel@tonic-gate if (trace) 6617c478bd9Sstevel@tonic-gate fprintf(trace,"Success: push(%s), return %c",maps[d].mapto, c); 6627c478bd9Sstevel@tonic-gate #endif 6637c478bd9Sstevel@tonic-gate return(c); /* first char of map string */ 6647c478bd9Sstevel@tonic-gate contin:; 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate #ifdef MDEBUG 6687c478bd9Sstevel@tonic-gate if (trace) 6697c478bd9Sstevel@tonic-gate fprintf(trace,"Fail: push(%s), return %c", &b[1], c); 6707c478bd9Sstevel@tonic-gate #endif 6717c478bd9Sstevel@tonic-gate macpush(&b[1],0); 6727c478bd9Sstevel@tonic-gate return(c); 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate /* 6767c478bd9Sstevel@tonic-gate * Push st onto the front of vmacp. This is tricky because we have to 6777c478bd9Sstevel@tonic-gate * worry about where vmacp was previously pointing. We also have to 6787c478bd9Sstevel@tonic-gate * check for overflow (which is typically from a recursive macro) 6797c478bd9Sstevel@tonic-gate * Finally we have to set a flag so the whole thing can be undone. 6807c478bd9Sstevel@tonic-gate * canundo is 1 iff we want to be able to undo the macro. This 6817c478bd9Sstevel@tonic-gate * is false for, for example, pushing back lookahead from fastpeekkey(), 6827c478bd9Sstevel@tonic-gate * since otherwise two fast escapes can clobber our undo. 6837c478bd9Sstevel@tonic-gate */ 684f6db9f27Scf46844 void 685f6db9f27Scf46844 macpush(unsigned char *st, int canundo) 6867c478bd9Sstevel@tonic-gate { 6877c478bd9Sstevel@tonic-gate unsigned char tmpbuf[BUFSIZE]; 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate if (st==0 || *st==0) 6907c478bd9Sstevel@tonic-gate return; 6917c478bd9Sstevel@tonic-gate #ifdef MDEBUG 6927c478bd9Sstevel@tonic-gate if (trace) 6937c478bd9Sstevel@tonic-gate fprintf(trace, "macpush(%s), canundo=%d\n",st,canundo); 6947c478bd9Sstevel@tonic-gate #endif 6957c478bd9Sstevel@tonic-gate if ((vmacp ? strlen(vmacp) : 0) + strlen(st) > BUFSIZE) 6967c478bd9Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Macro too long") : 6977c478bd9Sstevel@tonic-gate gettext("Macro too long - maybe recursive?")); 6987c478bd9Sstevel@tonic-gate if (vmacp) { 6997c478bd9Sstevel@tonic-gate strcpy(tmpbuf, vmacp); 7007c478bd9Sstevel@tonic-gate if (!FIXUNDO) 7017c478bd9Sstevel@tonic-gate canundo = 0; /* can't undo inside a macro anyway */ 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate strcpy(vmacbuf, st); 7047c478bd9Sstevel@tonic-gate if (vmacp) 7057c478bd9Sstevel@tonic-gate strcat(vmacbuf, tmpbuf); 7067c478bd9Sstevel@tonic-gate vmacp = vmacbuf; 7077c478bd9Sstevel@tonic-gate /* arrange to be able to undo the whole macro */ 7087c478bd9Sstevel@tonic-gate if (canundo) { 7097c478bd9Sstevel@tonic-gate #ifdef notdef 7107c478bd9Sstevel@tonic-gate otchng = tchng; 7117c478bd9Sstevel@tonic-gate vsave(); 7127c478bd9Sstevel@tonic-gate saveall(); 7137c478bd9Sstevel@tonic-gate inopen = -1; /* no need to save since it had to be 1 or -1 before */ 7147c478bd9Sstevel@tonic-gate vundkind = VMANY; 7157c478bd9Sstevel@tonic-gate #endif 7167c478bd9Sstevel@tonic-gate vch_mac = VC_NOCHANGE; 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate } 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate #ifdef UNDOTRACE 7217c478bd9Sstevel@tonic-gate visdump(s) 7227c478bd9Sstevel@tonic-gate unsigned char *s; 7237c478bd9Sstevel@tonic-gate { 724f6db9f27Scf46844 int i; 7257c478bd9Sstevel@tonic-gate 7267c478bd9Sstevel@tonic-gate if (!trace) return; 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate fprintf(trace, "\n%s: basWTOP=%d, basWLINES=%d, WTOP=%d, WBOT=%d, WLINES=%d, WCOLS=%d, WECHO=%d\n", 7297c478bd9Sstevel@tonic-gate s, basWTOP, basWLINES, WTOP, WBOT, WLINES, WCOLS, WECHO); 7307c478bd9Sstevel@tonic-gate fprintf(trace, " vcnt=%d, vcline=%d, cursor=%d, wcursor=%d, wdot=%d\n", 7317c478bd9Sstevel@tonic-gate vcnt, vcline, cursor-linebuf, wcursor-linebuf, wdot-zero); 7327c478bd9Sstevel@tonic-gate for (i=0; i<TUBELINES; i++) 7337c478bd9Sstevel@tonic-gate if (vtube[i] && *vtube[i]) 7347c478bd9Sstevel@tonic-gate fprintf(trace, "%d: '%s'\n", i, vtube[i]); 7357c478bd9Sstevel@tonic-gate tvliny(); 7367c478bd9Sstevel@tonic-gate } 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate vudump(s) 7397c478bd9Sstevel@tonic-gate unsigned char *s; 7407c478bd9Sstevel@tonic-gate { 741f6db9f27Scf46844 line *p; 7427c478bd9Sstevel@tonic-gate unsigned char savelb[1024]; 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate if (!trace) return; 7457c478bd9Sstevel@tonic-gate 7467c478bd9Sstevel@tonic-gate fprintf(trace, "\n%s: undkind=%d, vundkind=%d, unddel=%d, undap1=%d, undap2=%d,\n", 7477c478bd9Sstevel@tonic-gate s, undkind, vundkind, lineno(unddel), lineno(undap1), lineno(undap2)); 7487c478bd9Sstevel@tonic-gate fprintf(trace, " undadot=%d, dot=%d, dol=%d, unddol=%d, truedol=%d\n", 7497c478bd9Sstevel@tonic-gate lineno(undadot), lineno(dot), lineno(dol), lineno(unddol), lineno(truedol)); 7507c478bd9Sstevel@tonic-gate fprintf(trace, " [\n"); 7517c478bd9Sstevel@tonic-gate CP(savelb, linebuf); 7527c478bd9Sstevel@tonic-gate fprintf(trace, "linebuf = '%s'\n", linebuf); 7537c478bd9Sstevel@tonic-gate for (p=zero+1; p<=truedol; p++) { 7547c478bd9Sstevel@tonic-gate fprintf(trace, "%o ", *p); 755*23a1cceaSRoger A. Faulkner getaline(*p); 7567c478bd9Sstevel@tonic-gate fprintf(trace, "'%s'\n", linebuf); 7577c478bd9Sstevel@tonic-gate } 7587c478bd9Sstevel@tonic-gate fprintf(trace, "]\n"); 7597c478bd9Sstevel@tonic-gate CP(linebuf, savelb); 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate #endif 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate /* 7647c478bd9Sstevel@tonic-gate * Get a count from the keyed input stream. 7657c478bd9Sstevel@tonic-gate * A zero count is indistinguishable from no count. 7667c478bd9Sstevel@tonic-gate */ 767f6db9f27Scf46844 int 768f6db9f27Scf46844 vgetcnt(void) 7697c478bd9Sstevel@tonic-gate { 770f6db9f27Scf46844 int c, cnt; 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate cnt = 0; 7737c478bd9Sstevel@tonic-gate for (;;) { 7747c478bd9Sstevel@tonic-gate c = getkey(); 7757c478bd9Sstevel@tonic-gate if (!isdigit(c)) 7767c478bd9Sstevel@tonic-gate break; 7777c478bd9Sstevel@tonic-gate cnt *= 10, cnt += c - '0'; 7787c478bd9Sstevel@tonic-gate } 7797c478bd9Sstevel@tonic-gate ungetkey(c); 7807c478bd9Sstevel@tonic-gate Xhadcnt = 1; 7817c478bd9Sstevel@tonic-gate Xcnt = cnt; 7827c478bd9Sstevel@tonic-gate return(cnt); 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate /* 7867c478bd9Sstevel@tonic-gate * fastpeekkey is just like peekkey but insists the character come in 7877c478bd9Sstevel@tonic-gate * fast (within 1 second). This will succeed if it is the 2nd char of 7887c478bd9Sstevel@tonic-gate * a machine generated sequence (such as a function pad from an escape 7897c478bd9Sstevel@tonic-gate * flavor terminal) but fail for a human hitting escape then waiting. 7907c478bd9Sstevel@tonic-gate */ 791f6db9f27Scf46844 int 792f6db9f27Scf46844 fastpeekkey(void) 7937c478bd9Sstevel@tonic-gate { 7947c478bd9Sstevel@tonic-gate void trapalarm(); 795f6db9f27Scf46844 int c; 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate /* 7987c478bd9Sstevel@tonic-gate * If the user has set notimeout, we wait forever for a key. 7997c478bd9Sstevel@tonic-gate * If we are in a macro we do too, but since it's already 8007c478bd9Sstevel@tonic-gate * buffered internally it will return immediately. 8017c478bd9Sstevel@tonic-gate * In other cases we force this to die in 1 second. 8027c478bd9Sstevel@tonic-gate * This is pretty reliable (VMUNIX rounds it to .5 - 1.5 secs, 8037c478bd9Sstevel@tonic-gate * but UNIX truncates it to 0 - 1 secs) but due to system delays 8047c478bd9Sstevel@tonic-gate * there are times when arrow keys or very fast typing get counted 8057c478bd9Sstevel@tonic-gate * as separate. notimeout is provided for people who dislike such 8067c478bd9Sstevel@tonic-gate * nondeterminism. 8077c478bd9Sstevel@tonic-gate */ 8087c478bd9Sstevel@tonic-gate CATCH 8097c478bd9Sstevel@tonic-gate if (value(vi_TIMEOUT) && inopen >= 0) { 8107c478bd9Sstevel@tonic-gate signal(SIGALRM, trapalarm); 8117c478bd9Sstevel@tonic-gate setalarm(); 8127c478bd9Sstevel@tonic-gate } 8137c478bd9Sstevel@tonic-gate c = peekkey(); 8147c478bd9Sstevel@tonic-gate cancelalarm(); 8157c478bd9Sstevel@tonic-gate ONERR 8167c478bd9Sstevel@tonic-gate c = 0; 8177c478bd9Sstevel@tonic-gate ENDCATCH 8187c478bd9Sstevel@tonic-gate /* Should have an alternative method based on select for 4.2BSD */ 8197c478bd9Sstevel@tonic-gate return(c); 8207c478bd9Sstevel@tonic-gate } 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate static int ftfd; 8237c478bd9Sstevel@tonic-gate struct requestbuf { 8247c478bd9Sstevel@tonic-gate short time; 8257c478bd9Sstevel@tonic-gate short signo; 8267c478bd9Sstevel@tonic-gate }; 8277c478bd9Sstevel@tonic-gate 8287c478bd9Sstevel@tonic-gate /* 8297c478bd9Sstevel@tonic-gate * Arrange for SIGALRM to come in shortly, so we don't 8307c478bd9Sstevel@tonic-gate * hang very long if the user didn't type anything. There are 8317c478bd9Sstevel@tonic-gate * various ways to do this on different systems. 8327c478bd9Sstevel@tonic-gate */ 833f6db9f27Scf46844 void 834f6db9f27Scf46844 setalarm(void) 8357c478bd9Sstevel@tonic-gate { 8367c478bd9Sstevel@tonic-gate unsigned char ftname[20]; 8377c478bd9Sstevel@tonic-gate struct requestbuf rb; 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate #ifdef FTIOCSET 8407c478bd9Sstevel@tonic-gate /* 8417c478bd9Sstevel@tonic-gate * Use nonstandard "fast timer" to get better than 8427c478bd9Sstevel@tonic-gate * one second resolution. We must wait at least 8437c478bd9Sstevel@tonic-gate * 1/15th of a second because some keypads don't 8447c478bd9Sstevel@tonic-gate * transmit faster than this. 8457c478bd9Sstevel@tonic-gate */ 8467c478bd9Sstevel@tonic-gate 8477c478bd9Sstevel@tonic-gate /* Open ft psuedo-device - we need our own copy. */ 8487c478bd9Sstevel@tonic-gate if (ftfd == 0) { 8497c478bd9Sstevel@tonic-gate strcpy(ftname, "/dev/ft0"); 8507c478bd9Sstevel@tonic-gate while (ftfd <= 0 && ftname[7] <= '~') { 8517c478bd9Sstevel@tonic-gate ftfd = open(ftname, 0); 8527c478bd9Sstevel@tonic-gate if (ftfd <= 0) 8537c478bd9Sstevel@tonic-gate ftname[7] ++; 8547c478bd9Sstevel@tonic-gate } 8557c478bd9Sstevel@tonic-gate } 8567c478bd9Sstevel@tonic-gate if (ftfd <= 0) { /* Couldn't open a /dev/ft? */ 8577c478bd9Sstevel@tonic-gate alarm(1); 8587c478bd9Sstevel@tonic-gate } else { 8597c478bd9Sstevel@tonic-gate rb.time = 6; /* 6 ticks = 100 ms > 67 ms. */ 8607c478bd9Sstevel@tonic-gate rb.signo = SIGALRM; 8617c478bd9Sstevel@tonic-gate ioctl(ftfd, FTIOCSET, &rb); 8627c478bd9Sstevel@tonic-gate } 8637c478bd9Sstevel@tonic-gate #else 8647c478bd9Sstevel@tonic-gate /* 8657c478bd9Sstevel@tonic-gate * No special capabilities, so we use alarm, with 1 sec. resolution. 8667c478bd9Sstevel@tonic-gate */ 8677c478bd9Sstevel@tonic-gate alarm(1); 8687c478bd9Sstevel@tonic-gate #endif 8697c478bd9Sstevel@tonic-gate } 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate /* 8727c478bd9Sstevel@tonic-gate * Get rid of any impending incoming SIGALRM. 8737c478bd9Sstevel@tonic-gate */ 874f6db9f27Scf46844 void 875f6db9f27Scf46844 cancelalarm(void) 8767c478bd9Sstevel@tonic-gate { 8777c478bd9Sstevel@tonic-gate struct requestbuf rb; 8787c478bd9Sstevel@tonic-gate #ifdef FTIOCSET 8797c478bd9Sstevel@tonic-gate if (ftfd > 0) { 8807c478bd9Sstevel@tonic-gate rb.time = 0; 8817c478bd9Sstevel@tonic-gate rb.signo = SIGALRM; 8827c478bd9Sstevel@tonic-gate ioctl(ftfd, FTIOCCANCEL, &rb); 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate #endif 8857c478bd9Sstevel@tonic-gate alarm(0); /* Have to do this whether or not FTIOCSET */ 8867c478bd9Sstevel@tonic-gate } 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate void trapalarm() { 8897c478bd9Sstevel@tonic-gate alarm(0); 8907c478bd9Sstevel@tonic-gate longjmp(vreslab,1); 8917c478bd9Sstevel@tonic-gate } 892