source: trunk/minix/commands/elvis/opts.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

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