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