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*bbfd0aa6Scf46844 * Common Development and Distribution License (the "License"). 6*bbfd0aa6Scf46844 * 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 */ 21f6db9f27Scf46844 /* 22*bbfd0aa6Scf46844 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23f6db9f27Scf46844 * Use is subject to license terms. 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 */ 31f6db9f27Scf46844 32f6db9f27Scf46844 #pragma ident "%Z%%M% %I% %E% SMI" 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate #include "ex.h" 357c478bd9Sstevel@tonic-gate #include "ex_tty.h" 367c478bd9Sstevel@tonic-gate #include "ex_vis.h" 377c478bd9Sstevel@tonic-gate #ifndef PRESUNEUC 387c478bd9Sstevel@tonic-gate #include <wctype.h> 397c478bd9Sstevel@tonic-gate /* Undef putchar/getchar if they're defined. */ 407c478bd9Sstevel@tonic-gate #ifdef putchar 417c478bd9Sstevel@tonic-gate # undef putchar 427c478bd9Sstevel@tonic-gate #endif 437c478bd9Sstevel@tonic-gate #ifdef getchar 447c478bd9Sstevel@tonic-gate # undef getchar 457c478bd9Sstevel@tonic-gate #endif 467c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate /* 497c478bd9Sstevel@tonic-gate * This is the main routine for visual. 507c478bd9Sstevel@tonic-gate * We here decode the count and possible named buffer specification 517c478bd9Sstevel@tonic-gate * preceding a command and interpret a few of the commands. 527c478bd9Sstevel@tonic-gate * Commands which involve a target (i.e. an operator) are decoded 537c478bd9Sstevel@tonic-gate * in the routine operate in ex_voperate.c. 547c478bd9Sstevel@tonic-gate */ 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate #define forbid(a) { if (a) goto fonfon; } 577c478bd9Sstevel@tonic-gate 587c478bd9Sstevel@tonic-gate extern int windowchg; 597c478bd9Sstevel@tonic-gate extern int sigok; 60*bbfd0aa6Scf46844 #ifdef XPG6 61*bbfd0aa6Scf46844 int redisplay; /* XPG6 assertion 313 [count]r\n : Also used in ex_vops2.c */ 62*bbfd0aa6Scf46844 #endif 637c478bd9Sstevel@tonic-gate void redraw(), windowinit(); 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate #ifdef XPG4 667c478bd9Sstevel@tonic-gate extern int P_cursor_offset; 677c478bd9Sstevel@tonic-gate #endif 687c478bd9Sstevel@tonic-gate 69f6db9f27Scf46844 void 70f6db9f27Scf46844 vmain(void) 717c478bd9Sstevel@tonic-gate { 72f6db9f27Scf46844 int c, cnt, i; 737c478bd9Sstevel@tonic-gate wchar_t esave[TUBECOLS]; 747c478bd9Sstevel@tonic-gate extern wchar_t atube[]; 757c478bd9Sstevel@tonic-gate unsigned char *oglobp; 767c478bd9Sstevel@tonic-gate short d; 777c478bd9Sstevel@tonic-gate line *addr; 787c478bd9Sstevel@tonic-gate int ind, nlput; 797c478bd9Sstevel@tonic-gate int shouldpo = 0; 807c478bd9Sstevel@tonic-gate int tag_reset_wrap = 0; 817c478bd9Sstevel@tonic-gate int onumber, olist, (*OPline)(), (*OPutchar)(); 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate vch_mac = VC_NOTINMAC; 857c478bd9Sstevel@tonic-gate ixlatctl(0); 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /* 887c478bd9Sstevel@tonic-gate * If we started as a vi command (on the command line) 897c478bd9Sstevel@tonic-gate * then go process initial commands (recover, next or tag). 907c478bd9Sstevel@tonic-gate */ 917c478bd9Sstevel@tonic-gate if (initev) { 927c478bd9Sstevel@tonic-gate oglobp = globp; 937c478bd9Sstevel@tonic-gate globp = initev; 947c478bd9Sstevel@tonic-gate hadcnt = cnt = 0; 957c478bd9Sstevel@tonic-gate i = tchng; 967c478bd9Sstevel@tonic-gate addr = dot; 977c478bd9Sstevel@tonic-gate goto doinit; 987c478bd9Sstevel@tonic-gate } 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate vshowmode(""); /* As a precaution */ 1017c478bd9Sstevel@tonic-gate /* 1027c478bd9Sstevel@tonic-gate * NB: 1037c478bd9Sstevel@tonic-gate * 1047c478bd9Sstevel@tonic-gate * The current line is always in the line buffer linebuf, 1057c478bd9Sstevel@tonic-gate * and the cursor at the position cursor. You should do 1067c478bd9Sstevel@tonic-gate * a vsave() before moving off the line to make sure the disk 1077c478bd9Sstevel@tonic-gate * copy is updated if it has changed, and a getDOT() to get 1087c478bd9Sstevel@tonic-gate * the line back if you mung linebuf. The motion 1097c478bd9Sstevel@tonic-gate * routines in ex_vwind.c handle most of this. 1107c478bd9Sstevel@tonic-gate */ 1117c478bd9Sstevel@tonic-gate for (;;) { 1127c478bd9Sstevel@tonic-gate /* 1137c478bd9Sstevel@tonic-gate * Decode a visual command. 1147c478bd9Sstevel@tonic-gate * First sync the temp file if there has been a reasonable 1157c478bd9Sstevel@tonic-gate * amount of change. Clear state for decoding of next 1167c478bd9Sstevel@tonic-gate * command. 1177c478bd9Sstevel@tonic-gate */ 1187c478bd9Sstevel@tonic-gate TSYNC(); 1197c478bd9Sstevel@tonic-gate vglobp = 0; 1207c478bd9Sstevel@tonic-gate vreg = 0; 1217c478bd9Sstevel@tonic-gate hold = 0; 1227c478bd9Sstevel@tonic-gate seenprompt = 1; 1237c478bd9Sstevel@tonic-gate wcursor = 0; 1247c478bd9Sstevel@tonic-gate Xhadcnt = hadcnt = 0; 1257c478bd9Sstevel@tonic-gate Xcnt = cnt = 1; 1267c478bd9Sstevel@tonic-gate splitw = 0; 1277c478bd9Sstevel@tonic-gate if (i = holdupd && !windowchg) { 1287c478bd9Sstevel@tonic-gate if (state == VISUAL) { 1297c478bd9Sstevel@tonic-gate sigok = 1; 1307c478bd9Sstevel@tonic-gate (void)peekkey(); 1317c478bd9Sstevel@tonic-gate sigok = 0; 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate holdupd = 0; 1357c478bd9Sstevel@tonic-gate /* 1367c478bd9Sstevel@tonic-gate if (LINE(0) < ZERO) { 1377c478bd9Sstevel@tonic-gate vclear(); 1387c478bd9Sstevel@tonic-gate vcnt = 0; 1397c478bd9Sstevel@tonic-gate i = 3; 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate */ 1427c478bd9Sstevel@tonic-gate if (state != VISUAL) { 1437c478bd9Sstevel@tonic-gate vcnt = 0; 1447c478bd9Sstevel@tonic-gate vsave(); 1457c478bd9Sstevel@tonic-gate vrepaint(cursor); 1467c478bd9Sstevel@tonic-gate } else if (i == 3) 1477c478bd9Sstevel@tonic-gate vredraw(WTOP); 1487c478bd9Sstevel@tonic-gate else 1497c478bd9Sstevel@tonic-gate vsync(WTOP); 1507c478bd9Sstevel@tonic-gate vfixcurs(); 1517c478bd9Sstevel@tonic-gate } else if(windowchg) 1527c478bd9Sstevel@tonic-gate redraw(); 1537c478bd9Sstevel@tonic-gate 154*bbfd0aa6Scf46844 #ifdef XPG6 155*bbfd0aa6Scf46844 if (redisplay) { 156*bbfd0aa6Scf46844 /* XPG6 assertion 313 & 254 : after [count]r\n */ 157*bbfd0aa6Scf46844 fixdisplay(); 158*bbfd0aa6Scf46844 } 159*bbfd0aa6Scf46844 redisplay = 0; 160*bbfd0aa6Scf46844 #endif 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * Gobble up counts and named buffer specifications. 1637c478bd9Sstevel@tonic-gate */ 1647c478bd9Sstevel@tonic-gate for (;;) { 1657c478bd9Sstevel@tonic-gate looptop: 1667c478bd9Sstevel@tonic-gate #ifdef MDEBUG 1677c478bd9Sstevel@tonic-gate if (trace) 1687c478bd9Sstevel@tonic-gate fprintf(trace, "pc=%c",peekkey()); 1697c478bd9Sstevel@tonic-gate #endif 1707c478bd9Sstevel@tonic-gate sigok = 1; 1717c478bd9Sstevel@tonic-gate c = peekkey(); 1727c478bd9Sstevel@tonic-gate sigok = 0; 1737c478bd9Sstevel@tonic-gate if (isdigit(peekkey()) && peekkey() != '0') { 1747c478bd9Sstevel@tonic-gate hadcnt = 1; 1757c478bd9Sstevel@tonic-gate cnt = vgetcnt(); 1767c478bd9Sstevel@tonic-gate forbid (cnt <= 0); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate if (peekkey() != '"') 1797c478bd9Sstevel@tonic-gate break; 1807c478bd9Sstevel@tonic-gate (void)getkey(), c = getkey(); 1817c478bd9Sstevel@tonic-gate /* 1827c478bd9Sstevel@tonic-gate * Buffer names be letters or digits. 1837c478bd9Sstevel@tonic-gate * But not '0' as that is the source of 1847c478bd9Sstevel@tonic-gate * an 'empty' named buffer spec in the routine 1857c478bd9Sstevel@tonic-gate * kshift (see ex_temp.c). 1867c478bd9Sstevel@tonic-gate */ 1877c478bd9Sstevel@tonic-gate if(!isascii(c) && MB_CUR_MAX > 1) { 1887c478bd9Sstevel@tonic-gate /* get rest of character */ 1897c478bd9Sstevel@tonic-gate wchar_t wchar; 1907c478bd9Sstevel@tonic-gate char multic[MULTI_BYTE_MAX]; 1917c478bd9Sstevel@tonic-gate ungetkey(c); 1927c478bd9Sstevel@tonic-gate (void)_mbftowc(multic, &wchar, getkey, &Peekkey); 1937c478bd9Sstevel@tonic-gate } 1947c478bd9Sstevel@tonic-gate forbid (c == '0' || !isalpha(c) && !isascii(c) && !isdigit(c)); 1957c478bd9Sstevel@tonic-gate vreg = c; 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate reread: 1987c478bd9Sstevel@tonic-gate /* 1997c478bd9Sstevel@tonic-gate * Come to reread from below after some macro expansions. 2007c478bd9Sstevel@tonic-gate * The call to map allows use of function key pads 2017c478bd9Sstevel@tonic-gate * by performing a terminal dependent mapping of inputs. 2027c478bd9Sstevel@tonic-gate */ 2037c478bd9Sstevel@tonic-gate #ifdef MDEBUG 2047c478bd9Sstevel@tonic-gate if (trace) 2057c478bd9Sstevel@tonic-gate fprintf(trace,"pcb=%c,",peekkey()); 2067c478bd9Sstevel@tonic-gate #endif 2077c478bd9Sstevel@tonic-gate op = getkey(); 2087c478bd9Sstevel@tonic-gate maphopcnt = 0; 2097c478bd9Sstevel@tonic-gate do { 2107c478bd9Sstevel@tonic-gate /* 2117c478bd9Sstevel@tonic-gate * Keep mapping the char as long as it changes. 2127c478bd9Sstevel@tonic-gate * This allows for double mappings, e.g., q to #, 2137c478bd9Sstevel@tonic-gate * #1 to something else. 2147c478bd9Sstevel@tonic-gate */ 2157c478bd9Sstevel@tonic-gate c = op; 2167c478bd9Sstevel@tonic-gate op = map(c, arrows, 0); 2177c478bd9Sstevel@tonic-gate #ifdef MDEBUG 2187c478bd9Sstevel@tonic-gate if (trace) 2197c478bd9Sstevel@tonic-gate fprintf(trace,"pca=%c,",c); 2207c478bd9Sstevel@tonic-gate #endif 2217c478bd9Sstevel@tonic-gate /* 2227c478bd9Sstevel@tonic-gate * Maybe the mapped to char is a count. If so, we have 2237c478bd9Sstevel@tonic-gate * to go back to the "for" to interpret it. Likewise 2247c478bd9Sstevel@tonic-gate * for a buffer name. 2257c478bd9Sstevel@tonic-gate */ 2267c478bd9Sstevel@tonic-gate if ((isdigit(c) && c!='0') || c == '"') { 2277c478bd9Sstevel@tonic-gate ungetkey(c); 2287c478bd9Sstevel@tonic-gate goto looptop; 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate if (!value(vi_REMAP)) { 2317c478bd9Sstevel@tonic-gate c = op; 2327c478bd9Sstevel@tonic-gate break; 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate if (++maphopcnt > 256) 2357c478bd9Sstevel@tonic-gate error(gettext("Infinite macro loop")); 2367c478bd9Sstevel@tonic-gate } while (c != op); 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* 2397c478bd9Sstevel@tonic-gate * Begin to build an image of this command for possible 2407c478bd9Sstevel@tonic-gate * later repeat in the buffer workcmd. It will be copied 2417c478bd9Sstevel@tonic-gate * to lastcmd by the routine setLAST 2427c478bd9Sstevel@tonic-gate * if/when completely specified. 2437c478bd9Sstevel@tonic-gate */ 2447c478bd9Sstevel@tonic-gate lastcp = workcmd; 2457c478bd9Sstevel@tonic-gate if (!vglobp) 2467c478bd9Sstevel@tonic-gate *lastcp++ = c; 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* 2497c478bd9Sstevel@tonic-gate * First level command decode. 2507c478bd9Sstevel@tonic-gate */ 2517c478bd9Sstevel@tonic-gate switch (c) { 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate /* 2547c478bd9Sstevel@tonic-gate * ^L Clear screen e.g. after transmission error. 2557c478bd9Sstevel@tonic-gate */ 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate /* 2587c478bd9Sstevel@tonic-gate * ^R Retype screen, getting rid of @ lines. 2597c478bd9Sstevel@tonic-gate * If in open, equivalent to ^L. 2607c478bd9Sstevel@tonic-gate * On terminals where the right arrow key sends 2617c478bd9Sstevel@tonic-gate * ^L we make ^R act like ^L, since there is no 2627c478bd9Sstevel@tonic-gate * way to get ^L. These terminals (adm31, tvi) 2637c478bd9Sstevel@tonic-gate * are intelligent so ^R is useless. Soroc 2647c478bd9Sstevel@tonic-gate * will probably foul this up, but nobody has 2657c478bd9Sstevel@tonic-gate * one of them. 2667c478bd9Sstevel@tonic-gate */ 2677c478bd9Sstevel@tonic-gate case CTRL('l'): 2687c478bd9Sstevel@tonic-gate case CTRL('r'): 2697c478bd9Sstevel@tonic-gate if (c == CTRL('l') || (key_right && *key_right==CTRL('l'))) { 2707c478bd9Sstevel@tonic-gate vclear(); 2717c478bd9Sstevel@tonic-gate vdirty(0, vcnt); 2727c478bd9Sstevel@tonic-gate } 2737c478bd9Sstevel@tonic-gate if (state != VISUAL) { 2747c478bd9Sstevel@tonic-gate /* 2757c478bd9Sstevel@tonic-gate * Get a clean line, throw away the 2767c478bd9Sstevel@tonic-gate * memory of what is displayed now, 2777c478bd9Sstevel@tonic-gate * and move back onto the current line. 2787c478bd9Sstevel@tonic-gate */ 2797c478bd9Sstevel@tonic-gate vclean(); 2807c478bd9Sstevel@tonic-gate vcnt = 0; 2817c478bd9Sstevel@tonic-gate vmoveto(dot, cursor, 0); 2827c478bd9Sstevel@tonic-gate continue; 2837c478bd9Sstevel@tonic-gate } 2847c478bd9Sstevel@tonic-gate vredraw(WTOP); 2857c478bd9Sstevel@tonic-gate /* 2867c478bd9Sstevel@tonic-gate * Weird glitch -- when we enter visual 2877c478bd9Sstevel@tonic-gate * in a very small window we may end up with 2887c478bd9Sstevel@tonic-gate * no lines on the screen because the line 2897c478bd9Sstevel@tonic-gate * at the top is too long. This forces the screen 2907c478bd9Sstevel@tonic-gate * to be expanded to make room for it (after 2917c478bd9Sstevel@tonic-gate * we have printed @'s ick showing we goofed). 2927c478bd9Sstevel@tonic-gate */ 2937c478bd9Sstevel@tonic-gate if (vcnt == 0) 2947c478bd9Sstevel@tonic-gate vrepaint(cursor); 2957c478bd9Sstevel@tonic-gate vfixcurs(); 2967c478bd9Sstevel@tonic-gate continue; 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate /* 2997c478bd9Sstevel@tonic-gate * $ Escape just cancels the current command 3007c478bd9Sstevel@tonic-gate * with a little feedback. 3017c478bd9Sstevel@tonic-gate */ 3027c478bd9Sstevel@tonic-gate case ESCAPE: 303f6db9f27Scf46844 (void) beep(); 3047c478bd9Sstevel@tonic-gate continue; 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate /* 3077c478bd9Sstevel@tonic-gate * @ Macros. Bring in the macro and put it 3087c478bd9Sstevel@tonic-gate * in vmacbuf, point vglobp there and punt. 3097c478bd9Sstevel@tonic-gate */ 3107c478bd9Sstevel@tonic-gate case '@': 3117c478bd9Sstevel@tonic-gate c = getesc(); 3127c478bd9Sstevel@tonic-gate if (c == 0) 3137c478bd9Sstevel@tonic-gate continue; 3147c478bd9Sstevel@tonic-gate if (c == '@') 3157c478bd9Sstevel@tonic-gate c = lastmac; 3167c478bd9Sstevel@tonic-gate if (isupper(c)) 3177c478bd9Sstevel@tonic-gate c = tolower(c); 3187c478bd9Sstevel@tonic-gate forbid(!islower(c)); 3197c478bd9Sstevel@tonic-gate lastmac = c; 3207c478bd9Sstevel@tonic-gate vsave(); 3217c478bd9Sstevel@tonic-gate CATCH 3227c478bd9Sstevel@tonic-gate unsigned char tmpbuf[BUFSIZE]; 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate regbuf(c, tmpbuf, sizeof (vmacbuf)); 3257c478bd9Sstevel@tonic-gate macpush(tmpbuf, 1); 3267c478bd9Sstevel@tonic-gate ONERR 3277c478bd9Sstevel@tonic-gate lastmac = 0; 3287c478bd9Sstevel@tonic-gate splitw = 0; 3297c478bd9Sstevel@tonic-gate getDOT(); 3307c478bd9Sstevel@tonic-gate vrepaint(cursor); 3317c478bd9Sstevel@tonic-gate continue; 3327c478bd9Sstevel@tonic-gate ENDCATCH 3337c478bd9Sstevel@tonic-gate vmacp = vmacbuf; 3347c478bd9Sstevel@tonic-gate goto reread; 3357c478bd9Sstevel@tonic-gate 3367c478bd9Sstevel@tonic-gate /* 3377c478bd9Sstevel@tonic-gate * . Repeat the last (modifying) open/visual command. 3387c478bd9Sstevel@tonic-gate */ 3397c478bd9Sstevel@tonic-gate case '.': 3407c478bd9Sstevel@tonic-gate /* 3417c478bd9Sstevel@tonic-gate * Check that there was a last command, and 3427c478bd9Sstevel@tonic-gate * take its count and named buffer unless they 3437c478bd9Sstevel@tonic-gate * were given anew. Special case if last command 3447c478bd9Sstevel@tonic-gate * referenced a numeric named buffer -- increment 3457c478bd9Sstevel@tonic-gate * the number and go to a named buffer again. 3467c478bd9Sstevel@tonic-gate * This allows a sequence like "1pu.u.u... 3477c478bd9Sstevel@tonic-gate * to successively look for stuff in the kill chain 3487c478bd9Sstevel@tonic-gate * much as one does in EMACS with C-Y and M-Y. 3497c478bd9Sstevel@tonic-gate */ 3507c478bd9Sstevel@tonic-gate forbid (lastcmd[0] == 0); 3517c478bd9Sstevel@tonic-gate if (hadcnt) 3527c478bd9Sstevel@tonic-gate lastcnt = cnt; 3537c478bd9Sstevel@tonic-gate if (vreg) 3547c478bd9Sstevel@tonic-gate lastreg = vreg; 3557c478bd9Sstevel@tonic-gate else if (isdigit(lastreg) && lastreg < '9') 3567c478bd9Sstevel@tonic-gate lastreg++; 3577c478bd9Sstevel@tonic-gate vreg = lastreg; 3587c478bd9Sstevel@tonic-gate cnt = lastcnt; 3597c478bd9Sstevel@tonic-gate hadcnt = lasthad; 3607c478bd9Sstevel@tonic-gate vglobp = lastcmd; 3617c478bd9Sstevel@tonic-gate goto reread; 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gate /* 3647c478bd9Sstevel@tonic-gate * ^U Scroll up. A count sticks around for 3657c478bd9Sstevel@tonic-gate * future scrolls as the scroll amount. 3667c478bd9Sstevel@tonic-gate * Attempt to hold the indentation from the 3677c478bd9Sstevel@tonic-gate * top of the screen (in logical lines). 3687c478bd9Sstevel@tonic-gate * 3697c478bd9Sstevel@tonic-gate * BUG: A ^U near the bottom of the screen 3707c478bd9Sstevel@tonic-gate * on a dumb terminal (which can't roll back) 3717c478bd9Sstevel@tonic-gate * causes the screen to be cleared and then 3727c478bd9Sstevel@tonic-gate * redrawn almost as it was. In this case 3737c478bd9Sstevel@tonic-gate * one should simply move the cursor. 3747c478bd9Sstevel@tonic-gate */ 3757c478bd9Sstevel@tonic-gate case CTRL('u'): 3767c478bd9Sstevel@tonic-gate if (hadcnt) 3777c478bd9Sstevel@tonic-gate vSCROLL = cnt; 3787c478bd9Sstevel@tonic-gate cnt = vSCROLL; 3797c478bd9Sstevel@tonic-gate if (state == VISUAL) 3807c478bd9Sstevel@tonic-gate ind = vcline, cnt += ind; 3817c478bd9Sstevel@tonic-gate else 3827c478bd9Sstevel@tonic-gate ind = 0; 3837c478bd9Sstevel@tonic-gate vmoving = 0; 3847c478bd9Sstevel@tonic-gate vup(cnt, ind, 1); 385f6db9f27Scf46844 vnline((unsigned char *)NOSTR); 3867c478bd9Sstevel@tonic-gate continue; 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate /* 3897c478bd9Sstevel@tonic-gate * ^D Scroll down. Like scroll up. 3907c478bd9Sstevel@tonic-gate */ 3917c478bd9Sstevel@tonic-gate case CTRL('d'): 3927c478bd9Sstevel@tonic-gate #ifdef TRACE 3937c478bd9Sstevel@tonic-gate if (trace) 3947c478bd9Sstevel@tonic-gate fprintf(trace, "before vdown in ^D, dot=%d, wdot=%d, dol=%d\n", lineno(dot), lineno(wdot), lineno(dol)); 3957c478bd9Sstevel@tonic-gate #endif 3967c478bd9Sstevel@tonic-gate if (hadcnt) 3977c478bd9Sstevel@tonic-gate vSCROLL = cnt; 3987c478bd9Sstevel@tonic-gate cnt = vSCROLL; 3997c478bd9Sstevel@tonic-gate if (state == VISUAL) 4007c478bd9Sstevel@tonic-gate ind = vcnt - vcline - 1, cnt += ind; 4017c478bd9Sstevel@tonic-gate else 4027c478bd9Sstevel@tonic-gate ind = 0; 4037c478bd9Sstevel@tonic-gate vmoving = 0; 4047c478bd9Sstevel@tonic-gate vdown(cnt, ind, 1); 4057c478bd9Sstevel@tonic-gate #ifdef TRACE 4067c478bd9Sstevel@tonic-gate if (trace) 4077c478bd9Sstevel@tonic-gate fprintf(trace, "before vnline in ^D, dot=%d, wdot=%d, dol=%d\n", lineno(dot), lineno(wdot), lineno(dol)); 4087c478bd9Sstevel@tonic-gate #endif 409f6db9f27Scf46844 vnline((unsigned char *)NOSTR); 4107c478bd9Sstevel@tonic-gate #ifdef TRACE 4117c478bd9Sstevel@tonic-gate if (trace) 4127c478bd9Sstevel@tonic-gate fprintf(trace, "after vnline in ^D, dot=%d, wdot=%d, dol=%d\n", lineno(dot), lineno(wdot), lineno(dol)); 4137c478bd9Sstevel@tonic-gate #endif 4147c478bd9Sstevel@tonic-gate continue; 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate /* 4177c478bd9Sstevel@tonic-gate * ^E Glitch the screen down (one) line. 4187c478bd9Sstevel@tonic-gate * Cursor left on same line in file. 4197c478bd9Sstevel@tonic-gate */ 4207c478bd9Sstevel@tonic-gate case CTRL('e'): 4217c478bd9Sstevel@tonic-gate if (state != VISUAL) 4227c478bd9Sstevel@tonic-gate continue; 4237c478bd9Sstevel@tonic-gate if (!hadcnt) 4247c478bd9Sstevel@tonic-gate cnt = 1; 4257c478bd9Sstevel@tonic-gate /* Bottom line of file already on screen */ 4267c478bd9Sstevel@tonic-gate forbid(lineDOL()-lineDOT() <= vcnt-1-vcline); 4277c478bd9Sstevel@tonic-gate ind = vcnt - vcline - 1 + cnt; 4287c478bd9Sstevel@tonic-gate vdown(ind, ind, 1); 4297c478bd9Sstevel@tonic-gate vnline(cursor); 4307c478bd9Sstevel@tonic-gate continue; 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate /* 4337c478bd9Sstevel@tonic-gate * ^Y Like ^E but up 4347c478bd9Sstevel@tonic-gate */ 4357c478bd9Sstevel@tonic-gate case CTRL('y'): 4367c478bd9Sstevel@tonic-gate if (state != VISUAL) 4377c478bd9Sstevel@tonic-gate continue; 4387c478bd9Sstevel@tonic-gate if (!hadcnt) 4397c478bd9Sstevel@tonic-gate cnt = 1; 4407c478bd9Sstevel@tonic-gate forbid(lineDOT()-1<=vcline); /* line 1 already there */ 4417c478bd9Sstevel@tonic-gate ind = vcline + cnt; 4427c478bd9Sstevel@tonic-gate vup(ind, ind, 1); 4437c478bd9Sstevel@tonic-gate vnline(cursor); 4447c478bd9Sstevel@tonic-gate continue; 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate /* 4487c478bd9Sstevel@tonic-gate * m Mark position in mark register given 4497c478bd9Sstevel@tonic-gate * by following letter. Return is 4507c478bd9Sstevel@tonic-gate * accomplished via ' or `; former 4517c478bd9Sstevel@tonic-gate * to beginning of line where mark 4527c478bd9Sstevel@tonic-gate * was set, latter to column where marked. 4537c478bd9Sstevel@tonic-gate */ 4547c478bd9Sstevel@tonic-gate case 'm': 4557c478bd9Sstevel@tonic-gate /* 4567c478bd9Sstevel@tonic-gate * Getesc is generally used when a character 4577c478bd9Sstevel@tonic-gate * is read as a latter part of a command 4587c478bd9Sstevel@tonic-gate * to allow one to hit rubout/escape to cancel 4597c478bd9Sstevel@tonic-gate * what you have typed so far. These characters 4607c478bd9Sstevel@tonic-gate * are mapped to 0 by the subroutine. 4617c478bd9Sstevel@tonic-gate */ 4627c478bd9Sstevel@tonic-gate c = getesc(); 4637c478bd9Sstevel@tonic-gate if (c == 0) 4647c478bd9Sstevel@tonic-gate continue; 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate /* 4677c478bd9Sstevel@tonic-gate * Markreg checks that argument is a letter 4687c478bd9Sstevel@tonic-gate * and also maps ' and ` to the end of the range 4697c478bd9Sstevel@tonic-gate * to allow '' or `` to reference the previous 4707c478bd9Sstevel@tonic-gate * context mark. 4717c478bd9Sstevel@tonic-gate */ 4727c478bd9Sstevel@tonic-gate c = markreg(c); 4737c478bd9Sstevel@tonic-gate forbid (c == 0); 4747c478bd9Sstevel@tonic-gate vsave(); 4757c478bd9Sstevel@tonic-gate names[c - 'a'] = (*dot &~ 01); 4767c478bd9Sstevel@tonic-gate ncols[c - 'a'] = cursor; 4777c478bd9Sstevel@tonic-gate anymarks = 1; 4787c478bd9Sstevel@tonic-gate continue; 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate /* 4817c478bd9Sstevel@tonic-gate * ^F Window forwards, with 2 lines of continuity. 4827c478bd9Sstevel@tonic-gate * Count repeats. 4837c478bd9Sstevel@tonic-gate */ 4847c478bd9Sstevel@tonic-gate case CTRL('f'): 4857c478bd9Sstevel@tonic-gate vsave(); 4867c478bd9Sstevel@tonic-gate if (vcnt > 2) { 4877c478bd9Sstevel@tonic-gate addr = dot + (vcnt - vcline) - 2 + (cnt-1)*basWLINES; 4887c478bd9Sstevel@tonic-gate forbid(addr > dol); 4897c478bd9Sstevel@tonic-gate dot = addr; 4907c478bd9Sstevel@tonic-gate vcnt = vcline = 0; 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate vzop(0, 0, '+'); 4937c478bd9Sstevel@tonic-gate continue; 4947c478bd9Sstevel@tonic-gate 4957c478bd9Sstevel@tonic-gate /* 4967c478bd9Sstevel@tonic-gate * ^B Window backwards, with 2 lines of continuity. 4977c478bd9Sstevel@tonic-gate * Inverse of ^F. 4987c478bd9Sstevel@tonic-gate */ 4997c478bd9Sstevel@tonic-gate case CTRL('b'): 5007c478bd9Sstevel@tonic-gate vsave(); 5017c478bd9Sstevel@tonic-gate if (one + vcline != dot && vcnt > 2) { 5027c478bd9Sstevel@tonic-gate addr = dot - vcline + 2 - (cnt-1)*basWLINES; 5037c478bd9Sstevel@tonic-gate forbid (addr <= zero); 5047c478bd9Sstevel@tonic-gate dot = addr; 5057c478bd9Sstevel@tonic-gate vcnt = vcline = 0; 5067c478bd9Sstevel@tonic-gate } 5077c478bd9Sstevel@tonic-gate vzop(0, 0, '^'); 5087c478bd9Sstevel@tonic-gate continue; 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate /* 5117c478bd9Sstevel@tonic-gate * z Screen adjustment, taking a following character: 5127c478bd9Sstevel@tonic-gate * zcarriage_return current line to top 5137c478bd9Sstevel@tonic-gate * z<NL> like zcarriage_return 5147c478bd9Sstevel@tonic-gate * z- current line to bottom 5157c478bd9Sstevel@tonic-gate * also z+, z^ like ^F and ^B. 5167c478bd9Sstevel@tonic-gate * A preceding count is line to use rather 5177c478bd9Sstevel@tonic-gate * than current line. A count between z and 5187c478bd9Sstevel@tonic-gate * specifier character changes the screen size 5197c478bd9Sstevel@tonic-gate * for the redraw. 5207c478bd9Sstevel@tonic-gate * 5217c478bd9Sstevel@tonic-gate */ 5227c478bd9Sstevel@tonic-gate case 'z': 5237c478bd9Sstevel@tonic-gate if (state == VISUAL) { 5247c478bd9Sstevel@tonic-gate i = vgetcnt(); 5257c478bd9Sstevel@tonic-gate if (i > 0) 5267c478bd9Sstevel@tonic-gate vsetsiz(i); 5277c478bd9Sstevel@tonic-gate c = getesc(); 5287c478bd9Sstevel@tonic-gate if (c == 0) 5297c478bd9Sstevel@tonic-gate continue; 5307c478bd9Sstevel@tonic-gate } 5317c478bd9Sstevel@tonic-gate vsave(); 5327c478bd9Sstevel@tonic-gate vzop(hadcnt, cnt, c); 5337c478bd9Sstevel@tonic-gate continue; 5347c478bd9Sstevel@tonic-gate 5357c478bd9Sstevel@tonic-gate /* 5367c478bd9Sstevel@tonic-gate * Y Yank lines, abbreviation for y_ or yy. 5377c478bd9Sstevel@tonic-gate * Yanked lines can be put later if no 5387c478bd9Sstevel@tonic-gate * changes intervene, or can be put in named 5397c478bd9Sstevel@tonic-gate * buffers and put anytime in this session. 5407c478bd9Sstevel@tonic-gate */ 5417c478bd9Sstevel@tonic-gate case 'Y': 5427c478bd9Sstevel@tonic-gate ungetkey('_'); 5437c478bd9Sstevel@tonic-gate c = 'y'; 5447c478bd9Sstevel@tonic-gate break; 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate /* 5477c478bd9Sstevel@tonic-gate * J Join lines, 2 by default. Count is number 5487c478bd9Sstevel@tonic-gate * of lines to join (no join operator sorry.) 5497c478bd9Sstevel@tonic-gate */ 5507c478bd9Sstevel@tonic-gate case 'J': 5517c478bd9Sstevel@tonic-gate forbid (dot == dol); 5527c478bd9Sstevel@tonic-gate if (cnt == 1) 5537c478bd9Sstevel@tonic-gate cnt = 2; 5547c478bd9Sstevel@tonic-gate if (cnt > (i = dol - dot + 1)) 5557c478bd9Sstevel@tonic-gate cnt = i; 5567c478bd9Sstevel@tonic-gate vsave(); 5577c478bd9Sstevel@tonic-gate vmacchng(1); 5587c478bd9Sstevel@tonic-gate setLAST(); 5597c478bd9Sstevel@tonic-gate cursor = strend(linebuf); 5607c478bd9Sstevel@tonic-gate vremote(cnt, join, 0); 5617c478bd9Sstevel@tonic-gate notenam = (unsigned char *)"join"; 5627c478bd9Sstevel@tonic-gate vmoving = 0; 5637c478bd9Sstevel@tonic-gate killU(); 5647c478bd9Sstevel@tonic-gate vreplace(vcline, cnt, 1); 5657c478bd9Sstevel@tonic-gate if (!*cursor && cursor > linebuf) 5667c478bd9Sstevel@tonic-gate cursor--; 5677c478bd9Sstevel@tonic-gate if (notecnt == 2) 5687c478bd9Sstevel@tonic-gate notecnt = 0; 5697c478bd9Sstevel@tonic-gate vrepaint(cursor); 5707c478bd9Sstevel@tonic-gate continue; 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate /* 5737c478bd9Sstevel@tonic-gate * S Substitute text for whole lines, abbrev for c_. 5747c478bd9Sstevel@tonic-gate * Count is number of lines to change. 5757c478bd9Sstevel@tonic-gate */ 5767c478bd9Sstevel@tonic-gate case 'S': 5777c478bd9Sstevel@tonic-gate ungetkey('_'); 5787c478bd9Sstevel@tonic-gate c = 'c'; 5797c478bd9Sstevel@tonic-gate break; 5807c478bd9Sstevel@tonic-gate 5817c478bd9Sstevel@tonic-gate /* 5827c478bd9Sstevel@tonic-gate * O Create a new line above current and accept new 5837c478bd9Sstevel@tonic-gate * input text, to an escape, there. 5847c478bd9Sstevel@tonic-gate * A count specifies, for dumb terminals when 5857c478bd9Sstevel@tonic-gate * slowopen is not set, the number of physical 5867c478bd9Sstevel@tonic-gate * line space to open on the screen. 5877c478bd9Sstevel@tonic-gate * 5887c478bd9Sstevel@tonic-gate * o Like O, but opens lines below. 5897c478bd9Sstevel@tonic-gate */ 5907c478bd9Sstevel@tonic-gate case 'O': 5917c478bd9Sstevel@tonic-gate case 'o': 5927c478bd9Sstevel@tonic-gate vmacchng(1); 5937c478bd9Sstevel@tonic-gate voOpen(c, cnt); 5947c478bd9Sstevel@tonic-gate continue; 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate /* 5977c478bd9Sstevel@tonic-gate * C Change text to end of line, short for c$. 5987c478bd9Sstevel@tonic-gate */ 5997c478bd9Sstevel@tonic-gate case 'C': 6007c478bd9Sstevel@tonic-gate if (*cursor) { 6017c478bd9Sstevel@tonic-gate ungetkey('$'), c = 'c'; 6027c478bd9Sstevel@tonic-gate break; 6037c478bd9Sstevel@tonic-gate } 6047c478bd9Sstevel@tonic-gate goto appnd; 6057c478bd9Sstevel@tonic-gate 6067c478bd9Sstevel@tonic-gate /* 6077c478bd9Sstevel@tonic-gate * ~ Switch case of letter under cursor 6087c478bd9Sstevel@tonic-gate */ 6097c478bd9Sstevel@tonic-gate case '~': 6107c478bd9Sstevel@tonic-gate { 6117c478bd9Sstevel@tonic-gate unsigned char mbuf[2049]; 6127c478bd9Sstevel@tonic-gate unsigned char *ccursor = cursor; 6137c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC 6147c478bd9Sstevel@tonic-gate int tmp, length; 6157c478bd9Sstevel@tonic-gate wchar_t wchar; 6167c478bd9Sstevel@tonic-gate #else 6177c478bd9Sstevel@tonic-gate int tmp, len, n; 6187c478bd9Sstevel@tonic-gate wchar_t wc; 6197c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 6207c478bd9Sstevel@tonic-gate unsigned char tmp1; 6217c478bd9Sstevel@tonic-gate setLAST(); 6227c478bd9Sstevel@tonic-gate for (tmp = 0; tmp + 3 < 2048; ) { 6237c478bd9Sstevel@tonic-gate /* 6247c478bd9Sstevel@tonic-gate * Use multiple 'r' commands to replace 6257c478bd9Sstevel@tonic-gate * alpha with alternate case. 6267c478bd9Sstevel@tonic-gate */ 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate if(cnt-- <= 0) 6297c478bd9Sstevel@tonic-gate break; 6307c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC 6317c478bd9Sstevel@tonic-gate length = mbtowc(&wchar, (char *)ccursor, MULTI_BYTE_MAX); 6327c478bd9Sstevel@tonic-gate #else 6337c478bd9Sstevel@tonic-gate len = mbtowc(&wc, (char *)ccursor, MULTI_BYTE_MAX); 6347c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 6357c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC 6367c478bd9Sstevel@tonic-gate if(length > 1) { 6377c478bd9Sstevel@tonic-gate #else 6387c478bd9Sstevel@tonic-gate n = iswalpha(wc); 6397c478bd9Sstevel@tonic-gate if(len > 1 && !iswalpha(wc)) { 6407c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 6417c478bd9Sstevel@tonic-gate mbuf[tmp+0] = ' '; 6427c478bd9Sstevel@tonic-gate tmp++; 6437c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC 6447c478bd9Sstevel@tonic-gate ccursor += length; 6457c478bd9Sstevel@tonic-gate #else 6467c478bd9Sstevel@tonic-gate ccursor += len; 6477c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 6487c478bd9Sstevel@tonic-gate continue; 6497c478bd9Sstevel@tonic-gate } 6507c478bd9Sstevel@tonic-gate mbuf[tmp] = 'r'; 6517c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC 6527c478bd9Sstevel@tonic-gate mbuf[tmp+1] = *ccursor++; 6537c478bd9Sstevel@tonic-gate #else 6547c478bd9Sstevel@tonic-gate ccursor += ((len > 0) ? len : 1); 6557c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 6567c478bd9Sstevel@tonic-gate /* 6577c478bd9Sstevel@tonic-gate * If pointing to an alpha character, 6587c478bd9Sstevel@tonic-gate * change the case. 6597c478bd9Sstevel@tonic-gate */ 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate tmp1 = mbuf[tmp+1]; 6627c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC 6637c478bd9Sstevel@tonic-gate if (isupper((unsigned char)tmp1)) 6647c478bd9Sstevel@tonic-gate mbuf[tmp+1] = tolower((unsigned char)tmp1); 6657c478bd9Sstevel@tonic-gate else 6667c478bd9Sstevel@tonic-gate mbuf[tmp+1] = toupper((unsigned char)tmp1); 6677c478bd9Sstevel@tonic-gate #else 6687c478bd9Sstevel@tonic-gate if (iswupper(wc)) 6697c478bd9Sstevel@tonic-gate len = wctomb((char *)(mbuf + tmp + 1), 6707c478bd9Sstevel@tonic-gate (wc = towlower(wc))); 6717c478bd9Sstevel@tonic-gate else 6727c478bd9Sstevel@tonic-gate len = wctomb((char *)(mbuf + tmp + 1), 6737c478bd9Sstevel@tonic-gate (wc = towupper(wc))); 6747c478bd9Sstevel@tonic-gate tmp += len - 1; 6757c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 6767c478bd9Sstevel@tonic-gate if(*ccursor) 6777c478bd9Sstevel@tonic-gate /* 6787c478bd9Sstevel@tonic-gate * If at end of line do not advance 6797c478bd9Sstevel@tonic-gate * to the next character, else use a 6807c478bd9Sstevel@tonic-gate * space to advance 1 column. 6817c478bd9Sstevel@tonic-gate */ 6827c478bd9Sstevel@tonic-gate mbuf[tmp+2] = ' '; 6837c478bd9Sstevel@tonic-gate else { 6847c478bd9Sstevel@tonic-gate mbuf[tmp+2] = '\0'; 6857c478bd9Sstevel@tonic-gate tmp +=3; 6867c478bd9Sstevel@tonic-gate break; 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate tmp += 3; 6897c478bd9Sstevel@tonic-gate } 6907c478bd9Sstevel@tonic-gate 6917c478bd9Sstevel@tonic-gate mbuf[tmp] = 0; 6927c478bd9Sstevel@tonic-gate macpush(mbuf, 1); 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate continue; 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate 6977c478bd9Sstevel@tonic-gate /* 6987c478bd9Sstevel@tonic-gate * A Append at end of line, short for $a. 6997c478bd9Sstevel@tonic-gate */ 7007c478bd9Sstevel@tonic-gate case 'A': 7017c478bd9Sstevel@tonic-gate operate('$', 1); 7027c478bd9Sstevel@tonic-gate appnd: 7037c478bd9Sstevel@tonic-gate c = 'a'; 7047c478bd9Sstevel@tonic-gate /* fall into ... */ 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate /* 7077c478bd9Sstevel@tonic-gate * a Appends text after cursor. Text can continue 7087c478bd9Sstevel@tonic-gate * through arbitrary number of lines. 7097c478bd9Sstevel@tonic-gate */ 7107c478bd9Sstevel@tonic-gate case 'a': 7117c478bd9Sstevel@tonic-gate if (*cursor) { 7127c478bd9Sstevel@tonic-gate wchar_t wchar; 7137c478bd9Sstevel@tonic-gate int length = mbtowc(&wchar, (char *)cursor, MULTI_BYTE_MAX); 7147c478bd9Sstevel@tonic-gate if (state == HARDOPEN) { 7157c478bd9Sstevel@tonic-gate if(length < 0) { 7167c478bd9Sstevel@tonic-gate putoctal = 1; 7177c478bd9Sstevel@tonic-gate putchar(*cursor); 7187c478bd9Sstevel@tonic-gate putoctal = 0; 7197c478bd9Sstevel@tonic-gate } else 7207c478bd9Sstevel@tonic-gate putchar(wchar); 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate if(length < 0) 7237c478bd9Sstevel@tonic-gate cursor++; 7247c478bd9Sstevel@tonic-gate else 7257c478bd9Sstevel@tonic-gate cursor += length; 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate goto insrt; 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate /* 7307c478bd9Sstevel@tonic-gate * I Insert at beginning of whitespace of line, 7317c478bd9Sstevel@tonic-gate * short for ^i. 7327c478bd9Sstevel@tonic-gate */ 7337c478bd9Sstevel@tonic-gate case 'I': 7347c478bd9Sstevel@tonic-gate operate('^', 1); 7357c478bd9Sstevel@tonic-gate c = 'i'; 7367c478bd9Sstevel@tonic-gate /* fall into ... */ 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate /* 7397c478bd9Sstevel@tonic-gate * R Replace characters, one for one, by input 7407c478bd9Sstevel@tonic-gate * (logically), like repeated r commands. 7417c478bd9Sstevel@tonic-gate * 7427c478bd9Sstevel@tonic-gate * BUG: This is like the typeover mode of many other 7437c478bd9Sstevel@tonic-gate * editors, and is only rarely useful. Its 7447c478bd9Sstevel@tonic-gate * implementation is a hack in a low level 7457c478bd9Sstevel@tonic-gate * routine and it doesn't work very well, e.g. 7467c478bd9Sstevel@tonic-gate * you can't move around within a R, etc. 7477c478bd9Sstevel@tonic-gate */ 7487c478bd9Sstevel@tonic-gate case 'R': 7497c478bd9Sstevel@tonic-gate /* fall into... */ 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate /* 7527c478bd9Sstevel@tonic-gate * i Insert text to an escape in the buffer. 7537c478bd9Sstevel@tonic-gate * Text is arbitrary. This command reminds of 7547c478bd9Sstevel@tonic-gate * the i command in bare teco. 7557c478bd9Sstevel@tonic-gate */ 7567c478bd9Sstevel@tonic-gate case 'i': 7577c478bd9Sstevel@tonic-gate insrt: 7587c478bd9Sstevel@tonic-gate /* 7597c478bd9Sstevel@tonic-gate * Common code for all the insertion commands. 7607c478bd9Sstevel@tonic-gate * Save for redo, position cursor, prepare for append 7617c478bd9Sstevel@tonic-gate * at command and in visual undo. Note that nothing 7627c478bd9Sstevel@tonic-gate * is doomed, unless R when all is, and save the 7637c478bd9Sstevel@tonic-gate * current line in a the undo temporary buffer. 7647c478bd9Sstevel@tonic-gate */ 7657c478bd9Sstevel@tonic-gate vmacchng(1); 7667c478bd9Sstevel@tonic-gate setLAST(); 7677c478bd9Sstevel@tonic-gate vcursat(cursor); 7687c478bd9Sstevel@tonic-gate prepapp(); 7697c478bd9Sstevel@tonic-gate vnoapp(); 7707c478bd9Sstevel@tonic-gate doomed = c == 'R' ? 10000 : 0; 7717c478bd9Sstevel@tonic-gate if(FIXUNDO) 7727c478bd9Sstevel@tonic-gate vundkind = VCHNG; 7737c478bd9Sstevel@tonic-gate vmoving = 0; 7747c478bd9Sstevel@tonic-gate CP(vutmp, linebuf); 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate /* 7777c478bd9Sstevel@tonic-gate * If this is a repeated command, then suppress 7787c478bd9Sstevel@tonic-gate * fake insert mode on dumb terminals which looks 7797c478bd9Sstevel@tonic-gate * ridiculous and wastes lots of time even at 9600B. 7807c478bd9Sstevel@tonic-gate */ 7817c478bd9Sstevel@tonic-gate if (vglobp) 7827c478bd9Sstevel@tonic-gate hold = HOLDQIK; 7837c478bd9Sstevel@tonic-gate vappend(c, cnt, 0); 7847c478bd9Sstevel@tonic-gate continue; 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate /* 7877c478bd9Sstevel@tonic-gate * An attention, normally a DEL, just beeps. 7887c478bd9Sstevel@tonic-gate * If you are a vi command within ex, then 7897c478bd9Sstevel@tonic-gate * two ATTN's will drop you back to command mode. 7907c478bd9Sstevel@tonic-gate */ 7917c478bd9Sstevel@tonic-gate case ATTN: 792f6db9f27Scf46844 (void) beep(); 7937c478bd9Sstevel@tonic-gate if (initev || peekkey() != ATTN) 7947c478bd9Sstevel@tonic-gate continue; 7957c478bd9Sstevel@tonic-gate /* fall into... */ 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate /* 7987c478bd9Sstevel@tonic-gate * ^\ A quit always gets command mode. 7997c478bd9Sstevel@tonic-gate */ 8007c478bd9Sstevel@tonic-gate case QUIT: 8017c478bd9Sstevel@tonic-gate /* 8027c478bd9Sstevel@tonic-gate * Have to be careful if we were called 8037c478bd9Sstevel@tonic-gate * g/xxx/vi 8047c478bd9Sstevel@tonic-gate * since a return will just start up again. 8057c478bd9Sstevel@tonic-gate * So we simulate an interrupt. 8067c478bd9Sstevel@tonic-gate */ 8077c478bd9Sstevel@tonic-gate if (inglobal) 8087c478bd9Sstevel@tonic-gate onintr(0); 8097c478bd9Sstevel@tonic-gate /* fall into... */ 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate #ifdef notdef 8127c478bd9Sstevel@tonic-gate /* 8137c478bd9Sstevel@tonic-gate * q Quit back to command mode, unless called as 8147c478bd9Sstevel@tonic-gate * vi on command line in which case dont do it 8157c478bd9Sstevel@tonic-gate */ 8167c478bd9Sstevel@tonic-gate case 'q': /* quit */ 8177c478bd9Sstevel@tonic-gate if (initev) { 8187c478bd9Sstevel@tonic-gate vsave(); 8197c478bd9Sstevel@tonic-gate CATCH 8207c478bd9Sstevel@tonic-gate error(gettext("Q gets ex command mode, :q leaves vi")); 8217c478bd9Sstevel@tonic-gate ENDCATCH 8227c478bd9Sstevel@tonic-gate splitw = 0; 8237c478bd9Sstevel@tonic-gate getDOT(); 8247c478bd9Sstevel@tonic-gate vrepaint(cursor); 8257c478bd9Sstevel@tonic-gate continue; 8267c478bd9Sstevel@tonic-gate } 8277c478bd9Sstevel@tonic-gate #endif 8287c478bd9Sstevel@tonic-gate /* fall into... */ 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate /* 8317c478bd9Sstevel@tonic-gate * Q Is like q, but always gets to command mode 8327c478bd9Sstevel@tonic-gate * even if command line invocation was as vi. 8337c478bd9Sstevel@tonic-gate */ 8347c478bd9Sstevel@tonic-gate case 'Q': 8357c478bd9Sstevel@tonic-gate vsave(); 8367c478bd9Sstevel@tonic-gate /* 8377c478bd9Sstevel@tonic-gate * If we are in the middle of a macro, throw away 8387c478bd9Sstevel@tonic-gate * the rest and fix up undo. 8397c478bd9Sstevel@tonic-gate * This code copied from getbr(). 8407c478bd9Sstevel@tonic-gate */ 8417c478bd9Sstevel@tonic-gate if (vmacp) { 8427c478bd9Sstevel@tonic-gate vmacp = 0; 8437c478bd9Sstevel@tonic-gate if (inopen == -1) /* don't mess up undo for esc esc */ 8447c478bd9Sstevel@tonic-gate vundkind = VMANY; 8457c478bd9Sstevel@tonic-gate inopen = 1; /* restore old setting now that macro done */ 8467c478bd9Sstevel@tonic-gate } 8477c478bd9Sstevel@tonic-gate ixlatctl(1); 8487c478bd9Sstevel@tonic-gate return; 8497c478bd9Sstevel@tonic-gate 8507c478bd9Sstevel@tonic-gate 8517c478bd9Sstevel@tonic-gate /* 8527c478bd9Sstevel@tonic-gate * ZZ Like :x 8537c478bd9Sstevel@tonic-gate */ 8547c478bd9Sstevel@tonic-gate case 'Z': 8557c478bd9Sstevel@tonic-gate forbid(getkey() != 'Z'); 8567c478bd9Sstevel@tonic-gate oglobp = globp; 8577c478bd9Sstevel@tonic-gate globp = (unsigned char *)"x"; 8587c478bd9Sstevel@tonic-gate vclrech(0); 8597c478bd9Sstevel@tonic-gate goto gogo; 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate /* 8627c478bd9Sstevel@tonic-gate * P Put back text before cursor or before current 8637c478bd9Sstevel@tonic-gate * line. If text was whole lines goes back 8647c478bd9Sstevel@tonic-gate * as whole lines. If part of a single line 8657c478bd9Sstevel@tonic-gate * or parts of whole lines splits up current 8667c478bd9Sstevel@tonic-gate * line to form many new lines. 8677c478bd9Sstevel@tonic-gate * May specify a named buffer, or the delete 8687c478bd9Sstevel@tonic-gate * saving buffers 1-9. 8697c478bd9Sstevel@tonic-gate * 8707c478bd9Sstevel@tonic-gate * p Like P but after rather than before. 8717c478bd9Sstevel@tonic-gate */ 8727c478bd9Sstevel@tonic-gate case 'P': 8737c478bd9Sstevel@tonic-gate case 'p': 8747c478bd9Sstevel@tonic-gate vmoving = 0; 8757c478bd9Sstevel@tonic-gate #ifdef XPG4 8767c478bd9Sstevel@tonic-gate P_cursor_offset = 0; 8777c478bd9Sstevel@tonic-gate #endif 8787c478bd9Sstevel@tonic-gate #ifdef notdef 8797c478bd9Sstevel@tonic-gate forbid (!vreg && value(vi_UNDOMACRO) && inopen < 0); 8807c478bd9Sstevel@tonic-gate #endif 8817c478bd9Sstevel@tonic-gate /* 8827c478bd9Sstevel@tonic-gate * If previous delete was partial line, use an 8837c478bd9Sstevel@tonic-gate * append or insert to put it back so as to 8847c478bd9Sstevel@tonic-gate * use insert mode on intelligent terminals. 8857c478bd9Sstevel@tonic-gate */ 8867c478bd9Sstevel@tonic-gate if (!vreg && DEL[0]) { 8877c478bd9Sstevel@tonic-gate setLAST(); 8887c478bd9Sstevel@tonic-gate forbid ((unsigned char)DEL[128] == 0200); 8897c478bd9Sstevel@tonic-gate vglobp = DEL; 8907c478bd9Sstevel@tonic-gate ungetkey(c == 'p' ? 'a' : 'i'); 8917c478bd9Sstevel@tonic-gate goto reread; 8927c478bd9Sstevel@tonic-gate } 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate /* 8957c478bd9Sstevel@tonic-gate * If a register wasn't specified, then make 8967c478bd9Sstevel@tonic-gate * sure there is something to put back. 8977c478bd9Sstevel@tonic-gate */ 8987c478bd9Sstevel@tonic-gate forbid (!vreg && unddol == dol); 8997c478bd9Sstevel@tonic-gate /* 9007c478bd9Sstevel@tonic-gate * If we just did a macro the whole buffer is in 9017c478bd9Sstevel@tonic-gate * the undo save area. We don't want to put THAT. 9027c478bd9Sstevel@tonic-gate */ 9037c478bd9Sstevel@tonic-gate forbid (vundkind == VMANY && undkind==UNDALL); 9047c478bd9Sstevel@tonic-gate vsave(); 9057c478bd9Sstevel@tonic-gate vmacchng(1); 9067c478bd9Sstevel@tonic-gate setLAST(); 9077c478bd9Sstevel@tonic-gate i = 0; 9087c478bd9Sstevel@tonic-gate if (vreg && partreg(vreg) || !vreg && pkill[0]) { 9097c478bd9Sstevel@tonic-gate /* 9107c478bd9Sstevel@tonic-gate * Restoring multiple lines which were partial 9117c478bd9Sstevel@tonic-gate * lines; will leave cursor in middle 9127c478bd9Sstevel@tonic-gate * of line after shoving restored text in to 9137c478bd9Sstevel@tonic-gate * split the current line. 9147c478bd9Sstevel@tonic-gate */ 9157c478bd9Sstevel@tonic-gate i++; 9167c478bd9Sstevel@tonic-gate if (c == 'p' && *cursor) 9177c478bd9Sstevel@tonic-gate cursor = nextchr(cursor); 9187c478bd9Sstevel@tonic-gate } else { 9197c478bd9Sstevel@tonic-gate /* 9207c478bd9Sstevel@tonic-gate * In whole line case, have to back up dot 9217c478bd9Sstevel@tonic-gate * for P; also want to clear cursor so 9227c478bd9Sstevel@tonic-gate * cursor will eventually be positioned 9237c478bd9Sstevel@tonic-gate * at the beginning of the first put line. 9247c478bd9Sstevel@tonic-gate */ 9257c478bd9Sstevel@tonic-gate cursor = 0; 9267c478bd9Sstevel@tonic-gate if (c == 'P') { 9277c478bd9Sstevel@tonic-gate dot--, vcline--; 9287c478bd9Sstevel@tonic-gate c = 'p'; 9297c478bd9Sstevel@tonic-gate } 9307c478bd9Sstevel@tonic-gate } 9317c478bd9Sstevel@tonic-gate killU(); 9327c478bd9Sstevel@tonic-gate 9337c478bd9Sstevel@tonic-gate /* 9347c478bd9Sstevel@tonic-gate * The call to putreg can potentially 9357c478bd9Sstevel@tonic-gate * bomb since there may be nothing in a named buffer. 9367c478bd9Sstevel@tonic-gate * We thus put a catch in here. If we didn't and 9377c478bd9Sstevel@tonic-gate * there was an error we would end up in command mode. 9387c478bd9Sstevel@tonic-gate */ 9397c478bd9Sstevel@tonic-gate addr = dol; /* old dol */ 9407c478bd9Sstevel@tonic-gate CATCH 941f6db9f27Scf46844 vremote(1, 942f6db9f27Scf46844 vreg ? (int (*)())putreg : put, vreg); 9437c478bd9Sstevel@tonic-gate ONERR 9447c478bd9Sstevel@tonic-gate if (vreg == -1) { 9457c478bd9Sstevel@tonic-gate splitw = 0; 9467c478bd9Sstevel@tonic-gate if (op == 'P') 9477c478bd9Sstevel@tonic-gate dot++, vcline++; 9487c478bd9Sstevel@tonic-gate goto pfixup; 9497c478bd9Sstevel@tonic-gate } 9507c478bd9Sstevel@tonic-gate ENDCATCH 9517c478bd9Sstevel@tonic-gate splitw = 0; 9527c478bd9Sstevel@tonic-gate nlput = dol - addr + 1; 9537c478bd9Sstevel@tonic-gate if (!i) { 9547c478bd9Sstevel@tonic-gate /* 9557c478bd9Sstevel@tonic-gate * Increment undap1, undap2 to make up 9567c478bd9Sstevel@tonic-gate * for their incorrect initialization in the 9577c478bd9Sstevel@tonic-gate * routine vremote before calling put/putreg. 9587c478bd9Sstevel@tonic-gate */ 9597c478bd9Sstevel@tonic-gate if (FIXUNDO) 9607c478bd9Sstevel@tonic-gate undap1++, undap2++; 9617c478bd9Sstevel@tonic-gate vcline++; 9627c478bd9Sstevel@tonic-gate nlput--; 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate /* 9657c478bd9Sstevel@tonic-gate * After a put want current line first line, 9667c478bd9Sstevel@tonic-gate * and dot was made the last line put in code 9677c478bd9Sstevel@tonic-gate * run so far. This is why we increment vcline 9687c478bd9Sstevel@tonic-gate * above and decrease dot here. 9697c478bd9Sstevel@tonic-gate */ 9707c478bd9Sstevel@tonic-gate dot -= nlput - 1; 9717c478bd9Sstevel@tonic-gate } 9727c478bd9Sstevel@tonic-gate #ifdef TRACE 9737c478bd9Sstevel@tonic-gate if (trace) 9747c478bd9Sstevel@tonic-gate fprintf(trace, "vreplace(%d, %d, %d), undap1=%d, undap2=%d, dot=%d\n", vcline, i, nlput, lineno(undap1), lineno(undap2), lineno(dot)); 9757c478bd9Sstevel@tonic-gate #endif 9767c478bd9Sstevel@tonic-gate vreplace(vcline, i, nlput); 9777c478bd9Sstevel@tonic-gate #ifdef XPG4 9787c478bd9Sstevel@tonic-gate if (op == 'P' && i > 0) { 9797c478bd9Sstevel@tonic-gate dot += nlput - 1; 9807c478bd9Sstevel@tonic-gate vcline += nlput - 1; 9817c478bd9Sstevel@tonic-gate cursor += P_cursor_offset; 9827c478bd9Sstevel@tonic-gate } 9837c478bd9Sstevel@tonic-gate #endif 9847c478bd9Sstevel@tonic-gate if (state != VISUAL) { 9857c478bd9Sstevel@tonic-gate /* 9867c478bd9Sstevel@tonic-gate * Special case in open mode. 9877c478bd9Sstevel@tonic-gate * Force action on the screen when a single 9887c478bd9Sstevel@tonic-gate * line is put even if it is identical to 9897c478bd9Sstevel@tonic-gate * the current line, e.g. on YP; otherwise 9907c478bd9Sstevel@tonic-gate * you can't tell anything happened. 9917c478bd9Sstevel@tonic-gate */ 9927c478bd9Sstevel@tonic-gate vjumpto(dot, cursor, '.'); 9937c478bd9Sstevel@tonic-gate continue; 9947c478bd9Sstevel@tonic-gate } 9957c478bd9Sstevel@tonic-gate pfixup: 9967c478bd9Sstevel@tonic-gate vrepaint(cursor); 9977c478bd9Sstevel@tonic-gate vfixcurs(); 9987c478bd9Sstevel@tonic-gate continue; 9997c478bd9Sstevel@tonic-gate 10007c478bd9Sstevel@tonic-gate /* 10017c478bd9Sstevel@tonic-gate * ^^ Return to previous file. 10027c478bd9Sstevel@tonic-gate * Like a :e #, and thus can be used after a 10037c478bd9Sstevel@tonic-gate * "No Write" diagnostic. 10047c478bd9Sstevel@tonic-gate */ 10057c478bd9Sstevel@tonic-gate case CTRL('^'): 10067c478bd9Sstevel@tonic-gate forbid (hadcnt); 10077c478bd9Sstevel@tonic-gate vsave(); 10087c478bd9Sstevel@tonic-gate ckaw(); 10097c478bd9Sstevel@tonic-gate oglobp = globp; 10107c478bd9Sstevel@tonic-gate if (value(vi_AUTOWRITE) && !value(vi_READONLY)) 10117c478bd9Sstevel@tonic-gate globp = (unsigned char *)"e! #"; 10127c478bd9Sstevel@tonic-gate else 10137c478bd9Sstevel@tonic-gate globp = (unsigned char *)"e #"; 10147c478bd9Sstevel@tonic-gate goto gogo; 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate #ifdef TAG_STACK 10177c478bd9Sstevel@tonic-gate /* 10187c478bd9Sstevel@tonic-gate * ^T Pop the tag stack if enabled or else reset it 10197c478bd9Sstevel@tonic-gate * if not. 10207c478bd9Sstevel@tonic-gate */ 10217c478bd9Sstevel@tonic-gate case CTRL('t'): 10227c478bd9Sstevel@tonic-gate forbid (hadcnt); 10237c478bd9Sstevel@tonic-gate vsave(); 10247c478bd9Sstevel@tonic-gate oglobp = globp; 10257c478bd9Sstevel@tonic-gate globp = (unsigned char *) "pop"; 10267c478bd9Sstevel@tonic-gate goto gogo; 10277c478bd9Sstevel@tonic-gate #endif 10287c478bd9Sstevel@tonic-gate /* 10297c478bd9Sstevel@tonic-gate * ^] Takes word after cursor as tag, and then does 10307c478bd9Sstevel@tonic-gate * tag command. Read ``go right to''. 10317c478bd9Sstevel@tonic-gate * This is not a search, so the wrapscan setting 10327c478bd9Sstevel@tonic-gate * must be ignored. If set, then it is unset 10337c478bd9Sstevel@tonic-gate * here and restored later. 10347c478bd9Sstevel@tonic-gate */ 10357c478bd9Sstevel@tonic-gate case CTRL(']'): 10367c478bd9Sstevel@tonic-gate grabtag(); 10377c478bd9Sstevel@tonic-gate oglobp = globp; 10387c478bd9Sstevel@tonic-gate if (value(vi_WRAPSCAN) == 0) { 10397c478bd9Sstevel@tonic-gate tag_reset_wrap = 1; 10407c478bd9Sstevel@tonic-gate value(vi_WRAPSCAN) = 1; 10417c478bd9Sstevel@tonic-gate } 10427c478bd9Sstevel@tonic-gate globp = (unsigned char *)"tag"; 10437c478bd9Sstevel@tonic-gate goto gogo; 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate /* 10467c478bd9Sstevel@tonic-gate * & Like :& 10477c478bd9Sstevel@tonic-gate */ 10487c478bd9Sstevel@tonic-gate case '&': 10497c478bd9Sstevel@tonic-gate oglobp = globp; 10507c478bd9Sstevel@tonic-gate globp = (unsigned char *)"&"; 10517c478bd9Sstevel@tonic-gate goto gogo; 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate /* 10547c478bd9Sstevel@tonic-gate * ^G Bring up a status line at the bottom of 10557c478bd9Sstevel@tonic-gate * the screen, like a :file command. 10567c478bd9Sstevel@tonic-gate * 10577c478bd9Sstevel@tonic-gate * BUG: Was ^S but doesn't work in cbreak mode 10587c478bd9Sstevel@tonic-gate */ 10597c478bd9Sstevel@tonic-gate case CTRL('g'): 10607c478bd9Sstevel@tonic-gate oglobp = globp; 10617c478bd9Sstevel@tonic-gate globp = (unsigned char *)"file"; 10627c478bd9Sstevel@tonic-gate gogo: 10637c478bd9Sstevel@tonic-gate addr = dot; 10647c478bd9Sstevel@tonic-gate vsave(); 10657c478bd9Sstevel@tonic-gate goto doinit; 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate #ifdef SIGTSTP 10687c478bd9Sstevel@tonic-gate /* 10697c478bd9Sstevel@tonic-gate * ^Z: suspend editor session and temporarily return 10707c478bd9Sstevel@tonic-gate * to shell. Only works with Berkeley/IIASA process 10717c478bd9Sstevel@tonic-gate * control in kernel. 10727c478bd9Sstevel@tonic-gate */ 10737c478bd9Sstevel@tonic-gate case CTRL('z'): 10747c478bd9Sstevel@tonic-gate forbid(dosusp == 0); 10757c478bd9Sstevel@tonic-gate vsave(); 10767c478bd9Sstevel@tonic-gate oglobp = globp; 10777c478bd9Sstevel@tonic-gate globp = (unsigned char *)"stop"; 10787c478bd9Sstevel@tonic-gate goto gogo; 10797c478bd9Sstevel@tonic-gate #endif 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate /* 10827c478bd9Sstevel@tonic-gate * : Read a command from the echo area and 10837c478bd9Sstevel@tonic-gate * execute it in command mode. 10847c478bd9Sstevel@tonic-gate */ 10857c478bd9Sstevel@tonic-gate case ':': 10867c478bd9Sstevel@tonic-gate forbid (hadcnt); 10877c478bd9Sstevel@tonic-gate vsave(); 10887c478bd9Sstevel@tonic-gate i = tchng; 10897c478bd9Sstevel@tonic-gate addr = dot; 10907c478bd9Sstevel@tonic-gate if (readecho(c)) { 10917c478bd9Sstevel@tonic-gate esave[0] = 0; 10927c478bd9Sstevel@tonic-gate goto fixup; 10937c478bd9Sstevel@tonic-gate } 10947c478bd9Sstevel@tonic-gate getDOT(); 10957c478bd9Sstevel@tonic-gate /* 10967c478bd9Sstevel@tonic-gate * Use the visual undo buffer to store the global 10977c478bd9Sstevel@tonic-gate * string for command mode, since it is idle right now. 10987c478bd9Sstevel@tonic-gate */ 10997c478bd9Sstevel@tonic-gate oglobp = globp; strcpy(vutmp, genbuf+1); globp = vutmp; 11007c478bd9Sstevel@tonic-gate doinit: 11017c478bd9Sstevel@tonic-gate esave[0] = 0; 11027c478bd9Sstevel@tonic-gate fixech(); 11037c478bd9Sstevel@tonic-gate 11047c478bd9Sstevel@tonic-gate /* 11057c478bd9Sstevel@tonic-gate * Have to finagle around not to lose last 11067c478bd9Sstevel@tonic-gate * character after this command (when run from ex 11077c478bd9Sstevel@tonic-gate * command mode). This is clumsy. 11087c478bd9Sstevel@tonic-gate */ 11097c478bd9Sstevel@tonic-gate d = peekc; ungetchar(0); 11107c478bd9Sstevel@tonic-gate if (shouldpo) { 11117c478bd9Sstevel@tonic-gate /* 11127c478bd9Sstevel@tonic-gate * So after a "Hit return..." ":", we do 11137c478bd9Sstevel@tonic-gate * another "Hit return..." the next time 11147c478bd9Sstevel@tonic-gate */ 11157c478bd9Sstevel@tonic-gate pofix(); 11167c478bd9Sstevel@tonic-gate shouldpo = 0; 11177c478bd9Sstevel@tonic-gate } 11187c478bd9Sstevel@tonic-gate CATCH 11197c478bd9Sstevel@tonic-gate /* 11207c478bd9Sstevel@tonic-gate * Save old values of options so we can 11217c478bd9Sstevel@tonic-gate * notice when they change; switch into 11227c478bd9Sstevel@tonic-gate * cooked mode so we are interruptible. 11237c478bd9Sstevel@tonic-gate */ 11247c478bd9Sstevel@tonic-gate onumber = value(vi_NUMBER); 11257c478bd9Sstevel@tonic-gate olist = value(vi_LIST); 11267c478bd9Sstevel@tonic-gate OPline = Pline; 11277c478bd9Sstevel@tonic-gate OPutchar = Putchar; 11287c478bd9Sstevel@tonic-gate #ifndef CBREAK 11297c478bd9Sstevel@tonic-gate vcook(); 11307c478bd9Sstevel@tonic-gate #endif 11317c478bd9Sstevel@tonic-gate commands(1, 1); 11327c478bd9Sstevel@tonic-gate if (dot == zero && dol > zero) 11337c478bd9Sstevel@tonic-gate dot = one; 11347c478bd9Sstevel@tonic-gate #ifndef CBREAK 11357c478bd9Sstevel@tonic-gate vraw(); 11367c478bd9Sstevel@tonic-gate #endif 11377c478bd9Sstevel@tonic-gate ONERR 11387c478bd9Sstevel@tonic-gate #ifndef CBREAK 11397c478bd9Sstevel@tonic-gate vraw(); 11407c478bd9Sstevel@tonic-gate #endif 11417c478bd9Sstevel@tonic-gate copy(esave, vtube[WECHO], TUBECOLS * sizeof(wchar_t)); 11427c478bd9Sstevel@tonic-gate ENDCATCH 11437c478bd9Sstevel@tonic-gate fixol(); 11447c478bd9Sstevel@tonic-gate Pline = OPline; 11457c478bd9Sstevel@tonic-gate Putchar = OPutchar; 11467c478bd9Sstevel@tonic-gate ungetchar(d); 11477c478bd9Sstevel@tonic-gate globp = oglobp; 11487c478bd9Sstevel@tonic-gate 11497c478bd9Sstevel@tonic-gate /* 11507c478bd9Sstevel@tonic-gate * If we ended up with no lines in the buffer, make 11517c478bd9Sstevel@tonic-gate * a line. 11527c478bd9Sstevel@tonic-gate */ 11537c478bd9Sstevel@tonic-gate if (dot == zero) { 11547c478bd9Sstevel@tonic-gate fixzero(); 11557c478bd9Sstevel@tonic-gate } 11567c478bd9Sstevel@tonic-gate splitw = 0; 11577c478bd9Sstevel@tonic-gate 11587c478bd9Sstevel@tonic-gate /* 11597c478bd9Sstevel@tonic-gate * Special case: did list/number options change? 11607c478bd9Sstevel@tonic-gate */ 11617c478bd9Sstevel@tonic-gate if (onumber != value(vi_NUMBER)) 11627c478bd9Sstevel@tonic-gate setnumb(value(vi_NUMBER)); 11637c478bd9Sstevel@tonic-gate if (olist != value(vi_LIST)) 11647c478bd9Sstevel@tonic-gate setlist(value(vi_LIST)); 11657c478bd9Sstevel@tonic-gate 11667c478bd9Sstevel@tonic-gate fixup: 11677c478bd9Sstevel@tonic-gate /* 11687c478bd9Sstevel@tonic-gate * If a change occurred, other than 11697c478bd9Sstevel@tonic-gate * a write which clears changes, then 11707c478bd9Sstevel@tonic-gate * we should allow an undo even if . 11717c478bd9Sstevel@tonic-gate * didn't move. 11727c478bd9Sstevel@tonic-gate * 11737c478bd9Sstevel@tonic-gate * BUG: You can make this wrong by 11747c478bd9Sstevel@tonic-gate * tricking around with multiple commands 11757c478bd9Sstevel@tonic-gate * on one line of : escape, and including 11767c478bd9Sstevel@tonic-gate * a write command there, but it's not 11777c478bd9Sstevel@tonic-gate * worth worrying about. 11787c478bd9Sstevel@tonic-gate */ 11797c478bd9Sstevel@tonic-gate if (FIXUNDO && tchng && tchng != i) 11807c478bd9Sstevel@tonic-gate vundkind = VMANY, cursor = 0; 11817c478bd9Sstevel@tonic-gate 11827c478bd9Sstevel@tonic-gate /* 11837c478bd9Sstevel@tonic-gate * If we are about to do another :, hold off 11847c478bd9Sstevel@tonic-gate * updating of screen. 11857c478bd9Sstevel@tonic-gate */ 11867c478bd9Sstevel@tonic-gate if (vcnt < 0 && Peekkey == ':') { 11877c478bd9Sstevel@tonic-gate getDOT(); 11887c478bd9Sstevel@tonic-gate shouldpo = 1; 11897c478bd9Sstevel@tonic-gate continue; 11907c478bd9Sstevel@tonic-gate } 11917c478bd9Sstevel@tonic-gate shouldpo = 0; 11927c478bd9Sstevel@tonic-gate 11937c478bd9Sstevel@tonic-gate /* 11947c478bd9Sstevel@tonic-gate * In the case where the file being edited is 11957c478bd9Sstevel@tonic-gate * new; e.g. if the initial state hasn't been 11967c478bd9Sstevel@tonic-gate * saved yet, then do so now. 11977c478bd9Sstevel@tonic-gate */ 11987c478bd9Sstevel@tonic-gate if (unddol == truedol) { 11997c478bd9Sstevel@tonic-gate vundkind = VNONE; 12007c478bd9Sstevel@tonic-gate Vlines = lineDOL(); 12017c478bd9Sstevel@tonic-gate if (!inglobal) 12027c478bd9Sstevel@tonic-gate savevis(); 12037c478bd9Sstevel@tonic-gate addr = zero; 12047c478bd9Sstevel@tonic-gate vcnt = 0; 12057c478bd9Sstevel@tonic-gate if (esave[0] == 0) 12067c478bd9Sstevel@tonic-gate copy(esave, vtube[WECHO], TUBECOLS * sizeof(wchar_t)); 12077c478bd9Sstevel@tonic-gate } 12087c478bd9Sstevel@tonic-gate 12097c478bd9Sstevel@tonic-gate /* 12107c478bd9Sstevel@tonic-gate * If the current line moved reset the cursor position. 12117c478bd9Sstevel@tonic-gate */ 12127c478bd9Sstevel@tonic-gate if (dot != addr) { 12137c478bd9Sstevel@tonic-gate vmoving = 0; 12147c478bd9Sstevel@tonic-gate cursor = 0; 12157c478bd9Sstevel@tonic-gate } 12167c478bd9Sstevel@tonic-gate 12177c478bd9Sstevel@tonic-gate /* 12187c478bd9Sstevel@tonic-gate * If current line is not on screen or if we are 12197c478bd9Sstevel@tonic-gate * in open mode and . moved, then redraw. 12207c478bd9Sstevel@tonic-gate */ 12217c478bd9Sstevel@tonic-gate i = vcline + (dot - addr); 12227c478bd9Sstevel@tonic-gate if(windowchg) 12237c478bd9Sstevel@tonic-gate windowinit(); 12247c478bd9Sstevel@tonic-gate if (i < 0 || i >= vcnt && i >= -vcnt || state != VISUAL && dot != addr) { 12257c478bd9Sstevel@tonic-gate if (state == CRTOPEN) 12267c478bd9Sstevel@tonic-gate vup1(); 12277c478bd9Sstevel@tonic-gate if (vcnt > 0) 12287c478bd9Sstevel@tonic-gate vcnt = 0; 1229f6db9f27Scf46844 vjumpto(dot, (unsigned char *) 0, '.'); 12307c478bd9Sstevel@tonic-gate } else { 12317c478bd9Sstevel@tonic-gate /* 12327c478bd9Sstevel@tonic-gate * Current line IS on screen. 12337c478bd9Sstevel@tonic-gate * If we did a [Hit return...] then 12347c478bd9Sstevel@tonic-gate * restore vcnt and clear screen if in visual 12357c478bd9Sstevel@tonic-gate */ 12367c478bd9Sstevel@tonic-gate vcline = i; 12377c478bd9Sstevel@tonic-gate if (vcnt < 0) { 12387c478bd9Sstevel@tonic-gate vcnt = -vcnt; 12397c478bd9Sstevel@tonic-gate if (state == VISUAL) 12407c478bd9Sstevel@tonic-gate vclear(); 12417c478bd9Sstevel@tonic-gate else if (state == CRTOPEN) { 12427c478bd9Sstevel@tonic-gate vcnt = 0; 12437c478bd9Sstevel@tonic-gate } 12447c478bd9Sstevel@tonic-gate } 12457c478bd9Sstevel@tonic-gate 12467c478bd9Sstevel@tonic-gate /* 12477c478bd9Sstevel@tonic-gate * Limit max value of vcnt based on $ 12487c478bd9Sstevel@tonic-gate */ 12497c478bd9Sstevel@tonic-gate i = vcline + lineDOL() - lineDOT() + 1; 12507c478bd9Sstevel@tonic-gate if (i < vcnt) 12517c478bd9Sstevel@tonic-gate vcnt = i; 12527c478bd9Sstevel@tonic-gate 12537c478bd9Sstevel@tonic-gate /* 12547c478bd9Sstevel@tonic-gate * Dirty and repaint. 12557c478bd9Sstevel@tonic-gate */ 12567c478bd9Sstevel@tonic-gate vdirty(0, lines); 12577c478bd9Sstevel@tonic-gate vrepaint(cursor); 12587c478bd9Sstevel@tonic-gate } 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate /* 12617c478bd9Sstevel@tonic-gate * If in visual, put back the echo area 12627c478bd9Sstevel@tonic-gate * if it was clobbered. 12637c478bd9Sstevel@tonic-gate */ 12647c478bd9Sstevel@tonic-gate if (state == VISUAL) { 12657c478bd9Sstevel@tonic-gate int sdc = destcol, sdl = destline; 12667c478bd9Sstevel@tonic-gate 12677c478bd9Sstevel@tonic-gate splitw++; 12687c478bd9Sstevel@tonic-gate vigoto(WECHO, 0); 12697c478bd9Sstevel@tonic-gate for (i = 0; i < TUBECOLS - 1; i++) { 12707c478bd9Sstevel@tonic-gate if (esave[i] == 0) 12717c478bd9Sstevel@tonic-gate break; 12727c478bd9Sstevel@tonic-gate if(esave[i] != FILLER) 1273f6db9f27Scf46844 (void) vputchar(esave[i]); 12747c478bd9Sstevel@tonic-gate } 12757c478bd9Sstevel@tonic-gate splitw = 0; 12767c478bd9Sstevel@tonic-gate vgoto(sdl, sdc); 12777c478bd9Sstevel@tonic-gate } 12787c478bd9Sstevel@tonic-gate if (tag_reset_wrap == 1) { 12797c478bd9Sstevel@tonic-gate tag_reset_wrap = 0; 12807c478bd9Sstevel@tonic-gate value(vi_WRAPSCAN) = 0; 12817c478bd9Sstevel@tonic-gate } 12827c478bd9Sstevel@tonic-gate continue; 12837c478bd9Sstevel@tonic-gate 12847c478bd9Sstevel@tonic-gate /* 12857c478bd9Sstevel@tonic-gate * u undo the last changing command. 12867c478bd9Sstevel@tonic-gate */ 12877c478bd9Sstevel@tonic-gate case 'u': 12887c478bd9Sstevel@tonic-gate vundo(1); 12897c478bd9Sstevel@tonic-gate continue; 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate /* 12927c478bd9Sstevel@tonic-gate * U restore current line to initial state. 12937c478bd9Sstevel@tonic-gate */ 12947c478bd9Sstevel@tonic-gate case 'U': 12957c478bd9Sstevel@tonic-gate vUndo(); 12967c478bd9Sstevel@tonic-gate continue; 12977c478bd9Sstevel@tonic-gate 12987c478bd9Sstevel@tonic-gate fonfon: 1299f6db9f27Scf46844 (void) beep(); 13007c478bd9Sstevel@tonic-gate vmacp = 0; 13017c478bd9Sstevel@tonic-gate inopen = 1; /* might have been -1 */ 13027c478bd9Sstevel@tonic-gate continue; 13037c478bd9Sstevel@tonic-gate } 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate /* 13067c478bd9Sstevel@tonic-gate * Rest of commands are decoded by the operate 13077c478bd9Sstevel@tonic-gate * routine. 13087c478bd9Sstevel@tonic-gate */ 13097c478bd9Sstevel@tonic-gate operate(c, cnt); 13107c478bd9Sstevel@tonic-gate } 13117c478bd9Sstevel@tonic-gate } 13127c478bd9Sstevel@tonic-gate 13137c478bd9Sstevel@tonic-gate /* 13147c478bd9Sstevel@tonic-gate * Grab the word after the cursor so we can look for it as a tag. 13157c478bd9Sstevel@tonic-gate */ 1316f6db9f27Scf46844 void 1317f6db9f27Scf46844 grabtag(void) 13187c478bd9Sstevel@tonic-gate { 1319f6db9f27Scf46844 unsigned char *cp, *dp; 13207c478bd9Sstevel@tonic-gate 13217c478bd9Sstevel@tonic-gate cp = vpastwh(cursor); 13227c478bd9Sstevel@tonic-gate if (*cp) { 13237c478bd9Sstevel@tonic-gate dp = lasttag; 13247c478bd9Sstevel@tonic-gate do { 13257c478bd9Sstevel@tonic-gate if (dp < &lasttag[sizeof lasttag - 2]) 13267c478bd9Sstevel@tonic-gate *dp++ = *cp; 13277c478bd9Sstevel@tonic-gate cp++; 13287c478bd9Sstevel@tonic-gate /* only allow ascii alphabetics */ 13297c478bd9Sstevel@tonic-gate } while ((isascii(*cp) && isalpha(*cp)) || isdigit(*cp) || *cp == '_'); 13307c478bd9Sstevel@tonic-gate *dp++ = 0; 13317c478bd9Sstevel@tonic-gate } 13327c478bd9Sstevel@tonic-gate } 13337c478bd9Sstevel@tonic-gate 13347c478bd9Sstevel@tonic-gate /* 13357c478bd9Sstevel@tonic-gate * Before appending lines, set up addr1 and 13367c478bd9Sstevel@tonic-gate * the command mode undo information. 13377c478bd9Sstevel@tonic-gate */ 1338f6db9f27Scf46844 void 1339f6db9f27Scf46844 prepapp(void) 13407c478bd9Sstevel@tonic-gate { 13417c478bd9Sstevel@tonic-gate 13427c478bd9Sstevel@tonic-gate addr1 = dot; 13437c478bd9Sstevel@tonic-gate deletenone(); 13447c478bd9Sstevel@tonic-gate addr1++; 13457c478bd9Sstevel@tonic-gate appendnone(); 13467c478bd9Sstevel@tonic-gate } 13477c478bd9Sstevel@tonic-gate 13487c478bd9Sstevel@tonic-gate /* 13497c478bd9Sstevel@tonic-gate * Execute function f with the address bounds addr1 13507c478bd9Sstevel@tonic-gate * and addr2 surrounding cnt lines starting at dot. 13517c478bd9Sstevel@tonic-gate */ 1352f6db9f27Scf46844 void 13537c478bd9Sstevel@tonic-gate vremote(cnt, f, arg) 13547c478bd9Sstevel@tonic-gate int cnt, (*f)(), arg; 13557c478bd9Sstevel@tonic-gate { 1356f6db9f27Scf46844 int oing = inglobal; 13577c478bd9Sstevel@tonic-gate 13587c478bd9Sstevel@tonic-gate addr1 = dot; 13597c478bd9Sstevel@tonic-gate addr2 = dot + cnt - 1; 13607c478bd9Sstevel@tonic-gate inglobal = 0; 13617c478bd9Sstevel@tonic-gate if (FIXUNDO) 13627c478bd9Sstevel@tonic-gate undap1 = undap2 = dot; 13637c478bd9Sstevel@tonic-gate (*f)(arg); 13647c478bd9Sstevel@tonic-gate inglobal = oing; 13657c478bd9Sstevel@tonic-gate if (FIXUNDO) 13667c478bd9Sstevel@tonic-gate vundkind = VMANY; 1367*bbfd0aa6Scf46844 /* 1368*bbfd0aa6Scf46844 * XPG6 assertion 273: For the following commands, don't set vmcurs 1369*bbfd0aa6Scf46844 * to 0, so that undo positions the cursor column correctly when 1370*bbfd0aa6Scf46844 * we've moved off the initial line that was changed eg. when G has 1371*bbfd0aa6Scf46844 * moved us off the line, or when a multi-line change was done. 1372*bbfd0aa6Scf46844 */ 1373*bbfd0aa6Scf46844 if (lastcmd[0] != 'C' && lastcmd[0] != 'c' && lastcmd[0] != 'o' && 1374*bbfd0aa6Scf46844 lastcmd[0] != 'R' && lastcmd[0] != 'S' && lastcmd[0] != 's' && 1375*bbfd0aa6Scf46844 lastcmd[0] != 'i' && lastcmd[0] != 'a' && lastcmd[0] != 'A') { 13767c478bd9Sstevel@tonic-gate vmcurs = 0; 13777c478bd9Sstevel@tonic-gate } 1378*bbfd0aa6Scf46844 } 13797c478bd9Sstevel@tonic-gate 13807c478bd9Sstevel@tonic-gate /* 13817c478bd9Sstevel@tonic-gate * Save the current contents of linebuf, if it has changed. 13827c478bd9Sstevel@tonic-gate */ 1383f6db9f27Scf46844 void 1384f6db9f27Scf46844 vsave(void) 13857c478bd9Sstevel@tonic-gate { 13867c478bd9Sstevel@tonic-gate unsigned char temp[LBSIZE]; 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate strncpy(temp, linebuf, sizeof (temp)); 13897c478bd9Sstevel@tonic-gate if (FIXUNDO && vundkind == VCHNG || vundkind == VCAPU) { 13907c478bd9Sstevel@tonic-gate /* 13917c478bd9Sstevel@tonic-gate * If the undo state is saved in the temporary buffer 13927c478bd9Sstevel@tonic-gate * vutmp, then we sync this into the temp file so that 13937c478bd9Sstevel@tonic-gate * we will be able to undo even after we have moved off 13947c478bd9Sstevel@tonic-gate * the line. It would be possible to associate a line 13957c478bd9Sstevel@tonic-gate * with vutmp but we assume that vutmp is only associated 13967c478bd9Sstevel@tonic-gate * with line dot (e.g. in case ':') above, so beware. 13977c478bd9Sstevel@tonic-gate */ 13987c478bd9Sstevel@tonic-gate prepapp(); 13997c478bd9Sstevel@tonic-gate strcLIN(vutmp); 14007c478bd9Sstevel@tonic-gate putmark(dot); 14017c478bd9Sstevel@tonic-gate vremote(1, yank, 0); 14027c478bd9Sstevel@tonic-gate vundkind = VMCHNG; 14037c478bd9Sstevel@tonic-gate notecnt = 0; 14047c478bd9Sstevel@tonic-gate undkind = UNDCHANGE; 14057c478bd9Sstevel@tonic-gate } 14067c478bd9Sstevel@tonic-gate /* 14077c478bd9Sstevel@tonic-gate * Get the line out of the temp file and do nothing if it hasn't 14087c478bd9Sstevel@tonic-gate * changed. This may seem like a loss, but the line will 14097c478bd9Sstevel@tonic-gate * almost always be in a read buffer so this may well avoid disk i/o. 14107c478bd9Sstevel@tonic-gate */ 14117c478bd9Sstevel@tonic-gate getDOT(); 14127c478bd9Sstevel@tonic-gate if (strncmp(linebuf, temp, sizeof (temp)) == 0) 14137c478bd9Sstevel@tonic-gate return; 14147c478bd9Sstevel@tonic-gate strcLIN(temp); 14157c478bd9Sstevel@tonic-gate putmark(dot); 14167c478bd9Sstevel@tonic-gate } 14177c478bd9Sstevel@tonic-gate 14187c478bd9Sstevel@tonic-gate #undef forbid 1419f6db9f27Scf46844 #define forbid(a) if (a) { (void) beep(); return; } 14207c478bd9Sstevel@tonic-gate 14217c478bd9Sstevel@tonic-gate /* 14227c478bd9Sstevel@tonic-gate * Do a z operation. 14237c478bd9Sstevel@tonic-gate * Code here is rather long, and very uninteresting. 14247c478bd9Sstevel@tonic-gate */ 1425f6db9f27Scf46844 void 1426f6db9f27Scf46844 vzop(bool hadcnt, int cnt, int c) 14277c478bd9Sstevel@tonic-gate { 1428f6db9f27Scf46844 line *addr; 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate if (state != VISUAL) { 14317c478bd9Sstevel@tonic-gate /* 14327c478bd9Sstevel@tonic-gate * Z from open; always like a z=. 14337c478bd9Sstevel@tonic-gate * This code is a mess and should be cleaned up. 14347c478bd9Sstevel@tonic-gate */ 14357c478bd9Sstevel@tonic-gate vmoveitup(1, 1); 14367c478bd9Sstevel@tonic-gate vgoto(outline, 0); 14377c478bd9Sstevel@tonic-gate ostop(normf); 14387c478bd9Sstevel@tonic-gate setoutt(); 14397c478bd9Sstevel@tonic-gate addr2 = dot; 14407c478bd9Sstevel@tonic-gate vclear(); 14417c478bd9Sstevel@tonic-gate destline = WECHO; 14427c478bd9Sstevel@tonic-gate zop2(Xhadcnt ? Xcnt : value(vi_WINDOW) - 1, '='); 14437c478bd9Sstevel@tonic-gate if (state == CRTOPEN) 14447c478bd9Sstevel@tonic-gate putnl(); 14457c478bd9Sstevel@tonic-gate putNFL(); 14467c478bd9Sstevel@tonic-gate termreset(); 14477c478bd9Sstevel@tonic-gate Outchar = vputchar; 14487c478bd9Sstevel@tonic-gate (void)ostart(); 14497c478bd9Sstevel@tonic-gate vcnt = 0; 14507c478bd9Sstevel@tonic-gate outline = destline = 0; 14517c478bd9Sstevel@tonic-gate vjumpto(dot, cursor, 0); 14527c478bd9Sstevel@tonic-gate return; 14537c478bd9Sstevel@tonic-gate } 14547c478bd9Sstevel@tonic-gate if (hadcnt) { 14557c478bd9Sstevel@tonic-gate addr = zero + cnt; 14567c478bd9Sstevel@tonic-gate if (addr < one) 14577c478bd9Sstevel@tonic-gate addr = one; 14587c478bd9Sstevel@tonic-gate if (addr > dol) 14597c478bd9Sstevel@tonic-gate addr = dol; 14607c478bd9Sstevel@tonic-gate markit(addr); 14617c478bd9Sstevel@tonic-gate } else 14627c478bd9Sstevel@tonic-gate switch (c) { 14637c478bd9Sstevel@tonic-gate 14647c478bd9Sstevel@tonic-gate case '+': 14657c478bd9Sstevel@tonic-gate addr = dot + vcnt - vcline; 14667c478bd9Sstevel@tonic-gate break; 14677c478bd9Sstevel@tonic-gate 14687c478bd9Sstevel@tonic-gate case '^': 14697c478bd9Sstevel@tonic-gate addr = dot - vcline - 1; 14707c478bd9Sstevel@tonic-gate forbid (addr < one); 14717c478bd9Sstevel@tonic-gate c = '-'; 14727c478bd9Sstevel@tonic-gate break; 14737c478bd9Sstevel@tonic-gate 14747c478bd9Sstevel@tonic-gate default: 14757c478bd9Sstevel@tonic-gate addr = dot; 14767c478bd9Sstevel@tonic-gate break; 14777c478bd9Sstevel@tonic-gate } 14787c478bd9Sstevel@tonic-gate switch (c) { 14797c478bd9Sstevel@tonic-gate 14807c478bd9Sstevel@tonic-gate case '.': 14817c478bd9Sstevel@tonic-gate case '-': 14827c478bd9Sstevel@tonic-gate break; 14837c478bd9Sstevel@tonic-gate 14847c478bd9Sstevel@tonic-gate case '^': 14857c478bd9Sstevel@tonic-gate forbid (addr <= one); 14867c478bd9Sstevel@tonic-gate break; 14877c478bd9Sstevel@tonic-gate 14887c478bd9Sstevel@tonic-gate case '+': 14897c478bd9Sstevel@tonic-gate forbid (addr >= dol); 14907c478bd9Sstevel@tonic-gate /* fall into ... */ 14917c478bd9Sstevel@tonic-gate 14927c478bd9Sstevel@tonic-gate case CR: 14937c478bd9Sstevel@tonic-gate case NL: 14947c478bd9Sstevel@tonic-gate c = CR; 14957c478bd9Sstevel@tonic-gate break; 14967c478bd9Sstevel@tonic-gate 14977c478bd9Sstevel@tonic-gate default: 1498f6db9f27Scf46844 (void) beep(); 14997c478bd9Sstevel@tonic-gate return; 15007c478bd9Sstevel@tonic-gate } 15017c478bd9Sstevel@tonic-gate vmoving = 0; 1502f6db9f27Scf46844 vjumpto(addr, (unsigned char *)NOSTR, c); 15037c478bd9Sstevel@tonic-gate } 1504