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
set()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
setend()159 setend()
160 {
161
162 return (iswhite(peekchar()) || endcmd(peekchar()));
163 }
164
prall()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
propts()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
propt(op)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