Subversion Repositories planix.SVN

Rev

Rev 119 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
105 7u83 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
#if	!defined(lint) && defined(DOSCCS)
8
static char *sccsid = "@(#)ex_vadj.c	7.9 (Berkeley) 6/7/85";
9
#endif
10
 
11
#include "ex.h"
12
#include "ex_tty.h"
13
#include "ex_vis.h"
14
 
15
/*
16
 * Routines to deal with management of logical versus physical
17
 * display, opening and redisplaying lines on the screen, and
18
 * use of intelligent terminal operations.  Routines to deal with
19
 * screen cleanup after a change.
20
 */
21
 
22
/*
23
 * Display a new line at physical line p, returning
24
 * the depth of the newly displayed line.  We may decide
25
 * to expand the window on an intelligent terminal if it is
26
 * less than a full screen by deleting a line above the top of the
27
 * window before doing an insert line to keep all the good text
28
 * on the screen in which case the line may actually end up
29
 * somewhere other than line p.
30
 */
121 7u83 31
int
105 7u83 32
vopen(tp, p)
33
	line *tp;
34
	int p;
35
{
36
	register int cnt;
37
	register struct vlinfo *vp, *vpc;
38
 
39
#ifdef ADEBUG
40
	if (trace != NULL)
41
		tfixnl(), fprintf(trace, "vopen(%d, %d)\n", lineno(tp), p);
42
#endif
43
	if (state != VISUAL) {
44
		if (vcnt)
45
			if (hold & HOLDROL)
46
				vup1();
47
			else
48
				vclean();
49
 
50
		/*
51
		 * Forget all that we once knew.
52
		 */
53
		vcnt = vcline = 0;
54
		p = WBOT; LASTLINE = WBOT + 1;
55
		state = bastate;
56
		WTOP = basWTOP;
57
		WLINES = basWLINES;
58
	}
59
	vpc = &vlinfo[vcline];
60
	for (vp = &vlinfo[vcnt]; vp >= vpc; vp--)
61
		vlcopy(vp[1], vp[0]);
62
	vcnt++;
63
	if (Pline == numbline)
64
		/*
65
		 * Dirtying all the lines is rather inefficient
66
		 * internally, but number mode is used rarely
67
		 * and so its not worth optimizing.
68
		 */
69
		vdirty(vcline+1, WECHO);
118 7u83 70
	ex_getline(*tp);
105 7u83 71
 
72
	/*
73
	 * If we are opening at the top of the window, can try a window
74
	 * expansion at the top.
75
	 */
76
	if (state == VISUAL && vcline == 0 && vcnt > 1 && p > ZERO) {
77
		cnt = p + vdepth() - LINE(1);
78
		if (cnt > 0) {
79
			p -= cnt;
80
			if (p < ZERO)
81
				p = ZERO;
82
			WTOP = p;
83
			WLINES = WBOT - WTOP + 1;
84
		}
85
	}
86
	vpc->vliny = p, vpc->vdepth = 0, vpc->vflags = 0;
87
	cnt = vreopen(p, lineno(tp), vcline);
88
	if (vcline + 1 == vcnt)
89
		LINE(vcnt) = LINE(vcline) + cnt;
90
}
91
 
92
/*
93
 * Redisplay logical line l at physical line p with line number lineno.
94
 */
95
vreopen(p, lineno, l)
96
	int p, lineno, l;
97
{
98
	register int d;
99
	register struct vlinfo *vp = &vlinfo[l];
100
 
101
	d = vp->vdepth;
102
	if (d == 0 || (vp->vflags & VDIRT))
103
		vp->vdepth = d = vdepth();
104
	vp->vliny = p, vp->vflags &= ~VDIRT;
105
 
106
	/*
107
	 * Try to win by making the screen larger rather than inserting
108
	 * a line and driving text off the bottom.
109
	 */
110
	p = vglitchup(l, 0);
111
 
112
	/*
113
	 * BUG:		Should consider using CE here to clear to end of line.
114
	 *		As it stands we always strike over the current text.
115
	 *		Since often the current text is the same as what
116
	 *		we are overstriking with, it tends not to show.
117
	 *		On the other hand if it is different and we end up
118
	 *		spacing out a lot of text, we could have won with
119
	 *		a CE.  This is probably worthwhile at low speed
120
	 *		only however, since clearly computation will be
121
	 *		necessary to determine which way to go.
122
	 */
123
	vigoto(p, 0);
124
	pline(lineno);
125
 
126
	/*
127
	 * When we are typing part of a line for hardcopy open, don't
128
	 * want to type the '$' marking an end of line if in list mode.
129
	 */
130
	if (hold & HOLDDOL)
131
		return (d);
132
	if (Putchar == listchar)
133
		putchar('$');
134
 
135
	/*
136
	 * Optimization of cursor motion may prevent screen rollup if the
137
	 * line has blanks/tabs at the end unless we force the cursor to appear
138
	 * on the last line segment.
139
	 */
140
	if (vp->vliny + d - 1 > WBOT)
141
		vcsync();
142
 
143
	/*
144
	 * Switch into hardcopy open mode if we are in one line (adm3)
145
	 * open mode and this line is now too long.  If in hardcopy
146
	 * open mode, then call sethard to move onto the next line
147
	 * with appropriate positioning.
148
	 */
149
	if (state == ONEOPEN) {
150
		WCOLS = OCOLUMNS;
151
		if (vdepth() > 1) {
152
			WCOLS = TUBECOLS;
153
			sethard();
154
		} else
155
			WCOLS = TUBECOLS;
156
	} else if (state == HARDOPEN)
157
		sethard();
158
 
159
	/*
160
	 * Unless we filled (completely) the last line we typed on,
161
	 * we have to clear to the end of the line
162
	 * in case stuff is left from before.
163
	 */
164
	if (vp->vliny + d > destline) {
165
		if (IN && destcol == WCOLS)
166
			vigoto(vp->vliny + d - 1, 0);
167
		vclreol();
168
	}
169
	return (d);
170
}
171
 
172
/*
173
 * Real work for winning growing of window at top
174
 * when inserting in the middle of a partially full
175
 * screen on an intelligent terminal.  We have as argument
176
 * the logical line number to be inserted after, and the offset
177
 * from that line where the insert will go.
178
 * We look at the picture of depths and positions, and if we can
179
 * delete some (blank) lines from the top of the screen so that
180
 * later inserts will not push stuff off the bottom.
181
 */
182
vglitchup(l, o)
183
	int l, o;
184
{
185
	register struct vlinfo *vp = &vlinfo[l];
186
	register int need;
187
	register int p = vp->vliny;
188
	short oldhold, oldheldech;
189
	bool glitched = 0;
190
 
191
 	if (l < vcnt - 1) {
192
		need = p + vp->vdepth - (vp+1)->vliny;
193
		if (need > 0) {
194
			if (state == VISUAL && WTOP - ZERO >= need && AL && DL) {
195
				glitched++;
196
				WTOP -= need;
197
				WLINES = WBOT - WTOP + 1;
198
				p -= need;
199
				if (p + o == WTOP) {
200
					vp->vliny = WTOP;
201
					return (WTOP + o);
202
				}
203
				vdellin(WTOP, need, -1);
204
				oldheldech = heldech;
205
				oldhold = hold;
206
				hold |= HOLDECH;
207
			}
208
			vinslin((vp+1)->vliny, need, l);
209
			if (glitched) {
210
				hold = oldhold;
211
				heldech = oldheldech;
212
			}
213
		}
214
	} else
215
		vp[1].vliny = vp[0].vliny + vp->vdepth;
216
	return (p + o);
217
}
218
 
219
/*
220
 * Insert cnt blank lines before line p,
221
 * logically and (if supported) physically.
222
 */
223
vinslin(p, cnt, l)
224
	register int p, cnt;
225
	int l;
226
{
227
	register int i;
228
	bool could = 1;
229
 
230
#ifdef ADEBUG
231
	if (trace)
232
		tfixnl(), fprintf(trace, "vinslin(%d, %d, %d)\n", p, cnt, l);
233
#endif
234
	if (p + cnt > WBOT && CD) {
235
		/*
236
		 * Really quick -- clear to end of screen.
237
		 */
238
		cnt = WECHO + 1 - p;
239
		vgoto(p, 0), vputp(CD, cnt);
240
		vclrech(1);
241
		vadjAL(p, cnt);
242
	} else if (SR && p == WTOP && costSR < costAL) {
243
		/*
244
		 * Use reverse scroll mode of the terminal, at
245
		 * the top of the window.  Reverse linefeed works
246
		 * too, since we only use it from line WTOP.
247
		 */
248
		for (i = cnt; i > 0; i--) {
249
			vgoto(p, 0), vputp(SR, 0);
250
			if (i > 1 && (hold & HOLDAT) == 0)
251
				putchar('@');
252
			/*
253
			 * If we are at the top of the screen, and the
254
			 * terminal retains display above, then we
255
			 * should try to clear to end of line.
256
			 * Have to use CE since we don't remember what is
257
			 * actually on the line.
258
			 */
259
			if (CE && (DA || p != 0))
260
				vputp(CE, 1);
261
		}
262
		vadjAL(p, cnt);
263
	} else if (AL) {
264
		/*
265
		 * Use insert line.
266
		 */
267
		vgoto(p, 0);
268
		if (AL_PARM && (cnt>1 || *AL==0)) {
269
			/* insert cnt lines.  Should do @'s too. */
270
			vputp(tgoto(AL_PARM, p, cnt), WECHO+1-p);
271
		}
272
		else if (CS && *AL==0) {
273
			/* vt100 change scrolling region to fake AL */
274
			vputp(SC, 1);
275
			vputp(tgoto(CS, LINES-1,p), 1);
276
			vputp(RC, 1);	/* CS homes stupid cursor */
277
			for (i=cnt; i>0; i--)
278
				vputp(SR, 1);	/* should do @'s */
279
			vputp(tgoto(CS, LINES-1,0), 1);
280
			vputp(RC, 1);	/* Once again put it back */
281
		}
282
		else {
283
			vputp(AL, WECHO + 1 - p);
284
			for (i = cnt - 1; i > 0; i--) {
285
				vgoto(outline+1, 0);
286
				vputp(AL, WECHO + 1 - outline);
287
				if ((hold & HOLDAT) == 0)
288
					putchar('@');
289
			}
290
		}
291
		vadjAL(p, cnt);
292
	} else
293
		could = 0;
294
	vopenup(cnt, could, l);
295
}
296
 
297
/*
298
 * Logically open up after line l, cnt of them.
299
 * We need to know if it was done ``physically'' since in this
300
 * case we accept what the hardware gives us.  If we have to do
301
 * it ourselves (brute force) we will squish out @ lines in the process
302
 * if this will save us work.
303
 */
304
vopenup(cnt, could, l)
305
	int cnt;
306
	bool could;
307
{
308
	register struct vlinfo *vc = &vlinfo[l + 1];
309
	register struct vlinfo *ve = &vlinfo[vcnt];
310
 
311
#ifdef ADEBUG
312
	if (trace)
313
		tfixnl(), fprintf(trace, "vopenup(%d, %d, %d)\n", cnt, could, l);
314
#endif
315
	if (could)
316
		/*
317
		 * This will push @ lines down the screen,
318
		 * just as the hardware did.  Since the default
319
		 * for intelligent terminals is to never have @
320
		 * lines on the screen, this should never happen,
321
		 * and the code makes no special effort to be nice in this
322
		 * case, e.g. squishing out the @ lines by delete lines
323
		 * before doing append lines.
324
		 */
325
		for (; vc <= ve; vc++)
326
			vc->vliny += cnt;
327
	else {
328
		/*
329
		 * Will have to clean up brute force eventually,
330
		 * so push the line data around as little as possible.
331
		 */
332
		vc->vliny += cnt, vc->vflags |= VDIRT;
333
		while (vc < ve) {
334
			register int i = vc->vliny + vc->vdepth;
335
 
336
			vc++;
337
			if (i <= vc->vliny)
338
				break;
339
			vc->vliny = i, vc->vflags |= VDIRT;
340
		}
341
	}
342
	vscrap();
343
}
344
 
345
/*
346
 * Adjust data structure internally to account for insertion of
347
 * blank lines on the screen.
348
 */
349
vadjAL(p, cnt)
350
	int p, cnt;
351
{
352
#ifndef	BIT8
353
	char *tlines[TUBELINES];
354
#else
355
	short *tlines[TUBELINES];
356
#endif
357
	register int from, to;
358
 
359
#ifdef ADEBUG
360
	if (trace)
361
		tfixnl(), fprintf(trace, "vadjal(%d, %d)\n", p, cnt);
362
#endif
363
	copy(tlines, vtube, sizeof vtube);	/*SASSIGN*/
364
	for (from = p, to = p + cnt; to <= WECHO; from++, to++)
365
		vtube[to] = tlines[from];
366
	for (to = p; from <= WECHO; from++, to++) {
367
		vtube[to] = tlines[from];
368
		vclrbyte(vtube[to], WCOLS);
369
	}
370
	/*
371
	 * Have to clear the echo area since its contents aren't
372
	 * necessarily consistent with the rest of the display.
373
	 */
374
	vclrech(0);
375
}
376
 
377
/*
378
 * Roll the screen up logically and physically
379
 * so that line dl is the bottom line on the screen.
380
 */
381
vrollup(dl)
382
	int dl;
383
{
384
	register int cnt;
385
	register int dc = destcol;
386
 
387
#ifdef ADEBUG
388
	if (trace)
389
		tfixnl(), fprintf(trace, "vrollup(%d)\n", dl);
390
#endif
391
	cnt = dl - (splitw ? WECHO : WBOT);
392
	if (splitw && (state == VISUAL || state == CRTOPEN))
393
		holdupd = 1;
394
	vmoveitup(cnt, 1);
395
	vscroll(cnt);
396
	destline = dl - cnt, destcol = dc;
397
}
398
 
399
vup1()
400
{
401
 
402
	vrollup(WBOT + 1);
403
}
404
 
405
/*
406
 * Scroll the screen up cnt lines physically.
407
 * If doclr is true, do a clear eol if the terminal
408
 * has standout (to prevent it from scrolling up)
409
 */
410
vmoveitup(cnt, doclr)
411
	register int cnt;
412
	bool doclr;
413
{
414
 
415
	if (cnt == 0)
416
		return;
417
#ifdef ADEBUG
418
	if (trace)
419
		tfixnl(), fprintf(trace, "vmoveitup(%d)\n", cnt);
420
#endif
421
	if (doclr && (SO || SE))
422
		vclrech(0);
423
	if (SF) {
424
		destline = WECHO;
425
		destcol = (NONL ? 0 : outcol % WCOLS);
426
		fgoto();
427
		while (cnt > 0)
428
			vputp(SF, 0), cnt--;
429
		return;
430
	}
431
	destline = WECHO + cnt;
432
	destcol = (NONL ? 0 : outcol % WCOLS);
433
	fgoto();
434
	if (state == ONEOPEN || state == HARDOPEN) {
435
		outline = destline = 0;
436
		vclrbyte(vtube[0], WCOLS);
437
	}
438
}
439
 
440
/*
441
 * Scroll the screen up cnt lines logically.
442
 */
443
vscroll(cnt)
444
	register int cnt;
445
{
446
	register int from, to;
447
#ifndef	BIT8
448
	char *tlines[TUBELINES];
449
#else
450
	short *tlines[TUBELINES];
451
#endif
452
 
453
#ifdef ADEBUG
454
	if (trace)
455
		fprintf(trace, "vscroll(%d)\n", cnt);
456
#endif
457
	if (cnt < 0 || cnt > TUBELINES)
458
		error("Internal error: vscroll");
459
	if (cnt == 0)
460
		return;
461
	copy(tlines, vtube, sizeof vtube);
462
	for (to = ZERO, from = ZERO + cnt; to <= WECHO - cnt; to++, from++)
463
		vtube[to] = tlines[from];
464
	for (from = ZERO; to <= WECHO; to++, from++) {
465
		vtube[to] = tlines[from];
466
		vclrbyte(vtube[to], WCOLS);
467
	}
468
	for (from = 0; from <= vcnt; from++)
469
		LINE(from) -= cnt;
470
}
471
 
472
/*
473
 * Discard logical lines due to physical wandering off the screen.
474
 */
475
vscrap()
476
{
477
	register int i, j;
478
 
479
#ifdef ADEBUG
480
	if (trace)
481
		tfixnl(), fprintf(trace, "vscrap\n"), tvliny();
482
#endif
483
	if (splitw)
484
		return;
485
	if (vcnt && WBOT != WECHO && LINE(0) < WTOP && LINE(0) >= ZERO) {
486
		WTOP = LINE(0);
487
		WLINES = WBOT - WTOP + 1;
488
	}
489
	for (j = 0; j < vcnt; j++)
490
		if (LINE(j) >= WTOP) {
491
			if (j == 0)
492
				break;
493
			/*
494
			 * Discard the first j physical lines off the top.
495
			 */
496
			vcnt -= j, vcline -= j;
497
			for (i = 0; i <= vcnt; i++)
498
				vlcopy(vlinfo[i], vlinfo[i + j]);
499
			break;
500
		}
501
	/*
502
	 * Discard lines off the bottom.
503
	 */
504
	if (vcnt) {
505
		for (j = 0; j <= vcnt; j++)
506
			if (LINE(j) > WBOT || LINE(j) + DEPTH(j) - 1 > WBOT) {
507
				vcnt = j;
508
				break;
509
			}
510
		LASTLINE = LINE(vcnt-1) + DEPTH(vcnt-1);
511
	}
512
#ifdef ADEBUG
513
	if (trace)
514
		tvliny();
515
#endif
516
	/*
517
	 * May have no lines!
518
	 */
519
}
520
 
521
/*
522
 * Repaint the screen, with cursor at curs, aftern an arbitrary change.
523
 * Handle notification on large changes.
524
 */
121 7u83 525
int
105 7u83 526
vrepaint(curs)
527
	char *curs;
528
{
121 7u83 529
#ifdef ADEBUG
530
	if (trace)
531
		fprintf(trace, "vrepaint(%d)\n", curs);
532
#endif
533
 
105 7u83 534
	wdot = NOLINE;
535
	/*
536
	 * In open want to notify first.
537
	 */
538
	noteit(0);
539
	vscrap();
540
 
541
	/*
542
	 * Deal with a totally useless display.
543
	 */
544
	if (vcnt == 0 || vcline < 0 || vcline > vcnt || holdupd && state != VISUAL) {
545
		register line *odol = dol;
546
 
547
		vcnt = 0;
548
		if (holdupd)
549
			if (state == VISUAL)
550
				ignore(peekkey());
551
			else
552
				vup1();
553
		holdupd = 0;
554
		if (odol == zero)
555
			fixzero();
556
		vcontext(dot, '.');
557
		noteit(1);
558
		if (noteit(1) == 0 && odol == zero) {
559
			CATCH
560
				error("No lines in buffer");
561
			ENDCATCH
562
			linebuf[0] = 0;
563
			splitw = 0;
564
		}
565
		vnline(curs);
566
		return;
567
	}
568
 
569
	/*
570
	 * Have some useful displayed text; refresh it.
571
	 */
572
	getDOT();
573
 
574
	/*
575
	 * This is for boundary conditions in open mode.
576
	 */
577
	if (FLAGS(0) & VDIRT)
578
		vsync(WTOP);
579
 
580
	/*
581
	 * If the current line is after the last displayed line
582
	 * or the bottom of the screen, then special effort is needed
583
	 * to get it on the screen.  We first try a redraw at the
584
	 * last line on the screen, hoping it will fill in where @
585
	 * lines are now.  If this doesn't work, then roll it onto
586
	 * the screen.
587
	 */
588
	if (vcline >= vcnt || LINE(vcline) > WBOT) {
589
		short oldhold = hold;
590
		hold |= HOLDAT, vredraw(LASTLINE), hold = oldhold;
591
		if (vcline >= vcnt) {
592
			register int i = vcline - vcnt + 1;
593
 
594
			dot -= i;
595
			vcline -= i;
596
			vroll(i);
597
		} else
598
			vsyncCL();
599
	} else
600
		vsync(vcline > 0 ? LINE(vcline - 1) : WTOP);
601
 
602
	/*
603
	 * Notification on large change for visual
604
	 * has to be done last or we may lose
605
	 * the echo area with redisplay.
606
	 */
607
	noteit(1);
608
 
609
	/*
610
	 * Finally.  Move the cursor onto the current line.
611
	 */
612
	vnline(curs);
613
}
614
 
615
/*
616
 * Fully cleanup the screen, leaving no @ lines except at end when
617
 * line after last won't completely fit.  The routine vsync is
618
 * more conservative and much less work on dumb terminals.
619
 */
620
vredraw(p)
621
	register int p;
622
{
623
	register int l;
624
	register line *tp;
625
	char temp[LBSIZE];
626
	bool anydl = 0;
627
	short oldhold = hold;
628
 
629
#ifdef ADEBUG
630
	if (trace)
631
		tfixnl(), fprintf(trace, "vredraw(%d)\n", p), tvliny();
632
#endif
121 7u83 633
 
105 7u83 634
	if (holdupd) {
635
		holdupd = 3;
636
		return;
637
	}
638
	if (state == HARDOPEN || splitw)
639
		return;
640
	if (p < 0 /* || p > WECHO */)
641
		error("Internal error: vredraw");
642
 
643
	/*
644
	 * Trim the ragged edges (lines which are off the screen but
645
	 * not yet logically discarded), save the current line, and
646
	 * search for first logical line affected by the redraw.
647
	 */
648
	vscrap();
115 7u83 649
	CP(temp, linebuf);
105 7u83 650
	l = 0;
651
	tp = dot - vcline;
652
	if (vcnt == 0)
653
		LINE(0) = WTOP;
654
	while (l < vcnt && LINE(l) < p)
655
		l++, tp++;
656
 
657
	/*
658
	 * We hold off echo area clearing during the redraw in deference
659
	 * to a final clear of the echo area at the end if appropriate.
660
	 */
661
	heldech = 0;
662
	hold |= HOLDECH;
663
	for (; l < vcnt && Peekkey != ATTN; l++) {
664
		if (l == vcline)
665
			strcLIN(temp);
666
		else
118 7u83 667
			ex_getline(*tp);
105 7u83 668
 
669
		/*
670
		 * Delete junk between displayed lines.
671
		 */
672
		if (LINE(l) != LINE(l + 1) && LINE(l) != p) {
673
			if (anydl == 0 && DB && CD) {
674
				hold = oldhold;
675
				vclrech(0);
676
				anydl = 1;
677
				hold |= HOLDECH;
678
				heldech = 0;
679
			}
680
			vdellin(p, LINE(l) - p, l);
681
		}
682
 
683
		/*
684
		 * If line image is not know to be up to date, then
685
		 * redisplay it;  else just skip onward.
686
		 */
687
		LINE(l) = p;
688
		if (FLAGS(l) & VDIRT) {
689
			DEPTH(l) = vdepth();
690
			if (l != vcline && p + DEPTH(l) - 1 > WBOT) {
691
				vscrap();
692
				break;
693
			}
694
			FLAGS(l) &= ~VDIRT;
695
			vreopen(p, lineno(tp), l);
696
			p = LINE(l) + DEPTH(l);
697
		} else
698
			p += DEPTH(l);
699
		tp++;
700
	}
701
 
702
	/*
703
	 * That takes care of lines which were already partially displayed.
704
	 * Now try to fill the rest of the screen with text.
705
	 */
706
	if (state == VISUAL && p <= WBOT) {
707
		int ovcline = vcline;
708
 
709
		vcline = l;
710
		for (; tp <= dol && Peekkey != ATTN; tp++) {
118 7u83 711
			ex_getline(*tp);
105 7u83 712
			if (p + vdepth() - 1 > WBOT)
713
				break;
714
			vopen(tp, p);
715
			p += DEPTH(vcline);
716
			vcline++;
717
		}
718
		vcline = ovcline;
719
	}
720
 
721
	/*
722
	 * Thats all the text we can get on.
723
	 * Now rest of lines (if any) get either a ~ if they
724
	 * are past end of file, or an @ if the next line won't fit.
725
	 */
726
	for (; p <= WBOT && Peekkey != ATTN; p++)			
727
		vclrlin(p, tp);
728
	strcLIN(temp);
729
	hold = oldhold;
730
	if (heldech)
731
		vclrech(0);
732
#ifdef ADEBUG
733
	if (trace)
734
		tvliny();
735
#endif
736
}
737
 
738
/*
739
 * Do the real work in deleting cnt lines starting at line p from
740
 * the display.  First affected line is line l.
741
 */
742
vdellin(p, cnt, l)
743
	int p, cnt, l;
744
{
745
	register int i;
746
 
747
	if (cnt == 0)
748
		return;
749
	if (DL == NOSTR || cnt < 0) {
750
		/*
751
		 * Can't do it; just remember that line l is munged.
752
		 */
753
		FLAGS(l) |= VDIRT;
754
		return;
755
	}
756
#ifdef ADEBUG
757
	if (trace)
758
		tfixnl(), fprintf(trace, "vdellin(%d, %d, %d)\n", p, cnt, l);
759
#endif
760
	/*
761
	 * Send the deletes to the screen and then adjust logical
762
	 * and physical internal data structures.
763
	 */
764
	vgoto(p, 0);
765
	if (DL_PARM && (cnt>1 || *DL==0)) {
766
		vputp(tgoto(DL_PARM, p, cnt), WECHO-p);
767
	}
768
	else if (CS && *DL==0) {
769
		/* vt100: fake DL by changing scrolling region */
770
		vputp(SC, 1);	/* Save since CS homes stupid cursor */
771
		vputp(tgoto(CS, LINES-1, p), 1);
772
		vputp(tgoto(CM, 0, LINES-1), 1);/* Go to lower left corner */
773
		for (i=0; i<cnt; i++)		/* .. and scroll cnt times */
774
			putch('\n');		/* should check NL too */
775
		vputp(tgoto(CS, LINES-1, 0), 1);/* restore scrolling region */
776
		vputp(RC, 1);			/* put cursor back */
777
	}
778
	else {
779
		for (i = 0; i < cnt; i++)
780
			vputp(DL, WECHO - p);
781
	}
782
	vadjDL(p, cnt);
783
	vcloseup(l, cnt);
784
}
785
/*
786
 * Adjust internal physical screen image to account for deleted lines.
787
 */
788
vadjDL(p, cnt)
789
	int p, cnt;
790
{
791
#ifndef	BIT8
792
	char *tlines[TUBELINES];
793
#else
794
	short *tlines[TUBELINES];
795
#endif
796
	register int from, to;
797
 
798
#ifdef ADEBUG
799
	if (trace)
800
		tfixnl(), fprintf(trace, "vadjDL(%d, %d)\n", p, cnt);
801
#endif
802
	/*
803
	 * Would like to use structured assignment but early
804
	 * v7 compiler (released with phototypesetter for v6)
805
	 * can't hack it.
806
	 */
807
	copy(tlines, vtube, sizeof vtube);	/*SASSIGN*/
808
	for (from = p + cnt, to = p; from <= WECHO; from++, to++)
809
		vtube[to] = tlines[from];
810
	for (from = p; to <= WECHO; from++, to++) {
811
		vtube[to] = tlines[from];
812
		vclrbyte(vtube[to], WCOLS);
813
	}
814
}
815
/*
816
 * Sync the screen, like redraw but more lazy and willing to leave
817
 * @ lines on the screen.  VsyncCL syncs starting at the current line.
818
 * In any case, if the redraw option is set then all syncs map to redraws
819
 * as if vsync didn't exist.
820
 */
821
vsyncCL()
822
{
823
 
824
	vsync(LINE(vcline));
825
}
826
 
121 7u83 827
int
105 7u83 828
vsync(p)
829
	register int p;
830
{
831
 
832
	if (value(REDRAW))
833
		vredraw(p);
834
	else
835
		vsync1(p);
836
}
837
 
838
/*
839
 * The guts of a sync.  Similar to redraw but
840
 * just less ambitous.
841
 */
842
vsync1(p)
843
	register int p;
844
{
845
	register int l;
846
	char temp[LBSIZE];
847
	register struct vlinfo *vp = &vlinfo[0];
848
	short oldhold = hold;
849
 
850
#ifdef ADEBUG
851
	if (trace)
852
		tfixnl(), fprintf(trace, "vsync1(%d)\n", p), tvliny();
853
#endif
854
	if (holdupd) {
855
		if (holdupd < 3)
856
			holdupd = 2;
857
		return;
858
	}
859
	if (state == HARDOPEN || splitw)
860
		return;
861
	vscrap();
115 7u83 862
	CP(temp, linebuf);
105 7u83 863
	if (vcnt == 0)
864
		LINE(0) = WTOP;
865
	l = 0;
866
	while (l < vcnt && vp->vliny < p)
867
		l++, vp++;
868
	heldech = 0;
869
	hold |= HOLDECH;
870
	while (p <= WBOT && Peekkey != ATTN) {
871
		/*
872
		 * Want to put a line here if not in visual and first line
873
		 * or if there are lies left and this line starts before
874
		 * the current line, or if this line is piled under the
875
		 * next line (vreplace does this and we undo it).
876
		 */
877
		if (l == 0 && state != VISUAL ||
878
		    (l < vcnt && (vp->vliny <= p || vp[0].vliny == vp[1].vliny))) {
879
			if (l == 0 || vp->vliny < p || (vp->vflags & VDIRT)) {
880
				if (l == vcline)
881
					strcLIN(temp);
882
				else
118 7u83 883
					ex_getline(dot[l - vcline]);
105 7u83 884
				/*
885
				 * Be careful that a long line doesn't cause the
886
				 * screen to shoot up.
887
				 */
888
				if (l != vcline && (vp->vflags & VDIRT)) {
889
					vp->vdepth = vdepth();
890
					vp->vflags &= ~VDIRT;
891
					if (p + vp->vdepth - 1 > WBOT)
892
						break;
893
				}
894
				vreopen(p, lineDOT() + (l - vcline), l);
895
			}
896
			p = vp->vliny + vp->vdepth;
897
			vp++;
898
			l++;
899
		} else
900
			/*
901
			 * A physical line between logical lines,
902
			 * so we settle for an @ at the beginning.
903
			 */
904
			vclrlin(p, dot + (l - vcline)), p++;
905
	}
906
	strcLIN(temp);
907
	hold = oldhold;
908
	if (heldech)
909
		vclrech(0);
910
}
911
 
912
/*
913
 * Subtract (logically) cnt physical lines from the 
914
 * displayed position of lines starting with line l.
915
 */
916
vcloseup(l, cnt)
917
	int l;
918
	register int cnt;
919
{
920
	register int i;
921
 
922
#ifdef ADEBUG
923
	if (trace)
924
		tfixnl(), fprintf(trace, "vcloseup(%d, %d)\n", l, cnt);
925
#endif
926
	for (i = l + 1; i <= vcnt; i++)
927
		LINE(i) -= cnt;
928
}
929
 
930
/*
931
 * Workhorse for rearranging line descriptors on changes.
932
 * The idea here is that, starting with line l, cnt lines
933
 * have been replaced with newcnt lines.  All of these may
934
 * be ridiculous, i.e. l may be -1000, cnt 50 and newcnt 0,
935
 * since we may be called from an undo after the screen has
936
 * moved a lot.  Thus we have to be careful.
937
 *
938
 * Many boundary conditions here.
939
 */
940
vreplace(l, cnt, newcnt)
941
	int l, cnt, newcnt;
942
{
943
	register int from, to, i;
944
	bool savenote = 0;
945
 
946
#ifdef ADEBUG
947
	if (trace) {
948
		tfixnl(), fprintf(trace, "vreplace(%d, %d, %d)\n", l, cnt, newcnt);
949
		tvliny();
950
	}
951
#endif
952
	if (l >= vcnt)
953
		return;
954
	if (l < 0) {
955
		if (l + cnt < 0) {
956
			/*
957
			 * Nothing on the screen is relevant.
958
			 * Settle for redrawing from scratch (later).
959
			 */
960
			vcnt = 0;
961
			return;
962
		}
963
		/*
964
		 * Normalize l to top of screen; the add is
965
		 * really a subtract from cnt since l is negative.
966
		 */
967
		cnt += l;
968
		l = 0;
969
 
970
		/*
971
		 * Unseen lines were affect so notify (later).
972
		 */
973
		savenote++;
974
	}
975
 
976
	/*
977
	 * These shouldn't happen
978
	 * but would cause great havoc.
979
	 */
980
	if (cnt < 0)
981
		cnt = 0;
982
	if (newcnt < 0)
983
		newcnt = 0;
984
 
985
	/*
986
	 * Surely worthy of note if more than report
987
	 * lines were changed.
988
	 */
989
	if (cnt > value(REPORT) || newcnt > value(REPORT))
990
		savenote++;
991
 
992
	/*
993
	 * Same number of lines affeted as on screen, and we
994
	 * can insert and delete lines.  Thus we just type
995
	 * over them, since otherwise we will push them
996
	 * slowly off the screen, a clear lose.
997
	 */
998
	if (cnt == newcnt || vcnt - l == newcnt && AL && DL) {
999
		if (cnt > 1 && l + cnt > vcnt)
1000
			savenote++;
1001
		vdirty(l, newcnt);
1002
	} else {
1003
		/*
1004
		 * Lines are going away, squish them out.
1005
		 */
1006
		if (cnt > 0) {
1007
			/*
1008
			 * If non-displayed lines went away,
1009
			 * always notify.
1010
			 */
1011
			if (cnt > 1 && l + cnt > vcnt)
1012
				savenote++;
1013
			if (l + cnt >= vcnt)
1014
				cnt = vcnt - l;
1015
			else
1016
				for (from = l + cnt, to = l; from <= vcnt; to++, from++)
1017
					vlcopy(vlinfo[to], vlinfo[from]);
1018
			vcnt -= cnt;
1019
		}
1020
		/*
1021
		 * Open up space for new lines appearing.
1022
		 * All new lines are piled in the same place,
1023
		 * and will be unpiled by vredraw/vsync, which
1024
		 * inserts lines in front as it unpiles.
1025
		 */
1026
		if (newcnt > 0) {
1027
			/*
1028
			 * Newlines are appearing which may not show,
1029
			 * so notify (this is only approximately correct
1030
			 * when long lines are present).
1031
			 */
1032
			if (newcnt > 1 && l + newcnt > vcnt + 1)
1033
				savenote++;
1034
 
1035
			/*
1036
			 * If there will be more lines than fit, then
1037
			 * just throw way the rest of the stuff on the screen.
1038
			 */
1039
			if (l + newcnt > WBOT && AL && DL) {
1040
				vcnt = l;
1041
				goto skip;
1042
			}
1043
			from = vcnt, to = vcnt + newcnt;
1044
			i = TUBELINES - to;
1045
			if (i < 0)
1046
				from += i, to += i;
1047
			vcnt = to;
1048
			for (; from >= l; from--, to--)
1049
				vlcopy(vlinfo[to], vlinfo[from]);
1050
			for (from = to + 1, to = l; to < l + newcnt && to <= WBOT + 1; to++) {
1051
				LINE(to) = LINE(from);
1052
				DEPTH(to) = 0;
1053
				FLAGS(to) = VDIRT;
1054
			}
1055
		}
1056
	}
1057
skip:
1058
	if (Pline == numbline && cnt != newcnt)
1059
		/*
1060
		 * When lines positions are shifted, the numbers
1061
		 * will be wrong.
1062
		 */
1063
		vdirty(l, WECHO);
1064
	if (!savenote)
1065
		notecnt = 0;
1066
#ifdef ADEBUG
1067
	if (trace)
1068
		tvliny();
1069
#endif
1070
}
1071
 
1072
/*
1073
 * Start harcopy open.
1074
 * Print an image of the line to the left of the cursor
1075
 * under the full print of the line and position the cursor.
1076
 * If we are in a scroll ^D within hardcopy open then all this
1077
 * is suppressed.
1078
 */
1079
sethard()
1080
{
1081
 
1082
	if (state == VISUAL)
1083
		return;
1084
	rubble = 0;
1085
	state = HARDOPEN;
1086
	if (hold & HOLDROL)
1087
		return;
1088
	vup1();
1089
	LINE(0) = WBOT;
1090
	if (Pline == numbline)
1091
		vgoto(WBOT, 0), printf("%6d  ", lineDOT());
1092
}
1093
 
1094
/*
1095
 * Mark the lines starting at base for i lines
1096
 * as dirty so that they will be checked for correct
1097
 * display at next sync/redraw.
1098
 */
1099
vdirty(base, i)
1100
	register int base, i;
1101
{
1102
	register int l;
1103
 
1104
	for (l = base; l < vcnt; l++) {
1105
		if (--i < 0)
1106
			return;
1107
		FLAGS(l) |= VDIRT;
1108
	}
1109
}