xref: /openbsd-src/usr.bin/vi/vi/v_put.c (revision 721c3ea39d2f81e07c2d7c0976681cb89b2dd3b5)
1 /*	$OpenBSD: v_put.c,v 1.8 2016/05/27 09:18:12 martijn Exp $	*/
2 
3 /*-
4  * Copyright (c) 1992, 1993, 1994
5  *	The Regents of the University of California.  All rights reserved.
6  * Copyright (c) 1992, 1993, 1994, 1995, 1996
7  *	Keith Bostic.  All rights reserved.
8  *
9  * See the LICENSE file for redistribution information.
10  */
11 
12 #include "config.h"
13 
14 #include <sys/types.h>
15 #include <sys/queue.h>
16 #include <sys/time.h>
17 
18 #include <bitstring.h>
19 #include <limits.h>
20 #include <stdio.h>
21 
22 #include "../common/common.h"
23 #include "vi.h"
24 
25 static void	inc_buf(SCR *, VICMD *);
26 
27 /*
28  * v_Put -- [buffer]P
29  *	Insert the contents of the buffer before the cursor.
30  *
31  * PUBLIC: int v_Put(SCR *, VICMD *);
32  */
33 int
v_Put(SCR * sp,VICMD * vp)34 v_Put(SCR *sp, VICMD *vp)
35 {
36 	u_long cnt;
37 
38 	if (F_ISSET(vp, VC_ISDOT))
39 		inc_buf(sp, vp);
40 
41 	/*
42 	 * !!!
43 	 * Historic vi did not support a count with the 'p' and 'P'
44 	 * commands.  It's useful, so we do.
45 	 */
46 	for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
47 		if (put(sp, NULL,
48 		    F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
49 		    &vp->m_start, &vp->m_final, 0))
50 			return (1);
51 		vp->m_start = vp->m_final;
52 		if (INTERRUPTED(sp))
53 			return (1);
54 	}
55 	return (0);
56 }
57 
58 /*
59  * v_put -- [buffer]p
60  *	Insert the contents of the buffer after the cursor.
61  *
62  * PUBLIC: int v_put(SCR *, VICMD *);
63  */
64 int
v_put(SCR * sp,VICMD * vp)65 v_put(SCR *sp, VICMD *vp)
66 {
67 	u_long cnt;
68 
69 	if (F_ISSET(vp, VC_ISDOT))
70 		inc_buf(sp, vp);
71 
72 	/*
73 	 * !!!
74 	 * Historic vi did not support a count with the 'p' and 'P'
75 	 * commands.  It's useful, so we do.
76 	 */
77 	for (cnt = F_ISSET(vp, VC_C1SET) ? vp->count : 1; cnt--;) {
78 		if (put(sp, NULL,
79 		    F_ISSET(vp, VC_BUFFER) ? &vp->buffer : NULL,
80 		    &vp->m_start, &vp->m_final, 1))
81 			return (1);
82 		vp->m_start = vp->m_final;
83 		if (INTERRUPTED(sp))
84 			return (1);
85 	}
86 	return (0);
87 }
88 
89 /*
90  * !!!
91  * Historical whackadoo.  The dot command `puts' the numbered buffer
92  * after the last one put.  For example, `"4p.' would put buffer #4
93  * and buffer #5.  If the user continued to enter '.', the #9 buffer
94  * would be repeatedly output.  This was not documented, and is a bit
95  * tricky to reconstruct.  Historical versions of vi also dropped the
96  * contents of the default buffer after each put, so after `"4p' the
97  * default buffer would be empty.  This makes no sense to me, so we
98  * don't bother.  Don't assume sequential order of numeric characters.
99  *
100  * And, if that weren't exciting enough, failed commands don't normally
101  * set the dot command.  Well, boys and girls, an exception is that
102  * the buffer increment gets done regardless of the success of the put.
103  */
104 static void
inc_buf(SCR * sp,VICMD * vp)105 inc_buf(SCR *sp, VICMD *vp)
106 {
107 	CHAR_T v;
108 
109 	switch (vp->buffer) {
110 	case '1':
111 		v = '2';
112 		break;
113 	case '2':
114 		v = '3';
115 		break;
116 	case '3':
117 		v = '4';
118 		break;
119 	case '4':
120 		v = '5';
121 		break;
122 	case '5':
123 		v = '6';
124 		break;
125 	case '6':
126 		v = '7';
127 		break;
128 	case '7':
129 		v = '8';
130 		break;
131 	case '8':
132 		v = '9';
133 		break;
134 	default:
135 		return;
136 	}
137 	VIP(sp)->sdot.buffer = vp->buffer = v;
138 }
139