4.4BSD snapshot (revision 8.1)
[unix-history] / usr / src / usr.bin / ex / ex_vops2.c
CommitLineData
dac571dd
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
eb035710 8static char sccsid[] = "@(#)ex_vops2.c 8.1 (Berkeley) %G%";
dac571dd
DF
9#endif not lint
10
09035cec
MH
11#include "ex.h"
12#include "ex_tty.h"
13#include "ex_vis.h"
14
15/*
16 * Low level routines for operations sequences,
17 * and mostly, insert mode (and a subroutine
18 * to read an input line, including in the echo area.)
19 */
299f2784
MH
20extern char *vUA1, *vUA2; /* mjm: extern; also in ex_vops.c */
21extern char *vUD1, *vUD2; /* mjm: extern; also in ex_vops.c */
09035cec
MH
22
23/*
24 * Obleeperate characters in hardcopy
25 * open with \'s.
26 */
27bleep(i, cp)
28 register int i;
29 char *cp;
30{
31
32 i -= column(cp);
33 do
5a6c967e 34 ex_putchar('\\' | QUOTE);
09035cec
MH
35 while (--i >= 0);
36 rubble = 1;
37}
38
39/*
40 * Common code for middle part of delete
41 * and change operating on parts of lines.
42 */
43vdcMID()
44{
45 register char *cp;
46
47 squish();
48 setLAST();
887e3e0d
MH
49 if (FIXUNDO)
50 vundkind = VCHNG, CP(vutmp, linebuf);
09035cec
MH
51 if (wcursor < cursor)
52 cp = wcursor, wcursor = cursor, cursor = cp;
53 vUD1 = vUA1 = vUA2 = cursor; vUD2 = wcursor;
54 return (column(wcursor - 1));
55}
56
57/*
58 * Take text from linebuf and stick it
59 * in the VBSIZE buffer BUF. Used to save
60 * deleted text of part of line.
61 */
62takeout(BUF)
63 char *BUF;
64{
65 register char *cp;
66
67 if (wcursor < linebuf)
68 wcursor = linebuf;
69 if (cursor == wcursor) {
70 beep();
71 return;
72 }
73 if (wcursor < cursor) {
74 cp = wcursor;
75 wcursor = cursor;
76 cursor = cp;
77 }
5a6c967e 78 ex_setBUF(BUF);
09035cec
MH
79 if ((BUF[0] & (QUOTE|TRIM)) == OVERBUF)
80 beep();
81}
82
83/*
84 * Are we at the end of the printed representation of the
85 * line? Used internally in hardcopy open.
86 */
87ateopr()
88{
89 register int i, c;
90 register char *cp = vtube[destline] + destcol;
91
92 for (i = WCOLS - destcol; i > 0; i--) {
93 c = *cp++;
94 if (c == 0)
95 return (1);
96 if (c != ' ' && (c & QUOTE) == 0)
97 return (0);
98 }
99 return (1);
100}
101
102/*
103 * Append.
104 *
105 * This routine handles the top level append, doing work
106 * as each new line comes in, and arranging repeatability.
107 * It also handles append with repeat counts, and calculation
108 * of autoindents for new lines.
109 */
110bool vaifirst;
111bool gobbled;
112char *ogcursor;
113
114vappend(ch, cnt, indent)
299f2784 115 int ch; /* mjm: char --> int */
09035cec
MH
116 int cnt, indent;
117{
118 register int i;
119 register char *gcursor;
120 bool escape;
04379bab 121 int repcnt, savedoomed;
09035cec 122 short oldhold = hold;
5a6c967e 123#ifdef SIGWINCH
48be689d 124 int oldmask;
5a6c967e 125#endif
09035cec
MH
126
127 /*
128 * Before a move in hardopen when the line is dirty
129 * or we are in the middle of the printed representation,
130 * we retype the line to the left of the cursor so the
131 * insert looks clean.
132 */
133 if (ch != 'o' && state == HARDOPEN && (rubble || !ateopr())) {
134 rubble = 1;
135 gcursor = cursor;
136 i = *gcursor;
137 *gcursor = ' ';
138 wcursor = gcursor;
139 vmove();
140 *gcursor = i;
141 }
142 vaifirst = indent == 0;
143
144 /*
145 * Handle replace character by (eventually)
146 * limiting the number of input characters allowed
147 * in the vgetline routine.
148 */
149 if (ch == 'r')
150 repcnt = 2;
151 else
152 repcnt = 0;
153
154 /*
155 * If an autoindent is specified, then
156 * generate a mixture of blanks to tabs to implement
157 * it and place the cursor after the indent.
158 * Text read by the vgetline routine will be placed in genbuf,
159 * so the indent is generated there.
160 */
161 if (value(AUTOINDENT) && indent != 0) {
162 gcursor = genindent(indent);
163 *gcursor = 0;
164 vgotoCL(qcolumn(cursor - 1, genbuf));
165 } else {
166 gcursor = genbuf;
167 *gcursor = 0;
168 if (ch == 'o')
169 vfixcurs();
170 }
171
172 /*
173 * Prepare for undo. Pointers delimit inserted portion of line.
174 */
175 vUA1 = vUA2 = cursor;
176
177 /*
178 * If we are not in a repeated command and a ^@ comes in
179 * then this means the previous inserted text.
180 * If there is none or it was too long to be saved,
181 * then beep() and also arrange to undo any damage done
182 * so far (e.g. if we are a change.)
183 */
184 if ((vglobp && *vglobp == 0) || peekbr()) {
185 if ((INS[0] & (QUOTE|TRIM)) == OVERBUF) {
186 beep();
187 if (!splitw)
188 ungetkey('u');
189 doomed = 0;
190 hold = oldhold;
191 return;
192 }
193 /*
194 * Unread input from INS.
195 * An escape will be generated at end of string.
196 * Hold off n^^2 type update on dumb terminals.
197 */
198 vglobp = INS;
199 hold |= HOLDQIK;
200 } else if (vglobp == 0)
201 /*
202 * Not a repeated command, get
203 * a new inserted text for repeat.
204 */
205 INS[0] = 0;
206
207 /*
208 * For wrapmargin to hack away second space after a '.'
209 * when the first space caused a line break we keep
210 * track that this happened in gobblebl, which says
211 * to gobble up a blank silently.
212 */
213 gobblebl = 0;
214
5a6c967e 215#ifdef SIGWINCH
48be689d 216 oldmask = sigblock(sigmask(SIGWINCH));
5a6c967e 217#endif
09035cec
MH
218 /*
219 * Text gathering loop.
220 * New text goes into genbuf starting at gcursor.
221 * cursor preserves place in linebuf where text will eventually go.
222 */
223 if (*cursor == 0 || state == CRTOPEN)
224 hold |= HOLDROL;
225 for (;;) {
226 if (ch == 'r' && repcnt == 0)
227 escape = 0;
228 else {
04379bab 229 gcursor = vgetline(repcnt, gcursor, &escape, ch);
09035cec
MH
230
231 /*
232 * After an append, stick information
233 * about the ^D's and ^^D's and 0^D's in
234 * the repeated text buffer so repeated
235 * inserts of stuff indented with ^D as backtab's
236 * can work.
237 */
238 if (HADUP)
239 addtext("^");
240 else if (HADZERO)
241 addtext("0");
242 while (CDCNT > 0)
243 addtext("\204"), CDCNT--;
244 if (gobbled)
245 addtext(" ");
246 addtext(ogcursor);
247 }
248 repcnt = 0;
249
250 /*
251 * Smash the generated and preexisting indents together
252 * and generate one cleanly made out of tabs and spaces
253 * if we are using autoindent.
254 */
255 if (!vaifirst && value(AUTOINDENT)) {
256 i = fixindent(indent);
257 if (!HADUP)
258 indent = i;
259 gcursor = strend(genbuf);
260 }
261
262 /*
263 * Limit the repetition count based on maximum
264 * possible line length; do output implied
265 * by further count (> 1) and cons up the new line
266 * in linebuf.
267 */
268 cnt = vmaxrep(ch, cnt);
269 CP(gcursor + 1, cursor);
270 do {
271 CP(cursor, genbuf);
272 if (cnt > 1) {
273 int oldhold = hold;
274
275 Outchar = vinschar;
276 hold |= HOLDQIK;
5a6c967e 277 ex_printf("%s", genbuf);
09035cec
MH
278 hold = oldhold;
279 Outchar = vputchar;
280 }
281 cursor += gcursor - genbuf;
282 } while (--cnt > 0);
283 endim();
284 vUA2 = cursor;
285 if (escape != '\n')
286 CP(cursor, gcursor + 1);
287
288 /*
289 * If doomed characters remain, clobber them,
290 * and reopen the line to get the display exact.
291 */
292 if (state != HARDOPEN) {
293 DEPTH(vcline) = 0;
04379bab 294 savedoomed = doomed;
09035cec
MH
295 if (doomed > 0) {
296 register int cind = cindent();
297
298 physdc(cind, cind + doomed);
299 doomed = 0;
300 }
301 i = vreopen(LINE(vcline), lineDOT(), vcline);
f0f2d980
MH
302#ifdef TRACE
303 if (trace)
304 fprintf(trace, "restoring doomed from %d to %d\n", doomed, savedoomed);
305#endif
306 if (ch == 'R')
307 doomed = savedoomed;
09035cec
MH
308 }
309
310 /*
311 * All done unless we are continuing on to another line.
312 */
313 if (escape != '\n')
314 break;
315
316 /*
317 * Set up for the new line.
318 * First save the current line, then construct a new
319 * first image for the continuation line consisting
320 * of any new autoindent plus the pushed ahead text.
321 */
322 killU();
323 addtext(gobblebl ? " " : "\n");
324 vsave();
325 cnt = 1;
326 if (value(AUTOINDENT)) {
327#ifdef LISPCODE
328 if (value(LISP))
329 indent = lindent(dot + 1);
330 else
331#endif
332 if (!HADUP && vaifirst)
333 indent = whitecnt(linebuf);
334 vaifirst = 0;
335 strcLIN(vpastwh(gcursor + 1));
336 gcursor = genindent(indent);
337 *gcursor = 0;
338 if (gcursor + strlen(linebuf) > &genbuf[LBSIZE - 2])
339 gcursor = genbuf;
340 CP(gcursor, linebuf);
341 } else {
342 CP(genbuf, gcursor + 1);
343 gcursor = genbuf;
344 }
345
346 /*
347 * If we started out as a single line operation and are now
348 * turning into a multi-line change, then we had better yank
349 * out dot before it changes so that undo will work
350 * correctly later.
351 */
887e3e0d 352 if (FIXUNDO && vundkind == VCHNG) {
09035cec
MH
353 vremote(1, yank, 0);
354 undap1--;
355 }
356
357 /*
358 * Now do the append of the new line in the buffer,
359 * and update the display. If slowopen
360 * we don't do very much.
361 */
362 vdoappend(genbuf);
363 vundkind = VMANYINS;
364 vcline++;
365 if (state != VISUAL)
366 vshow(dot, NOLINE);
367 else {
368 i += LINE(vcline - 1);
369 vopen(dot, i);
370 if (value(SLOWOPEN))
371 vscrap();
372 else
373 vsync1(LINE(vcline));
374 }
375 strcLIN(gcursor);
376 *gcursor = 0;
377 cursor = linebuf;
378 vgotoCL(qcolumn(cursor - 1, genbuf));
379 }
380
381 /*
382 * All done with insertion, position the cursor
383 * and sync the screen.
384 */
385 hold = oldhold;
386 if (cursor > linebuf)
387 cursor--;
388 if (state != HARDOPEN)
389 vsyncCL();
390 else if (cursor > linebuf)
391 back1();
392 doomed = 0;
393 wcursor = cursor;
394 vmove();
5a6c967e 395#ifdef SIGWINCH
48be689d 396 (void)sigsetmask(oldmask);
5a6c967e 397#endif
09035cec
MH
398}
399
400/*
401 * Subroutine for vgetline to back up a single character position,
402 * backwards around end of lines (vgoto can't hack columns which are
403 * less than 0 in general).
404 */
405back1()
406{
407
408 vgoto(destline - 1, WCOLS + destcol - 1);
409}
410
411/*
412 * Get a line into genbuf after gcursor.
413 * Cnt limits the number of input characters
414 * accepted and is used for handling the replace
415 * single character command. Aescaped is the location
416 * where we stick a termination indicator (whether we
417 * ended with an ESCAPE or a newline/return.
418 *
419 * We do erase-kill type processing here and also
420 * are careful about the way we do this so that it is
421 * repeatable. (I.e. so that your kill doesn't happen,
422 * when you repeat an insert if it was escaped with \ the
04379bab
MH
423 * first time you did it. commch is the command character
424 * involved, including the prompt for readline.
09035cec
MH
425 */
426char *
04379bab 427vgetline(cnt, gcursor, aescaped, commch)
09035cec
MH
428 int cnt;
429 register char *gcursor;
430 bool *aescaped;
04379bab 431 char commch;
09035cec
MH
432{
433 register int c, ch;
434 register char *cp;
04379bab 435 int x, y, iwhite, backsl=0;
09035cec 436 char *iglobp;
d266c416 437 char cstr[2];
09035cec
MH
438 int (*OO)() = Outchar;
439
440 /*
441 * Clear the output state and counters
442 * for autoindent backwards motion (counts of ^D, etc.)
443 * Remember how much white space at beginning of line so
444 * as not to allow backspace over autoindent.
445 */
446 *aescaped = 0;
447 ogcursor = gcursor;
448 flusho();
449 CDCNT = 0;
450 HADUP = 0;
451 HADZERO = 0;
452 gobbled = 0;
453 iwhite = whitecnt(genbuf);
454 iglobp = vglobp;
455
456 /*
457 * Carefully avoid using vinschar in the echo area.
458 */
459 if (splitw)
460 Outchar = vputchar;
461 else {
462 Outchar = vinschar;
463 vprepins();
464 }
465 for (;;) {
04379bab 466 backsl = 0;
09035cec
MH
467 if (gobblebl)
468 gobblebl--;
469 if (cnt != 0) {
470 cnt--;
471 if (cnt == 0)
472 goto vadone;
473 }
d266c416
MH
474 c = getkey();
475 if (c != ATTN)
476 c &= (QUOTE|TRIM);
477 ch = c;
478 maphopcnt = 0;
5a6c967e 479 if (vglobp == 0 && Peek_key == 0 && commch != 'r')
887e3e0d 480 while ((ch = map(c, immacs)) != c) {
09035cec 481 c = ch;
887e3e0d
MH
482 if (!value(REMAP))
483 break;
d266c416
MH
484 if (++maphopcnt > 256)
485 error("Infinite macro loop");
887e3e0d 486 }
09035cec
MH
487 if (!iglobp) {
488
489 /*
490 * Erase-kill type processing.
491 * Only happens if we were not reading
492 * from untyped input when we started.
493 * Map users erase to ^H, kill to -1 for switch.
494 */
d266c416 495#ifndef USG3TTY
09035cec 496 if (c == tty.sg_erase)
65bacefd 497 c = CTRL('h');
09035cec
MH
498 else if (c == tty.sg_kill)
499 c = -1;
d266c416
MH
500#else
501 if (c == tty.c_cc[VERASE])
65bacefd 502 c = CTRL('h');
d266c416
MH
503 else if (c == tty.c_cc[VKILL])
504 c = -1;
505#endif
09035cec
MH
506 switch (c) {
507
508 /*
509 * ^? Interrupt drops you back to visual
510 * command mode with an unread interrupt
511 * still in the input buffer.
512 *
513 * ^\ Quit does the same as interrupt.
514 * If you are a ex command rather than
515 * a vi command this will drop you
516 * back to command mode for sure.
517 */
518 case ATTN:
519 case QUIT:
520 ungetkey(c);
521 goto vadone;
522
523 /*
524 * ^H Backs up a character in the input.
525 *
526 * BUG: Can't back around line boundaries.
527 * This is hard because stuff has
528 * already been saved for repeat.
529 */
65bacefd 530 case CTRL('h'):
09035cec
MH
531bakchar:
532 cp = gcursor - 1;
533 if (cp < ogcursor) {
534 if (splitw) {
535 /*
536 * Backspacing over readecho
537 * prompt. Pretend delete but
538 * don't beep.
539 */
540 ungetkey(c);
541 goto vadone;
542 }
543 beep();
544 continue;
545 }
546 goto vbackup;
547
548 /*
549 * ^W Back up a white/non-white word.
550 */
65bacefd 551 case CTRL('w'):
09035cec
MH
552 wdkind = 1;
553 for (cp = gcursor; cp > ogcursor && isspace(cp[-1]); cp--)
554 continue;
555 for (c = wordch(cp - 1);
556 cp > ogcursor && wordof(c, cp - 1); cp--)
557 continue;
558 goto vbackup;
559
560 /*
561 * users kill Kill input on this line, back to
562 * the autoindent.
563 */
564 case -1:
565 cp = ogcursor;
566vbackup:
567 if (cp == gcursor) {
568 beep();
569 continue;
570 }
571 endim();
572 *cp = 0;
573 c = cindent();
574 vgotoCL(qcolumn(cursor - 1, genbuf));
575 if (doomed >= 0)
576 doomed += c - cindent();
577 gcursor = cp;
578 continue;
579
580 /*
581 * \ Followed by erase or kill
582 * maps to just the erase or kill.
583 */
584 case '\\':
585 x = destcol, y = destline;
5a6c967e 586 ex_putchar('\\');
09035cec
MH
587 vcsync();
588 c = getkey();
d266c416 589#ifndef USG3TTY
04379bab 590 if (c == tty.sg_erase || c == tty.sg_kill)
d266c416
MH
591#else
592 if (c == tty.c_cc[VERASE]
04379bab 593 || c == tty.c_cc[VKILL])
d266c416 594#endif
04379bab 595 {
09035cec
MH
596 vgoto(y, x);
597 if (doomed >= 0)
598 doomed++;
599 goto def;
600 }
601 ungetkey(c), c = '\\';
04379bab
MH
602 backsl = 1;
603 break;
09035cec
MH
604
605 /*
606 * ^Q Super quote following character
607 * Only ^@ is verboten (trapped at
608 * a lower level) and \n forces a line
609 * split so doesn't really go in.
610 *
611 * ^V Synonym for ^Q
612 */
65bacefd
KB
613 case CTRL('q'):
614 case CTRL('v'):
09035cec 615 x = destcol, y = destline;
5a6c967e 616 ex_putchar('^');
09035cec
MH
617 vgoto(y, x);
618 c = getkey();
619#ifdef TIOCSETC
620 if (c == ATTN)
621 c = nttyc.t_intrc;
622#endif
623 if (c != NL) {
624 if (doomed >= 0)
625 doomed++;
626 goto def;
627 }
628 break;
629 }
630 }
631
632 /*
633 * If we get a blank not in the echo area
634 * consider splitting the window in the wrapmargin.
635 */
d266c416
MH
636 if (c != NL && !splitw) {
637 if (c == ' ' && gobblebl) {
09035cec
MH
638 gobbled = 1;
639 continue;
640 }
04379bab
MH
641 if (value(WRAPMARGIN) &&
642 (outcol >= OCOLUMNS - value(WRAPMARGIN) ||
643 backsl && outcol==0) &&
644 commch != 'r') {
d266c416
MH
645 /*
646 * At end of word and hit wrapmargin.
647 * Move the word to next line and keep going.
648 */
649 wdkind = 1;
650 *gcursor++ = c;
04379bab
MH
651 if (backsl)
652 *gcursor++ = getkey();
d266c416
MH
653 *gcursor = 0;
654 /*
655 * Find end of previous word if we are past it.
656 */
657 for (cp=gcursor; cp>ogcursor && isspace(cp[-1]); cp--)
658 ;
04379bab 659 if (outcol+(backsl?OCOLUMNS:0) - (gcursor-cp) >= OCOLUMNS - value(WRAPMARGIN)) {
d266c416
MH
660 /*
661 * Find beginning of previous word.
662 */
663 for (; cp>ogcursor && !isspace(cp[-1]); cp--)
664 ;
665 if (cp <= ogcursor) {
666 /*
667 * There is a single word that
668 * is too long to fit. Just
669 * let it pass, but beep for
670 * each new letter to warn
671 * the luser.
672 */
673 c = *--gcursor;
674 *gcursor = 0;
675 beep();
676 goto dontbreak;
677 }
678 /*
679 * Save it for next line.
680 */
681 macpush(cp, 0);
682 cp--;
683 }
684 macpush("\n", 0);
685 /*
686 * Erase white space before the word.
687 */
688 while (cp > ogcursor && isspace(cp[-1]))
689 cp--; /* skip blank */
690 gobblebl = 3;
691 goto vbackup;
09035cec 692 }
d266c416
MH
693 dontbreak:;
694 }
695
696 /*
697 * Word abbreviation mode.
698 */
699 cstr[0] = c;
700 if (anyabbrs && gcursor > ogcursor && !wordch(cstr) && wordch(gcursor-1)) {
5a6c967e
CH
701 int wdtype, abno;
702
703 cstr[1] = 0;
704 wdkind = 1;
705 cp = gcursor - 1;
706 for (wdtype = wordch(cp - 1);
707 cp > ogcursor && wordof(wdtype, cp - 1); cp--)
708 ;
709 *gcursor = 0;
710 for (abno=0; abbrevs[abno].mapto; abno++) {
711 if (eq(cp, abbrevs[abno].cap)) {
712 macpush(cstr, 0);
713 macpush(abbrevs[abno].mapto, 1);
714 goto vbackup;
d266c416 715 }
5a6c967e 716 }
09035cec 717 }
d266c416 718
09035cec
MH
719 switch (c) {
720
721 /*
722 * ^M Except in repeat maps to \n.
723 */
724 case CR:
725 if (vglobp)
726 goto def;
727 c = '\n';
728 /* presto chango ... */
729
730 /*
731 * \n Start new line.
732 */
733 case NL:
734 *aescaped = c;
735 goto vadone;
736
737 /*
738 * escape End insert unless repeat and more to repeat.
739 */
740 case ESCAPE:
741 if (lastvgk)
742 goto def;
743 goto vadone;
744
745 /*
746 * ^D Backtab.
747 * ^T Software forward tab.
748 *
749 * Unless in repeat where this means these
750 * were superquoted in.
751 */
65bacefd
KB
752 case CTRL('d'):
753 case CTRL('t'):
09035cec
MH
754 if (vglobp)
755 goto def;
756 /* fall into ... */
757
758 /*
759 * ^D|QUOTE Is a backtab (in a repeated command).
760 */
65bacefd 761 case CTRL('d') | QUOTE:
09035cec
MH
762 *gcursor = 0;
763 cp = vpastwh(genbuf);
764 c = whitecnt(genbuf);
65bacefd 765 if (ch == CTRL('t')) {
09035cec
MH
766 /*
767 * ^t just generates new indent replacing
768 * current white space rounded up to soft
769 * tab stop increment.
770 */
771 if (cp != gcursor)
772 /*
773 * BUG: Don't hack ^T except
774 * right after initial
775 * white space.
776 */
777 continue;
778 cp = genindent(iwhite = backtab(c + value(SHIFTWIDTH) + 1));
779 ogcursor = cp;
780 goto vbackup;
781 }
782 /*
783 * ^D works only if we are at the (end of) the
784 * generated autoindent. We count the ^D for repeat
785 * purposes.
786 */
787 if (c == iwhite && c != 0)
788 if (cp == gcursor) {
789 iwhite = backtab(c);
790 CDCNT++;
791 ogcursor = cp = genindent(iwhite);
792 goto vbackup;
793 } else if (&cp[1] == gcursor &&
794 (*cp == '^' || *cp == '0')) {
795 /*
796 * ^^D moves to margin, then back
797 * to current indent on next line.
798 *
799 * 0^D moves to margin and then
800 * stays there.
801 */
802 HADZERO = *cp == '0';
803 ogcursor = cp = genbuf;
804 HADUP = 1 - HADZERO;
805 CDCNT = 1;
806 endim();
807 back1();
887e3e0d 808 vputchar(' ');
09035cec
MH
809 goto vbackup;
810 }
811 if (vglobp && vglobp - iglobp >= 2 &&
812 (vglobp[-2] == '^' || vglobp[-2] == '0')
813 && gcursor == ogcursor + 1)
814 goto bakchar;
815 continue;
816
817 default:
818 /*
819 * Possibly discard control inputs.
820 */
821 if (!vglobp && junk(c)) {
822 beep();
823 continue;
824 }
825def:
04379bab 826 if (!backsl) {
5a6c967e 827 ex_putchar(c);
0ab2d2a9 828 flush();
04379bab 829 }
09035cec
MH
830 if (gcursor > &genbuf[LBSIZE - 2])
831 error("Line too long");
832 *gcursor++ = c & TRIM;
833 vcsync();
09035cec
MH
834 if (value(SHOWMATCH) && !iglobp)
835 if (c == ')' || c == '}')
836 lsmatch(gcursor);
09035cec
MH
837 continue;
838 }
839 }
840vadone:
841 *gcursor = 0;
d266c416
MH
842 if (Outchar != termchar)
843 Outchar = OO;
09035cec
MH
844 endim();
845 return (gcursor);
846}
847
848int vgetsplit();
849char *vsplitpt;
850
851/*
852 * Append the line in buffer at lp
853 * to the buffer after dot.
854 */
855vdoappend(lp)
856 char *lp;
857{
858 register int oing = inglobal;
859
860 vsplitpt = lp;
861 inglobal = 1;
862 ignore(append(vgetsplit, dot));
863 inglobal = oing;
864}
865
866/*
867 * Subroutine for vdoappend to pass to append.
868 */
869vgetsplit()
870{
871
872 if (vsplitpt == 0)
873 return (EOF);
874 strcLIN(vsplitpt);
875 vsplitpt = 0;
876 return (0);
877}
878
879/*
880 * Vmaxrep determines the maximum repetitition factor
881 * allowed that will yield total line length less than
44232d5b 882 * LBSIZE characters and also does hacks for the R command.
09035cec
MH
883 */
884vmaxrep(ch, cnt)
885 char ch;
886 register int cnt;
887{
888 register int len, replen;
889
890 if (cnt > LBSIZE - 2)
891 cnt = LBSIZE - 2;
892 replen = strlen(genbuf);
893 if (ch == 'R') {
894 len = strlen(cursor);
895 if (replen < len)
896 len = replen;
897 CP(cursor, cursor + len);
898 vUD2 += len;
899 }
900 len = strlen(linebuf);
901 if (len + cnt * replen <= LBSIZE - 2)
902 return (cnt);
903 cnt = (LBSIZE - 2 - len) / replen;
904 if (cnt == 0) {
905 vsave();
906 error("Line too long");
907 }
908 return (cnt);
909}