1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29
30 /* Copyright (c) 1981 Regents of the University of California */
31
32 #include "ex.h"
33 #include "ex_temp.h"
34 #include "ex_tty.h"
35
36 /*
37 * Set command.
38 */
39 unsigned char optname[ONMSZ];
40
41 void
set(void)42 set(void)
43 {
44 unsigned char *cp;
45 struct option *op;
46 int c;
47 bool no;
48 extern short ospeed;
49 #ifdef TRACE
50 int k, label;
51 line *tmpadr;
52 #endif
53
54 setnoaddr();
55 if (skipend()) {
56 if (peekchar() != EOF)
57 ignchar();
58 propts();
59 return;
60 }
61 do {
62 cp = optname;
63 do {
64 if (cp < &optname[ONMSZ - 2])
65 *cp++ = getchar();
66 } while (isalnum(peekchar()));
67 *cp = 0;
68 cp = optname;
69 if (eq("all", cp)) {
70 if (inopen)
71 pofix();
72 prall();
73 goto next;
74 }
75 no = 0;
76 #ifdef TRACE
77 /*
78 * General purpose test code for looking at address of those
79 * invisible marks (as well as the visible ones).
80 */
81 if (eq("marks", cp)) {
82 viprintf("Marks Address\n\r");
83 viprintf(" \n");
84 viprintf("\n");
85 for (k = 0; k <= 25; k++)
86 viprintf("Mark:%c\t%d\n", k+'a', names[k]);
87 goto next;
88 }
89
90 /*
91 * General purpose test code for looking at
92 * named registers.
93 */
94
95 if (eq("named",cp)) {
96 if (inopen)
97 pofix();
98 shownam();
99 goto next;
100 }
101
102 /*
103 * General purpose test code for looking at
104 * numbered registers.
105 */
106
107 if (eq("nbrreg",cp)) {
108 if (inopen)
109 pofix();
110 shownbr();
111 goto next;
112 }
113
114 /*
115 * General purpose test code for looking at addresses
116 * in the edit and save areas of VI.
117 */
118
119 if (eq("buffers",cp)) {
120 if (inopen)
121 pofix();
122 viprintf("\nLabels Address Contents\n");
123 viprintf("====== ======= ========");
124 for (tmpadr = zero; tmpadr <= dol; tmpadr++) {
125 label =0;
126 if (tmpadr == zero) {
127 viprintf("ZERO:\t");
128 label = 2;
129 }
130 if (tmpadr == one) {
131 if (label > 0)
132 viprintf("\nONE:\t");
133 else
134 viprintf("ONE:\t");
135 label = 1;
136 }
137 if (tmpadr == dot) {
138 if (label > 0)
139 viprintf("\nDOT:\t");
140 else
141 viprintf("DOT:\t");
142 label = 1;
143 }
144 if (tmpadr == undap1) {
145 if (label > 0)
146 viprintf("\nUNDAP1:\t");
147 else
148 viprintf("UNDAP1:\t");
149 label = 1;
150 }
151 if (tmpadr == undap2) {
152 if (label > 0)
153 viprintf("\nUNDAP2:\t");
154 else
155 viprintf("UNDAP2:\t");
156 label = 1;
157 }
158 if (tmpadr == unddel) {
159 if (label > 0)
160 viprintf("\nUNDDEL:\t");
161 else
162 viprintf("UNDDEL:\t");
163 label = 1;
164 }
165 if (tmpadr == dol) {
166 if (label > 0)
167 viprintf("\nDOL:\t");
168 else
169 viprintf("DOL:\t");
170 label = 1;
171 }
172 for (k=0; k<=25; k++)
173 if (names[k] == (*tmpadr &~ 01)) {
174 if (label > 0)
175 viprintf(
176 "\nMark:%c\t%d\t", k+'a', names[k]);
177 else
178 viprintf(
179 "Mark:%c\t%d\t", k+'a', names[k]);
180 label=1;
181 }
182 if (label == 0)
183 continue;
184
185 if (label == 2)
186 viprintf("%d\n", tmpadr);
187 else {
188 viprintf("%d\t", tmpadr);
189 getaline(*tmpadr);
190 pline(lineno(tmpadr));
191 putchar('\n');
192 }
193 }
194
195 for (tmpadr = dol+1; tmpadr <= unddol; tmpadr++) {
196 label =0;
197 if (tmpadr == dol+1) {
198 viprintf("DOL+1:\t");
199 label = 1;
200 }
201 if (tmpadr == unddel) {
202 if (label > 0)
203 viprintf("\nUNDDEL:\t");
204 else
205 viprintf("UNDDEL:\t");
206 label = 1;
207 }
208 if (tmpadr == unddol) {
209 if (label > 0)
210 viprintf("\nUNDDOL:\t");
211 else
212 viprintf("UNDDOL:\t");
213 label = 1;
214 }
215 for (k=0; k<=25; k++)
216 if (names[k] == (*tmpadr &~ 01)) {
217 if (label > 0)
218 viprintf(
219 "\nMark:%c\t%d\t", k+'a', names[k]);
220 else
221 viprintf(
222 "Mark:%c\t%d\t", k+'a', names[k]);
223 label=1;
224 }
225 if (label == 0)
226 continue;
227 if (label == 2)
228 viprintf("%d\n", tmpadr);
229 else {
230 viprintf("%d\t", tmpadr);
231 getaline(*tmpadr);
232 pline(lineno(tmpadr));
233 putchar('\n');
234 }
235 }
236 goto next;
237 }
238 #endif
239 if (cp[0] == 'n' && cp[1] == 'o' && cp[2] != 'v') {
240 cp += 2;
241 no++;
242 }
243 /* Implement w300, w1200, and w9600 specially */
244 if (eq(cp, "w300")) {
245 if (ospeed >= B1200) {
246 dontset:
247 (void)getchar(); /* = */
248 (void)getnum(); /* value */
249 continue;
250 }
251 cp = (unsigned char *)"window";
252 } else if (eq(cp, "w1200")) {
253 if (ospeed < B1200 || ospeed >= B2400)
254 goto dontset;
255 cp = (unsigned char *)"window";
256 } else if (eq(cp, "w9600")) {
257 if (ospeed < B2400)
258 goto dontset;
259 cp = (unsigned char *)"window";
260 }
261 for (op = options; op < &options[vi_NOPTS]; op++)
262 if (eq(op->oname, cp) || op->oabbrev && eq(op->oabbrev, cp))
263 break;
264 if (op->oname == 0)
265 serror(value(vi_TERSE) ? (unsigned char *)
266 gettext("%s: No such option") :
267 (unsigned char *)
268 gettext("%s: No such option - 'set all' gives all option values"), cp);
269 c = skipwh();
270 if (peekchar() == '?') {
271 ignchar();
272 printone:
273 propt(op);
274 noonl();
275 goto next;
276 }
277 if (op->otype == ONOFF) {
278 op->ovalue = 1 - no;
279 if (op == &options[vi_PROMPT])
280 oprompt = 1 - no;
281 goto next;
282 }
283 if (no)
284 serror((unsigned char *)
285 gettext("Option %s is not a toggle"), op->oname);
286 if (c != 0 || setend())
287 goto printone;
288 if (getchar() != '=')
289 serror(value(vi_TERSE) ? (unsigned char *)
290 gettext("Missing =") :
291 (unsigned char *)
292 gettext("Missing = in assignment to option %s"),
293 op->oname);
294 switch (op->otype) {
295
296 case NUMERIC:
297 if (!isdigit(peekchar()))
298 error(value(vi_TERSE) ?
299 gettext("Digits required") : gettext("Digits required after ="));
300 op->ovalue = getnum();
301 if (value(vi_TABSTOP) <= 0)
302 value(vi_TABSTOP) = TABS;
303 if (op == &options[vi_WINDOW]) {
304 if (value(vi_WINDOW) >= lines)
305 value(vi_WINDOW) = lines-1;
306 vsetsiz(value(vi_WINDOW));
307 }
308 break;
309
310 case STRING:
311 case OTERM:
312 cp = optname;
313 while (!setend()) {
314 if (cp >= &optname[ONMSZ])
315 error(value(vi_TERSE) ?
316 gettext("String too long") : gettext("String too long in option assignment"));
317 /* adb change: allow whitepace in strings */
318 if( (*cp = getchar()) == '\\')
319 if( peekchar() != EOF)
320 *cp = getchar();
321 cp++;
322 }
323 *cp = 0;
324 if (op->otype == OTERM) {
325 /*
326 * At first glance it seems like we shouldn't care if the terminal type
327 * is changed inside visual mode, as long as we assume the screen is
328 * a mess and redraw it. However, it's a much harder problem than that.
329 * If you happen to change from 1 crt to another that both have the same
330 * size screen, it's OK. But if the screen size if different, the stuff
331 * that gets initialized in vop() will be wrong. This could be overcome
332 * by redoing the initialization, e.g. making the first 90% of vop into
333 * a subroutine. However, the most useful case is where you forgot to do
334 * a setenv before you went into the editor and it thinks you're on a dumb
335 * terminal. Ex treats this like hardcopy and goes into HARDOPEN mode.
336 * This loses because the first part of vop calls oop in this case.
337 */
338 if (inopen)
339 error(gettext("Can't change type of terminal from within open/visual"));
340 unterm();
341 setterm(optname);
342 } else {
343 CP(op->osvalue, optname);
344 op->odefault = 1;
345 }
346 break;
347 }
348 next:
349 flush();
350 } while (!skipend());
351 eol();
352 }
353
354 void
unterm(void)355 unterm(void)
356 {
357 /*
358 * All terminal mapped statements must be deleted.
359 * All user-defined mapped statements, cap=descr,
360 * are left unchanged.
361 */
362
363 int i;
364
365 for (i=0; i < MAXNOMACS; i++) {
366
367 /*
368 * Unmap any terminal-defined arrow keys
369 */
370
371 if (arrows[i].cap && arrows[i].descr &&
372 strcmp(arrows[i].cap, arrows[i].descr))
373 addmac(arrows[i].cap, NOSTR, NOSTR, arrows);
374
375 /*
376 * Unmap any terminal-defined function keys
377 */
378
379 if (immacs[i].cap && immacs[i].descr && strcmp(immacs[i].cap, immacs[i].descr))
380 addmac(immacs[i].cap, NOSTR, NOSTR, immacs);
381
382 }
383 }
384
385
386 int
setend(void)387 setend(void)
388 {
389
390 return (iswhite(peekchar()) || endcmd(peekchar()));
391 }
392
393 void
prall(void)394 prall(void)
395 {
396 int incr = (vi_NOPTS + 2) / 3;
397 int rows = incr;
398 struct option *op = options;
399
400 for (; rows; rows--, op++) {
401 propt(op);
402 gotab(24);
403 propt(&op[incr]);
404 if (&op[2*incr] < &options[vi_NOPTS]) {
405 gotab(56);
406 propt(&op[2 * incr]);
407 }
408 putNFL();
409 }
410 }
411
412 void
propts(void)413 propts(void)
414 {
415 struct option *op;
416
417 for (op = options; op < &options[vi_NOPTS]; op++) {
418 if (op == &options[vi_TTYTYPE])
419 continue;
420 switch (op->otype) {
421
422 case ONOFF:
423 case NUMERIC:
424 if (op->ovalue == op->odefault)
425 continue;
426 break;
427
428 case STRING:
429 if (op->odefault == 0)
430 continue;
431 break;
432 }
433 propt(op);
434 putchar(' ');
435 }
436 noonl();
437 flush();
438 }
439
440 void
propt(struct option * op)441 propt(struct option *op)
442 {
443 unsigned char *name;
444
445 name = (unsigned char *)op->oname;
446
447 switch (op->otype) {
448
449 case ONOFF:
450 viprintf("%s%s", op->ovalue ? "" : "no", name);
451 break;
452
453 case NUMERIC:
454 viprintf("%s=%d", name, op->ovalue);
455 break;
456
457 case STRING:
458 case OTERM:
459 viprintf("%s=%s", name, op->osvalue);
460 break;
461 }
462 }
463