Commit | Line | Data |
---|---|---|
15637ed4 RG |
1 | /* opts.c */ |
2 | ||
3 | /* Author: | |
4 | * Steve Kirkendall | |
5 | * 14407 SW Teal Blvd. #C | |
6 | * Beaverton, OR 97005 | |
7 | * kirkenda@cs.pdx.edu | |
8 | */ | |
9 | ||
10 | ||
11 | /* This file contains the code that manages the run-time options -- The | |
12 | * values that can be modified via the "set" command. | |
13 | */ | |
14 | ||
15 | #include "config.h" | |
16 | #include "vi.h" | |
17 | #include "ctype.h" | |
18 | #ifndef NULL | |
19 | #define NULL (char *)0 | |
20 | #endif | |
15637ed4 RG |
21 | |
22 | /* maximum width to permit for strings, including ="" */ | |
23 | #define MAXWIDTH 20 | |
24 | ||
25 | /* These are the default values of all options */ | |
26 | char o_autoindent[1] = {FALSE}; | |
27 | char o_autoprint[1] = {TRUE}; | |
28 | char o_autotab[1] = {TRUE}; | |
29 | char o_autowrite[1] = {FALSE}; | |
08746e8b | 30 | char o_columns[3] = {80, 32, ~0}; |
15637ed4 RG |
31 | char o_directory[30] = TMPDIR; |
32 | char o_edcompatible[1] = {FALSE}; | |
33 | char o_equalprg[80] = {"fmt"}; | |
34 | char o_errorbells[1] = {TRUE}; | |
35 | char o_exrefresh[1] = {TRUE}; | |
36 | char o_ignorecase[1] = {FALSE}; | |
37 | char o_keytime[3] = {2, 0, 50}; | |
38 | char o_keywordprg[80] = {KEYWORDPRG}; | |
39 | char o_lines[3] = {25, 2, 96}; | |
40 | char o_list[1] = {FALSE}; | |
41 | char o_number[1] = {FALSE}; | |
42 | char o_readonly[1] = {FALSE}; | |
43 | char o_remap[1] = {TRUE}; | |
44 | char o_report[3] = {5, 1, 127}; | |
45 | char o_scroll[3] = {12, 1, 127}; | |
46 | char o_shell[60] = SHELL; | |
08746e8b | 47 | char o_shiftwidth[3] = {8, 1, ~0}; |
15637ed4 RG |
48 | char o_sidescroll[3] = {8, 1, 40}; |
49 | char o_sync[1] = {NEEDSYNC}; | |
50 | char o_tabstop[3] = {8, 1, 40}; | |
51 | char o_term[30] = "?"; | |
52 | char o_flash[1] = {TRUE}; | |
53 | char o_warn[1] = {TRUE}; | |
54 | char o_wrapscan[1] = {TRUE}; | |
55 | ||
56 | #ifndef CRUNCH | |
57 | char o_beautify[1] = {FALSE}; | |
58 | char o_exrc[1] = {FALSE}; | |
59 | char o_mesg[1] = {TRUE}; | |
60 | char o_more[1] = {TRUE}; | |
08746e8b | 61 | char o_nearscroll[3] = {15, 0, ~0}; |
15637ed4 RG |
62 | char o_novice[1] = {FALSE}; |
63 | char o_prompt[1] = {TRUE}; | |
64 | char o_taglength[3] = {0, 0, 30}; | |
08746e8b | 65 | char o_tags[256] = {"tags"}; |
15637ed4 RG |
66 | char o_terse[1] = {FALSE}; |
67 | char o_window[3] = {0, 1, 24}; | |
08746e8b | 68 | char o_wrapmargin[3] = {0, 0, ~0}; |
15637ed4 RG |
69 | char o_writeany[1] = {FALSE}; |
70 | #endif | |
71 | ||
72 | #ifndef NO_ERRLIST | |
73 | char o_cc[30] = {CC_COMMAND}; | |
74 | char o_make[30] = {MAKE_COMMAND}; | |
75 | #endif | |
76 | ||
77 | #ifndef NO_CHARATTR | |
78 | char o_charattr[1] = {FALSE}; | |
79 | #endif | |
80 | ||
81 | #ifndef NO_DIGRAPH | |
82 | char o_digraph[1] = {FALSE}; | |
83 | char o_flipcase[80] | |
84 | # ifdef CS_IBMPC | |
85 | = {"\207\200\201\232\202\220\204\216\206\217\221\222\224\231\244\245"} | |
86 | # endif | |
87 | # ifdef CS_LATIN1 | |
88 | /* initialized by initopts() */ | |
89 | # endif | |
90 | ; | |
91 | #endif | |
92 | ||
93 | #ifndef NO_SENTENCE | |
94 | char o_hideformat[1] = {FALSE}; | |
95 | #endif | |
96 | ||
97 | #ifndef NO_EXTENSIONS | |
98 | char o_inputmode[1] = {FALSE}; | |
99 | char o_ruler[1] = {FALSE}; | |
100 | #endif | |
101 | ||
102 | #ifndef NO_MAGIC | |
103 | char o_magic[1] = {TRUE}; | |
104 | #endif | |
105 | ||
106 | #ifndef NO_MODELINES | |
107 | char o_modelines[1] = {FALSE}; | |
108 | #endif | |
109 | ||
110 | #ifndef NO_SENTENCE | |
111 | char o_paragraphs[30] = "PPppIPLPQP"; | |
112 | char o_sections[30] = "NHSHSSSEse"; | |
113 | #endif | |
114 | ||
115 | #if MSDOS | |
116 | char o_pcbios[1] = {TRUE}; | |
117 | #endif | |
118 | ||
119 | #ifndef NO_SHOWMATCH | |
120 | char o_showmatch[1] = {FALSE}; | |
121 | #endif | |
122 | ||
123 | #ifndef NO_SHOWMODE | |
124 | char o_smd[1] = {FALSE}; | |
125 | #endif | |
126 | ||
08746e8b AM |
127 | #ifndef NO_TAGSTACK |
128 | char o_tagstack[1] = {TRUE}; | |
129 | #endif | |
130 | ||
131 | ||
15637ed4 RG |
132 | |
133 | /* The following describes the names & types of all options */ | |
134 | #define BOOL 0 | |
135 | #define NUM 1 | |
136 | #define STR 2 | |
137 | #define SET 0x01 /* this option has had its value altered */ | |
138 | #define CANSET 0x02 /* this option can be set at any time */ | |
139 | #define RCSET 0x06 /* this option can be set in a .exrc file only */ | |
140 | #define NOSAVE 0x0a /* this option should never be saved by mkexrc */ | |
141 | #define WSET 0x20 /* is this the "window" size option? */ | |
142 | #define MR 0x40 /* does this option affect the way text is displayed? */ | |
143 | struct | |
144 | { | |
145 | char *name; /* name of an option */ | |
146 | char *nm; /* short name of an option */ | |
147 | char type; /* type of an option */ | |
148 | char flags; /* boolean: has this option been set? */ | |
149 | char *value; /* value */ | |
150 | } | |
151 | opts[] = | |
152 | { | |
153 | /* name type flags value */ | |
154 | { "autoindent", "ai", BOOL, CANSET, o_autoindent }, | |
155 | { "autoprint", "ap", BOOL, CANSET, o_autoprint }, | |
156 | { "autotab", "at", BOOL, CANSET, o_autotab }, | |
157 | { "autowrite", "aw", BOOL, CANSET, o_autowrite }, | |
158 | #ifndef CRUNCH | |
159 | { "beautify", "bf", BOOL, CANSET, o_beautify }, | |
160 | #endif | |
161 | #ifndef NO_ERRLIST | |
162 | { "cc", "cc", STR, CANSET, o_cc }, | |
163 | #endif | |
164 | #ifndef NO_CHARATTR | |
165 | { "charattr", "ca", BOOL, CANSET|MR, o_charattr }, | |
166 | #endif | |
167 | { "columns", "co", NUM, SET|NOSAVE|MR, o_columns }, | |
168 | #ifndef NO_DIGRAPH | |
169 | { "digraph", "dig", BOOL, CANSET, o_digraph }, | |
170 | #endif | |
171 | { "directory", "dir", STR, RCSET, o_directory }, | |
172 | { "edcompatible","ed", BOOL, CANSET, o_edcompatible }, | |
173 | { "equalprg", "ep", STR, CANSET, o_equalprg }, | |
174 | { "errorbells", "eb", BOOL, CANSET, o_errorbells }, | |
175 | #ifndef CRUNCH | |
176 | { "exrc", "exrc", BOOL, CANSET, o_exrc }, | |
177 | #endif | |
178 | { "exrefresh", "er", BOOL, CANSET, o_exrefresh }, | |
179 | { "flash", "vbell",BOOL, CANSET, o_flash }, | |
180 | #ifndef NO_DIGRAPH | |
181 | { "flipcase", "fc", STR, CANSET, o_flipcase }, | |
182 | #endif | |
183 | #ifndef NO_SENTENCE | |
184 | { "hideformat", "hf", BOOL, CANSET|MR, o_hideformat }, | |
185 | #endif | |
186 | { "ignorecase", "ic", BOOL, CANSET, o_ignorecase }, | |
187 | #ifndef NO_EXTENSIONS | |
188 | { "inputmode", "im", BOOL, CANSET, o_inputmode }, | |
189 | #endif | |
190 | { "keytime", "kt", NUM, CANSET, o_keytime }, | |
191 | { "keywordprg", "kp", STR, CANSET, o_keywordprg }, | |
192 | { "lines", "ls", NUM, SET|NOSAVE|MR, o_lines }, | |
193 | { "list", "li", BOOL, CANSET|MR, o_list }, | |
194 | #ifndef NO_MAGIC | |
195 | { "magic", "ma", BOOL, CANSET, o_magic }, | |
196 | #endif | |
197 | #ifndef NO_ERRLIST | |
198 | { "make", "mk", STR, CANSET, o_make }, | |
199 | #endif | |
200 | #ifndef CRUNCH | |
201 | { "mesg", "me", BOOL, CANSET, o_mesg }, | |
202 | #endif | |
203 | #ifndef NO_MODELINES | |
204 | { "modelines", "ml", BOOL, CANSET, o_modelines }, | |
205 | #endif | |
206 | #ifndef CRUNCH | |
207 | { "more", "mo", BOOL, CANSET, o_more }, | |
08746e8b | 208 | { "nearscroll", "ns", NUM, CANSET, o_nearscroll }, |
15637ed4 RG |
209 | { "novice", "nov", BOOL, CANSET, o_novice }, |
210 | #endif | |
211 | { "number", "nu", BOOL, CANSET|MR, o_number }, | |
212 | #ifndef NO_SENTENCE | |
213 | { "paragraphs", "para", STR, CANSET, o_paragraphs }, | |
214 | #endif | |
215 | #if MSDOS | |
216 | { "pcbios", "pc", BOOL, SET|NOSAVE, o_pcbios }, | |
217 | #endif | |
218 | #ifndef CRUNCH | |
219 | { "prompt", "pr", BOOL, CANSET, o_prompt }, | |
220 | #endif | |
221 | { "readonly", "ro", BOOL, CANSET, o_readonly }, | |
222 | { "remap", "remap",BOOL, CANSET, o_remap }, | |
223 | { "report", "re", NUM, CANSET, o_report }, | |
224 | #ifndef NO_EXTENSIONS | |
225 | { "ruler", "ru", BOOL, CANSET, o_ruler }, | |
226 | #endif | |
227 | { "scroll", "sc", NUM, CANSET, o_scroll }, | |
228 | #ifndef NO_SENTENCE | |
229 | { "sections", "sect", STR, CANSET, o_sections }, | |
230 | #endif | |
231 | { "shell", "sh", STR, CANSET, o_shell }, | |
232 | #ifndef NO_SHOWMATCH | |
233 | { "showmatch", "sm", BOOL, CANSET, o_showmatch }, | |
234 | #endif | |
235 | #ifndef NO_SHOWMODE | |
236 | { "showmode", "smd", BOOL, CANSET, o_smd }, | |
237 | #endif | |
238 | { "shiftwidth", "sw", NUM, CANSET, o_shiftwidth }, | |
239 | { "sidescroll", "ss", NUM, CANSET, o_sidescroll }, | |
240 | { "sync", "sy", BOOL, CANSET, o_sync }, | |
241 | { "tabstop", "ts", NUM, CANSET|MR, o_tabstop }, | |
242 | #ifndef CRUNCH | |
243 | { "taglength", "tl", NUM, CANSET, o_taglength }, | |
08746e8b AM |
244 | { "tags", "tag", STR, CANSET, o_tags }, |
245 | #endif | |
246 | #ifndef NO_TAGSTACK | |
247 | { "tagstack", "tgs", BOOL, CANSET, o_tagstack }, | |
15637ed4 RG |
248 | #endif |
249 | { "term", "te", STR, SET, o_term }, | |
250 | #ifndef CRUNCH | |
251 | { "terse", "tr", BOOL, CANSET, o_terse }, | |
252 | { "timeout", "to", BOOL, CANSET, o_keytime }, | |
253 | #endif | |
254 | #ifndef CRUNCH | |
255 | { "window", "wi", NUM, CANSET|MR|WSET, o_window }, | |
256 | { "wrapmargin", "wm", NUM, CANSET, o_wrapmargin }, | |
257 | #endif | |
258 | { "wrapscan", "ws", BOOL, CANSET, o_wrapscan }, | |
259 | #ifndef CRUNCH | |
260 | { "writeany", "wr", BOOL, CANSET, o_writeany }, | |
261 | #endif | |
262 | { NULL, NULL, 0, CANSET, NULL } | |
263 | }; | |
264 | ||
265 | ||
266 | /* This function initializes certain options from environment variables, etc. */ | |
267 | void initopts() | |
268 | { | |
269 | char *val; | |
270 | int i; | |
271 | ||
272 | /* set some stuff from environment variables */ | |
273 | #if MSDOS | |
274 | if (val = getenv("COMSPEC")) /* yes, ASSIGNMENT! */ | |
275 | #else | |
276 | if (val = getenv("SHELL")) /* yes, ASSIGNMENT! */ | |
277 | #endif | |
278 | { | |
279 | strcpy(o_shell, val); | |
280 | } | |
281 | ||
282 | strcpy(o_term, termtype); | |
283 | #if MSDOS | |
284 | if (strcmp(termtype, "pcbios")) | |
285 | { | |
286 | o_pcbios[0] = FALSE; | |
287 | } | |
288 | else | |
289 | { | |
290 | o_pcbios[0] = TRUE; | |
291 | } | |
292 | #endif | |
293 | ||
294 | #if AMIGA || MSDOS || TOS | |
295 | if ((val = getenv("TMP")) /* yes, ASSIGNMENT! */ | |
296 | || (val = getenv("TEMP"))) | |
297 | strcpy(o_directory, val); | |
298 | #endif | |
299 | ||
300 | #ifndef CRUNCH | |
301 | if ((val = getenv("LINES")) && atoi(val) > 4) /* yes, ASSIGNMENT! */ | |
302 | { | |
303 | LINES = atoi(val); | |
304 | } | |
305 | if ((val = getenv("COLUMNS")) && atoi(val) > 30) /* yes, ASSIGNMENT! */ | |
306 | { | |
307 | COLS = atoi(val); | |
308 | } | |
309 | #endif | |
310 | *o_lines = LINES; | |
311 | *o_columns = COLS; | |
312 | *o_scroll = LINES / 2 - 1; | |
313 | #ifndef CRUNCH | |
314 | if (o_window[0] == 0) | |
315 | { | |
316 | o_window[0] = o_window[2] = *o_lines; | |
317 | } | |
08746e8b | 318 | *o_nearscroll = *o_lines; |
15637ed4 RG |
319 | #endif |
320 | ||
321 | /* disable the flash option if we don't know how to do a flash */ | |
322 | if (!has_VB) | |
323 | { | |
324 | for (i = 0; opts[i].value != o_flash; i++) | |
325 | { | |
326 | } | |
327 | opts[i].flags &= ~CANSET; | |
328 | *o_flash = FALSE; | |
329 | } | |
330 | ||
331 | #ifndef NO_DIGRAPH | |
332 | # ifdef CS_LATIN1 | |
333 | for (i = 0, val = o_flipcase; i < 32; i++) | |
334 | { | |
335 | /* leave out the multiply/divide symbols */ | |
336 | if (i == 23) | |
337 | continue; | |
338 | ||
339 | /* add lower/uppercase pair */ | |
340 | *val++ = i + 0xe0; | |
341 | *val++ = i + 0xc0; | |
342 | } | |
343 | *val = '\0'; | |
344 | # endif /* CS_LATIN1 */ | |
345 | ||
346 | /* initialize the ctype package */ | |
347 | _ct_init(o_flipcase); | |
348 | #else | |
349 | _ct_init(""); | |
350 | #endif /* not NO_DIGRAPH */ | |
351 | } | |
352 | ||
353 | /* This function lists the current values of all options */ | |
354 | void dumpopts(all) | |
355 | int all; /* boolean: dump all options, or just set ones? */ | |
356 | { | |
357 | #ifndef NO_OPTCOLS | |
358 | int i, j, k; | |
359 | char nbuf[4]; /* used for converting numbers to ASCII */ | |
360 | int widths[5]; /* width of each column, including gap */ | |
361 | int ncols; /* number of columns */ | |
362 | int nrows; /* number of options per column */ | |
363 | int nset; /* number of options to be output */ | |
364 | int width; /* width of a particular option */ | |
365 | int todump[60]; /* indicies of options to be dumped */ | |
366 | ||
367 | /* step 1: count the number of set options */ | |
368 | for (nset = i = 0; opts[i].name; i++) | |
369 | { | |
370 | if (all || (opts[i].flags & SET)) | |
371 | { | |
372 | todump[nset++] = i; | |
373 | } | |
374 | } | |
375 | ||
376 | /* step two: try to use as many columns as possible */ | |
377 | for (ncols = (nset > 5 ? 5 : nset); ncols > 1; ncols--) | |
378 | { | |
379 | /* how many would go in this column? */ | |
380 | nrows = (nset + ncols - 1) / ncols; | |
381 | ||
382 | /* figure out the width of each column */ | |
383 | for (i = 0; i < ncols; i++) | |
384 | { | |
385 | widths[i] = 0; | |
386 | for (j = 0, k = nrows * i; j < nrows && k < nset; j++, k++) | |
387 | { | |
388 | /* figure out the width of a particular option */ | |
389 | switch (opts[todump[k]].type) | |
390 | { | |
391 | case BOOL: | |
392 | if (!*opts[todump[k]].value) | |
393 | width = 2; | |
394 | else | |
395 | width = 0; | |
396 | break; | |
397 | ||
398 | case STR: | |
399 | width = 3 + strlen(opts[todump[k]].value); | |
400 | if (width > MAXWIDTH) | |
401 | width = MAXWIDTH; | |
402 | break; | |
403 | ||
404 | case NUM: | |
405 | width = 4; | |
406 | break; | |
407 | } | |
408 | width += strlen(opts[todump[k]].name); | |
409 | ||
410 | /* if this is the widest so far, widen col */ | |
411 | if (width > widths[i]) | |
412 | { | |
413 | widths[i] = width; | |
414 | } | |
415 | } | |
416 | ||
417 | } | |
418 | ||
419 | /* if the total width is narrow enough, then use it */ | |
420 | for (width = -2, i = 0; i < ncols; i++) | |
421 | { | |
422 | width += widths[i] + 2; | |
423 | } | |
424 | if (width < COLS - 1) | |
425 | { | |
426 | break; | |
427 | } | |
428 | } | |
429 | ||
430 | /* step 3: output the columns */ | |
431 | nrows = (nset + ncols - 1) / ncols; | |
432 | for (i = 0; i < nrows; i++) | |
433 | { | |
434 | for (j = 0; j < ncols; j++) | |
435 | { | |
436 | /* if we hit the end of the options, quit */ | |
437 | k = i + j * nrows; | |
438 | if (k >= nset) | |
439 | { | |
440 | break; | |
441 | } | |
442 | ||
443 | /* output this option's value */ | |
444 | width = 0; | |
445 | switch (opts[todump[k]].type) | |
446 | { | |
447 | case BOOL: | |
448 | if (!*opts[todump[k]].value) | |
449 | { | |
450 | qaddch('n'); | |
451 | qaddch('o'); | |
452 | width = 2; | |
453 | } | |
454 | qaddstr(opts[todump[k]].name); | |
455 | width += strlen(opts[todump[k]].name); | |
456 | break; | |
457 | ||
458 | case NUM: | |
459 | sprintf(nbuf, "%-3d", UCHAR(*opts[todump[k]].value)); | |
460 | qaddstr(opts[todump[k]].name); | |
461 | qaddch('='); | |
462 | qaddstr(nbuf); | |
463 | width = 4 + strlen(opts[todump[k]].name); | |
464 | break; | |
465 | ||
466 | case STR: | |
467 | qaddstr(opts[todump[k]].name); | |
468 | qaddch('='); | |
469 | qaddch('"'); | |
470 | strcpy(tmpblk.c, opts[todump[k]].value); | |
471 | width = 3 + strlen(tmpblk.c); | |
472 | if (width > MAXWIDTH) | |
473 | { | |
474 | width = MAXWIDTH; | |
475 | strcpy(tmpblk.c + MAXWIDTH - 6, "..."); | |
476 | } | |
477 | qaddstr(tmpblk.c); | |
478 | qaddch('"'); | |
479 | width += strlen(opts[todump[k]].name); | |
480 | break; | |
481 | } | |
482 | ||
483 | /* pad the field to the correct size */ | |
484 | if (k + nrows <= nset) | |
485 | { | |
486 | while (width < widths[j] + 2) | |
487 | { | |
488 | qaddch(' '); | |
489 | width++; | |
490 | } | |
491 | } | |
492 | } | |
493 | addch('\n'); | |
494 | exrefresh(); | |
495 | } | |
496 | #else | |
497 | int i; | |
498 | int col; | |
499 | char nbuf[4]; | |
500 | ||
501 | for (i = col = 0; opts[i].name; i++) | |
502 | { | |
503 | /* if not set and not all, ignore this option */ | |
504 | if (!all && !(opts[i].flags & SET)) | |
505 | { | |
506 | continue; | |
507 | } | |
508 | ||
509 | /* align this option in one of the columns */ | |
510 | if (col > 52) | |
511 | { | |
512 | addch('\n'); | |
513 | col = 0; | |
514 | } | |
515 | else if (col > 26) | |
516 | { | |
517 | while (col < 52) | |
518 | { | |
519 | qaddch(' '); | |
520 | col++; | |
521 | } | |
522 | } | |
523 | else if (col > 0) | |
524 | { | |
525 | while (col < 26) | |
526 | { | |
527 | qaddch(' '); | |
528 | col++; | |
529 | } | |
530 | } | |
531 | ||
532 | switch (opts[i].type) | |
533 | { | |
534 | case BOOL: | |
535 | if (!*opts[i].value) | |
536 | { | |
537 | qaddch('n'); | |
538 | qaddch('o'); | |
539 | col += 2; | |
540 | } | |
541 | qaddstr(opts[i].name); | |
542 | col += strlen(opts[i].name); | |
543 | break; | |
544 | ||
545 | case NUM: | |
546 | sprintf(nbuf, "%-3d", UCHAR(*opts[i].value)); | |
547 | qaddstr(opts[i].name); | |
548 | qaddch('='); | |
549 | qaddstr(nbuf); | |
550 | col += 4 + strlen(opts[i].name); | |
551 | break; | |
552 | ||
553 | case STR: | |
554 | qaddstr(opts[i].name); | |
555 | qaddch('='); | |
556 | qaddch('"'); | |
557 | qaddstr(opts[i].value); | |
558 | qaddch('"'); | |
559 | col += 3 + strlen(opts[i].name) + strlen(opts[i].value); | |
560 | break; | |
561 | } | |
562 | exrefresh(); | |
563 | } | |
564 | if (col > 0) | |
565 | { | |
566 | addch('\n'); | |
567 | exrefresh(); | |
568 | } | |
569 | #endif | |
570 | } | |
571 | ||
572 | #ifndef NO_MKEXRC | |
573 | /* This function saves the current configuration of options to a file */ | |
574 | void saveopts(fd) | |
575 | int fd; /* file descriptor to write to */ | |
576 | { | |
577 | int i; | |
578 | char buf[256], *pos; | |
579 | ||
580 | /* write each set options */ | |
581 | for (i = 0; opts[i].name; i++) | |
582 | { | |
583 | /* if unset or unsettable, ignore this option */ | |
584 | if ((opts[i].flags & (SET|CANSET|NOSAVE)) != (SET|CANSET)) | |
585 | { | |
586 | continue; | |
587 | } | |
588 | ||
589 | strcpy(buf, "set "); | |
590 | pos = &buf[4]; | |
591 | switch (opts[i].type) | |
592 | { | |
593 | case BOOL: | |
594 | if (!*opts[i].value) | |
595 | { | |
596 | *pos++='n'; | |
597 | *pos++='o'; | |
598 | } | |
599 | strcpy(pos, opts[i].name); | |
600 | strcat(pos, "\n"); | |
601 | break; | |
602 | ||
603 | case NUM: | |
604 | sprintf(pos, "%s=%-3d\n", opts[i].name, *opts[i].value & 0xff); | |
605 | break; | |
606 | ||
607 | case STR: | |
608 | sprintf(pos, "%s=\"%s\"\n", opts[i].name, opts[i].value); | |
609 | break; | |
610 | } | |
611 | twrite(fd, buf, (unsigned)strlen(buf)); | |
612 | } | |
613 | } | |
614 | #endif | |
615 | ||
616 | ||
617 | /* This function changes the values of one or more options. */ | |
618 | void setopts(assignments) | |
619 | char *assignments; /* a string containing option assignments */ | |
620 | { | |
621 | char *name; /* name of variable in assignments */ | |
622 | char *value; /* value of the variable */ | |
623 | char *scan; /* used for moving through strings */ | |
624 | char *build; /* used for copying chars from "scan" */ | |
625 | char *prefix; /* pointer to "neg" or "no" at front of a boolean */ | |
626 | int quote; /* boolean: inside '"' quotes? */ | |
627 | int i, j; | |
628 | ||
629 | #ifndef CRUNCH | |
630 | /* reset the upper limit of "window" option to lines-1 */ | |
631 | *o_window = *o_lines - 1; | |
632 | #endif | |
633 | ||
634 | /* for each assignment... */ | |
635 | for (name = assignments; *name; ) | |
636 | { | |
637 | /* skip whitespace */ | |
638 | if (*name == ' ' || *name == '\t') | |
639 | { | |
640 | name++; | |
641 | continue; | |
642 | } | |
643 | ||
644 | /* after the name, find the value (if any) */ | |
645 | for (scan = name; isalnum(*scan); scan++) | |
646 | { | |
647 | } | |
648 | if (*scan == '=') | |
649 | { | |
650 | *scan++ = '\0'; | |
651 | value = build = scan; | |
652 | for (quote = FALSE; *scan && (quote || !isspace(*scan)); scan++) | |
653 | { | |
654 | if (*scan == '"') | |
655 | { | |
656 | quote = !quote; | |
657 | } | |
658 | else if (*scan == '\\' && scan[1]) | |
659 | { | |
660 | *build++ = *++scan; | |
661 | } | |
662 | else | |
663 | { | |
664 | *build++ = *scan; | |
665 | } | |
666 | } | |
667 | if (*scan) | |
668 | scan++; | |
669 | *build = '\0'; | |
670 | } | |
671 | else /* no "=" so it is probably boolean... */ | |
672 | { | |
673 | if (*scan) | |
674 | { | |
675 | *scan++ = '\0'; | |
676 | } | |
677 | value = NULL; | |
678 | prefix = name; | |
679 | #ifndef CRUNCH | |
680 | if (!strcmp(name, "novice")) | |
681 | /* don't check for a "no" prefix */; | |
682 | else | |
683 | #endif | |
684 | if (prefix[0] == 'n' && prefix[1] == 'o') | |
685 | name += 2; | |
686 | else if (prefix[0] == 'n' && prefix[1] == 'e' && prefix[2] == 'g') | |
687 | name += 3; | |
688 | } | |
689 | ||
690 | /* find the variable */ | |
691 | for (i = 0; | |
692 | opts[i].name && strcmp(opts[i].name, name) && strcmp(opts[i].nm, name); | |
693 | i++) | |
694 | { | |
695 | } | |
696 | ||
697 | /* change the variable */ | |
698 | if (!opts[i].name) | |
699 | { | |
08746e8b AM |
700 | /* only complain about unknown options if we're editing |
701 | * a file; i.e., if we're not executing the .exrc now. | |
702 | */ | |
703 | if (tmpfd >= 0) | |
704 | msg("invalid option name \"%s\"", name); | |
15637ed4 RG |
705 | } |
706 | else if ((opts[i].flags & CANSET) != CANSET) | |
707 | { | |
708 | msg("option \"%s\" can't be altered", name); | |
709 | } | |
710 | else if ((opts[i].flags & RCSET) != CANSET && nlines >= 1L) | |
711 | { | |
712 | msg("option \"%s\" can only be set in a %s file", name, EXRC); | |
713 | } | |
714 | else if (value) | |
715 | { | |
716 | switch (opts[i].type) | |
717 | { | |
718 | case BOOL: | |
719 | msg("option \"[no]%s\" is boolean", name); | |
720 | break; | |
721 | ||
722 | case NUM: | |
723 | j = atoi(value); | |
724 | if (j == 0 && *value != '0') | |
725 | { | |
726 | msg("option \"%s\" must have a numeric value", name); | |
727 | } | |
728 | else if (j < opts[i].value[1] || j > (opts[i].value[2] & 0xff)) | |
729 | { | |
730 | msg("option \"%s\" must have a value between %d and %d", | |
731 | name, opts[i].value[1], opts[i].value[2] & 0xff); | |
732 | } | |
733 | else | |
734 | { | |
735 | *opts[i].value = atoi(value); | |
736 | opts[i].flags |= SET; | |
737 | } | |
738 | break; | |
739 | ||
740 | case STR: | |
741 | strcpy(opts[i].value, value); | |
742 | opts[i].flags |= SET; | |
743 | break; | |
744 | } | |
745 | if (opts[i].flags & MR) | |
746 | { | |
747 | redraw(MARK_UNSET, FALSE); | |
748 | } | |
749 | #ifndef CRUNCH | |
750 | if (opts[i].flags & WSET) | |
751 | { | |
752 | wset = TRUE; | |
753 | } | |
754 | #endif | |
755 | } | |
756 | else /* valid option, no value */ | |
757 | { | |
758 | if (opts[i].type == BOOL) | |
759 | { | |
760 | if (prefix == name) | |
761 | *opts[i].value = TRUE; | |
762 | else if (prefix[1] == 'o') | |
763 | *opts[i].value = FALSE; | |
764 | else | |
765 | *opts[i].value = !*opts[i].value; | |
766 | ||
767 | opts[i].flags |= SET; | |
768 | if (opts[i].flags & MR) | |
769 | { | |
770 | redraw(MARK_UNSET, FALSE); | |
771 | } | |
772 | } | |
773 | else | |
774 | { | |
775 | msg("option \"%s\" must be given a value", name); | |
776 | } | |
777 | } | |
778 | ||
779 | /* move on to the next option */ | |
780 | name = scan; | |
781 | } | |
782 | ||
783 | /* special processing ... */ | |
784 | ||
785 | #ifndef CRUNCH | |
786 | /* if "novice" is set, then ":set report=1 showmode nomagic" */ | |
787 | if (*o_novice) | |
788 | { | |
789 | *o_report = 1; | |
790 | # ifndef NO_SHOWMODE | |
791 | *o_smd = TRUE; | |
792 | # endif | |
793 | # ifndef NO_MAGIC | |
794 | *o_magic = FALSE; | |
795 | # endif | |
796 | } | |
797 | #endif | |
798 | ||
799 | /* if "readonly" then set the READONLY flag for this file */ | |
800 | if (*o_readonly) | |
801 | { | |
802 | setflag(file, READONLY); | |
803 | } | |
804 | ||
805 | #ifndef NO_DIGRAPH | |
806 | /* re-initialize the ctype package */ | |
807 | _ct_init(o_flipcase); | |
808 | #endif /* not NO_DIGRAPH */ | |
809 | ||
810 | /* copy o_lines and o_columns into LINES and COLS */ | |
811 | LINES = (*o_lines & 255); | |
812 | COLS = (*o_columns & 255); | |
813 | } |