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