Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
99 7u83 1
/*
2
 * This code contains changes by
3
 *      Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
4
 *
5
 * Conditions 1, 2, and 4 and the no-warranty notice below apply
6
 * to these changes.
7
 *
8
 *
9
 * Copyright (c) 1980, 1993
10
 * 	The Regents of the University of California.  All rights reserved.
11
 *
12
 * Redistribution and use in source and binary forms, with or without
13
 * modification, are permitted provided that the following conditions
14
 * are met:
15
 * 1. Redistributions of source code must retain the above copyright
16
 *    notice, this list of conditions and the following disclaimer.
17
 * 2. Redistributions in binary form must reproduce the above copyright
18
 *    notice, this list of conditions and the following disclaimer in the
19
 *    documentation and/or other materials provided with the distribution.
20
 * 3. All advertising materials mentioning features or use of this software
21
 *    must display the following acknowledgement:
22
 * 	This product includes software developed by the University of
23
 * 	California, Berkeley and its contributors.
24
 * 4. Neither the name of the University nor the names of its contributors
25
 *    may be used to endorse or promote products derived from this software
26
 *    without specific prior written permission.
27
 *
28
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38
 * SUCH DAMAGE.
39
 *
40
 *
41
 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
42
 *
43
 * Redistribution and use in source and binary forms, with or without
44
 * modification, are permitted provided that the following conditions
45
 * are met:
46
 *   Redistributions of source code and documentation must retain the
47
 *    above copyright notice, this list of conditions and the following
48
 *    disclaimer.
49
 *   Redistributions in binary form must reproduce the above copyright
50
 *    notice, this list of conditions and the following disclaimer in the
51
 *    documentation and/or other materials provided with the distribution.
52
 *   All advertising materials mentioning features or use of this software
53
 *    must display the following acknowledgement:
54
 *      This product includes software developed or owned by Caldera
55
 *      International, Inc.
56
 *   Neither the name of Caldera International, Inc. nor the names of
57
 *    other contributors may be used to endorse or promote products
58
 *    derived from this software without specific prior written permission.
59
 *
60
 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
61
 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
62
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
63
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64
 * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
65
 * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
66
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
67
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
68
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
69
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
70
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
71
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
72
 */
73
 
74
#ifndef	lint
75
#ifdef	DOSCCS
76
static char sccsid[] = "@(#)ex_vops.c	1.26 (gritter) 1/13/05";
77
#endif
78
#endif
79
 
80
/* from ex_vops.c	7.7 (Berkeley) 6/7/85 */
81
 
82
#include "ex.h"
83
#include "ex_tty.h"
84
#include "ex_vis.h"
85
 
86
/*
87
 * This file defines the operation sequences which interface the
88
 * logical changes to the file buffer with the internal and external
89
 * display representations.
90
 */
91
 
92
/*
93
 * Undo.
94
 *
95
 * Undo is accomplished in two ways.  We often for small changes in the
96
 * current line know how (in terms of a change operator) how the change
97
 * occurred.  Thus on an intelligent terminal we can undo the operation
98
 * by another such operation, using insert and delete character
99
 * stuff.  The pointers vU[AD][12] index the buffer vutmp when this
100
 * is possible and provide the necessary information.
101
 *
102
 * The other case is that the change involved multiple lines or that
103
 * we have moved away from the line or forgotten how the change was
104
 * accomplished.  In this case we do a redisplay and hope that the
105
 * low level optimization routines (which don't look for winning
106
 * via insert/delete character) will not lose too badly.
107
 */
108
char	*vUA1, *vUA2;
109
char	*vUD1, *vUD2;
110
 
111
void 
112
vUndo(void)
113
{
114
 
115
	/*
116
	 * Avoid UU which clobbers ability to do u.
117
	 */
118
	if (vundkind == VCAPU || vUNDdot != dot) {
119
		beep();
120
		return;
121
	}
122
	CP(vutmp, linebuf);
123
	vUD1 = linebuf; vUD2 = strend(linebuf);
124
	putmk1(dot, vUNDsav);
125
	getDOT();
126
	vUA1 = linebuf; vUA2 = strend(linebuf);
127
	vundkind = VCAPU;
128
	if (state == ONEOPEN || state == HARDOPEN) {
129
		vjumpto(dot, vUNDcurs, 0);
130
		return;
131
	}
132
	vdirty(vcline, 1);
133
	vsyncCL();
134
	cursor = linebuf;
135
	vfixcurs();
136
}
137
 
138
void 
139
vundo (
140
    int show	/* if true update the screen */
141
)
142
{
143
	register int cnt;
144
	register line *addr;
145
	register char *cp;
146
	char temp[LBSIZE];
147
	bool savenote;
148
	int (*OO)(int);
149
	short oldhold = hold;
150
 
151
	switch (vundkind) {
152
 
153
	case VMANYINS:
154
		wcursor = 0;
155
		addr1 = undap1;
156
		addr2 = undap2 - 1;
157
		vsave();
158
		YANKreg('1');
159
		notecnt = 0;
160
		/* fall into ... */
161
 
162
	case VMANY:
163
	case VMCHNG:
164
		vsave();
165
		addr = dot - vcline;
166
		notecnt = 1;
167
		if (undkind == UNDPUT && undap1 == undap2) {
168
			beep();
169
			break;
170
		}
171
		/*
172
		 * Undo() call below basically replaces undap1 to undap2-1
173
		 * with dol through unddol-1.  Hack screen image to
174
		 * reflect this replacement.
175
		 */
176
		if (show)
177
			if (undkind == UNDMOVE)
178
				vdirty(0, TLINES);
179
			else
180
				vreplace(undap1 - addr, undap2 - undap1,
181
				    undkind == UNDPUT ? 0 : unddol - dol);
182
		savenote = notecnt;
183
		undo(1);
184
		if (show && (vundkind != VMCHNG || addr != dot))
185
			killU();
186
		vundkind = VMANY;
187
		cnt = dot - addr;
188
		if (cnt < 0 || cnt > vcnt || state != VISUAL) {
189
			if (show)
190
				vjumpto(dot, NOSTR, '.');
191
			break;
192
		}
193
		if (!savenote)
194
			notecnt = 0;
195
		if (show) {
196
			vcline = cnt;
197
			vrepaint(vmcurs);
198
		}
199
		vmcurs = 0;
200
		break;
201
 
202
	case VCHNG:
203
	case VCAPU:
204
		vundkind = VCHNG;
205
		CP(temp, vutmp);
206
		CP(vutmp, linebuf);
207
		doomed = column(vUA2 - 1) - column(vUA1 - 1);
208
		strcLIN(temp);
209
		cp = vUA1; vUA1 = vUD1; vUD1 = cp;
210
		cp = vUA2; vUA2 = vUD2; vUD2 = cp;
211
		if (!show)
212
			break;
213
		cursor = vUD1;
214
		if (state == HARDOPEN) {
215
			doomed = 0;
216
			vsave();
217
			vopen(dot, WBOT);
218
			vnline(cursor);
219
			break;
220
		}
221
		/*
222
		 * Pseudo insert command.
223
		 */
224
		vcursat(cursor);
225
		OO = Outchar; Outchar = vinschar; hold |= HOLDQIK;
226
		vprepins();
227
		temp[vUA2 - linebuf] = 0;
228
		for (cp = &temp[vUA1 - linebuf]; *cp;) {
229
			int	c, n;
230
			nextc(c, cp, n);
231
			cp += n;
232
			putchar(c);
233
		}
234
		Outchar = OO; hold = oldhold;
235
		endim();
236
		physdc(cindent(), cindent() + doomed);
237
		doomed = 0;
238
		vdirty(vcline, 1);
239
		vsyncCL();
240
		if (cursor > linebuf && cursor >= strend(linebuf))
241
			cursor += skipleft(linebuf, cursor);
242
		vfixcurs();
243
		break;
244
 
245
	case VNONE:
246
		beep();
247
		break;
248
	}
249
}
250
 
251
/*
252
 * Routine to handle a change inside a macro.
253
 * Fromvis is true if we were called from a visual command (as
254
 * opposed to an ex command).  This has nothing to do with being
255
 * in open/visual mode as :s/foo/bar is not fromvis.
256
 */
257
void 
258
vmacchng(int fromvis)
259
{
260
	line *savedot, *savedol;
261
	char *savecursor;
262
	char savelb[LBSIZE];
263
	int nlines, more;
264
	/* register line *a1, *a2; */
265
	/* char ch; */	/* DEBUG */
266
 
267
	if (!inopen)
268
		return;
269
	if (!vmacp)
270
		vch_mac = VC_NOTINMAC;
271
#ifdef TRACE
272
	if (trace)
273
		fprintf(trace, "vmacchng, vch_mac=%d, linebuf='%s', *dot=%o\n", vch_mac, linebuf, *dot);
274
#endif
275
	if (vmacp && fromvis)
276
		vsave();
277
#ifdef TRACE
278
	if (trace)
279
		fprintf(trace, "after vsave, linebuf='%s', *dot=%o\n", linebuf, *dot);
280
#endif
281
	switch(vch_mac) {
282
	case VC_NOCHANGE:
283
		vch_mac = VC_ONECHANGE;
284
		break;
285
	case VC_ONECHANGE:
286
		/* Save current state somewhere */
287
#ifdef TRACE
288
		vudump("before vmacchng hairy case");
289
#endif
290
		savedot = dot; savedol = dol; savecursor = cursor;
291
		CP(savelb, linebuf);
292
		nlines = dol - zero;
293
		while ((line *) endcore - truedol < nlines)
294
			morelines();
295
		copyw(truedol+1, zero+1, nlines);
296
		truedol += nlines;
297
 
298
#ifdef TRACE
299
		visdump("before vundo");
300
#endif
301
		/* Restore state as it was at beginning of macro */
302
		vundo(0);
303
#ifdef TRACE
304
		visdump("after vundo");
305
		vudump("after vundo");
306
#endif
307
 
308
		/* Do the saveall we should have done then */
309
		saveall();
310
#ifdef TRACE
311
		vudump("after saveall");
312
#endif
313
 
314
		/* Restore current state from where saved */
315
		more = savedol - dol; /* amount we shift everything by */
316
		if (more)
317
			(*(more>0 ? copywR : copyw))(savedol+1, dol+1, truedol-dol);
318
		unddol += more; truedol += more; undap2 += more;
319
 
320
		truedol -= nlines;
321
		copyw(zero+1, truedol+1, nlines);
322
		dot = savedot; dol = savedol ; cursor = savecursor;
323
		CP(linebuf, savelb);
324
		vch_mac = VC_MANYCHANGE;
325
 
326
		/* Arrange that no further undo saving happens within macro */
327
		otchng = tchng;	/* Copied this line blindly - bug? */
328
		inopen = -1;	/* no need to save since it had to be 1 or -1 before */
329
		vundkind = VMANY;
330
#ifdef TRACE
331
		vudump("after vmacchng");
332
#endif
333
		break;
334
	case VC_NOTINMAC:
335
	case VC_MANYCHANGE:
336
		/* Nothing to do for various reasons. */
337
		break;
338
	}
339
}
340
 
341
/*
342
 * Initialize undo information before an append.
343
 */
344
void 
345
vnoapp(void)
346
{
347
 
348
	vUD1 = vUD2 = cursor;
349
}
350
 
351
/*
352
 * All the rest of the motion sequences have one or more
353
 * cases to deal with.  In the case wdot == 0, operation
354
 * is totally within current line, from cursor to wcursor.
355
 * If wdot is given, but wcursor is 0, then operation affects
356
 * the inclusive line range.  The hardest case is when both wdot
357
 * and wcursor are given, then operation affects from line dot at
358
 * cursor to line wdot at wcursor.
359
 */
360
 
361
/*
362
 * Move is simple, except for moving onto new lines in hardcopy open mode.
363
 */
364
/*ARGSUSED*/
365
void 
366
vmove(int unused)
367
{
368
	register int cnt;
369
 
370
	if (wdot) {
371
		if (wdot < one || wdot > dol) {
372
			beep();
373
			return;
374
		}
375
		cnt = wdot - dot;
376
		wdot = NOLINE;
377
		if (cnt)
378
			killU();
379
		vupdown(cnt, wcursor);
380
		return;
381
	}
382
 
383
	/*
384
	 * When we move onto a new line, save information for U undo.
385
	 */
386
	if (vUNDdot != dot) {
387
		vUNDsav = *dot;
388
		vUNDcurs = wcursor;
389
		vUNDdot = dot;
390
	}
391
 
392
	/*
393
	 * In hardcopy open, type characters to left of cursor
394
	 * on new line, or back cursor up if its to left of where we are.
395
	 * In any case if the current line is ``rubbled'' i.e. has trashy
396
	 * looking overstrikes on it or \'s from deletes, we reprint
397
	 * so it is more comprehensible (and also because we can't work
398
	 * if we let it get more out of sync since column() won't work right.
399
	 */
400
	if (state == HARDOPEN) {
401
		register char *cp;
402
		if (rubble) {
403
			register int c;
404
			int oldhold = hold;
405
 
406
			sethard();
407
			cp = wcursor;
408
			c = *cp;
409
			*cp = 0;
410
			hold |= HOLDDOL;
411
			vreopen(WTOP, lineDOT(), vcline);
412
			hold = oldhold;
413
			*cp = c;
414
		} else if (wcursor > cursor) {
415
			vfixcurs();
416
			for (cp = cursor; *cp && cp < wcursor;) {
417
				int	c, n;
418
				nextc(c, cp, n);
419
				cp += n;
420
				c &= TRIM;
421
				putchar(c ? c : ' ');
422
			}
423
		}
424
	}
425
	vsetcurs(wcursor);
426
}
427
 
428
/*
429
 * Delete operator.
430
 *
431
 * Hard case of deleting a range where both wcursor and wdot
432
 * are specified is treated as a special case of change and handled
433
 * by vchange (although vchange may pass it back if it degenerates
434
 * to a full line range delete.)
435
 */
436
void 
437
vdelete(int c)
438
{
439
	register char *cp;
440
	register int i;
441
 
442
	if (wdot) {
443
		if (wcursor) {
444
			vchange(EOF);
445
			return;
446
		}
447
		if ((i = xdw()) < 0)
448
			return;
449
		if (state != VISUAL) {
450
			vgoto(LINE(0), 0);
451
			vputchar('@');
452
		}
453
		wdot = dot;
454
		vremote(i, delete, 0);
455
		notenam = "delete";
456
		DEL[0] = 0;
457
		killU();
458
		vreplace(vcline, i, 0);
459
		if (wdot > dol)
460
			vcline--;
461
		vrepaint(NOSTR);
462
		return;
463
	}
464
	if (wcursor < linebuf)
465
		wcursor = linebuf;
466
	if (cursor == wcursor) {
467
		beep();
468
		return;
469
	}
470
	i = vdcMID();
471
	cp = cursor;
472
	setDEL();
473
	CP(cp, wcursor);
474
	if (cp > linebuf && (cp[0] == 0 || c == '#'))
475
		cp--;
476
	if (state == HARDOPEN) {
477
		bleep(i, cp);
478
		cursor = cp;
479
		return;
480
	}
481
	physdc(column(cursor + skipleft(linebuf, cursor)), i);
482
	DEPTH(vcline) = 0;
483
	vreopen(LINE(vcline), lineDOT(), vcline);
484
	vsyncCL();
485
	vsetcurs(cp);
486
}
487
 
488
/*
489
 * Change operator.
490
 *
491
 * In a single line we mark the end of the changed area with '$'.
492
 * On multiple whole lines, we clear the lines first.
493
 * Across lines with both wcursor and wdot given, we delete
494
 * and sync then append (but one operation for undo).
495
 */
496
void 
497
vchange(int c)
498
{
499
	register char *cp;
500
	register int i, ind, cnt;
501
	line *addr;
502
 
503
	if (wdot) {
504
		/*
505
		 * Change/delete of lines or across line boundaries.
506
		 */
507
		if ((cnt = xdw()) < 0)
508
			return;
509
		getDOT();
510
		if (wcursor && cnt == 1) {
511
			/*
512
			 * Not really.
513
			 */
514
			wdot = 0;
515
			if (c == EOF) {
516
				vdelete(c);
517
				return;
518
			}
519
			goto smallchange;
520
		}
521
		if (cursor && wcursor) {
522
			/*
523
			 * Across line boundaries, but not
524
			 * necessarily whole lines.
525
			 * Construct what will be left.
526
			 */
527
			*cursor = 0;
528
			strcpy(genbuf, linebuf);
529
			getline(*wdot);
530
			if (strlen(genbuf) + strlen(wcursor) > LBSIZE - 2) {
531
				getDOT();
532
				beep();
533
				return;
534
			}
535
			strcat(genbuf, wcursor);
536
			if (c == EOF && *vpastwh(genbuf) == 0) {
537
				/*
538
				 * Although this is a delete
539
				 * spanning line boundaries, what
540
				 * would be left is all white space,
541
				 * so take it all away.
542
				 */
543
				wcursor = 0;
544
				getDOT();
545
				op = 0;
546
				notpart(lastreg);
547
				notpart('1');
548
				vdelete(c);
549
				return;
550
			}
551
			ind = -1;
552
		} else if (c == EOF && wcursor == 0) {
553
			vdelete(c);
554
			return;
555
		} else
556
#ifdef LISPCODE
557
			/*
558
			 * We are just substituting text for whole lines,
559
			 * so determine the first autoindent.
560
			 */
561
			if (value(LISP) && value(AUTOINDENT))
562
				ind = lindent(dot);
563
			else
564
#endif
565
				ind = whitecnt(linebuf);
566
		i = vcline >= 0 ? LINE(vcline) : WTOP;
567
 
568
		/*
569
		 * Delete the lines from the buffer,
570
		 * and remember how the partial stuff came about in
571
		 * case we are told to put.
572
		 */
573
		addr = dot;
574
		vremote(cnt, delete, 0);
575
		setpk();
576
		notenam = "delete";
577
		if (c != EOF)
578
			notenam = "change";
579
		/*
580
		 * If DEL[0] were nonzero, put would put it back
581
		 * rather than the deleted lines.
582
		 */
583
		DEL[0] = 0;
584
		if (cnt > 1)
585
			killU();
586
 
587
		/*
588
		 * Now hack the screen image coordination.
589
		 */
590
		vreplace(vcline, cnt, 0);
591
		wdot = NOLINE;
592
		noteit(0);
593
		vcline--;
594
		if (addr <= dol)
595
			dot--;
596
 
597
		/*
598
		 * If this is a across line delete/change,
599
		 * cursor stays where it is; just splice together the pieces
600
		 * of the new line.  Otherwise generate a autoindent
601
		 * after a S command.
602
		 */
603
		if (ind >= 0) {
604
			*genindent(ind) = 0;
605
			vdoappend(genbuf);
606
		} else {
607
			vmcurs = cursor;
608
			strcLIN(genbuf);
609
			vdoappend(linebuf);
610
		}
611
 
612
		/*
613
		 * Indicate a change on hardcopies by
614
		 * erasing the current line.
615
		 */
616
		if (c != EOF && state != VISUAL && state != HARDOPEN) {
617
			int oldhold = hold;
618
 
619
			hold |= HOLDAT, vclrlin(i, dot), hold = oldhold;
620
		}
621
 
622
		/*
623
		 * Open the line (logically) on the screen, and 
624
		 * update the screen tail.  Unless we are really a delete
625
		 * go off and gather up inserted characters.
626
		 */
627
		vcline++;
628
		if (vcline < 0)
629
			vcline = 0;
630
		vopen(dot, i);
631
		vsyncCL();
632
		noteit(1);
633
		if (c != EOF) {
634
			if (ind >= 0) {
635
				cursor = linebuf;
636
				linebuf[0] = 0;
637
				vfixcurs();
638
			} else {
639
				ind = 0;
640
				vcursat(cursor);
641
			}
642
			vappend('x', 1, ind);
643
			return;
644
		}
645
		if (*cursor == 0 && cursor > linebuf)
646
			cursor += skipleft(linebuf, cursor);
647
		vrepaint(cursor);
648
		return;
649
	}
650
 
651
smallchange:
652
	/*
653
	 * The rest of this is just low level hacking on changes
654
	 * of small numbers of characters.
655
	 */
656
	if (wcursor < linebuf)
657
		wcursor = linebuf;
658
	if (cursor == wcursor) {
659
		beep();
660
		return;
661
	}
662
	i = vdcMID();
663
	cp = cursor;
664
	if (state != HARDOPEN)
665
		vfixcurs();
666
 
667
	/*
668
	 * Put out the \\'s indicating changed text in hardcopy,
669
	 * or mark the end of the change with $ if not hardcopy.
670
	 */
671
	if (state == HARDOPEN) 
672
		bleep(i, cp);
673
	else {
674
		int	c, d, n;
675
		vcursbef(wcursor);
676
		d = skipleft(linebuf, wcursor);
677
		nextc(c, &wcursor[d], n);
678
		if (colsc(c) > 1)
679
			putchar(' ');
680
		putchar('$');
681
		i = cindent();
682
	}
683
 
684
	/*
685
	 * Remember the deleted text for possible put,
686
	 * and then prepare and execute the input portion of the change.
687
	 */
688
	cursor = cp;
689
	setDEL();
690
	CP(cursor, wcursor);
691
	if (state != HARDOPEN) {
692
		vcursaft(cursor - 1);
693
		doomed = i - cindent();
694
	} else {
695
/*
696
		sethard();
697
		wcursor = cursor;
698
		cursor = linebuf;
699
		vgoto(outline, value(NUMBER) << 3);
700
		vmove();
701
*/
702
		doomed = 0;
703
	}
704
	prepapp();
705
	vappend('c', 1, 0);
706
}
707
 
708
/*
709
 * Open new lines.
710
 *
711
 * Tricky thing here is slowopen.  This causes display updating
712
 * to be held off so that 300 baud dumb terminals don't lose badly.
713
 * This also suppressed counts, which otherwise say how many blank
714
 * space to open up.  Counts are also suppressed on intelligent terminals.
715
 * Actually counts are obsoleted, since if your terminal is slow
716
 * you are better off with slowopen.
717
 */
718
void 
719
voOpen (
720
    int c,	/* mjm: char --> int */
721
    register int cnt
722
)
723
{
724
	register int ind = 0, i;
725
	short oldhold = hold;
726
#ifdef	SIGWINCH
727
	sigset_t set, oset;
728
#endif
729
 
730
	if (value(SLOWOPEN) || value(REDRAW) && AL && DL)
731
		cnt = 1;
732
#ifdef	SIGWINCH
733
	sigemptyset(&set);
734
	sigaddset(&set, SIGWINCH);
735
	sigprocmask(SIG_BLOCK, &set, &oset);
736
#endif
737
	vsave();
738
	setLAST();
739
	if (value(AUTOINDENT))
740
		ind = whitecnt(linebuf);
741
	if (c == 'O') {
742
		vcline--;
743
		dot--;
744
		if (dot > zero)
745
			getDOT();
746
	}
747
	if (value(AUTOINDENT)) {
748
#ifdef LISPCODE
749
		if (value(LISP))
750
			ind = lindent(dot + 1);
751
#endif
752
	}
753
	killU();
754
	prepapp();
755
	if (FIXUNDO)
756
		vundkind = VMANY;
757
	if (state != VISUAL)
758
		c = WBOT + 1;
759
	else {
760
		c = vcline < 0 ? WTOP - cnt : LINE(vcline) + DEPTH(vcline);
761
		if (c < ZERO)
762
			c = ZERO;
763
		i = LINE(vcline + 1) - c;
764
		if (i < cnt && c <= WBOT && (!AL || !DL))
765
			vinslin(c, cnt - i, vcline);
766
	}
767
	*genindent(ind) = 0;
768
	vdoappend(genbuf);
769
	vcline++;
770
	oldhold = hold;
771
	hold |= HOLDROL;
772
	vopen(dot, c);
773
	hold = oldhold;
774
	if (value(SLOWOPEN))
775
		/*
776
		 * Oh, so lazy!
777
		 */
778
		vscrap();
779
	else
780
		vsync1(LINE(vcline));
781
	cursor = linebuf;
782
	linebuf[0] = 0;
783
	vappend('o', 1, ind);
784
#ifdef	SIGWINCH
785
	sigprocmask(SIG_SETMASK, &oset, NULL);
786
#endif
787
}
788
 
789
/*
790
 * > < and = shift operators.
791
 *
792
 * Note that =, which aligns lisp, is just a ragged sort of shift,
793
 * since it never distributes text between lines.
794
 */
795
char	vshnam[2] = { 'x', 0 };
796
 
797
/*ARGSUSED*/
798
void 
799
vshftop(int unused)
800
{
801
	register line *addr;
802
	register int cnt;
803
 
804
	if ((cnt = xdw()) < 0)
805
		return;
806
	addr = dot;
807
	vremote(cnt, vshift, 0);
808
	vshnam[0] = op;
809
	notenam = vshnam;
810
	dot = addr;
811
	vreplace(vcline, cnt, cnt);
812
	if (state == HARDOPEN)
813
		vcnt = 0;
814
	vrepaint(NOSTR);
815
}
816
 
817
/*
818
 * !.
819
 *
820
 * Filter portions of the buffer through unix commands.
821
 */
822
/*ARGSUSED*/
823
void 
824
vfilter(int unused)
825
{
826
	register line *addr;
827
	register int cnt;
828
	char *oglobp;
829
	short d;
830
#ifdef	BIT8
831
	cell cuxb[UXBSIZE + 2];
832
#endif
833
 
834
	if ((cnt = xdw()) < 0)
835
		return;
836
	if (vglobp)
837
#ifdef	BIT8
838
		vglobp = cuxb;
839
#else
840
		vglobp = uxb;
841
#endif
842
	if (readecho('!'))
843
		return;
844
	oglobp = globp; globp = genbuf + 1;
845
	d = peekc; ungetchar(0);
846
	CATCH
847
		fixech();
848
		unix0(0);
849
#ifdef	BIT8
850
		str2cell(cuxb, uxb);
851
#endif
852
	ONERR
853
		splitw = 0;
854
		ungetchar(d);
855
		vrepaint(cursor);
856
		globp = oglobp;
857
		return;
858
	ENDCATCH
859
	ungetchar(d); globp = oglobp;
860
	addr = dot;
861
	CATCH
862
		vgoto(WECHO, 0); flusho();
863
		vremote(cnt, filter, 2);
864
	ONERR
865
		vdirty(0, TLINES);
866
	ENDCATCH
867
	if (dot == zero && dol > zero)
868
		dot = one;
869
	splitw = 0;
870
	notenam = "";
871
	/*
872
	 * BUG: we shouldn't be depending on what undap2 and undap1 are,
873
	 * since we may be inside a macro.  What's really wanted is the
874
	 * number of lines we read from the filter.  However, the mistake
875
	 * will be an overestimate so it only results in extra work,
876
	 * it shouldn't cause any real screwups.
877
	 */
878
	vreplace(vcline, cnt, undap2 - undap1);
879
	dot = addr;
880
	if (dot > dol) {
881
		dot--;
882
		vcline--;
883
	}
884
	vrepaint(NOSTR);
885
}
886
 
887
/*
888
 * Xdw exchanges dot and wdot if appropriate and also checks
889
 * that wdot is reasonable.  Its name comes from
890
 *	xchange dotand wdot
891
 */
892
int 
893
xdw(void)
894
{
895
	register char *cp;
896
	register int cnt;
897
/*
898
	register int notp = 0;
899
 */
900
 
901
	if (wdot == NOLINE || wdot < one || wdot > dol) {
902
		beep();
903
		return (-1);
904
	}
905
	vsave();
906
	setLAST();
907
	if (dot > wdot || (dot == wdot && wcursor != 0 && cursor > wcursor)) {
908
		register line *addr;
909
 
910
		vcline -= dot - wdot;
911
		addr = dot; dot = wdot; wdot = addr;
912
		cp = cursor; cursor = wcursor; wcursor = cp;
913
	}
914
	/*
915
	 * If a region is specified but wcursor is at the begining
916
	 * of the last line, then we move it to be the end of the
917
	 * previous line (actually off the end).
918
	 */
919
	if (cursor && wcursor == linebuf && wdot > dot) {
920
		wdot--;
921
		getDOT();
922
		if (vpastwh(linebuf) >= cursor)
923
			wcursor = 0;
924
		else {
925
			getline(*wdot);
926
			wcursor = strend(linebuf);
927
			getDOT();
928
		}
929
		/*
930
		 * Should prepare in caller for possible dot == wdot.
931
		 */
932
	}
933
	cnt = wdot - dot + 1;
934
	if (vreg) {
935
		vremote(cnt, YANKreg, vreg);
936
/*
937
		if (notp)
938
			notpart(vreg);
939
 */
940
	}
941
 
942
	/*
943
	 * Kill buffer code.  If delete operator is c or d, then save
944
	 * the region in numbered buffers.
945
	 *
946
	 * BUG:			This may be somewhat inefficient due
947
	 *			to the way named buffer are implemented,
948
	 *			necessitating some optimization.
949
	 */
950
	vreg = 0;
951
	if (any(op, "cd")) {
952
		vremote(cnt, YANKreg, '1');
953
/*
954
		if (notp)
955
			notpart('1');
956
 */
957
	}
958
	return (cnt);
959
}
960
 
961
/*
962
 * Routine for vremote to call to implement shifts.
963
 */
964
/*ARGSUSED*/
965
void 
966
vshift(int unused)
967
{
968
 
969
	shift(op, 1);
970
}
971
 
972
/*
973
 * Replace a single character with the next input character.
974
 * A funny kind of insert.
975
 */
976
void 
977
vrep(register int cnt)
978
{
979
	register int i, c;
980
 
981
	if (cnt > strlen(cursor)) {
982
		beep();
983
		return;
984
	}
985
	showmode('r');
986
	i = column(cursor + cnt - 1);
987
	vcursat(cursor);
988
	doomed = i - cindent();
989
	if (!vglobp) {
990
		c = getesc();
991
		if (c == 0) {
992
			showmode(0);
993
			vfixcurs();
994
			return;
995
		}
996
		ungetkey(c);
997
	}
998
	CP(vutmp, linebuf);
999
	if (FIXUNDO)
1000
		vundkind = VCHNG;
1001
	wcursor = cursor;
1002
	for (i = 0; i < cnt; i++)
1003
		wcursor += skipright(cursor, wcursor);
1004
	vUD1 = cursor; vUD2 = wcursor;
1005
	CP(cursor, wcursor);
1006
	prepapp();
1007
	vappend('r', cnt, 0);
1008
	*lastcp++ = INS[0];
1009
	setLAST();
1010
}
1011
 
1012
/*
1013
 * Yank.
1014
 *
1015
 * Yanking to string registers occurs for free (essentially)
1016
 * in the routine xdw().
1017
 */
1018
/*ARGSUSED*/
1019
void 
1020
vyankit(int unused)
1021
{
1022
	register int cnt;
1023
 
1024
	if (wdot) {
1025
		if ((cnt = xdw()) < 0)
1026
			return;
1027
		vremote(cnt, yank, 0);
1028
		setpk();
1029
		notenam = "yank";
1030
		if (FIXUNDO)
1031
			vundkind = VNONE;
1032
		DEL[0] = 0;
1033
		wdot = NOLINE;
1034
		if (notecnt <= vcnt - vcline && notecnt < value(REPORT))
1035
			notecnt = 0;
1036
		vrepaint(cursor);
1037
		return;
1038
	}
1039
	takeout(DEL);
1040
}
1041
 
1042
/*
1043
 * Set pkill variables so a put can
1044
 * know how to put back partial text.
1045
 * This is necessary because undo needs the complete
1046
 * line images to be saved, while a put wants to trim
1047
 * the first and last lines.  The compromise
1048
 * is for put to be more clever.
1049
 */
1050
void 
1051
setpk(void)
1052
{
1053
 
1054
	if (wcursor) {
1055
		pkill[0] = cursor;
1056
		pkill[1] = wcursor;
1057
	}
1058
}
1059
 
1060
/*
1061
 * Kill the last deleted part of a line so that "p" does not put it back.
1062
 * This is to be called from ex commands that delete some text.
1063
 */
1064
void
1065
vkillDEL(void)
1066
{
1067
	DEL[0] = 0;
1068
}