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
bleep(int i,unsigned char * cp)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
vdcMID(void)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
takeout(unsigned char * BUF)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
ateopr(void)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
vappend(int ch,int cnt,int indent)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
imultlinerep(int savecnt,line * startsrcline,int startsrccol,int endsrccol)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
omultlinerep(int savecnt,line * startsrcline,int endsrccol)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
rmultlinerep(int savecnt,int endsrccol)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
fixdisplay(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
back1(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 *
vgetline(cnt,gcursor,aescaped,commch)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
vdoappend(unsigned char * lp)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
vgetsplit(void)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
vmaxrep(unsigned char ch,int cnt)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
reccnt(unsigned char * cap,unsigned char * mapto)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