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 5bbfd0aa6Scf46844 * Common Development and Distribution License (the "License"). 6bbfd0aa6Scf46844 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21*23a1cceaSRoger A. Faulkner 227c478bd9Sstevel@tonic-gate /* 23*23a1cceaSRoger A. Faulkner * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 277c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* Copyright (c) 1981 Regents of the University of California */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include "ex.h" 337c478bd9Sstevel@tonic-gate #include "ex_tty.h" 347c478bd9Sstevel@tonic-gate #include "ex_vis.h" 357c478bd9Sstevel@tonic-gate #ifndef PRESUNEUC 367c478bd9Sstevel@tonic-gate #include <wctype.h> 377c478bd9Sstevel@tonic-gate /* Undef putchar/getchar if they're defined. */ 387c478bd9Sstevel@tonic-gate #ifdef putchar 397c478bd9Sstevel@tonic-gate # undef putchar 407c478bd9Sstevel@tonic-gate #endif 417c478bd9Sstevel@tonic-gate #ifdef getchar 427c478bd9Sstevel@tonic-gate # undef getchar 437c478bd9Sstevel@tonic-gate #endif 447c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 457c478bd9Sstevel@tonic-gate 463a5240e9Scf46844 extern size_t strlcpy(char *, const char *, size_t); 473a5240e9Scf46844 487c478bd9Sstevel@tonic-gate /* 497c478bd9Sstevel@tonic-gate * Low level routines for operations sequences, 507c478bd9Sstevel@tonic-gate * and mostly, insert mode (and a subroutine 517c478bd9Sstevel@tonic-gate * to read an input line, including in the echo area.) 527c478bd9Sstevel@tonic-gate */ 537c478bd9Sstevel@tonic-gate extern unsigned char *vUA1, *vUA2; /* extern; also in ex_vops.c */ 547c478bd9Sstevel@tonic-gate extern unsigned char *vUD1, *vUD2; /* extern; also in ex_vops.c */ 557c478bd9Sstevel@tonic-gate 56bbfd0aa6Scf46844 #ifdef XPG6 57bbfd0aa6Scf46844 /* XPG6 assertion 313 & 254 [count]r\n : Also used in ex_vmain.c */ 58bbfd0aa6Scf46844 extern int redisplay; 59bbfd0aa6Scf46844 #endif 60bbfd0aa6Scf46844 61f6db9f27Scf46844 int vmaxrep(unsigned char, int); 623a5240e9Scf46844 static void imultlinerep(int, line *, int, int); 633a5240e9Scf46844 static void omultlinerep(int, line *, int); 64bbfd0aa6Scf46844 #ifdef XPG6 65bbfd0aa6Scf46844 static void rmultlinerep(int, int); 66bbfd0aa6Scf46844 #endif 67bbfd0aa6Scf46844 void fixdisplay(void); 68f6db9f27Scf46844 697c478bd9Sstevel@tonic-gate /* 707c478bd9Sstevel@tonic-gate * Obleeperate characters in hardcopy 717c478bd9Sstevel@tonic-gate * open with \'s. 727c478bd9Sstevel@tonic-gate */ 73f6db9f27Scf46844 void 74f6db9f27Scf46844 bleep(int i, unsigned char *cp) 757c478bd9Sstevel@tonic-gate { 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate i -= lcolumn(nextchr(cp)); 787c478bd9Sstevel@tonic-gate do 797c478bd9Sstevel@tonic-gate putchar('\\' | QUOTE); 807c478bd9Sstevel@tonic-gate while (--i >= 0); 817c478bd9Sstevel@tonic-gate rubble = 1; 827c478bd9Sstevel@tonic-gate } 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* 857c478bd9Sstevel@tonic-gate * Common code for middle part of delete 867c478bd9Sstevel@tonic-gate * and change operating on parts of lines. 877c478bd9Sstevel@tonic-gate */ 88f6db9f27Scf46844 int 89f6db9f27Scf46844 vdcMID(void) 907c478bd9Sstevel@tonic-gate { 91f6db9f27Scf46844 unsigned char *cp; 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate squish(); 947c478bd9Sstevel@tonic-gate setLAST(); 957c478bd9Sstevel@tonic-gate if (FIXUNDO) 967c478bd9Sstevel@tonic-gate vundkind = VCHNG, CP(vutmp, linebuf); 977c478bd9Sstevel@tonic-gate if (wcursor < cursor) 987c478bd9Sstevel@tonic-gate cp = wcursor, wcursor = cursor, cursor = cp; 997c478bd9Sstevel@tonic-gate vUD1 = vUA1 = vUA2 = cursor; vUD2 = wcursor; 100bbfd0aa6Scf46844 /* 101bbfd0aa6Scf46844 * XPG6 assertion 273: Set vmcurs so that undo positions the 102bbfd0aa6Scf46844 * cursor column correctly when we've moved off the initial line 103bbfd0aa6Scf46844 * that was changed, as with the C, c, and s commands, 104bbfd0aa6Scf46844 * when G has moved us off the line, or when a 105bbfd0aa6Scf46844 * multi-line change was done. 106bbfd0aa6Scf46844 */ 107bbfd0aa6Scf46844 fixundo(); 1087c478bd9Sstevel@tonic-gate return (lcolumn(wcursor)); 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* 1127c478bd9Sstevel@tonic-gate * Take text from linebuf and stick it 1137c478bd9Sstevel@tonic-gate * in the VBSIZE buffer BUF. Used to save 1147c478bd9Sstevel@tonic-gate * deleted text of part of line. 1157c478bd9Sstevel@tonic-gate */ 116f6db9f27Scf46844 void 117f6db9f27Scf46844 takeout(unsigned char *BUF) 1187c478bd9Sstevel@tonic-gate { 119f6db9f27Scf46844 unsigned char *cp; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate if (wcursor < linebuf) 1227c478bd9Sstevel@tonic-gate wcursor = linebuf; 1237c478bd9Sstevel@tonic-gate if (cursor == wcursor) { 124f6db9f27Scf46844 (void) beep(); 1257c478bd9Sstevel@tonic-gate return; 1267c478bd9Sstevel@tonic-gate } 1277c478bd9Sstevel@tonic-gate if (wcursor < cursor) { 1287c478bd9Sstevel@tonic-gate cp = wcursor; 1297c478bd9Sstevel@tonic-gate wcursor = cursor; 1307c478bd9Sstevel@tonic-gate cursor = cp; 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate setBUF(BUF); 1337c478bd9Sstevel@tonic-gate if ((unsigned char)BUF[128] == 0200) 134f6db9f27Scf46844 (void) beep(); 1357c478bd9Sstevel@tonic-gate } 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate /* 1387c478bd9Sstevel@tonic-gate * Are we at the end of the printed representation of the 1397c478bd9Sstevel@tonic-gate * line? Used internally in hardcopy open. 1407c478bd9Sstevel@tonic-gate */ 141f6db9f27Scf46844 int 142f6db9f27Scf46844 ateopr(void) 1437c478bd9Sstevel@tonic-gate { 144f6db9f27Scf46844 wchar_t i, c; 145f6db9f27Scf46844 wchar_t *cp = vtube[destline] + destcol; 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate for (i = WCOLS - destcol; i > 0; i--) { 1487c478bd9Sstevel@tonic-gate c = *cp++; 1497c478bd9Sstevel@tonic-gate if (c == 0) { 1507c478bd9Sstevel@tonic-gate /* 1517c478bd9Sstevel@tonic-gate * Optimization to consider returning early, saving 1527c478bd9Sstevel@tonic-gate * CPU time. We have to make a special check that 1537c478bd9Sstevel@tonic-gate * we aren't missing a mode indicator. 1547c478bd9Sstevel@tonic-gate */ 1557c478bd9Sstevel@tonic-gate if (destline == WECHO && destcol < WCOLS-11 && vtube[WECHO][WCOLS-20]) 1567c478bd9Sstevel@tonic-gate return 0; 1577c478bd9Sstevel@tonic-gate return (1); 1587c478bd9Sstevel@tonic-gate } 1597c478bd9Sstevel@tonic-gate if (c != ' ' && (c & QUOTE) == 0) 1607c478bd9Sstevel@tonic-gate return (0); 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate return (1); 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate /* 1667c478bd9Sstevel@tonic-gate * Append. 1677c478bd9Sstevel@tonic-gate * 1687c478bd9Sstevel@tonic-gate * This routine handles the top level append, doing work 1697c478bd9Sstevel@tonic-gate * as each new line comes in, and arranging repeatability. 1707c478bd9Sstevel@tonic-gate * It also handles append with repeat counts, and calculation 1717c478bd9Sstevel@tonic-gate * of autoindents for new lines. 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate bool vaifirst; 1747c478bd9Sstevel@tonic-gate bool gobbled; 1757c478bd9Sstevel@tonic-gate unsigned char *ogcursor; 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate static int INSCDCNT; /* number of ^D's (backtabs) in insertion buffer */ 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate static int inscdcnt; /* 1807c478bd9Sstevel@tonic-gate * count of ^D's (backtabs) not seen yet when doing 1817c478bd9Sstevel@tonic-gate * repeat of insertion 1827c478bd9Sstevel@tonic-gate */ 1837c478bd9Sstevel@tonic-gate 184f6db9f27Scf46844 void 185f6db9f27Scf46844 vappend(int ch, int cnt, int indent) 1867c478bd9Sstevel@tonic-gate { 187f6db9f27Scf46844 int i; 188f6db9f27Scf46844 unsigned char *gcursor; 1897c478bd9Sstevel@tonic-gate bool escape; 1907c478bd9Sstevel@tonic-gate int repcnt, savedoomed; 1917c478bd9Sstevel@tonic-gate short oldhold = hold; 1923a5240e9Scf46844 int savecnt = cnt; 1933a5240e9Scf46844 line *startsrcline; 1943a5240e9Scf46844 int startsrccol, endsrccol; 1953a5240e9Scf46844 int gotNL = 0; 1963a5240e9Scf46844 int imultlinecnt = 0; 1973a5240e9Scf46844 int omultlinecnt = 0; 1983a5240e9Scf46844 1993a5240e9Scf46844 if ((savecnt > 1) && (ch == 'o' || ch == 'O')) { 2003a5240e9Scf46844 omultlinecnt = 1; 2013a5240e9Scf46844 } 2023a5240e9Scf46844 #ifdef XPG6 2033a5240e9Scf46844 if ((savecnt > 1) && (ch == 'a' || ch == 'A' || ch == 'i' || ch == 'I')) 2043a5240e9Scf46844 imultlinecnt = 1; 2053a5240e9Scf46844 #endif /* XPG6 */ 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate /* 2087c478bd9Sstevel@tonic-gate * Before a move in hardopen when the line is dirty 2097c478bd9Sstevel@tonic-gate * or we are in the middle of the printed representation, 2107c478bd9Sstevel@tonic-gate * we retype the line to the left of the cursor so the 2117c478bd9Sstevel@tonic-gate * insert looks clean. 2127c478bd9Sstevel@tonic-gate */ 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate if (ch != 'o' && state == HARDOPEN && (rubble || !ateopr())) { 2157c478bd9Sstevel@tonic-gate rubble = 1; 2167c478bd9Sstevel@tonic-gate gcursor = cursor; 2177c478bd9Sstevel@tonic-gate i = *gcursor; 2187c478bd9Sstevel@tonic-gate *gcursor = ' '; 2197c478bd9Sstevel@tonic-gate wcursor = gcursor; 220f6db9f27Scf46844 (void) vmove(); 2217c478bd9Sstevel@tonic-gate *gcursor = i; 2227c478bd9Sstevel@tonic-gate } 223bbfd0aa6Scf46844 /* 224bbfd0aa6Scf46844 * If vrep() passed indent = 0, this is the 'r' command, 225bbfd0aa6Scf46844 * so don't autoindent until the last char. 226bbfd0aa6Scf46844 */ 2277c478bd9Sstevel@tonic-gate vaifirst = indent == 0; 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate /* 2307c478bd9Sstevel@tonic-gate * Handle replace character by (eventually) 2317c478bd9Sstevel@tonic-gate * limiting the number of input characters allowed 2327c478bd9Sstevel@tonic-gate * in the vgetline routine. 2337c478bd9Sstevel@tonic-gate */ 2347c478bd9Sstevel@tonic-gate if (ch == 'r') 2357c478bd9Sstevel@tonic-gate repcnt = 2; 2367c478bd9Sstevel@tonic-gate else 2377c478bd9Sstevel@tonic-gate repcnt = 0; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate /* 2407c478bd9Sstevel@tonic-gate * If an autoindent is specified, then 2417c478bd9Sstevel@tonic-gate * generate a mixture of blanks to tabs to implement 2427c478bd9Sstevel@tonic-gate * it and place the cursor after the indent. 2437c478bd9Sstevel@tonic-gate * Text read by the vgetline routine will be placed in genbuf, 2447c478bd9Sstevel@tonic-gate * so the indent is generated there. 2457c478bd9Sstevel@tonic-gate */ 2467c478bd9Sstevel@tonic-gate if (value(vi_AUTOINDENT) && indent != 0) { 2477c478bd9Sstevel@tonic-gate unsigned char x; 2487c478bd9Sstevel@tonic-gate gcursor = genindent(indent); 2497c478bd9Sstevel@tonic-gate *gcursor = 0; 2507c478bd9Sstevel@tonic-gate vgotoCL(nqcolumn(lastchr(linebuf, cursor), genbuf)); 2517c478bd9Sstevel@tonic-gate } else { 2527c478bd9Sstevel@tonic-gate gcursor = genbuf; 2537c478bd9Sstevel@tonic-gate *gcursor = 0; 2547c478bd9Sstevel@tonic-gate if (ch == 'o') 2557c478bd9Sstevel@tonic-gate vfixcurs(); 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate /* 2597c478bd9Sstevel@tonic-gate * Prepare for undo. Pointers delimit inserted portion of line. 2607c478bd9Sstevel@tonic-gate */ 2617c478bd9Sstevel@tonic-gate vUA1 = vUA2 = cursor; 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate /* 2647c478bd9Sstevel@tonic-gate * If we are not in a repeated command and a ^@ comes in 2657c478bd9Sstevel@tonic-gate * then this means the previous inserted text. 2667c478bd9Sstevel@tonic-gate * If there is none or it was too long to be saved, 2677c478bd9Sstevel@tonic-gate * then beep() and also arrange to undo any damage done 2687c478bd9Sstevel@tonic-gate * so far (e.g. if we are a change.) 2697c478bd9Sstevel@tonic-gate */ 2707c478bd9Sstevel@tonic-gate switch (ch) { 2717c478bd9Sstevel@tonic-gate case 'r': 2727c478bd9Sstevel@tonic-gate break; 2737c478bd9Sstevel@tonic-gate case 'a': 2747c478bd9Sstevel@tonic-gate /* 2757c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 2767c478bd9Sstevel@tonic-gate * "A" is a terse mode message corresponding to 2777c478bd9Sstevel@tonic-gate * "APPEND MODE". 2787c478bd9Sstevel@tonic-gate * Translated message of "A" must be 1 character (not byte). 2797c478bd9Sstevel@tonic-gate * Or, just leave it. 2807c478bd9Sstevel@tonic-gate */ 2817c478bd9Sstevel@tonic-gate if (value(vi_TERSE)) { 2827c478bd9Sstevel@tonic-gate vshowmode(gettext("A")); 2837c478bd9Sstevel@tonic-gate } else { 2847c478bd9Sstevel@tonic-gate vshowmode(gettext("APPEND MODE")); 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate break; 2877c478bd9Sstevel@tonic-gate case 's': 2887c478bd9Sstevel@tonic-gate /* 2897c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 2907c478bd9Sstevel@tonic-gate * "S" is a terse mode message corresponding to 2917c478bd9Sstevel@tonic-gate * "SUBSTITUTE MODE". 2927c478bd9Sstevel@tonic-gate * Translated message of "S" must be 1 character (not byte). 2937c478bd9Sstevel@tonic-gate * Or, just leave it. 2947c478bd9Sstevel@tonic-gate */ 2957c478bd9Sstevel@tonic-gate if (value(vi_TERSE)) { 2967c478bd9Sstevel@tonic-gate vshowmode(gettext("S")); 2977c478bd9Sstevel@tonic-gate } else { 2987c478bd9Sstevel@tonic-gate vshowmode(gettext("SUBSTITUTE MODE")); 2997c478bd9Sstevel@tonic-gate } 3007c478bd9Sstevel@tonic-gate break; 3017c478bd9Sstevel@tonic-gate case 'c': 3027c478bd9Sstevel@tonic-gate /* 3037c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 3047c478bd9Sstevel@tonic-gate * "C" is a terse mode message corresponding to 3057c478bd9Sstevel@tonic-gate * "CHANGE MODE". 3067c478bd9Sstevel@tonic-gate * Translated message of "C" must be 1 character (not byte). 3077c478bd9Sstevel@tonic-gate * Or, just leave it. 3087c478bd9Sstevel@tonic-gate */ 3097c478bd9Sstevel@tonic-gate if (value(vi_TERSE)) { 3107c478bd9Sstevel@tonic-gate vshowmode(gettext("C")); 3117c478bd9Sstevel@tonic-gate } else { 3127c478bd9Sstevel@tonic-gate vshowmode(gettext("CHANGE MODE")); 3137c478bd9Sstevel@tonic-gate } 3147c478bd9Sstevel@tonic-gate break; 3157c478bd9Sstevel@tonic-gate case 'R': 3167c478bd9Sstevel@tonic-gate /* 3177c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 3187c478bd9Sstevel@tonic-gate * "R" is a terse mode message corresponding to 3197c478bd9Sstevel@tonic-gate * "REPLACE MODE". 3207c478bd9Sstevel@tonic-gate * Translated message of "R" must be 1 character (not byte). 3217c478bd9Sstevel@tonic-gate * Or, just leave it. 3227c478bd9Sstevel@tonic-gate */ 3237c478bd9Sstevel@tonic-gate if (value(vi_TERSE)) { 3247c478bd9Sstevel@tonic-gate vshowmode(gettext("R")); 3257c478bd9Sstevel@tonic-gate } else { 3267c478bd9Sstevel@tonic-gate vshowmode(gettext("REPLACE MODE")); 3277c478bd9Sstevel@tonic-gate } 3287c478bd9Sstevel@tonic-gate break; 3297c478bd9Sstevel@tonic-gate case 'o': 3307c478bd9Sstevel@tonic-gate /* 3317c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 3327c478bd9Sstevel@tonic-gate * "O" is a terse mode message corresponding to 3337c478bd9Sstevel@tonic-gate * "OPEN MODE". 3347c478bd9Sstevel@tonic-gate * Translated message of "O" must be 1 character (not byte). 3357c478bd9Sstevel@tonic-gate * Or, just leave it. 3367c478bd9Sstevel@tonic-gate */ 3377c478bd9Sstevel@tonic-gate if (value(vi_TERSE)) { 3387c478bd9Sstevel@tonic-gate vshowmode(gettext("O")); 3397c478bd9Sstevel@tonic-gate } else { 3407c478bd9Sstevel@tonic-gate vshowmode(gettext("OPEN MODE")); 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate break; 3437c478bd9Sstevel@tonic-gate case 'i': 3447c478bd9Sstevel@tonic-gate /* 3457c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 3467c478bd9Sstevel@tonic-gate * "I" is a terse mode message corresponding to 3477c478bd9Sstevel@tonic-gate * "INSERT MODE" and the following "INPUT MODE". 3487c478bd9Sstevel@tonic-gate * Translated message of "I" must be 1 character (not byte). 3497c478bd9Sstevel@tonic-gate * Or, just leave it. 3507c478bd9Sstevel@tonic-gate */ 3517c478bd9Sstevel@tonic-gate if (value(vi_TERSE)) { 3527c478bd9Sstevel@tonic-gate vshowmode(gettext("I")); 3537c478bd9Sstevel@tonic-gate } else { 3547c478bd9Sstevel@tonic-gate vshowmode(gettext("INSERT MODE")); 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate break; 3577c478bd9Sstevel@tonic-gate default: 3587c478bd9Sstevel@tonic-gate /* 3597c478bd9Sstevel@tonic-gate * TRANSLATION_NOTE 3607c478bd9Sstevel@tonic-gate * "I" is a terse mode message corresponding to 3617c478bd9Sstevel@tonic-gate * "INPUT MODE" and the previous "INSERT MODE". 3627c478bd9Sstevel@tonic-gate * Translated message of "I" must be 1 character (not byte). 3637c478bd9Sstevel@tonic-gate * Or, just leave it. 3647c478bd9Sstevel@tonic-gate */ 3657c478bd9Sstevel@tonic-gate if (value(vi_TERSE)) { 3667c478bd9Sstevel@tonic-gate vshowmode(gettext("I")); 3677c478bd9Sstevel@tonic-gate } else { 3687c478bd9Sstevel@tonic-gate vshowmode(gettext("INPUT MODE")); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate } 3717c478bd9Sstevel@tonic-gate ixlatctl(1); 3727c478bd9Sstevel@tonic-gate if ((vglobp && *vglobp == 0) || peekbr()) { 3737c478bd9Sstevel@tonic-gate if (INS[128] == 0200) { 374f6db9f27Scf46844 (void) beep(); 3757c478bd9Sstevel@tonic-gate if (!splitw) 3767c478bd9Sstevel@tonic-gate ungetkey('u'); 3777c478bd9Sstevel@tonic-gate doomed = 0; 3787c478bd9Sstevel@tonic-gate hold = oldhold; 3797c478bd9Sstevel@tonic-gate return; 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate /* 3827c478bd9Sstevel@tonic-gate * Unread input from INS. 3837c478bd9Sstevel@tonic-gate * An escape will be generated at end of string. 3847c478bd9Sstevel@tonic-gate * Hold off n^^2 type update on dumb terminals. 3857c478bd9Sstevel@tonic-gate */ 3867c478bd9Sstevel@tonic-gate vglobp = INS; 3877c478bd9Sstevel@tonic-gate inscdcnt = INSCDCNT; 3887c478bd9Sstevel@tonic-gate hold |= HOLDQIK; 3897c478bd9Sstevel@tonic-gate } else if (vglobp == 0) { 3907c478bd9Sstevel@tonic-gate /* 3917c478bd9Sstevel@tonic-gate * Not a repeated command, get 3927c478bd9Sstevel@tonic-gate * a new inserted text for repeat. 3937c478bd9Sstevel@tonic-gate */ 3947c478bd9Sstevel@tonic-gate INS[0] = 0; 3957c478bd9Sstevel@tonic-gate INS[128] = 0; 3967c478bd9Sstevel@tonic-gate INSCDCNT = 0; 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate /* 4007c478bd9Sstevel@tonic-gate * For wrapmargin to hack away second space after a '.' 4017c478bd9Sstevel@tonic-gate * when the first space caused a line break we keep 4027c478bd9Sstevel@tonic-gate * track that this happened in gobblebl, which says 4037c478bd9Sstevel@tonic-gate * to gobble up a blank silently. 4047c478bd9Sstevel@tonic-gate */ 4057c478bd9Sstevel@tonic-gate gobblebl = 0; 4067c478bd9Sstevel@tonic-gate 4073a5240e9Scf46844 startsrcline = dot; 4083a5240e9Scf46844 startsrccol = cursor - linebuf; 4093a5240e9Scf46844 4107c478bd9Sstevel@tonic-gate /* 4117c478bd9Sstevel@tonic-gate * Text gathering loop. 4127c478bd9Sstevel@tonic-gate * New text goes into genbuf starting at gcursor. 4137c478bd9Sstevel@tonic-gate * cursor preserves place in linebuf where text will eventually go. 4147c478bd9Sstevel@tonic-gate */ 4157c478bd9Sstevel@tonic-gate if (*cursor == 0 || state == CRTOPEN) 4167c478bd9Sstevel@tonic-gate hold |= HOLDROL; 4177c478bd9Sstevel@tonic-gate for (;;) { 4187c478bd9Sstevel@tonic-gate if (ch == 'r' && repcnt == 0) 4197c478bd9Sstevel@tonic-gate escape = 0; 4207c478bd9Sstevel@tonic-gate else { 4217c478bd9Sstevel@tonic-gate ixlatctl(1); 422bbfd0aa6Scf46844 /* 423bbfd0aa6Scf46844 * When vgetline() returns, gcursor is 424bbfd0aa6Scf46844 * pointing to '\0' and vgetline() has 425bbfd0aa6Scf46844 * read an ESCAPE or NL. 426bbfd0aa6Scf46844 */ 4277c478bd9Sstevel@tonic-gate gcursor = vgetline(repcnt, gcursor, &escape, ch); 4283a5240e9Scf46844 if (escape == '\n') { 4293a5240e9Scf46844 gotNL = 1; 430bbfd0aa6Scf46844 #ifdef XPG6 431bbfd0aa6Scf46844 if (ch == 'r') { 432bbfd0aa6Scf46844 /* 433bbfd0aa6Scf46844 * XPG6 assertion 313 [count]r\n : 434bbfd0aa6Scf46844 * Arrange to set cursor correctly. 435bbfd0aa6Scf46844 */ 436bbfd0aa6Scf46844 endsrccol = gcursor - genbuf - 1; 437bbfd0aa6Scf46844 } 438bbfd0aa6Scf46844 #endif /* XPG6 */ 4393a5240e9Scf46844 } else { 4403a5240e9Scf46844 /* 4413a5240e9Scf46844 * Upon escape, gcursor is pointing to '\0' 4423a5240e9Scf46844 * terminating the string in genbuf. 4433a5240e9Scf46844 */ 4443a5240e9Scf46844 endsrccol = gcursor - genbuf - 1; 4453a5240e9Scf46844 } 4467c478bd9Sstevel@tonic-gate ixlatctl(0); 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate /* 4497c478bd9Sstevel@tonic-gate * After an append, stick information 4507c478bd9Sstevel@tonic-gate * about the ^D's and ^^D's and 0^D's in 4517c478bd9Sstevel@tonic-gate * the repeated text buffer so repeated 4527c478bd9Sstevel@tonic-gate * inserts of stuff indented with ^D as backtab's 4537c478bd9Sstevel@tonic-gate * can work. 4547c478bd9Sstevel@tonic-gate */ 4557c478bd9Sstevel@tonic-gate if (HADUP) 4567c478bd9Sstevel@tonic-gate addtext("^"); 4577c478bd9Sstevel@tonic-gate else if (HADZERO) 4587c478bd9Sstevel@tonic-gate addtext("0"); 4597c478bd9Sstevel@tonic-gate if(!vglobp) 4607c478bd9Sstevel@tonic-gate INSCDCNT = CDCNT; 4617c478bd9Sstevel@tonic-gate while (CDCNT > 0) { 4627c478bd9Sstevel@tonic-gate addtext("\004"); 4637c478bd9Sstevel@tonic-gate CDCNT--; 4647c478bd9Sstevel@tonic-gate } 4657c478bd9Sstevel@tonic-gate if (gobbled) 4667c478bd9Sstevel@tonic-gate addtext(" "); 4677c478bd9Sstevel@tonic-gate addtext(ogcursor); 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate repcnt = 0; 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate /* 4727c478bd9Sstevel@tonic-gate * Smash the generated and preexisting indents together 4737c478bd9Sstevel@tonic-gate * and generate one cleanly made out of tabs and spaces 474bbfd0aa6Scf46844 * if we are using autoindent and this isn't 'r' command. 4757c478bd9Sstevel@tonic-gate */ 4767c478bd9Sstevel@tonic-gate if (!vaifirst && value(vi_AUTOINDENT)) { 4777c478bd9Sstevel@tonic-gate i = fixindent(indent); 4787c478bd9Sstevel@tonic-gate if (!HADUP) 4797c478bd9Sstevel@tonic-gate indent = i; 4807c478bd9Sstevel@tonic-gate gcursor = strend(genbuf); 4817c478bd9Sstevel@tonic-gate } 4827c478bd9Sstevel@tonic-gate 4837c478bd9Sstevel@tonic-gate /* 4843a5240e9Scf46844 * Set cnt to 1 to avoid repeating the text on the same line. 4853a5240e9Scf46844 * Do this for commands 'i', 'I', 'a', and 'A', if we're 4863a5240e9Scf46844 * inserting anything with a newline for XPG6. Always do this 4873a5240e9Scf46844 * for commands 'o' and 'O'. 4883a5240e9Scf46844 */ 4893a5240e9Scf46844 if ((imultlinecnt && gotNL) || omultlinecnt) { 4903a5240e9Scf46844 cnt = 1; 4913a5240e9Scf46844 } 4923a5240e9Scf46844 4933a5240e9Scf46844 /* 4947c478bd9Sstevel@tonic-gate * Limit the repetition count based on maximum 4957c478bd9Sstevel@tonic-gate * possible line length; do output implied 4967c478bd9Sstevel@tonic-gate * by further count (> 1) and cons up the new line 4977c478bd9Sstevel@tonic-gate * in linebuf. 4987c478bd9Sstevel@tonic-gate */ 4997c478bd9Sstevel@tonic-gate cnt = vmaxrep(ch, cnt); 500bbfd0aa6Scf46844 /* 501bbfd0aa6Scf46844 * cursor points to linebuf 502bbfd0aa6Scf46844 * Copy remaining old text (cursor) in original 503bbfd0aa6Scf46844 * line to after new text (gcursor + 1) in genbuf. 504bbfd0aa6Scf46844 */ 5057c478bd9Sstevel@tonic-gate CP(gcursor + 1, cursor); 506bbfd0aa6Scf46844 /* 507bbfd0aa6Scf46844 * For [count] r \n command, when replacing [count] chars 508bbfd0aa6Scf46844 * with '\n', this loop replaces [count] chars with "". 509bbfd0aa6Scf46844 */ 5107c478bd9Sstevel@tonic-gate do { 511bbfd0aa6Scf46844 /* cp new text (genbuf) into linebuf (cursor) */ 5127c478bd9Sstevel@tonic-gate CP(cursor, genbuf); 5137c478bd9Sstevel@tonic-gate if (cnt > 1) { 5147c478bd9Sstevel@tonic-gate int oldhold = hold; 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate Outchar = vinschar; 5177c478bd9Sstevel@tonic-gate hold |= HOLDQIK; 518f6db9f27Scf46844 viprintf("%s", genbuf); 5197c478bd9Sstevel@tonic-gate hold = oldhold; 5207c478bd9Sstevel@tonic-gate Outchar = vputchar; 5217c478bd9Sstevel@tonic-gate } 522bbfd0aa6Scf46844 /* point cursor after new text in linebuf */ 5237c478bd9Sstevel@tonic-gate cursor += gcursor - genbuf; 5247c478bd9Sstevel@tonic-gate } while (--cnt > 0); 5257c478bd9Sstevel@tonic-gate endim(); 5267c478bd9Sstevel@tonic-gate vUA2 = cursor; 527bbfd0aa6Scf46844 /* add the remaining old text after the cursor */ 5287c478bd9Sstevel@tonic-gate if (escape != '\n') 5297c478bd9Sstevel@tonic-gate CP(cursor, gcursor + 1); 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate /* 5327c478bd9Sstevel@tonic-gate * If doomed characters remain, clobber them, 5337c478bd9Sstevel@tonic-gate * and reopen the line to get the display exact. 534bbfd0aa6Scf46844 * eg. c$ to change to end of line 5357c478bd9Sstevel@tonic-gate */ 5367c478bd9Sstevel@tonic-gate if (state != HARDOPEN) { 5377c478bd9Sstevel@tonic-gate DEPTH(vcline) = 0; 5387c478bd9Sstevel@tonic-gate savedoomed = doomed; 5397c478bd9Sstevel@tonic-gate if (doomed > 0) { 540f6db9f27Scf46844 int cind = cindent(); 5417c478bd9Sstevel@tonic-gate 5427c478bd9Sstevel@tonic-gate physdc(cind, cind + doomed); 5437c478bd9Sstevel@tonic-gate doomed = 0; 5447c478bd9Sstevel@tonic-gate } 5457c478bd9Sstevel@tonic-gate if(MB_CUR_MAX > 1) 5467c478bd9Sstevel@tonic-gate rewrite = _ON; 5477c478bd9Sstevel@tonic-gate i = vreopen(LINE(vcline), lineDOT(), vcline); 5487c478bd9Sstevel@tonic-gate if(MB_CUR_MAX > 1) 5497c478bd9Sstevel@tonic-gate rewrite = _OFF; 5507c478bd9Sstevel@tonic-gate #ifdef TRACE 5517c478bd9Sstevel@tonic-gate if (trace) 5527c478bd9Sstevel@tonic-gate fprintf(trace, "restoring doomed from %d to %d\n", doomed, savedoomed); 5537c478bd9Sstevel@tonic-gate #endif 5547c478bd9Sstevel@tonic-gate if (ch == 'R') 5557c478bd9Sstevel@tonic-gate doomed = savedoomed; 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate /* 559bbfd0aa6Scf46844 * Unless we are continuing on to another line 560bbfd0aa6Scf46844 * (got a NL), break out of the for loop (got 561bbfd0aa6Scf46844 * an ESCAPE). 5627c478bd9Sstevel@tonic-gate */ 5637c478bd9Sstevel@tonic-gate if (escape != '\n') { 5647c478bd9Sstevel@tonic-gate vshowmode(""); 5657c478bd9Sstevel@tonic-gate break; 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate /* 5697c478bd9Sstevel@tonic-gate * Set up for the new line. 5707c478bd9Sstevel@tonic-gate * First save the current line, then construct a new 5717c478bd9Sstevel@tonic-gate * first image for the continuation line consisting 5727c478bd9Sstevel@tonic-gate * of any new autoindent plus the pushed ahead text. 5737c478bd9Sstevel@tonic-gate */ 5747c478bd9Sstevel@tonic-gate killU(); 5757c478bd9Sstevel@tonic-gate addtext(gobblebl ? " " : "\n"); 576bbfd0aa6Scf46844 /* save vutmp (for undo state) into temp file */ 5777c478bd9Sstevel@tonic-gate vsave(); 5787c478bd9Sstevel@tonic-gate cnt = 1; 5797c478bd9Sstevel@tonic-gate if (value(vi_AUTOINDENT)) { 5807c478bd9Sstevel@tonic-gate if (value(vi_LISP)) 5817c478bd9Sstevel@tonic-gate indent = lindent(dot + 1); 5827c478bd9Sstevel@tonic-gate else 5837c478bd9Sstevel@tonic-gate if (!HADUP && vaifirst) 5847c478bd9Sstevel@tonic-gate indent = whitecnt(linebuf); 5857c478bd9Sstevel@tonic-gate vaifirst = 0; 5867c478bd9Sstevel@tonic-gate strcLIN(vpastwh(gcursor + 1)); 5877c478bd9Sstevel@tonic-gate gcursor = genindent(indent); 5887c478bd9Sstevel@tonic-gate *gcursor = 0; 5897c478bd9Sstevel@tonic-gate if (gcursor + strlen(linebuf) > &genbuf[LBSIZE - 2]) 5907c478bd9Sstevel@tonic-gate gcursor = genbuf; 5917c478bd9Sstevel@tonic-gate CP(gcursor, linebuf); 5927c478bd9Sstevel@tonic-gate } else { 593bbfd0aa6Scf46844 /* 594bbfd0aa6Scf46844 * Put gcursor at start of genbuf to wipe 595bbfd0aa6Scf46844 * out previous line in preparation for 596bbfd0aa6Scf46844 * the next vgetline() loop. 597bbfd0aa6Scf46844 */ 5987c478bd9Sstevel@tonic-gate CP(genbuf, gcursor + 1); 5997c478bd9Sstevel@tonic-gate gcursor = genbuf; 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate 6027c478bd9Sstevel@tonic-gate /* 6037c478bd9Sstevel@tonic-gate * If we started out as a single line operation and are now 6047c478bd9Sstevel@tonic-gate * turning into a multi-line change, then we had better yank 6057c478bd9Sstevel@tonic-gate * out dot before it changes so that undo will work 6067c478bd9Sstevel@tonic-gate * correctly later. 6077c478bd9Sstevel@tonic-gate */ 6087c478bd9Sstevel@tonic-gate if (FIXUNDO && vundkind == VCHNG) { 6097c478bd9Sstevel@tonic-gate vremote(1, yank, 0); 6107c478bd9Sstevel@tonic-gate undap1--; 6117c478bd9Sstevel@tonic-gate } 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate /* 6147c478bd9Sstevel@tonic-gate * Now do the append of the new line in the buffer, 615bbfd0aa6Scf46844 * and update the display, ie: append genbuf to 616bbfd0aa6Scf46844 * the file after dot. If slowopen 6177c478bd9Sstevel@tonic-gate * we don't do very much. 6187c478bd9Sstevel@tonic-gate */ 6197c478bd9Sstevel@tonic-gate vdoappend(genbuf); 6207c478bd9Sstevel@tonic-gate vundkind = VMANYINS; 6217c478bd9Sstevel@tonic-gate vcline++; 6227c478bd9Sstevel@tonic-gate if (state != VISUAL) 6237c478bd9Sstevel@tonic-gate vshow(dot, NOLINE); 6247c478bd9Sstevel@tonic-gate else { 6257c478bd9Sstevel@tonic-gate i += LINE(vcline - 1); 6267c478bd9Sstevel@tonic-gate vopen(dot, i); 6277c478bd9Sstevel@tonic-gate if (value(vi_SLOWOPEN)) 6287c478bd9Sstevel@tonic-gate vscrap(); 6297c478bd9Sstevel@tonic-gate else 6307c478bd9Sstevel@tonic-gate vsync1(LINE(vcline)); 6317c478bd9Sstevel@tonic-gate } 6327c478bd9Sstevel@tonic-gate switch (ch) { 6337c478bd9Sstevel@tonic-gate case 'r': 6347c478bd9Sstevel@tonic-gate break; 6357c478bd9Sstevel@tonic-gate case 'a': 6367c478bd9Sstevel@tonic-gate if (value(vi_TERSE)) { 6377c478bd9Sstevel@tonic-gate vshowmode(gettext("A")); 6387c478bd9Sstevel@tonic-gate } else { 6397c478bd9Sstevel@tonic-gate vshowmode(gettext("APPEND MODE")); 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate break; 6427c478bd9Sstevel@tonic-gate case 's': 6437c478bd9Sstevel@tonic-gate if (value(vi_TERSE)) { 6447c478bd9Sstevel@tonic-gate vshowmode(gettext("S")); 6457c478bd9Sstevel@tonic-gate } else { 6467c478bd9Sstevel@tonic-gate vshowmode(gettext("SUBSTITUTE MODE")); 6477c478bd9Sstevel@tonic-gate } 6487c478bd9Sstevel@tonic-gate break; 6497c478bd9Sstevel@tonic-gate case 'c': 6507c478bd9Sstevel@tonic-gate if (value(vi_TERSE)) { 6517c478bd9Sstevel@tonic-gate vshowmode(gettext("C")); 6527c478bd9Sstevel@tonic-gate } else { 6537c478bd9Sstevel@tonic-gate vshowmode(gettext("CHANGE MODE")); 6547c478bd9Sstevel@tonic-gate } 6557c478bd9Sstevel@tonic-gate break; 6567c478bd9Sstevel@tonic-gate case 'R': 6577c478bd9Sstevel@tonic-gate if (value(vi_TERSE)) { 6587c478bd9Sstevel@tonic-gate vshowmode(gettext("R")); 6597c478bd9Sstevel@tonic-gate } else { 6607c478bd9Sstevel@tonic-gate vshowmode(gettext("REPLACE MODE")); 6617c478bd9Sstevel@tonic-gate } 6627c478bd9Sstevel@tonic-gate break; 6637c478bd9Sstevel@tonic-gate case 'i': 6647c478bd9Sstevel@tonic-gate if (value(vi_TERSE)) { 6657c478bd9Sstevel@tonic-gate vshowmode(gettext("I")); 6667c478bd9Sstevel@tonic-gate } else { 6677c478bd9Sstevel@tonic-gate vshowmode(gettext("INSERT MODE")); 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate break; 6707c478bd9Sstevel@tonic-gate case 'o': 6717c478bd9Sstevel@tonic-gate if (value(vi_TERSE)) { 6727c478bd9Sstevel@tonic-gate vshowmode(gettext("O")); 6737c478bd9Sstevel@tonic-gate } else { 6747c478bd9Sstevel@tonic-gate vshowmode(gettext("OPEN MODE")); 6757c478bd9Sstevel@tonic-gate } 6767c478bd9Sstevel@tonic-gate break; 6777c478bd9Sstevel@tonic-gate default: 6787c478bd9Sstevel@tonic-gate if (value(vi_TERSE)) { 6797c478bd9Sstevel@tonic-gate vshowmode(gettext("I")); 6807c478bd9Sstevel@tonic-gate } else { 6817c478bd9Sstevel@tonic-gate vshowmode(gettext("INPUT MODE")); 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate } 6847c478bd9Sstevel@tonic-gate strcLIN(gcursor); 685bbfd0aa6Scf46844 /* zero genbuf */ 6867c478bd9Sstevel@tonic-gate *gcursor = 0; 6877c478bd9Sstevel@tonic-gate cursor = linebuf; 6887c478bd9Sstevel@tonic-gate vgotoCL(nqcolumn(cursor - 1, genbuf)); 6893a5240e9Scf46844 } /* end for (;;) loop in vappend() */ 6903a5240e9Scf46844 6913a5240e9Scf46844 if (imultlinecnt && gotNL) { 6923a5240e9Scf46844 imultlinerep(savecnt, startsrcline, startsrccol, endsrccol); 6933a5240e9Scf46844 } else if (omultlinecnt) { 6943a5240e9Scf46844 omultlinerep(savecnt, startsrcline, endsrccol); 695bbfd0aa6Scf46844 #ifdef XPG6 696bbfd0aa6Scf46844 } else if (savecnt > 1 && ch == 'r' && gotNL) { 697bbfd0aa6Scf46844 /* 698bbfd0aa6Scf46844 * XPG6 assertion 313 & 254 : Position cursor for [count]r\n 699bbfd0aa6Scf46844 * then insert [count -1] newlines. 700bbfd0aa6Scf46844 */ 701bbfd0aa6Scf46844 endsrccol = gcursor - genbuf - 1; 702bbfd0aa6Scf46844 rmultlinerep(savecnt, endsrccol); 703bbfd0aa6Scf46844 #endif /* XPG6 */ 7047c478bd9Sstevel@tonic-gate } 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate /* 7077c478bd9Sstevel@tonic-gate * All done with insertion, position the cursor 7087c478bd9Sstevel@tonic-gate * and sync the screen. 7097c478bd9Sstevel@tonic-gate */ 7107c478bd9Sstevel@tonic-gate hold = oldhold; 7113a5240e9Scf46844 if ((imultlinecnt && gotNL) || omultlinecnt) { 7123a5240e9Scf46844 fixdisplay(); 713bbfd0aa6Scf46844 #ifdef XPG6 714bbfd0aa6Scf46844 } else if (savecnt > 1 && ch == 'r' && gotNL) { 715bbfd0aa6Scf46844 fixdisplay(); 716bbfd0aa6Scf46844 /* 717bbfd0aa6Scf46844 * XPG6 assertion 313 & 254 [count]r\n : Set flag to call 718bbfd0aa6Scf46844 * fixdisplay() after operate() has finished. To be sure that 719bbfd0aa6Scf46844 * the text (after the last \n followed by an indent) is always 720bbfd0aa6Scf46844 * displayed, fixdisplay() is called right before getting 721bbfd0aa6Scf46844 * the next command. 722bbfd0aa6Scf46844 */ 723bbfd0aa6Scf46844 redisplay = 1; 724bbfd0aa6Scf46844 #endif /* XPG6 */ 7253a5240e9Scf46844 } else if (cursor > linebuf) { 7267c478bd9Sstevel@tonic-gate cursor = lastchr(linebuf, cursor); 727bbfd0aa6Scf46844 #ifdef XPG6 728bbfd0aa6Scf46844 /* 729bbfd0aa6Scf46844 * XPG6 assertion 313 & 254 [count]r\n : 730bbfd0aa6Scf46844 * For 'r' command, when the replacement char causes new 731bbfd0aa6Scf46844 * lines to be created, point cursor to first non-blank. 732bbfd0aa6Scf46844 * The old code, ie: cursor = lastchr(linebuf, cursor); 733bbfd0aa6Scf46844 * set cursor to the blank before the first non-blank 734bbfd0aa6Scf46844 * for r\n 735bbfd0aa6Scf46844 */ 736bbfd0aa6Scf46844 if (ch == 'r' && gotNL && isblank((int)*cursor)) 737bbfd0aa6Scf46844 ++cursor; 738bbfd0aa6Scf46844 #endif /* XPG6 */ 7393a5240e9Scf46844 } 7407c478bd9Sstevel@tonic-gate if (state != HARDOPEN) 7417c478bd9Sstevel@tonic-gate vsyncCL(); 7427c478bd9Sstevel@tonic-gate else if (cursor > linebuf) 7437c478bd9Sstevel@tonic-gate back1(); 7447c478bd9Sstevel@tonic-gate doomed = 0; 7457c478bd9Sstevel@tonic-gate wcursor = cursor; 746f6db9f27Scf46844 (void) vmove(); 7477c478bd9Sstevel@tonic-gate } 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate /* 7503a5240e9Scf46844 * XPG6 7513a5240e9Scf46844 * To repeat multi-line input for [count]a, [count]A, [count]i, [count]I, 7523a5240e9Scf46844 * or a subsequent [count]. : 7533a5240e9Scf46844 * insert input count-1 more times. 7543a5240e9Scf46844 */ 7553a5240e9Scf46844 7563a5240e9Scf46844 static void 7573a5240e9Scf46844 imultlinerep(int savecnt, line *startsrcline, int startsrccol, int endsrccol) 7583a5240e9Scf46844 { 7593a5240e9Scf46844 int tmpcnt = 2; /* 1st insert counts as 1 repeat */ 7603a5240e9Scf46844 line *srcline, *endsrcline; 7613a5240e9Scf46844 size_t destsize = LBSIZE - endsrccol - 1; 7623a5240e9Scf46844 7633a5240e9Scf46844 endsrcline = dot; 7643a5240e9Scf46844 7653a5240e9Scf46844 /* Save linebuf into temp file before moving off the line. */ 7663a5240e9Scf46844 vsave(); 7673a5240e9Scf46844 7683a5240e9Scf46844 /* 7693a5240e9Scf46844 * At this point the temp file contains the first iteration of 7703a5240e9Scf46844 * a multi-line insert, and we need to repeat it savecnt - 1 7713a5240e9Scf46844 * more times in the temp file. dot is the last line in the 7723a5240e9Scf46844 * first iteration of the insert. Decrement dot so that 7733a5240e9Scf46844 * vdoappend() will append each new line before the last line. 7743a5240e9Scf46844 */ 7753a5240e9Scf46844 --dot; 7763a5240e9Scf46844 --vcline; 7773a5240e9Scf46844 /* 7783a5240e9Scf46844 * Use genbuf to rebuild the last line in the 1st iteration 7793a5240e9Scf46844 * of the repeated insert, then copy this line to the temp file. 7803a5240e9Scf46844 */ 7813a5240e9Scf46844 (void) strlcpy((char *)genbuf, (char *)linebuf, sizeof (genbuf)); 782*23a1cceaSRoger A. Faulkner getaline(*startsrcline); 7833a5240e9Scf46844 if (strlcpy((char *)(genbuf + endsrccol + 1), 7843a5240e9Scf46844 (char *)(linebuf + startsrccol), destsize) >= destsize) { 7853a5240e9Scf46844 error(gettext("Line too long")); 7863a5240e9Scf46844 } 7873a5240e9Scf46844 vdoappend(genbuf); 7883a5240e9Scf46844 vcline++; 7893a5240e9Scf46844 /* 7903a5240e9Scf46844 * Loop from the second line of the first iteration 7913a5240e9Scf46844 * through endsrcline, appending after dot. 7923a5240e9Scf46844 */ 7933a5240e9Scf46844 ++startsrcline; 7943a5240e9Scf46844 7953a5240e9Scf46844 while (tmpcnt <= savecnt) { 7963a5240e9Scf46844 for (srcline = startsrcline; srcline <= endsrcline; 7973a5240e9Scf46844 ++srcline) { 7983a5240e9Scf46844 if ((tmpcnt == savecnt) && 7993a5240e9Scf46844 (srcline == endsrcline)) { 8003a5240e9Scf46844 /* 8013a5240e9Scf46844 * The last line is already in place, 8023a5240e9Scf46844 * just make it the current line. 8033a5240e9Scf46844 */ 8043a5240e9Scf46844 vcline++; 8053a5240e9Scf46844 dot++; 8063a5240e9Scf46844 getDOT(); 8073a5240e9Scf46844 cursor = linebuf + endsrccol; 8083a5240e9Scf46844 } else { 809*23a1cceaSRoger A. Faulkner getaline(*srcline); 8103a5240e9Scf46844 /* copy linebuf to temp file */ 8113a5240e9Scf46844 vdoappend(linebuf); 8123a5240e9Scf46844 vcline++; 8133a5240e9Scf46844 } 8143a5240e9Scf46844 } 8153a5240e9Scf46844 ++tmpcnt; 8163a5240e9Scf46844 } 8173a5240e9Scf46844 } 8183a5240e9Scf46844 8193a5240e9Scf46844 /* 8203a5240e9Scf46844 * To repeat input for [count]o, [count]O, or a subsequent [count]. : 8213a5240e9Scf46844 * append input count-1 more times to the end of the already added 8223a5240e9Scf46844 * text, each time starting on a new line. 8233a5240e9Scf46844 */ 8243a5240e9Scf46844 8253a5240e9Scf46844 static void 8263a5240e9Scf46844 omultlinerep(int savecnt, line *startsrcline, int endsrccol) 8273a5240e9Scf46844 { 8283a5240e9Scf46844 int tmpcnt = 2; /* 1st insert counts as 1 repeat */ 8293a5240e9Scf46844 line *srcline, *endsrcline; 8303a5240e9Scf46844 8313a5240e9Scf46844 endsrcline = dot; 8323a5240e9Scf46844 /* Save linebuf into temp file before moving off the line. */ 8333a5240e9Scf46844 vsave(); 8343a5240e9Scf46844 8353a5240e9Scf46844 /* 8363a5240e9Scf46844 * Loop from the first line of the first iteration 8373a5240e9Scf46844 * through endsrcline, appending after dot. 8383a5240e9Scf46844 */ 8393a5240e9Scf46844 while (tmpcnt <= savecnt) { 8403a5240e9Scf46844 for (srcline = startsrcline; srcline <= endsrcline; ++srcline) { 841*23a1cceaSRoger A. Faulkner getaline(*srcline); 8423a5240e9Scf46844 /* copy linebuf to temp file */ 8433a5240e9Scf46844 vdoappend(linebuf); 8443a5240e9Scf46844 vcline++; 8453a5240e9Scf46844 } 8463a5240e9Scf46844 ++tmpcnt; 8473a5240e9Scf46844 } 8483a5240e9Scf46844 cursor = linebuf + endsrccol; 8493a5240e9Scf46844 } 8503a5240e9Scf46844 851bbfd0aa6Scf46844 #ifdef XPG6 852bbfd0aa6Scf46844 /* 853bbfd0aa6Scf46844 * XPG6 assertion 313 & 254 : To repeat '\n' for [count]r\n 854bbfd0aa6Scf46844 * insert '\n' savecnt-1 more times before the already added '\n'. 855bbfd0aa6Scf46844 */ 856bbfd0aa6Scf46844 857bbfd0aa6Scf46844 static void 858bbfd0aa6Scf46844 rmultlinerep(int savecnt, int endsrccol) 859bbfd0aa6Scf46844 { 860bbfd0aa6Scf46844 int tmpcnt = 2; /* 1st replacement counts as 1 repeat */ 861bbfd0aa6Scf46844 862bbfd0aa6Scf46844 /* Save linebuf into temp file before moving off the line. */ 863bbfd0aa6Scf46844 vsave(); 864bbfd0aa6Scf46844 /* 865bbfd0aa6Scf46844 * At this point the temp file contains the line followed by '\n', 866bbfd0aa6Scf46844 * which is preceded by indentation if autoindent is set. 867bbfd0aa6Scf46844 * '\n' must be repeated [savecnt - 1] more times in the temp file. 868bbfd0aa6Scf46844 * dot is the current line containing the '\n'. Decrement dot so that 869bbfd0aa6Scf46844 * vdoappend() will append each '\n' before the current '\n'. 870bbfd0aa6Scf46844 * This will allow only the last line to contain any autoindent 871bbfd0aa6Scf46844 * characters. 872bbfd0aa6Scf46844 */ 873bbfd0aa6Scf46844 --dot; 874bbfd0aa6Scf46844 --vcline; 875bbfd0aa6Scf46844 876bbfd0aa6Scf46844 /* 877bbfd0aa6Scf46844 * Append after dot. 878bbfd0aa6Scf46844 */ 879bbfd0aa6Scf46844 while (tmpcnt <= savecnt) { 880bbfd0aa6Scf46844 linebuf[0] = '\0'; 881bbfd0aa6Scf46844 /* append linebuf below current line in temp file */ 882bbfd0aa6Scf46844 vdoappend(linebuf); 883bbfd0aa6Scf46844 vcline++; 884bbfd0aa6Scf46844 ++tmpcnt; 885bbfd0aa6Scf46844 } 886bbfd0aa6Scf46844 /* set the current line to the line after the last '\n' */ 887bbfd0aa6Scf46844 ++dot; 888bbfd0aa6Scf46844 ++vcline; 889bbfd0aa6Scf46844 /* point cursor after (linebuf + endsrccol) */ 890bbfd0aa6Scf46844 vcursaft(linebuf + endsrccol); 891bbfd0aa6Scf46844 } 892bbfd0aa6Scf46844 #endif /* XPG6 */ 893bbfd0aa6Scf46844 8943a5240e9Scf46844 /* 8953a5240e9Scf46844 * Similiar to a ctrl-l, however always vrepaint() in case the last line 8963a5240e9Scf46844 * of the repeat would exceed the bottom of the screen. 8973a5240e9Scf46844 */ 8983a5240e9Scf46844 899bbfd0aa6Scf46844 void 9003a5240e9Scf46844 fixdisplay(void) 9013a5240e9Scf46844 { 9023a5240e9Scf46844 vclear(); 9033a5240e9Scf46844 vdirty(0, vcnt); 9043a5240e9Scf46844 if (state != VISUAL) { 9053a5240e9Scf46844 vclean(); 9063a5240e9Scf46844 vcnt = 0; 9073a5240e9Scf46844 vmoveto(dot, cursor, 0); 9083a5240e9Scf46844 } else { 9093a5240e9Scf46844 vredraw(WTOP); 9103a5240e9Scf46844 vrepaint(cursor); 9113a5240e9Scf46844 vfixcurs(); 9123a5240e9Scf46844 } 9133a5240e9Scf46844 } 9143a5240e9Scf46844 9153a5240e9Scf46844 /* 9167c478bd9Sstevel@tonic-gate * Subroutine for vgetline to back up a single character position, 9177c478bd9Sstevel@tonic-gate * backwards around end of lines (vgoto can't hack columns which are 9187c478bd9Sstevel@tonic-gate * less than 0 in general). 9197c478bd9Sstevel@tonic-gate */ 920f6db9f27Scf46844 void 921f6db9f27Scf46844 back1(void) 9227c478bd9Sstevel@tonic-gate { 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate vgoto(destline - 1, WCOLS + destcol - 1); 9257c478bd9Sstevel@tonic-gate } 9267c478bd9Sstevel@tonic-gate 9277c478bd9Sstevel@tonic-gate /* 9287c478bd9Sstevel@tonic-gate * Get a line into genbuf after gcursor. 9297c478bd9Sstevel@tonic-gate * Cnt limits the number of input characters 9307c478bd9Sstevel@tonic-gate * accepted and is used for handling the replace 9317c478bd9Sstevel@tonic-gate * single character command. Aescaped is the location 9327c478bd9Sstevel@tonic-gate * where we stick a termination indicator (whether we 9337c478bd9Sstevel@tonic-gate * ended with an ESCAPE or a newline/return. 9347c478bd9Sstevel@tonic-gate * 9357c478bd9Sstevel@tonic-gate * We do erase-kill type processing here and also 9367c478bd9Sstevel@tonic-gate * are careful about the way we do this so that it is 9377c478bd9Sstevel@tonic-gate * repeatable. (I.e. so that your kill doesn't happen, 9387c478bd9Sstevel@tonic-gate * when you repeat an insert if it was escaped with \ the 9397c478bd9Sstevel@tonic-gate * first time you did it. commch is the command character 9407c478bd9Sstevel@tonic-gate * involved, including the prompt for readline. 9417c478bd9Sstevel@tonic-gate */ 9427c478bd9Sstevel@tonic-gate unsigned char * 9437c478bd9Sstevel@tonic-gate vgetline(cnt, gcursor, aescaped, commch) 9447c478bd9Sstevel@tonic-gate int cnt; 945f6db9f27Scf46844 unsigned char *gcursor; 9467c478bd9Sstevel@tonic-gate bool *aescaped; 9477c478bd9Sstevel@tonic-gate unsigned char commch; 9487c478bd9Sstevel@tonic-gate { 949f6db9f27Scf46844 int c, ch; 950f6db9f27Scf46844 unsigned char *cp, *pcp; 9517c478bd9Sstevel@tonic-gate int x, y, iwhite, backsl=0; 9527c478bd9Sstevel@tonic-gate unsigned char *iglobp; 9537c478bd9Sstevel@tonic-gate int (*OO)() = Outchar; 9547c478bd9Sstevel@tonic-gate int length, width; 9557c478bd9Sstevel@tonic-gate unsigned char multic[MULTI_BYTE_MAX+1]; 9567c478bd9Sstevel@tonic-gate wchar_t wchar = 0; 9577c478bd9Sstevel@tonic-gate unsigned char *p; 9587c478bd9Sstevel@tonic-gate int len; 9597c478bd9Sstevel@tonic-gate 9607c478bd9Sstevel@tonic-gate 9617c478bd9Sstevel@tonic-gate /* 9627c478bd9Sstevel@tonic-gate * Clear the output state and counters 9637c478bd9Sstevel@tonic-gate * for autoindent backwards motion (counts of ^D, etc.) 9647c478bd9Sstevel@tonic-gate * Remember how much white space at beginning of line so 9657c478bd9Sstevel@tonic-gate * as not to allow backspace over autoindent. 9667c478bd9Sstevel@tonic-gate */ 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate *aescaped = 0; 9697c478bd9Sstevel@tonic-gate ogcursor = gcursor; 9707c478bd9Sstevel@tonic-gate flusho(); 9717c478bd9Sstevel@tonic-gate CDCNT = 0; 9727c478bd9Sstevel@tonic-gate HADUP = 0; 9737c478bd9Sstevel@tonic-gate HADZERO = 0; 9747c478bd9Sstevel@tonic-gate gobbled = 0; 9757c478bd9Sstevel@tonic-gate iwhite = whitecnt(genbuf); 9767c478bd9Sstevel@tonic-gate iglobp = vglobp; 9777c478bd9Sstevel@tonic-gate 9787c478bd9Sstevel@tonic-gate /* 9797c478bd9Sstevel@tonic-gate * Clear abbreviation recursive-use count 9807c478bd9Sstevel@tonic-gate */ 9817c478bd9Sstevel@tonic-gate abbrepcnt = 0; 9827c478bd9Sstevel@tonic-gate /* 9837c478bd9Sstevel@tonic-gate * Carefully avoid using vinschar in the echo area. 9847c478bd9Sstevel@tonic-gate */ 9857c478bd9Sstevel@tonic-gate if (splitw) 9867c478bd9Sstevel@tonic-gate Outchar = vputchar; 9877c478bd9Sstevel@tonic-gate else { 9887c478bd9Sstevel@tonic-gate Outchar = vinschar; 9897c478bd9Sstevel@tonic-gate vprepins(); 9907c478bd9Sstevel@tonic-gate } 9917c478bd9Sstevel@tonic-gate for (;;) { 9927c478bd9Sstevel@tonic-gate length = 0; 9937c478bd9Sstevel@tonic-gate backsl = 0; 9947c478bd9Sstevel@tonic-gate if (gobblebl) 9957c478bd9Sstevel@tonic-gate gobblebl--; 9967c478bd9Sstevel@tonic-gate if (cnt != 0) { 9977c478bd9Sstevel@tonic-gate cnt--; 9987c478bd9Sstevel@tonic-gate if (cnt == 0) 9997c478bd9Sstevel@tonic-gate goto vadone; 10007c478bd9Sstevel@tonic-gate } 10017c478bd9Sstevel@tonic-gate c = getkey(); 10027c478bd9Sstevel@tonic-gate if (c != ATTN) 10037c478bd9Sstevel@tonic-gate c &= 0377; 10047c478bd9Sstevel@tonic-gate ch = c; 10057c478bd9Sstevel@tonic-gate maphopcnt = 0; 10067c478bd9Sstevel@tonic-gate if (vglobp == 0 && Peekkey == 0 && commch != 'r') 10077c478bd9Sstevel@tonic-gate while ((ch = map(c, immacs, commch)) != c) { 10087c478bd9Sstevel@tonic-gate c = ch; 10097c478bd9Sstevel@tonic-gate if (!value(vi_REMAP)) 10107c478bd9Sstevel@tonic-gate break; 10117c478bd9Sstevel@tonic-gate if (++maphopcnt > 256) 10127c478bd9Sstevel@tonic-gate error(gettext("Infinite macro loop")); 10137c478bd9Sstevel@tonic-gate } 10147c478bd9Sstevel@tonic-gate if (!iglobp) { 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate /* 10177c478bd9Sstevel@tonic-gate * Erase-kill type processing. 10187c478bd9Sstevel@tonic-gate * Only happens if we were not reading 10197c478bd9Sstevel@tonic-gate * from untyped input when we started. 10207c478bd9Sstevel@tonic-gate * Map users erase to ^H, kill to -1 for switch. 10217c478bd9Sstevel@tonic-gate */ 10227c478bd9Sstevel@tonic-gate if (c == tty.c_cc[VERASE]) 10237c478bd9Sstevel@tonic-gate c = CTRL('h'); 10247c478bd9Sstevel@tonic-gate else if (c == tty.c_cc[VKILL]) 10257c478bd9Sstevel@tonic-gate c = -1; 10267c478bd9Sstevel@tonic-gate switch (c) { 10277c478bd9Sstevel@tonic-gate 10287c478bd9Sstevel@tonic-gate /* 10297c478bd9Sstevel@tonic-gate * ^? Interrupt drops you back to visual 10307c478bd9Sstevel@tonic-gate * command mode with an unread interrupt 10317c478bd9Sstevel@tonic-gate * still in the input buffer. 10327c478bd9Sstevel@tonic-gate * 10337c478bd9Sstevel@tonic-gate * ^\ Quit does the same as interrupt. 10347c478bd9Sstevel@tonic-gate * If you are a ex command rather than 10357c478bd9Sstevel@tonic-gate * a vi command this will drop you 10367c478bd9Sstevel@tonic-gate * back to command mode for sure. 10377c478bd9Sstevel@tonic-gate */ 10387c478bd9Sstevel@tonic-gate case ATTN: 10397c478bd9Sstevel@tonic-gate case QUIT: 10407c478bd9Sstevel@tonic-gate ungetkey(c); 10417c478bd9Sstevel@tonic-gate goto vadone; 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate /* 10447c478bd9Sstevel@tonic-gate * ^H Backs up a character in the input. 10457c478bd9Sstevel@tonic-gate * 10467c478bd9Sstevel@tonic-gate * BUG: Can't back around line boundaries. 10477c478bd9Sstevel@tonic-gate * This is hard because stuff has 10487c478bd9Sstevel@tonic-gate * already been saved for repeat. 10497c478bd9Sstevel@tonic-gate */ 10507c478bd9Sstevel@tonic-gate case CTRL('h'): 10517c478bd9Sstevel@tonic-gate bakchar: 10527c478bd9Sstevel@tonic-gate cp = lastchr(ogcursor, gcursor); 10537c478bd9Sstevel@tonic-gate if (cp < ogcursor) { 10547c478bd9Sstevel@tonic-gate if (splitw) { 10557c478bd9Sstevel@tonic-gate /* 10567c478bd9Sstevel@tonic-gate * Backspacing over readecho 10577c478bd9Sstevel@tonic-gate * prompt. Pretend delete but 10587c478bd9Sstevel@tonic-gate * don't beep. 10597c478bd9Sstevel@tonic-gate */ 10607c478bd9Sstevel@tonic-gate ungetkey(c); 10617c478bd9Sstevel@tonic-gate goto vadone; 10627c478bd9Sstevel@tonic-gate } 1063f6db9f27Scf46844 (void) beep(); 10647c478bd9Sstevel@tonic-gate continue; 10657c478bd9Sstevel@tonic-gate } 10667c478bd9Sstevel@tonic-gate goto vbackup; 10677c478bd9Sstevel@tonic-gate 10687c478bd9Sstevel@tonic-gate /* 10697c478bd9Sstevel@tonic-gate * ^W Back up a white/non-white word. 10707c478bd9Sstevel@tonic-gate */ 10717c478bd9Sstevel@tonic-gate case CTRL('w'): 10727c478bd9Sstevel@tonic-gate wdkind = 1; 10737c478bd9Sstevel@tonic-gate for (cp = gcursor; cp > ogcursor && isspace(cp[-1]); cp--) 10747c478bd9Sstevel@tonic-gate continue; 10757c478bd9Sstevel@tonic-gate pcp = lastchr(ogcursor, cp); 10767c478bd9Sstevel@tonic-gate for (c = wordch(pcp); 10777c478bd9Sstevel@tonic-gate cp > ogcursor && wordof(c, pcp); cp = pcp, pcp = lastchr(ogcursor, cp)) 10787c478bd9Sstevel@tonic-gate continue; 10797c478bd9Sstevel@tonic-gate goto vbackup; 10807c478bd9Sstevel@tonic-gate 10817c478bd9Sstevel@tonic-gate /* 10827c478bd9Sstevel@tonic-gate * users kill Kill input on this line, back to 10837c478bd9Sstevel@tonic-gate * the autoindent. 10847c478bd9Sstevel@tonic-gate */ 10857c478bd9Sstevel@tonic-gate case -1: 10867c478bd9Sstevel@tonic-gate cp = ogcursor; 10877c478bd9Sstevel@tonic-gate vbackup: 10887c478bd9Sstevel@tonic-gate if (cp == gcursor) { 1089f6db9f27Scf46844 (void) beep(); 10907c478bd9Sstevel@tonic-gate continue; 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate endim(); 10937c478bd9Sstevel@tonic-gate *cp = 0; 10947c478bd9Sstevel@tonic-gate c = cindent(); 10957c478bd9Sstevel@tonic-gate vgotoCL(nqcolumn(lastchr(linebuf, cursor), genbuf)); 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate if (doomed >= 0) 10987c478bd9Sstevel@tonic-gate doomed += c - cindent(); 10997c478bd9Sstevel@tonic-gate gcursor = cp; 11007c478bd9Sstevel@tonic-gate continue; 11017c478bd9Sstevel@tonic-gate 11027c478bd9Sstevel@tonic-gate /* 11037c478bd9Sstevel@tonic-gate * \ Followed by erase or kill 11047c478bd9Sstevel@tonic-gate * maps to just the erase or kill. 11057c478bd9Sstevel@tonic-gate */ 11067c478bd9Sstevel@tonic-gate case '\\': 11077c478bd9Sstevel@tonic-gate x = destcol, y = destline; 11087c478bd9Sstevel@tonic-gate putchar('\\'); 11097c478bd9Sstevel@tonic-gate vcsync(); 11107c478bd9Sstevel@tonic-gate c = getkey(); 11117c478bd9Sstevel@tonic-gate if (c == tty.c_cc[VERASE] 11127c478bd9Sstevel@tonic-gate || c == tty.c_cc[VKILL]) 11137c478bd9Sstevel@tonic-gate { 11147c478bd9Sstevel@tonic-gate vgoto(y, x); 11157c478bd9Sstevel@tonic-gate if (doomed >= 0) 11167c478bd9Sstevel@tonic-gate doomed++; 11177c478bd9Sstevel@tonic-gate multic[0] = wchar = c; 11187c478bd9Sstevel@tonic-gate length = 1; 11197c478bd9Sstevel@tonic-gate goto def; 11207c478bd9Sstevel@tonic-gate } 11217c478bd9Sstevel@tonic-gate ungetkey(c), c = '\\'; 11227c478bd9Sstevel@tonic-gate backsl = 1; 11237c478bd9Sstevel@tonic-gate break; 11247c478bd9Sstevel@tonic-gate 11257c478bd9Sstevel@tonic-gate /* 11267c478bd9Sstevel@tonic-gate * ^Q Super quote following character 11277c478bd9Sstevel@tonic-gate * Only ^@ is verboten (trapped at 11287c478bd9Sstevel@tonic-gate * a lower level) and \n forces a line 11297c478bd9Sstevel@tonic-gate * split so doesn't really go in. 11307c478bd9Sstevel@tonic-gate * 11317c478bd9Sstevel@tonic-gate * ^V Synonym for ^Q 11327c478bd9Sstevel@tonic-gate */ 11337c478bd9Sstevel@tonic-gate case CTRL('q'): 11347c478bd9Sstevel@tonic-gate case CTRL('v'): 11357c478bd9Sstevel@tonic-gate x = destcol, y = destline; 11367c478bd9Sstevel@tonic-gate putchar('^'); 11377c478bd9Sstevel@tonic-gate vgoto(y, x); 11387c478bd9Sstevel@tonic-gate c = getkey(); 11397c478bd9Sstevel@tonic-gate #ifdef USG 11407c478bd9Sstevel@tonic-gate if (c == ATTN) 11417c478bd9Sstevel@tonic-gate c = tty.c_cc[VINTR]; 11427c478bd9Sstevel@tonic-gate #endif 11437c478bd9Sstevel@tonic-gate if (c != NL) { 11447c478bd9Sstevel@tonic-gate if (doomed >= 0) 11457c478bd9Sstevel@tonic-gate doomed++; 11467c478bd9Sstevel@tonic-gate multic[0] = wchar = c; 11477c478bd9Sstevel@tonic-gate length = 1; 11487c478bd9Sstevel@tonic-gate goto def; 11497c478bd9Sstevel@tonic-gate } 11507c478bd9Sstevel@tonic-gate break; 11517c478bd9Sstevel@tonic-gate } 11527c478bd9Sstevel@tonic-gate } 11537c478bd9Sstevel@tonic-gate 11547c478bd9Sstevel@tonic-gate /* 11557c478bd9Sstevel@tonic-gate * If we get a blank not in the echo area 11567c478bd9Sstevel@tonic-gate * consider splitting the window in the wrapmargin. 11577c478bd9Sstevel@tonic-gate */ 11587c478bd9Sstevel@tonic-gate if(!backsl) { 11597c478bd9Sstevel@tonic-gate ungetkey(c); 11607c478bd9Sstevel@tonic-gate if((length = _mbftowc((char *)multic, &wchar, getkey, &Peekkey)) <= 0) { 1161f6db9f27Scf46844 (void) beep(); 11627c478bd9Sstevel@tonic-gate continue; 11637c478bd9Sstevel@tonic-gate } 11647c478bd9Sstevel@tonic-gate } else { 11657c478bd9Sstevel@tonic-gate length = 1; 11667c478bd9Sstevel@tonic-gate multic[0] = '\\'; 11677c478bd9Sstevel@tonic-gate } 11687c478bd9Sstevel@tonic-gate 11697c478bd9Sstevel@tonic-gate if (c != NL && !splitw) { 11707c478bd9Sstevel@tonic-gate if (c == ' ' && gobblebl) { 11717c478bd9Sstevel@tonic-gate gobbled = 1; 11727c478bd9Sstevel@tonic-gate continue; 11737c478bd9Sstevel@tonic-gate } 11747c478bd9Sstevel@tonic-gate if ((width = wcwidth(wchar)) <= 0) 11757c478bd9Sstevel@tonic-gate width = (wchar <= 0177 ? 1 : 4); 11767c478bd9Sstevel@tonic-gate if (value(vi_WRAPMARGIN) && 11777c478bd9Sstevel@tonic-gate (outcol + width - 1 >= OCOLUMNS - value(vi_WRAPMARGIN) || 11787c478bd9Sstevel@tonic-gate backsl && outcol==0) && 11797c478bd9Sstevel@tonic-gate commch != 'r') { 11807c478bd9Sstevel@tonic-gate /* 11817c478bd9Sstevel@tonic-gate * At end of word and hit wrapmargin. 11827c478bd9Sstevel@tonic-gate * Move the word to next line and keep going. 11837c478bd9Sstevel@tonic-gate */ 11847c478bd9Sstevel@tonic-gate unsigned char *wp; 11857c478bd9Sstevel@tonic-gate int bytelength; 11867c478bd9Sstevel@tonic-gate #ifndef PRESUNEUC 11877c478bd9Sstevel@tonic-gate unsigned char *tgcursor; 11887c478bd9Sstevel@tonic-gate wchar_t wc1, wc2; 11897c478bd9Sstevel@tonic-gate tgcursor = gcursor; 11907c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 11917c478bd9Sstevel@tonic-gate wdkind = 1; 11927c478bd9Sstevel@tonic-gate strncpy(gcursor, multic, length); 11937c478bd9Sstevel@tonic-gate gcursor += length; 11947c478bd9Sstevel@tonic-gate if (backsl) { 11957c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC 11967c478bd9Sstevel@tonic-gate if((length = mbftowc((char *)multic, &wchar, getkey, &Peekkey)) <= 0) { 11977c478bd9Sstevel@tonic-gate #else 11987c478bd9Sstevel@tonic-gate if((length = _mbftowc((char *)multic, &wchar, getkey, &Peekkey)) <= 0) { 11997c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 1200f6db9f27Scf46844 (void) beep(); 12017c478bd9Sstevel@tonic-gate continue; 12027c478bd9Sstevel@tonic-gate } 12037c478bd9Sstevel@tonic-gate strncpy(gcursor, multic, length); 12047c478bd9Sstevel@tonic-gate gcursor += length; 12057c478bd9Sstevel@tonic-gate } 12067c478bd9Sstevel@tonic-gate *gcursor = 0; 12077c478bd9Sstevel@tonic-gate /* 12087c478bd9Sstevel@tonic-gate * Find end of previous word if we are past it. 12097c478bd9Sstevel@tonic-gate */ 12107c478bd9Sstevel@tonic-gate for (cp=gcursor; cp>ogcursor && isspace(cp[-1]); cp--) 12117c478bd9Sstevel@tonic-gate ; 12127c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC 12137c478bd9Sstevel@tonic-gate /* find screen width of previous word */ 12147c478bd9Sstevel@tonic-gate width = 0; 12157c478bd9Sstevel@tonic-gate for(wp = cp; *wp; ) 12167c478bd9Sstevel@tonic-gate #else 12177c478bd9Sstevel@tonic-gate /* count screen width of pending characters */ 12187c478bd9Sstevel@tonic-gate width = 0; 12197c478bd9Sstevel@tonic-gate for(wp = tgcursor; wp < cp;) 12207c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 12217c478bd9Sstevel@tonic-gate if((bytelength = mbtowc(&wchar, (char *)wp, MULTI_BYTE_MAX)) < 0) { 12227c478bd9Sstevel@tonic-gate width+=4; 12237c478bd9Sstevel@tonic-gate wp++; 12247c478bd9Sstevel@tonic-gate } else { 12257c478bd9Sstevel@tonic-gate int curwidth = wcwidth(wchar); 12267c478bd9Sstevel@tonic-gate if(curwidth <= 0) 12277c478bd9Sstevel@tonic-gate width += (*wp < 0200 ? 2 : 4); 12287c478bd9Sstevel@tonic-gate else 12297c478bd9Sstevel@tonic-gate width += curwidth; 12307c478bd9Sstevel@tonic-gate wp += bytelength; 12317c478bd9Sstevel@tonic-gate } 12327c478bd9Sstevel@tonic-gate 12337c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC 12347c478bd9Sstevel@tonic-gate if (outcol+(backsl?OCOLUMNS:0) - width >= OCOLUMNS - value(vi_WRAPMARGIN)) { 12357c478bd9Sstevel@tonic-gate #else 12367c478bd9Sstevel@tonic-gate if (outcol+(backsl?OCOLUMNS:0) + width -1 >= OCOLUMNS - value(vi_WRAPMARGIN)) { 12377c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 12387c478bd9Sstevel@tonic-gate /* 12397c478bd9Sstevel@tonic-gate * Find beginning of previous word. 12407c478bd9Sstevel@tonic-gate */ 12417c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC 12427c478bd9Sstevel@tonic-gate for (; cp>ogcursor && !isspace(cp[-1]); cp--) 12437c478bd9Sstevel@tonic-gate ; 12447c478bd9Sstevel@tonic-gate #else 12457c478bd9Sstevel@tonic-gate wc1 = wc2 = 0; 12467c478bd9Sstevel@tonic-gate while (cp>ogcursor) { 12477c478bd9Sstevel@tonic-gate if (isspace(cp[-1])) { 12487c478bd9Sstevel@tonic-gate break; 12497c478bd9Sstevel@tonic-gate } 12507c478bd9Sstevel@tonic-gate if (!multibyte) { 12517c478bd9Sstevel@tonic-gate cp--; 12527c478bd9Sstevel@tonic-gate continue; 12537c478bd9Sstevel@tonic-gate } 12547c478bd9Sstevel@tonic-gate wp = (unsigned char *)(cp - 12557c478bd9Sstevel@tonic-gate MB_CUR_MAX); 12567c478bd9Sstevel@tonic-gate if (wp < ogcursor) 12577c478bd9Sstevel@tonic-gate wp = ogcursor; 12587c478bd9Sstevel@tonic-gate while (cp > wp) { 12597c478bd9Sstevel@tonic-gate /* 7tabs */if (wc2) { 12607c478bd9Sstevel@tonic-gate /* 7tabs */ if ((bytelength = mbtowc(&wc1, (char *)wp, cp-wp)) != cp-wp) { 12617c478bd9Sstevel@tonic-gate /* 7tabs */ wp++; 12627c478bd9Sstevel@tonic-gate /* 7tabs */ wc1 = 0; 12637c478bd9Sstevel@tonic-gate /* 7tabs */ continue; 12647c478bd9Sstevel@tonic-gate /* 7tabs */ } 12657c478bd9Sstevel@tonic-gate /* 7tabs */} else { 12667c478bd9Sstevel@tonic-gate /* 7tabs */ if ((bytelength = mbtowc(&wc2, (char *)wp, cp-wp)) != cp-wp) { 12677c478bd9Sstevel@tonic-gate /* 7tabs */ wp++; 12687c478bd9Sstevel@tonic-gate /* 7tabs */ wc2 = 0; 12697c478bd9Sstevel@tonic-gate /* 7tabs */ continue; 12707c478bd9Sstevel@tonic-gate /* 7tabs */ } 12717c478bd9Sstevel@tonic-gate /* 7tabs */} 12727c478bd9Sstevel@tonic-gate /* 7tabs */if (wc1) { 12737c478bd9Sstevel@tonic-gate /* 7tabs */ if (wdbdg && (!iswascii(wc1) || !iswascii(wc2))) { 12747c478bd9Sstevel@tonic-gate /* 7tabs */ if ((*wdbdg)(wc1, wc2, 2) < 5) { 12757c478bd9Sstevel@tonic-gate /* 7tabs */ goto ws; 12767c478bd9Sstevel@tonic-gate /* 7tabs */ } 12777c478bd9Sstevel@tonic-gate /* 7tabs */ } 12787c478bd9Sstevel@tonic-gate /* 7tabs */ wc2 = wc1; 12797c478bd9Sstevel@tonic-gate /* 7tabs */ wc1 = 0; 12807c478bd9Sstevel@tonic-gate /* 7tabs */ cp -= bytelength - 1; 12817c478bd9Sstevel@tonic-gate /* 7tabs */ break; 12827c478bd9Sstevel@tonic-gate /* 7tabs */} else { 12837c478bd9Sstevel@tonic-gate /* 7tabs */ cp -= bytelength - 1; 12847c478bd9Sstevel@tonic-gate /* 7tabs */ break; 12857c478bd9Sstevel@tonic-gate /* 7tabs */} 12867c478bd9Sstevel@tonic-gate } 12877c478bd9Sstevel@tonic-gate cp--; 12887c478bd9Sstevel@tonic-gate } 12897c478bd9Sstevel@tonic-gate ws: 12907c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 12917c478bd9Sstevel@tonic-gate if (cp <= ogcursor) { 12927c478bd9Sstevel@tonic-gate /* 12937c478bd9Sstevel@tonic-gate * There is a single word that 12947c478bd9Sstevel@tonic-gate * is too long to fit. Just 12957c478bd9Sstevel@tonic-gate * let it pass, but beep for 12967c478bd9Sstevel@tonic-gate * each new letter to warn 12977c478bd9Sstevel@tonic-gate * the luser. 12987c478bd9Sstevel@tonic-gate */ 12997c478bd9Sstevel@tonic-gate gcursor -= length; 13007c478bd9Sstevel@tonic-gate c = *gcursor; 13017c478bd9Sstevel@tonic-gate *gcursor = 0; 1302f6db9f27Scf46844 (void) beep(); 13037c478bd9Sstevel@tonic-gate goto dontbreak; 13047c478bd9Sstevel@tonic-gate } 13057c478bd9Sstevel@tonic-gate /* 13067c478bd9Sstevel@tonic-gate * Save it for next line. 13077c478bd9Sstevel@tonic-gate */ 13087c478bd9Sstevel@tonic-gate macpush(cp, 0); 13097c478bd9Sstevel@tonic-gate #ifdef PRESUNEUC 13107c478bd9Sstevel@tonic-gate cp--; 13117c478bd9Sstevel@tonic-gate #endif /* PRESUNEUC */ 13127c478bd9Sstevel@tonic-gate } 13137c478bd9Sstevel@tonic-gate macpush("\n", 0); 13147c478bd9Sstevel@tonic-gate /* 13157c478bd9Sstevel@tonic-gate * Erase white space before the word. 13167c478bd9Sstevel@tonic-gate */ 13177c478bd9Sstevel@tonic-gate while (cp > ogcursor && isspace(cp[-1])) 13187c478bd9Sstevel@tonic-gate cp--; /* skip blank */ 13197c478bd9Sstevel@tonic-gate gobblebl = 3; 13207c478bd9Sstevel@tonic-gate goto vbackup; 13217c478bd9Sstevel@tonic-gate } 13227c478bd9Sstevel@tonic-gate dontbreak:; 13237c478bd9Sstevel@tonic-gate } 13247c478bd9Sstevel@tonic-gate 13257c478bd9Sstevel@tonic-gate /* 13267c478bd9Sstevel@tonic-gate * Word abbreviation mode. 13277c478bd9Sstevel@tonic-gate */ 13287c478bd9Sstevel@tonic-gate if (anyabbrs && gcursor > ogcursor && !wordch(multic) && wordch(lastchr(ogcursor, gcursor))) { 13297c478bd9Sstevel@tonic-gate int wdtype, abno; 13307c478bd9Sstevel@tonic-gate 13317c478bd9Sstevel@tonic-gate multic[length] = 0; 13327c478bd9Sstevel@tonic-gate wdkind = 1; 13337c478bd9Sstevel@tonic-gate cp = lastchr(ogcursor, gcursor); 13347c478bd9Sstevel@tonic-gate pcp = lastchr(ogcursor, cp); 13357c478bd9Sstevel@tonic-gate for (wdtype = wordch(pcp); 13367c478bd9Sstevel@tonic-gate cp > ogcursor && wordof(wdtype, pcp); cp = pcp, pcp = lastchr(ogcursor, pcp)) 13377c478bd9Sstevel@tonic-gate ; 13387c478bd9Sstevel@tonic-gate *gcursor = 0; 13397c478bd9Sstevel@tonic-gate for (abno=0; abbrevs[abno].mapto; abno++) { 13407c478bd9Sstevel@tonic-gate if (eq(cp, abbrevs[abno].cap)) { 13417c478bd9Sstevel@tonic-gate if(abbrepcnt == 0) { 13427c478bd9Sstevel@tonic-gate if(reccnt(abbrevs[abno].cap, abbrevs[abno].mapto)) 13437c478bd9Sstevel@tonic-gate abbrepcnt = 1; 13447c478bd9Sstevel@tonic-gate macpush(multic, 0); 13457c478bd9Sstevel@tonic-gate macpush(abbrevs[abno].mapto); 13467c478bd9Sstevel@tonic-gate goto vbackup; 13477c478bd9Sstevel@tonic-gate } else 13487c478bd9Sstevel@tonic-gate abbrepcnt = 0; 13497c478bd9Sstevel@tonic-gate } 13507c478bd9Sstevel@tonic-gate } 13517c478bd9Sstevel@tonic-gate } 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate switch (c) { 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate /* 13567c478bd9Sstevel@tonic-gate * ^M Except in repeat maps to \n. 13577c478bd9Sstevel@tonic-gate */ 13587c478bd9Sstevel@tonic-gate case CR: 13597c478bd9Sstevel@tonic-gate if (vglobp) { 13607c478bd9Sstevel@tonic-gate multic[0] = wchar = c; 13617c478bd9Sstevel@tonic-gate length = 1; 13627c478bd9Sstevel@tonic-gate goto def; 13637c478bd9Sstevel@tonic-gate } 13647c478bd9Sstevel@tonic-gate c = '\n'; 13657c478bd9Sstevel@tonic-gate /* presto chango ... */ 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate /* 13687c478bd9Sstevel@tonic-gate * \n Start new line. 13697c478bd9Sstevel@tonic-gate */ 13707c478bd9Sstevel@tonic-gate case NL: 13717c478bd9Sstevel@tonic-gate *aescaped = c; 13727c478bd9Sstevel@tonic-gate goto vadone; 13737c478bd9Sstevel@tonic-gate 13747c478bd9Sstevel@tonic-gate /* 13757c478bd9Sstevel@tonic-gate * escape End insert unless repeat and more to repeat. 13767c478bd9Sstevel@tonic-gate */ 13777c478bd9Sstevel@tonic-gate case ESCAPE: 13787c478bd9Sstevel@tonic-gate if (lastvgk) { 13797c478bd9Sstevel@tonic-gate multic[0] = wchar = c; 13807c478bd9Sstevel@tonic-gate length = 1; 13817c478bd9Sstevel@tonic-gate goto def; 13827c478bd9Sstevel@tonic-gate } 13837c478bd9Sstevel@tonic-gate goto vadone; 13847c478bd9Sstevel@tonic-gate 13857c478bd9Sstevel@tonic-gate /* 13867c478bd9Sstevel@tonic-gate * ^D Backtab. 13877c478bd9Sstevel@tonic-gate * ^T Software forward tab. 13887c478bd9Sstevel@tonic-gate * 13897c478bd9Sstevel@tonic-gate * Unless in repeat where this means these 13907c478bd9Sstevel@tonic-gate * were superquoted in. 13917c478bd9Sstevel@tonic-gate */ 13927c478bd9Sstevel@tonic-gate case CTRL('t'): 13937c478bd9Sstevel@tonic-gate if (vglobp) { 13947c478bd9Sstevel@tonic-gate multic[0] = wchar = c; 13957c478bd9Sstevel@tonic-gate length = 1; 13967c478bd9Sstevel@tonic-gate goto def; 13977c478bd9Sstevel@tonic-gate } 13987c478bd9Sstevel@tonic-gate /* fall into ... */ 13997c478bd9Sstevel@tonic-gate 14007c478bd9Sstevel@tonic-gate *gcursor = 0; 14017c478bd9Sstevel@tonic-gate cp = vpastwh(genbuf); 14027c478bd9Sstevel@tonic-gate c = whitecnt(genbuf); 14037c478bd9Sstevel@tonic-gate if (ch == CTRL('t')) { 14047c478bd9Sstevel@tonic-gate /* 14057c478bd9Sstevel@tonic-gate * ^t just generates new indent replacing 14067c478bd9Sstevel@tonic-gate * current white space rounded up to soft 14077c478bd9Sstevel@tonic-gate * tab stop increment. 14087c478bd9Sstevel@tonic-gate */ 14097c478bd9Sstevel@tonic-gate if (cp != gcursor) 14107c478bd9Sstevel@tonic-gate /* 14117c478bd9Sstevel@tonic-gate * BUG: Don't hack ^T except 14127c478bd9Sstevel@tonic-gate * right after initial 14137c478bd9Sstevel@tonic-gate * white space. 14147c478bd9Sstevel@tonic-gate */ 14157c478bd9Sstevel@tonic-gate continue; 14167c478bd9Sstevel@tonic-gate cp = genindent(iwhite = backtab(c + value(vi_SHIFTWIDTH) + 1)); 14177c478bd9Sstevel@tonic-gate ogcursor = cp; 14187c478bd9Sstevel@tonic-gate goto vbackup; 14197c478bd9Sstevel@tonic-gate } 14207c478bd9Sstevel@tonic-gate /* 14217c478bd9Sstevel@tonic-gate * ^D works only if we are at the (end of) the 14227c478bd9Sstevel@tonic-gate * generated autoindent. We count the ^D for repeat 14237c478bd9Sstevel@tonic-gate * purposes. 14247c478bd9Sstevel@tonic-gate */ 14257c478bd9Sstevel@tonic-gate case CTRL('d'): 14267c478bd9Sstevel@tonic-gate /* check if ^d was superquoted in */ 14277c478bd9Sstevel@tonic-gate if(vglobp && inscdcnt <= 0) { 14287c478bd9Sstevel@tonic-gate multic[0] = wchar = c; 14297c478bd9Sstevel@tonic-gate length = 1; 14307c478bd9Sstevel@tonic-gate goto def; 14317c478bd9Sstevel@tonic-gate } 14327c478bd9Sstevel@tonic-gate if(vglobp) 14337c478bd9Sstevel@tonic-gate inscdcnt--; 14347c478bd9Sstevel@tonic-gate *gcursor = 0; 14357c478bd9Sstevel@tonic-gate cp = vpastwh(genbuf); 14367c478bd9Sstevel@tonic-gate c = whitecnt(genbuf); 14377c478bd9Sstevel@tonic-gate if (c == iwhite && c != 0) 14387c478bd9Sstevel@tonic-gate if (cp == gcursor) { 14397c478bd9Sstevel@tonic-gate iwhite = backtab(c); 14407c478bd9Sstevel@tonic-gate CDCNT++; 14417c478bd9Sstevel@tonic-gate ogcursor = cp = genindent(iwhite); 14427c478bd9Sstevel@tonic-gate goto vbackup; 14437c478bd9Sstevel@tonic-gate } else if (&cp[1] == gcursor && 14447c478bd9Sstevel@tonic-gate (*cp == '^' || *cp == '0')) { 14457c478bd9Sstevel@tonic-gate /* 14467c478bd9Sstevel@tonic-gate * ^^D moves to margin, then back 14477c478bd9Sstevel@tonic-gate * to current indent on next line. 14487c478bd9Sstevel@tonic-gate * 14497c478bd9Sstevel@tonic-gate * 0^D moves to margin and then 14507c478bd9Sstevel@tonic-gate * stays there. 14517c478bd9Sstevel@tonic-gate */ 14527c478bd9Sstevel@tonic-gate HADZERO = *cp == '0'; 14537c478bd9Sstevel@tonic-gate ogcursor = cp = genbuf; 14547c478bd9Sstevel@tonic-gate HADUP = 1 - HADZERO; 14557c478bd9Sstevel@tonic-gate CDCNT = 1; 14567c478bd9Sstevel@tonic-gate endim(); 14577c478bd9Sstevel@tonic-gate back1(); 1458f6db9f27Scf46844 (void) vputchar(' '); 14597c478bd9Sstevel@tonic-gate goto vbackup; 14607c478bd9Sstevel@tonic-gate } 14617c478bd9Sstevel@tonic-gate 14627c478bd9Sstevel@tonic-gate if (vglobp && vglobp - iglobp >= 2) { 14637c478bd9Sstevel@tonic-gate if ((p = vglobp - MB_CUR_MAX) < iglobp) 14647c478bd9Sstevel@tonic-gate p = iglobp; 14657c478bd9Sstevel@tonic-gate for ( ; p < &vglobp[-2]; p += len) { 14667c478bd9Sstevel@tonic-gate if ((len = mblen((char *)p, MB_CUR_MAX)) <= 0) 14677c478bd9Sstevel@tonic-gate len = 1; 14687c478bd9Sstevel@tonic-gate } 14697c478bd9Sstevel@tonic-gate if ((p == &vglobp[-2]) && 14707c478bd9Sstevel@tonic-gate (*p == '^' || *p == '0') && 14717c478bd9Sstevel@tonic-gate gcursor == ogcursor + 1) 14727c478bd9Sstevel@tonic-gate goto bakchar; 14737c478bd9Sstevel@tonic-gate } 14747c478bd9Sstevel@tonic-gate continue; 14757c478bd9Sstevel@tonic-gate 14767c478bd9Sstevel@tonic-gate default: 14777c478bd9Sstevel@tonic-gate /* 14787c478bd9Sstevel@tonic-gate * Possibly discard control inputs. 14797c478bd9Sstevel@tonic-gate */ 14807c478bd9Sstevel@tonic-gate if (!vglobp && junk(c)) { 1481f6db9f27Scf46844 (void) beep(); 14827c478bd9Sstevel@tonic-gate continue; 14837c478bd9Sstevel@tonic-gate } 14847c478bd9Sstevel@tonic-gate def: 14857c478bd9Sstevel@tonic-gate if (!backsl) { 14867c478bd9Sstevel@tonic-gate putchar(wchar); 14877c478bd9Sstevel@tonic-gate flush(); 14887c478bd9Sstevel@tonic-gate } 14897c478bd9Sstevel@tonic-gate if (gcursor + length - 1 > &genbuf[LBSIZE - 2]) 14907c478bd9Sstevel@tonic-gate error(gettext("Line too long")); 14917c478bd9Sstevel@tonic-gate (void)strncpy(gcursor, multic, length); 14927c478bd9Sstevel@tonic-gate gcursor += length; 14937c478bd9Sstevel@tonic-gate vcsync(); 14947c478bd9Sstevel@tonic-gate if (value(vi_SHOWMATCH) && !iglobp) 14957c478bd9Sstevel@tonic-gate if (c == ')' || c == '}') 14967c478bd9Sstevel@tonic-gate lsmatch(gcursor); 14977c478bd9Sstevel@tonic-gate continue; 14987c478bd9Sstevel@tonic-gate } 14997c478bd9Sstevel@tonic-gate } 15007c478bd9Sstevel@tonic-gate vadone: 15017c478bd9Sstevel@tonic-gate *gcursor = 0; 15027c478bd9Sstevel@tonic-gate if (Outchar != termchar) 15037c478bd9Sstevel@tonic-gate Outchar = OO; 15047c478bd9Sstevel@tonic-gate endim(); 15057c478bd9Sstevel@tonic-gate return (gcursor); 15067c478bd9Sstevel@tonic-gate } 15077c478bd9Sstevel@tonic-gate 15087c478bd9Sstevel@tonic-gate int vgetsplit(); 15097c478bd9Sstevel@tonic-gate unsigned char *vsplitpt; 15107c478bd9Sstevel@tonic-gate 15117c478bd9Sstevel@tonic-gate /* 15127c478bd9Sstevel@tonic-gate * Append the line in buffer at lp 15137c478bd9Sstevel@tonic-gate * to the buffer after dot. 15147c478bd9Sstevel@tonic-gate */ 1515f6db9f27Scf46844 void 1516f6db9f27Scf46844 vdoappend(unsigned char *lp) 15177c478bd9Sstevel@tonic-gate { 1518f6db9f27Scf46844 int oing = inglobal; 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate vsplitpt = lp; 15217c478bd9Sstevel@tonic-gate inglobal = 1; 15227c478bd9Sstevel@tonic-gate (void)append(vgetsplit, dot); 15237c478bd9Sstevel@tonic-gate inglobal = oing; 15247c478bd9Sstevel@tonic-gate } 15257c478bd9Sstevel@tonic-gate 15267c478bd9Sstevel@tonic-gate /* 15277c478bd9Sstevel@tonic-gate * Subroutine for vdoappend to pass to append. 15287c478bd9Sstevel@tonic-gate */ 1529f6db9f27Scf46844 int 1530f6db9f27Scf46844 vgetsplit(void) 15317c478bd9Sstevel@tonic-gate { 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate if (vsplitpt == 0) 15347c478bd9Sstevel@tonic-gate return (EOF); 15357c478bd9Sstevel@tonic-gate strcLIN(vsplitpt); 15367c478bd9Sstevel@tonic-gate vsplitpt = 0; 15377c478bd9Sstevel@tonic-gate return (0); 15387c478bd9Sstevel@tonic-gate } 15397c478bd9Sstevel@tonic-gate 15407c478bd9Sstevel@tonic-gate /* 15417c478bd9Sstevel@tonic-gate * Vmaxrep determines the maximum repetition factor 15427c478bd9Sstevel@tonic-gate * allowed that will yield total line length less than 15437c478bd9Sstevel@tonic-gate * LBSIZE characters and also does hacks for the R command. 15447c478bd9Sstevel@tonic-gate */ 1545f6db9f27Scf46844 int 1546f6db9f27Scf46844 vmaxrep(unsigned char ch, int cnt) 15477c478bd9Sstevel@tonic-gate { 1548f6db9f27Scf46844 int len; 15497c478bd9Sstevel@tonic-gate unsigned char *cp; 15507c478bd9Sstevel@tonic-gate int repcnt, oldcnt, replen; 15517c478bd9Sstevel@tonic-gate if (cnt > LBSIZE - 2) 15527c478bd9Sstevel@tonic-gate cnt = LBSIZE - 2; 15537c478bd9Sstevel@tonic-gate if (ch == 'R') { 15547c478bd9Sstevel@tonic-gate len = strlen(cursor); 15557c478bd9Sstevel@tonic-gate oldcnt = 0; 15567c478bd9Sstevel@tonic-gate for(cp = cursor; *cp; ) { 15577c478bd9Sstevel@tonic-gate oldcnt++; 15587c478bd9Sstevel@tonic-gate cp = nextchr(cp); 15597c478bd9Sstevel@tonic-gate } 15607c478bd9Sstevel@tonic-gate repcnt = 0; 15617c478bd9Sstevel@tonic-gate for(cp = genbuf; *cp; ) { 15627c478bd9Sstevel@tonic-gate repcnt++; 15637c478bd9Sstevel@tonic-gate cp = nextchr(cp); 15647c478bd9Sstevel@tonic-gate } 15657c478bd9Sstevel@tonic-gate /* 15667c478bd9Sstevel@tonic-gate * if number of characters in replacement string 15677c478bd9Sstevel@tonic-gate * (repcnt) is less than number of characters following 15687c478bd9Sstevel@tonic-gate * cursor (oldcnt), find end of repcnt 15697c478bd9Sstevel@tonic-gate * characters after cursor 15707c478bd9Sstevel@tonic-gate */ 15717c478bd9Sstevel@tonic-gate if(repcnt < oldcnt) { 15727c478bd9Sstevel@tonic-gate for(cp = cursor; repcnt > 0; repcnt--) 15737c478bd9Sstevel@tonic-gate cp = nextchr(cp); 15747c478bd9Sstevel@tonic-gate len = cp - cursor; 15757c478bd9Sstevel@tonic-gate } 15767c478bd9Sstevel@tonic-gate CP(cursor, cursor + len); 15777c478bd9Sstevel@tonic-gate vUD2 += len; 15787c478bd9Sstevel@tonic-gate } 15797c478bd9Sstevel@tonic-gate len = strlen(linebuf); 15807c478bd9Sstevel@tonic-gate replen = strlen(genbuf); 15817c478bd9Sstevel@tonic-gate if (len + cnt * replen <= LBSIZE - 2) 15827c478bd9Sstevel@tonic-gate return (cnt); 15837c478bd9Sstevel@tonic-gate cnt = (LBSIZE - 2 - len) / replen; 15847c478bd9Sstevel@tonic-gate if (cnt == 0) { 15857c478bd9Sstevel@tonic-gate vsave(); 15867c478bd9Sstevel@tonic-gate error(gettext("Line too long")); 15877c478bd9Sstevel@tonic-gate } 15887c478bd9Sstevel@tonic-gate return (cnt); 15897c478bd9Sstevel@tonic-gate } 15907c478bd9Sstevel@tonic-gate 15917c478bd9Sstevel@tonic-gate /* 15927c478bd9Sstevel@tonic-gate * Determine how many occurrences of word 'CAP' are in 'MAPTO'. To be 15937c478bd9Sstevel@tonic-gate * considered an occurrence there must be both a nonword-prefix, a 15947c478bd9Sstevel@tonic-gate * complete match of 'CAP' within 'MAPTO', and a nonword-suffix. 15957c478bd9Sstevel@tonic-gate * Note that the beginning and end of 'MAPTO' are considered to be 15967c478bd9Sstevel@tonic-gate * valid nonword delimiters. 15977c478bd9Sstevel@tonic-gate */ 1598f6db9f27Scf46844 int 1599f6db9f27Scf46844 reccnt(unsigned char *cap, unsigned char *mapto) 16007c478bd9Sstevel@tonic-gate { 1601f6db9f27Scf46844 int i, cnt, final; 16027c478bd9Sstevel@tonic-gate 16037c478bd9Sstevel@tonic-gate cnt = 0; 16047c478bd9Sstevel@tonic-gate final = strlen(mapto) - strlen(cap); 16057c478bd9Sstevel@tonic-gate 16067c478bd9Sstevel@tonic-gate for (i=0; i <= final; i++) 16077c478bd9Sstevel@tonic-gate if ((strncmp(cap, mapto+i, strlen(cap)) == 0) /* match */ 16087c478bd9Sstevel@tonic-gate && (i == 0 || !wordch(&mapto[i-1])) /* prefix ok */ 16097c478bd9Sstevel@tonic-gate && (i == final || !wordch(&mapto[i+strlen(cap)]))) /* suffix ok */ 16107c478bd9Sstevel@tonic-gate cnt++; 16117c478bd9Sstevel@tonic-gate return (cnt); 16127c478bd9Sstevel@tonic-gate } 16137c478bd9Sstevel@tonic-gate 1614