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