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