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_argv.h" 370Sstevel@tonic-gate #include "ex_temp.h" 380Sstevel@tonic-gate #include "ex_tty.h" 390Sstevel@tonic-gate #include "ex_vis.h" 40*802Scf46844 #include <unistd.h> 410Sstevel@tonic-gate 420Sstevel@tonic-gate extern bool pflag, nflag; /* extern; also in ex_cmds.c */ 430Sstevel@tonic-gate extern int poffset; /* extern; also in ex_cmds.c */ 440Sstevel@tonic-gate extern short slevel; /* extern; has level of source() */ 450Sstevel@tonic-gate 460Sstevel@tonic-gate /* 470Sstevel@tonic-gate * Subroutines for major command loop. 480Sstevel@tonic-gate */ 490Sstevel@tonic-gate 500Sstevel@tonic-gate /* 510Sstevel@tonic-gate * Is there a single letter indicating a named buffer next? 520Sstevel@tonic-gate */ 53*802Scf46844 int 54*802Scf46844 cmdreg(void) 550Sstevel@tonic-gate { 56*802Scf46844 int c = 0; 57*802Scf46844 int wh = skipwh(); 580Sstevel@tonic-gate 590Sstevel@tonic-gate #ifdef XPG4 600Sstevel@tonic-gate if (wh && isalpha(c = peekchar()) && isascii(c) && !isdigit(c)) 610Sstevel@tonic-gate #else /* XPG4 */ 620Sstevel@tonic-gate if (wh && isalpha(c = peekchar()) && isascii(c)) 630Sstevel@tonic-gate #endif /* XPG4 */ 640Sstevel@tonic-gate c = getchar(); 650Sstevel@tonic-gate 660Sstevel@tonic-gate #ifdef XPG4 670Sstevel@tonic-gate if (isdigit(c)) { 680Sstevel@tonic-gate c = 0; 690Sstevel@tonic-gate } 700Sstevel@tonic-gate #endif /* XPG4 */ 710Sstevel@tonic-gate return (c); 720Sstevel@tonic-gate } 730Sstevel@tonic-gate 740Sstevel@tonic-gate /* 750Sstevel@tonic-gate * Tell whether the character ends a command 760Sstevel@tonic-gate */ 77*802Scf46844 int 78*802Scf46844 endcmd(int ch) 790Sstevel@tonic-gate { 800Sstevel@tonic-gate switch (ch) { 810Sstevel@tonic-gate 820Sstevel@tonic-gate case '\n': 830Sstevel@tonic-gate case EOF: 840Sstevel@tonic-gate endline = 1; 850Sstevel@tonic-gate return (1); 860Sstevel@tonic-gate 870Sstevel@tonic-gate case '|': 880Sstevel@tonic-gate case '"': 890Sstevel@tonic-gate endline = 0; 900Sstevel@tonic-gate return (1); 910Sstevel@tonic-gate } 920Sstevel@tonic-gate return (0); 930Sstevel@tonic-gate } 940Sstevel@tonic-gate 950Sstevel@tonic-gate /* 960Sstevel@tonic-gate * Insist on the end of the command. 970Sstevel@tonic-gate */ 98*802Scf46844 void 99*802Scf46844 eol(void) 1000Sstevel@tonic-gate { 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate if (!skipend()) 1030Sstevel@tonic-gate error(value(vi_TERSE) ? gettext("Extra chars") : 1040Sstevel@tonic-gate gettext("Extra characters at end of command")); 1050Sstevel@tonic-gate ignnEOF(); 1060Sstevel@tonic-gate } 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate #ifdef XPG4 1090Sstevel@tonic-gate /* 1100Sstevel@tonic-gate * Print out the message in the error message file at str, 1110Sstevel@tonic-gate * with i an integer argument to printf. 1120Sstevel@tonic-gate */ 1130Sstevel@tonic-gate /*VARARGS2*/ 114*802Scf46844 void 1150Sstevel@tonic-gate error(str, i) 116*802Scf46844 unsigned char *str; 1170Sstevel@tonic-gate int i; 1180Sstevel@tonic-gate { 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate errcnt++; 1210Sstevel@tonic-gate noerror(str, i); 1220Sstevel@tonic-gate } 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate /* 1250Sstevel@tonic-gate * noerror(): like error(), but doesn't inc errcnt. 1260Sstevel@tonic-gate * the reason why we created this routine, instead of fixing up errcnt 1270Sstevel@tonic-gate * after error() is called, is because we will do a longjmp, and 1280Sstevel@tonic-gate * not a return. it does other things closing file i/o, reset, etc; 1290Sstevel@tonic-gate * so we follow those procedures. 1300Sstevel@tonic-gate */ 1310Sstevel@tonic-gate /*VARARGS2*/ 132*802Scf46844 void 1330Sstevel@tonic-gate noerror(str, i) 134*802Scf46844 unsigned char *str; 1350Sstevel@tonic-gate int i; 1360Sstevel@tonic-gate { 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate error0(); 1390Sstevel@tonic-gate merror(str, i); 1400Sstevel@tonic-gate if (writing) { 141*802Scf46844 serror((unsigned char *) 142*802Scf46844 gettext(" [Warning - %s is incomplete]"), file); 1430Sstevel@tonic-gate writing = 0; 1440Sstevel@tonic-gate } 1450Sstevel@tonic-gate error1(str); 1460Sstevel@tonic-gate } 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate #else /* !XPG4 */ 1490Sstevel@tonic-gate /* 1500Sstevel@tonic-gate * Print out the message in the error message file at str, 1510Sstevel@tonic-gate * with i an integer argument to printf. 1520Sstevel@tonic-gate */ 1530Sstevel@tonic-gate /*VARARGS2*/ 154*802Scf46844 void 1550Sstevel@tonic-gate error(str, i) 156*802Scf46844 unsigned char *str; 1570Sstevel@tonic-gate int i; 1580Sstevel@tonic-gate { 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate errcnt++; 1610Sstevel@tonic-gate error0(); 1620Sstevel@tonic-gate merror(str, i); 1630Sstevel@tonic-gate if (writing) { 164*802Scf46844 serror((unsigned char *) 165*802Scf46844 gettext(" [Warning - %s is incomplete]"), file); 1660Sstevel@tonic-gate writing = 0; 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate error1(str); 1690Sstevel@tonic-gate } 1700Sstevel@tonic-gate #endif /* XPG4 */ 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate /* 1730Sstevel@tonic-gate * Rewind the argument list. 1740Sstevel@tonic-gate */ 175*802Scf46844 void 176*802Scf46844 erewind(void) 1770Sstevel@tonic-gate { 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate argc = argc0; 1800Sstevel@tonic-gate argv = argv0; 1810Sstevel@tonic-gate args = args0; 1820Sstevel@tonic-gate if (argc > 1 && !hush && cur_term) { 183*802Scf46844 viprintf(mesg(value(vi_TERSE) ? gettext("%d files") : 1840Sstevel@tonic-gate gettext("%d files to edit")), argc); 1850Sstevel@tonic-gate if (inopen) 1860Sstevel@tonic-gate putchar(' '); 1870Sstevel@tonic-gate else 1880Sstevel@tonic-gate putNFL(); 1890Sstevel@tonic-gate } 1900Sstevel@tonic-gate } 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate /* 1930Sstevel@tonic-gate * Guts of the pre-printing error processing. 1940Sstevel@tonic-gate * If in visual and catching errors, then we don't mung up the internals, 1950Sstevel@tonic-gate * just fixing up the echo area for the print. 1960Sstevel@tonic-gate * Otherwise we reset a number of externals, and discard unused input. 1970Sstevel@tonic-gate */ 198*802Scf46844 void 199*802Scf46844 error0(void) 2000Sstevel@tonic-gate { 2010Sstevel@tonic-gate 2020Sstevel@tonic-gate if (laste) { 2030Sstevel@tonic-gate #ifdef VMUNIX 2040Sstevel@tonic-gate tlaste(); 2050Sstevel@tonic-gate #endif 2060Sstevel@tonic-gate laste = 0; 2070Sstevel@tonic-gate sync(); 2080Sstevel@tonic-gate } 2090Sstevel@tonic-gate if (vcatch) { 2100Sstevel@tonic-gate if (splitw == 0) 2110Sstevel@tonic-gate fixech(); 2120Sstevel@tonic-gate if (!enter_standout_mode || !exit_bold) 2130Sstevel@tonic-gate dingdong(); 2140Sstevel@tonic-gate return; 2150Sstevel@tonic-gate } 2160Sstevel@tonic-gate if (input) { 2170Sstevel@tonic-gate input = strend(input) - 1; 2180Sstevel@tonic-gate if (*input == '\n') 2190Sstevel@tonic-gate setlastchar('\n'); 2200Sstevel@tonic-gate input = 0; 2210Sstevel@tonic-gate } 2220Sstevel@tonic-gate setoutt(); 2230Sstevel@tonic-gate flush(); 2240Sstevel@tonic-gate resetflav(); 2250Sstevel@tonic-gate if (!enter_standout_mode || !exit_bold) 2260Sstevel@tonic-gate dingdong(); 2270Sstevel@tonic-gate if (inopen) { 2280Sstevel@tonic-gate /* 2290Sstevel@tonic-gate * We are coming out of open/visual ungracefully. 2300Sstevel@tonic-gate * Restore columns, undo, and fix tty mode. 2310Sstevel@tonic-gate */ 2320Sstevel@tonic-gate columns = OCOLUMNS; 2330Sstevel@tonic-gate undvis(); 2340Sstevel@tonic-gate ostop(normf); 2350Sstevel@tonic-gate /* ostop should be doing this 2360Sstevel@tonic-gate putpad(cursor_normal); 2370Sstevel@tonic-gate putpad(key_eol); 2380Sstevel@tonic-gate */ 2390Sstevel@tonic-gate putnl(); 2400Sstevel@tonic-gate } 2410Sstevel@tonic-gate inopen = 0; 2420Sstevel@tonic-gate holdcm = 0; 2430Sstevel@tonic-gate } 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate /* 2460Sstevel@tonic-gate * Post error printing processing. 2470Sstevel@tonic-gate * Close the i/o file if left open. 2480Sstevel@tonic-gate * If catching in visual then throw to the visual catch, 2490Sstevel@tonic-gate * else if a child after a fork, then exit. 2500Sstevel@tonic-gate * Otherwise, in the normal command mode error case, 2510Sstevel@tonic-gate * finish state reset, and throw to top. 2520Sstevel@tonic-gate */ 253*802Scf46844 void 254*802Scf46844 error1(unsigned char *str) 2550Sstevel@tonic-gate { 2560Sstevel@tonic-gate bool die; 2570Sstevel@tonic-gate extern short ttyindes; 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate if ((io > 0) && (io != ttyindes)) { 2600Sstevel@tonic-gate close(io); 2610Sstevel@tonic-gate io = -1; 2620Sstevel@tonic-gate } 2630Sstevel@tonic-gate 2640Sstevel@tonic-gate die = (getpid() != ppid); /* Only children die */ 2650Sstevel@tonic-gate inappend = inglobal = 0; 2660Sstevel@tonic-gate globp = vglobp = vmacp = 0; 2670Sstevel@tonic-gate if (vcatch && !die) { 2680Sstevel@tonic-gate inopen = 1; 2690Sstevel@tonic-gate vcatch = 0; 2700Sstevel@tonic-gate if (str) 2710Sstevel@tonic-gate noonl(); 2720Sstevel@tonic-gate fixol(); 2730Sstevel@tonic-gate if (slevel > 0) 2740Sstevel@tonic-gate reset(); 2750Sstevel@tonic-gate longjmp(vreslab,1); 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate if (str && !vcatch) 2780Sstevel@tonic-gate putNFL(); 2790Sstevel@tonic-gate if (die) 2800Sstevel@tonic-gate exit(++errcnt); 2810Sstevel@tonic-gate lseek(0, 0L, 2); 2820Sstevel@tonic-gate if (inglobal) 2830Sstevel@tonic-gate setlastchar('\n'); 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate if (inexrc) { 2860Sstevel@tonic-gate lprintf(gettext("Error detected in .exrc.[Hit return to continue] "), 0); 2870Sstevel@tonic-gate putNFL(); 2880Sstevel@tonic-gate getkey(); 2890Sstevel@tonic-gate } 2900Sstevel@tonic-gate 2910Sstevel@tonic-gate while ((lastchar() != '\n') && (lastchar() != EOF)) 2920Sstevel@tonic-gate ignchar(); 2930Sstevel@tonic-gate ungetchar(0); 2940Sstevel@tonic-gate endline = 1; 2950Sstevel@tonic-gate reset(); 2960Sstevel@tonic-gate } 2970Sstevel@tonic-gate 298*802Scf46844 void 299*802Scf46844 fixol(void) 3000Sstevel@tonic-gate { 3010Sstevel@tonic-gate if (Outchar != vputchar) { 3020Sstevel@tonic-gate flush(); 3030Sstevel@tonic-gate if (state == ONEOPEN || state == HARDOPEN) 3040Sstevel@tonic-gate outline = destline = 0; 3050Sstevel@tonic-gate Outchar = vputchar; 3060Sstevel@tonic-gate vcontin(1); 3070Sstevel@tonic-gate /* 3080Sstevel@tonic-gate * Outchar could be set to termchar() through vcontin(). 3090Sstevel@tonic-gate * So reset it again. 3100Sstevel@tonic-gate */ 3110Sstevel@tonic-gate Outchar = vputchar; 3120Sstevel@tonic-gate } else { 3130Sstevel@tonic-gate if (destcol) 3140Sstevel@tonic-gate vclreol(); 3150Sstevel@tonic-gate vclean(); 3160Sstevel@tonic-gate } 3170Sstevel@tonic-gate } 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate /* 3200Sstevel@tonic-gate * Does an ! character follow in the command stream? 3210Sstevel@tonic-gate */ 322*802Scf46844 int 323*802Scf46844 exclam(void) 3240Sstevel@tonic-gate { 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate if (peekchar() == '!') { 3270Sstevel@tonic-gate ignchar(); 3280Sstevel@tonic-gate return (1); 3290Sstevel@tonic-gate } 3300Sstevel@tonic-gate return (0); 3310Sstevel@tonic-gate } 3320Sstevel@tonic-gate 3330Sstevel@tonic-gate /* 3340Sstevel@tonic-gate * Make an argument list for e.g. next. 3350Sstevel@tonic-gate */ 336*802Scf46844 void 337*802Scf46844 makargs(void) 3380Sstevel@tonic-gate { 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate glob(&frob); 3410Sstevel@tonic-gate argc0 = frob.argc0; 3420Sstevel@tonic-gate argv0 = frob.argv; 3430Sstevel@tonic-gate args0 = argv0[0]; 3440Sstevel@tonic-gate erewind(); 3450Sstevel@tonic-gate } 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate /* 3480Sstevel@tonic-gate * Advance to next file in argument list. 3490Sstevel@tonic-gate */ 350*802Scf46844 void 351*802Scf46844 next(void) 3520Sstevel@tonic-gate { 3530Sstevel@tonic-gate extern short isalt; /* defined in ex_io.c */ 3540Sstevel@tonic-gate 3550Sstevel@tonic-gate if (argc == 0) 356*802Scf46844 error(value(vi_TERSE) ? 357*802Scf46844 (unsigned char *)gettext("No more files") : 358*802Scf46844 (unsigned char *)gettext("No more files to edit")); 3590Sstevel@tonic-gate morargc = argc; 3600Sstevel@tonic-gate isalt = (strcmp(altfile, args)==0) + 1; 3610Sstevel@tonic-gate if (savedfile[0]) 3620Sstevel@tonic-gate CP(altfile, savedfile); 3630Sstevel@tonic-gate (void) strlcpy(savedfile, args, sizeof (savedfile)); 3640Sstevel@tonic-gate argc--; 3650Sstevel@tonic-gate args = argv ? *++argv : strend(args) + 1; 3660Sstevel@tonic-gate #if i386 || i286 3670Sstevel@tonic-gate destcol = 0; 3680Sstevel@tonic-gate #endif 3690Sstevel@tonic-gate } 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate /* 3720Sstevel@tonic-gate * Eat trailing flags and offsets after a command, 3730Sstevel@tonic-gate * saving for possible later post-command prints. 3740Sstevel@tonic-gate */ 375*802Scf46844 void 376*802Scf46844 donewline(void) 3770Sstevel@tonic-gate { 378*802Scf46844 int c; 3790Sstevel@tonic-gate 3800Sstevel@tonic-gate resetflav(); 3810Sstevel@tonic-gate for (;;) { 3820Sstevel@tonic-gate c = getchar(); 3830Sstevel@tonic-gate switch (c) { 3840Sstevel@tonic-gate 3850Sstevel@tonic-gate case '^': 3860Sstevel@tonic-gate case '-': 3870Sstevel@tonic-gate poffset--; 3880Sstevel@tonic-gate break; 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate case '+': 3910Sstevel@tonic-gate poffset++; 3920Sstevel@tonic-gate break; 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate case 'l': 3950Sstevel@tonic-gate listf++; 3960Sstevel@tonic-gate break; 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate case '#': 3990Sstevel@tonic-gate nflag++; 4000Sstevel@tonic-gate break; 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate case 'p': 4030Sstevel@tonic-gate listf = 0; 4040Sstevel@tonic-gate break; 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate case ' ': 4070Sstevel@tonic-gate case '\t': 4080Sstevel@tonic-gate continue; 4090Sstevel@tonic-gate 4100Sstevel@tonic-gate case '"': 4110Sstevel@tonic-gate comment(); 4120Sstevel@tonic-gate setflav(); 4130Sstevel@tonic-gate return; 4140Sstevel@tonic-gate 4150Sstevel@tonic-gate default: 4160Sstevel@tonic-gate if (!endcmd(c)) 417*802Scf46844 serror(value(vi_TERSE) ? 418*802Scf46844 (unsigned char *)gettext("Extra chars") : 419*802Scf46844 (unsigned char *)gettext( 420*802Scf46844 "Extra characters at end of \"%s\" command"), 421*802Scf46844 Command); 4220Sstevel@tonic-gate if (c == EOF) 4230Sstevel@tonic-gate ungetchar(c); 4240Sstevel@tonic-gate setflav(); 4250Sstevel@tonic-gate return; 4260Sstevel@tonic-gate } 4270Sstevel@tonic-gate pflag++; 4280Sstevel@tonic-gate } 4290Sstevel@tonic-gate } 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate /* 4320Sstevel@tonic-gate * Before quit or respec of arg list, check that there are 4330Sstevel@tonic-gate * no more files in the arg list. 4340Sstevel@tonic-gate */ 435*802Scf46844 int 436*802Scf46844 nomore(void) 4370Sstevel@tonic-gate { 4380Sstevel@tonic-gate 4390Sstevel@tonic-gate if (argc == 0 || morargc == argc) 4400Sstevel@tonic-gate return(0); 4410Sstevel@tonic-gate morargc = argc; 4420Sstevel@tonic-gate if (argc == 1) { 4430Sstevel@tonic-gate merror(value(vi_TERSE) ? gettext("1 more file") : 4440Sstevel@tonic-gate gettext("1 more file to edit"), argc); 4450Sstevel@tonic-gate } else { 4460Sstevel@tonic-gate merror(value(vi_TERSE) ? gettext("%d more files") : 4470Sstevel@tonic-gate gettext("%d more files to edit"), argc); 4480Sstevel@tonic-gate } 4490Sstevel@tonic-gate return(1); 4500Sstevel@tonic-gate } 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate /* 4530Sstevel@tonic-gate * Before edit of new file check that either an ! follows 4540Sstevel@tonic-gate * or the file has not been changed. 4550Sstevel@tonic-gate */ 456*802Scf46844 int 457*802Scf46844 quickly(void) 4580Sstevel@tonic-gate { 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate if (exclam()) 4610Sstevel@tonic-gate return (1); 4620Sstevel@tonic-gate if (chng && dol > zero) { 4630Sstevel@tonic-gate /* 4640Sstevel@tonic-gate chng = 0; 4650Sstevel@tonic-gate */ 4660Sstevel@tonic-gate xchng = 0; 467*802Scf46844 error(value(vi_TERSE) ? (unsigned char *)gettext("No write") : 468*802Scf46844 (unsigned char *) 469*802Scf46844 gettext("No write since last change (:%s! overrides)"), 470*802Scf46844 Command); 4710Sstevel@tonic-gate } 4720Sstevel@tonic-gate return (0); 4730Sstevel@tonic-gate } 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate /* 4760Sstevel@tonic-gate * Reset the flavor of the output to print mode with no numbering. 4770Sstevel@tonic-gate */ 478*802Scf46844 void 479*802Scf46844 resetflav(void) 4800Sstevel@tonic-gate { 4810Sstevel@tonic-gate 4820Sstevel@tonic-gate if (inopen) 4830Sstevel@tonic-gate return; 4840Sstevel@tonic-gate listf = 0; 4850Sstevel@tonic-gate nflag = 0; 4860Sstevel@tonic-gate pflag = 0; 4870Sstevel@tonic-gate poffset = 0; 4880Sstevel@tonic-gate setflav(); 4890Sstevel@tonic-gate } 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate /* 4920Sstevel@tonic-gate * Print an error message with a %s type argument to printf. 4930Sstevel@tonic-gate * Message text comes from error message file. 4940Sstevel@tonic-gate */ 495*802Scf46844 void 496*802Scf46844 serror(unsigned char *str, unsigned char *cp) 4970Sstevel@tonic-gate { 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate error0(); 5000Sstevel@tonic-gate smerror(str, cp); 5010Sstevel@tonic-gate error1(str); 5020Sstevel@tonic-gate } 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate /* 5050Sstevel@tonic-gate * Set the flavor of the output based on the flags given 5060Sstevel@tonic-gate * and the number and list options to either number or not number lines 5070Sstevel@tonic-gate * and either use normally decoded (ARPAnet standard) characters or list mode, 5080Sstevel@tonic-gate * where end of lines are marked and tabs print as ^I. 5090Sstevel@tonic-gate */ 510*802Scf46844 void 511*802Scf46844 setflav(void) 5120Sstevel@tonic-gate { 5130Sstevel@tonic-gate 5140Sstevel@tonic-gate if (inopen) 5150Sstevel@tonic-gate return; 5160Sstevel@tonic-gate setnumb(nflag || value(vi_NUMBER)); 5170Sstevel@tonic-gate setlist(listf || value(vi_LIST)); 5180Sstevel@tonic-gate if (!inopen) 5190Sstevel@tonic-gate setoutt(); 5200Sstevel@tonic-gate } 5210Sstevel@tonic-gate 5220Sstevel@tonic-gate /* 5230Sstevel@tonic-gate * Skip white space and tell whether command ends then. 5240Sstevel@tonic-gate */ 525*802Scf46844 int 526*802Scf46844 skipend(void) 5270Sstevel@tonic-gate { 5280Sstevel@tonic-gate 5290Sstevel@tonic-gate pastwh(); 5300Sstevel@tonic-gate return (endcmd(peekchar()) && peekchar() != '"'); 5310Sstevel@tonic-gate } 5320Sstevel@tonic-gate 5330Sstevel@tonic-gate /* 5340Sstevel@tonic-gate * Set the command name for non-word commands. 5350Sstevel@tonic-gate */ 536*802Scf46844 void 537*802Scf46844 tailspec(int c) 5380Sstevel@tonic-gate { 5390Sstevel@tonic-gate static unsigned char foocmd[2]; 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate foocmd[0] = c; 5420Sstevel@tonic-gate Command = foocmd; 5430Sstevel@tonic-gate } 5440Sstevel@tonic-gate 5450Sstevel@tonic-gate /* 5460Sstevel@tonic-gate * Try to read off the rest of the command word. 5470Sstevel@tonic-gate * If alphabetics follow, then this is not the command we seek. 5480Sstevel@tonic-gate */ 549*802Scf46844 void 550*802Scf46844 tail(unsigned char *comm) 5510Sstevel@tonic-gate { 5520Sstevel@tonic-gate 5530Sstevel@tonic-gate tailprim(comm, 1, 0); 5540Sstevel@tonic-gate } 5550Sstevel@tonic-gate 556*802Scf46844 void 557*802Scf46844 tail2of(unsigned char *comm) 5580Sstevel@tonic-gate { 5590Sstevel@tonic-gate 5600Sstevel@tonic-gate tailprim(comm, 2, 0); 5610Sstevel@tonic-gate } 5620Sstevel@tonic-gate 5630Sstevel@tonic-gate unsigned char tcommand[20]; 5640Sstevel@tonic-gate 565*802Scf46844 void 566*802Scf46844 tailprim(unsigned char *comm, int i, bool notinvis) 5670Sstevel@tonic-gate { 568*802Scf46844 unsigned char *cp; 569*802Scf46844 int c; 5700Sstevel@tonic-gate 5710Sstevel@tonic-gate Command = comm; 5720Sstevel@tonic-gate for (cp = tcommand; i > 0; i--) 5730Sstevel@tonic-gate *cp++ = *comm++; 5740Sstevel@tonic-gate while (*comm && peekchar() == *comm) 5750Sstevel@tonic-gate *cp++ = getchar(), comm++; 5760Sstevel@tonic-gate c = peekchar(); 5770Sstevel@tonic-gate if (notinvis || (isalpha(c) && isascii(c))) { 5780Sstevel@tonic-gate /* 5790Sstevel@tonic-gate * Of the trailing lp funny business, only dl and dp 5800Sstevel@tonic-gate * survive the move from ed to ex. 5810Sstevel@tonic-gate */ 5820Sstevel@tonic-gate if (tcommand[0] == 'd' && any(c, "lp")) 5830Sstevel@tonic-gate goto ret; 5840Sstevel@tonic-gate if (tcommand[0] == 's' && any(c, "gcr")) 5850Sstevel@tonic-gate goto ret; 5860Sstevel@tonic-gate while (cp < &tcommand[19] && isalpha(c = peekchar()) && isascii(c)) 5870Sstevel@tonic-gate *cp++ = getchar(); 5880Sstevel@tonic-gate *cp = 0; 5890Sstevel@tonic-gate if (notinvis) 590*802Scf46844 serror(value(vi_TERSE) ? 591*802Scf46844 (unsigned char *)gettext("What?") : 592*802Scf46844 (unsigned char *)gettext( 593*802Scf46844 "%s: No such command from open/visual"), tcommand); 5940Sstevel@tonic-gate else 595*802Scf46844 serror(value(vi_TERSE) ? 596*802Scf46844 (unsigned char *)gettext("What?") : 597*802Scf46844 (unsigned char *)gettext( 598*802Scf46844 "%s: Not an editor command"), tcommand); 5990Sstevel@tonic-gate } 6000Sstevel@tonic-gate ret: 6010Sstevel@tonic-gate *cp = 0; 6020Sstevel@tonic-gate } 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate /* 6050Sstevel@tonic-gate * Continue after a : command from open/visual. 6060Sstevel@tonic-gate */ 607*802Scf46844 void 608*802Scf46844 vcontin(bool ask) 6090Sstevel@tonic-gate { 6100Sstevel@tonic-gate 6110Sstevel@tonic-gate if (vcnt > 0) 6120Sstevel@tonic-gate vcnt = -vcnt; 6130Sstevel@tonic-gate if (inopen) { 6140Sstevel@tonic-gate if (state != VISUAL) { 6150Sstevel@tonic-gate /* 6160Sstevel@tonic-gate * We don't know what a shell command may have left on 6170Sstevel@tonic-gate * the screen, so we move the cursor to the right place 6180Sstevel@tonic-gate * and then put out a newline. But this makes an extra 6190Sstevel@tonic-gate * blank line most of the time so we only do it for :sh 6200Sstevel@tonic-gate * since the prompt gets left on the screen. 6210Sstevel@tonic-gate * 6220Sstevel@tonic-gate * BUG: :!echo longer than current line \\c 6230Sstevel@tonic-gate * will mess it up. 6240Sstevel@tonic-gate */ 6250Sstevel@tonic-gate if (state == CRTOPEN) { 6260Sstevel@tonic-gate termreset(); 6270Sstevel@tonic-gate vgoto(WECHO, 0); 6280Sstevel@tonic-gate } 6290Sstevel@tonic-gate if (!ask) { 630*802Scf46844 (void) putch('\r'); 631*802Scf46844 (void) putch('\n'); 6320Sstevel@tonic-gate } 6330Sstevel@tonic-gate return; 6340Sstevel@tonic-gate } 6350Sstevel@tonic-gate if (ask) { 6360Sstevel@tonic-gate merror(gettext("[Hit return to continue] ")); 6370Sstevel@tonic-gate flush(); 6380Sstevel@tonic-gate } 6390Sstevel@tonic-gate #ifndef CBREAK 6400Sstevel@tonic-gate vraw(); 6410Sstevel@tonic-gate #endif 6420Sstevel@tonic-gate if (ask) { 6430Sstevel@tonic-gate #ifdef notdef 6440Sstevel@tonic-gate /* 6450Sstevel@tonic-gate * Gobble ^Q/^S since the tty driver should be eating 6460Sstevel@tonic-gate * them (as far as the user can see) 6470Sstevel@tonic-gate */ 6480Sstevel@tonic-gate while (peekkey() == CTRL('Q') || peekkey() == CTRL('S')) 6490Sstevel@tonic-gate ignore(getkey()); 6500Sstevel@tonic-gate #endif 6510Sstevel@tonic-gate if(getkey() == ':') { 6520Sstevel@tonic-gate /* Extra newlines, but no other way */ 653*802Scf46844 (void) putch('\n'); 6540Sstevel@tonic-gate outline = WECHO; 6550Sstevel@tonic-gate ungetkey(':'); 6560Sstevel@tonic-gate } 6570Sstevel@tonic-gate } 6580Sstevel@tonic-gate vclrech(1); 6590Sstevel@tonic-gate if (Peekkey != ':') { 6600Sstevel@tonic-gate fixterm(); 661*802Scf46844 putpad((unsigned char *)enter_ca_mode); 6620Sstevel@tonic-gate tostart(); 6630Sstevel@tonic-gate } 6640Sstevel@tonic-gate } 6650Sstevel@tonic-gate } 6660Sstevel@tonic-gate 6670Sstevel@tonic-gate /* 6680Sstevel@tonic-gate * Put out a newline (before a shell escape) 6690Sstevel@tonic-gate * if in open/visual. 6700Sstevel@tonic-gate */ 671*802Scf46844 void 672*802Scf46844 vnfl(void) 6730Sstevel@tonic-gate { 6740Sstevel@tonic-gate 6750Sstevel@tonic-gate if (inopen) { 6760Sstevel@tonic-gate if (state != VISUAL && state != CRTOPEN && destline <= WECHO) 6770Sstevel@tonic-gate vclean(); 6780Sstevel@tonic-gate else 6790Sstevel@tonic-gate vmoveitup(1, 0); 6800Sstevel@tonic-gate vgoto(WECHO, 0); 6810Sstevel@tonic-gate vclrbyte(vtube[WECHO], WCOLS); 6820Sstevel@tonic-gate tostop(); 6830Sstevel@tonic-gate /* replaced by the ostop above 6840Sstevel@tonic-gate putpad(cursor_normal); 6850Sstevel@tonic-gate putpad(key_eol); 6860Sstevel@tonic-gate */ 6870Sstevel@tonic-gate } 6880Sstevel@tonic-gate flush(); 6890Sstevel@tonic-gate } 690