xref: /original-bsd/usr.bin/ex/ex_set.c (revision 3705696b)
1 /*-
2  * Copyright (c) 1980, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.proprietary.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)ex_set.c	8.1 (Berkeley) 06/09/93";
10 #endif /* not lint */
11 
12 #include "ex.h"
13 #include "ex_temp.h"
14 #include "ex_tty.h"
15 
16 /*
17  * Set command.
18  */
19 char	optname[ONMSZ];
20 
21 set()
22 {
23 	register char *cp;
24 	register struct option *op;
25 	register int c;
26 	bool no;
27 	extern short ospeed;
28 
29 	setnoaddr();
30 	if (skipend()) {
31 		if (peekchar() != EOF)
32 			ignchar();
33 		propts();
34 		return;
35 	}
36 	do {
37 		cp = optname;
38 		do {
39 			if (cp < &optname[ONMSZ - 2])
40 				*cp++ = ex_getchar();
41 		} while (isalnum(peekchar()));
42 		*cp = 0;
43 		cp = optname;
44 		if (eq("all", cp)) {
45 			if (inopen)
46 				pofix();
47 			prall();
48 			goto next;
49 		}
50 		no = 0;
51 		if (cp[0] == 'n' && cp[1] == 'o') {
52 			cp += 2;
53 			no++;
54 		}
55 		/* Implement w300, w1200, and w9600 specially */
56 		if (eq(cp, "w300")) {
57 			if (ospeed >= B1200) {
58 dontset:
59 				ignore(ex_getchar());	/* = */
60 				ignore(getnum());	/* value */
61 				continue;
62 			}
63 			cp = "window";
64 		} else if (eq(cp, "w1200")) {
65 			if (ospeed < B1200 || ospeed >= B2400)
66 				goto dontset;
67 			cp = "window";
68 		} else if (eq(cp, "w9600")) {
69 			if (ospeed < B2400)
70 				goto dontset;
71 			cp = "window";
72 		}
73 		for (op = options; op < &options[NOPTS]; op++)
74 			if (eq(op->oname, cp) || op->oabbrev && eq(op->oabbrev, cp))
75 				break;
76 		if (op->oname == 0)
77 			serror("%s: No such option@- 'set all' gives all option values", cp);
78 		c = skipwh();
79 		if (peekchar() == '?') {
80 			ignchar();
81 printone:
82 			propt(op);
83 			noonl();
84 			goto next;
85 		}
86 		if (op->otype == ONOFF) {
87 			op->ovalue = 1 - no;
88 			if (op == &options[PROMPT])
89 				oprompt = 1 - no;
90 			goto next;
91 		}
92 		if (no)
93 			serror("Option %s is not a toggle", op->oname);
94 		if (c != 0 || setend())
95 			goto printone;
96 		if (ex_getchar() != '=')
97 			serror("Missing =@in assignment to option %s", op->oname);
98 		switch (op->otype) {
99 
100 		case NUMERIC:
101 			if (!isdigit(peekchar()))
102 				error("Digits required@after =");
103 			op->ovalue = getnum();
104 			if (value(TABSTOP) <= 0)
105 				value(TABSTOP) = TABS;
106 			if (value(HARDTABS) <= 0)
107 				value(HARDTABS) = TABS;
108 			if (op == &options[WINDOW]) {
109 				if (value(WINDOW) >= LINES)
110 					value(WINDOW) = LINES-1;
111 				vsetsiz(value(WINDOW));
112 			}
113 			break;
114 
115 		case STRING:
116 		case OTERM:
117 			cp = optname;
118 			while (!setend()) {
119 				if (cp >= &optname[ONMSZ])
120 					error("String too long@in option assignment");
121 				/* adb change:  allow whitepace in strings */
122 				if( (*cp = ex_getchar()) == '\\')
123 					if( peekchar() != EOF)
124 						*cp = ex_getchar();
125 				cp++;
126 			}
127 			*cp = 0;
128 			if (op->otype == OTERM) {
129 /*
130  * At first glance it seems like we shouldn't care if the terminal type
131  * is changed inside visual mode, as long as we assume the screen is
132  * a mess and redraw it. However, it's a much harder problem than that.
133  * If you happen to change from 1 crt to another that both have the same
134  * size screen, it's OK. But if the screen size if different, the stuff
135  * that gets initialized in vop() will be wrong. This could be overcome
136  * by redoing the initialization, e.g. making the first 90% of vop into
137  * a subroutine. However, the most useful case is where you forgot to do
138  * a setenv before you went into the editor and it thinks you're on a dumb
139  * terminal. Ex treats this like hardcopy and goes into HARDOPEN mode.
140  * This loses because the first part of vop calls oop in this case.
141  * The problem is so hard I gave up. I'm not saying it can't be done,
142  * but I am saying it probably isn't worth the effort.
143  */
144 				if (inopen)
145 error("Can't change type of terminal from within open/visual");
146 				setterm(optname);
147 			} else {
148 				CP(op->osvalue, optname);
149 				op->odefault = 1;
150 			}
151 			break;
152 		}
153 next:
154 		flush();
155 	} while (!skipend());
156 	eol();
157 }
158 
159 setend()
160 {
161 
162 	return (iswhite(peekchar()) || endcmd(peekchar()));
163 }
164 
165 prall()
166 {
167 	register int incr = (NOPTS + 2) / 3;
168 	register int rows = incr;
169 	register struct option *op = options;
170 
171 	for (; rows; rows--, op++) {
172 		propt(op);
173 		tab(24);
174 		propt(&op[incr]);
175 		if (&op[2*incr] < &options[NOPTS]) {
176 			tab(56);
177 			propt(&op[2 * incr]);
178 		}
179 		putNFL();
180 	}
181 }
182 
183 propts()
184 {
185 	register struct option *op;
186 
187 	for (op = options; op < &options[NOPTS]; op++) {
188 #ifdef V6
189 		if (op == &options[TERM])
190 #else
191 		if (op == &options[TTYTYPE])
192 #endif
193 			continue;
194 		switch (op->otype) {
195 
196 		case ONOFF:
197 		case NUMERIC:
198 			if (op->ovalue == op->odefault)
199 				continue;
200 			break;
201 
202 		case STRING:
203 			if (op->odefault == 0)
204 				continue;
205 			break;
206 		}
207 		propt(op);
208 		ex_putchar(' ');
209 	}
210 	noonl();
211 	flush();
212 }
213 
214 propt(op)
215 	register struct option *op;
216 {
217 	register char *name;
218 
219 	name = op->oname;
220 
221 	switch (op->otype) {
222 
223 	case ONOFF:
224 		ex_printf("%s%s", op->ovalue ? "" : "no", name);
225 		break;
226 
227 	case NUMERIC:
228 		ex_printf("%s=%d", name, op->ovalue);
229 		break;
230 
231 	case STRING:
232 	case OTERM:
233 		ex_printf("%s=%s", name, op->osvalue);
234 		break;
235 	}
236 }
237