1 /* opts.c */
2
3 /* Author:
4 * Steve Kirkendall
5 * 16820 SW Tallac Way
6 * Beaverton, OR 97006
7 * kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
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 #ifndef NULL
18 #define NULL (char *)0
19 #endif
20 extern char *getenv();
21
22 /* These are the default values of all options */
23 char o_autoindent[1] = {FALSE};
24 char o_autowrite[1] = {FALSE};
25 #ifndef NO_CHARATTR
26 char o_charattr[1] = {FALSE};
27 #endif
28 char o_columns[3] = {80, 32, 255};
29 char o_directory[30] = TMPDIR;
30 char o_errorbells[1] = {TRUE};
31 char o_exrefresh[1] = {TRUE};
32 #ifndef NO_SENTENCE
33 char o_hideformat[1] = {FALSE};
34 #endif
35 char o_ignorecase[1] = {FALSE};
36 #ifndef NO_EXTENSIONS
37 char o_inputmode[1] = {FALSE};
38 #endif
39 char o_keytime[3] = {2, 0, 5};
40 char o_keywordprg[80] = KEYWORDPRG;
41 char o_lines[3] = {25, 2, 50}; /* More lines? Enlarge kbuf */
42 char o_list[1] = {FALSE};
43 #ifndef NO_MAGIC
44 char o_magic[1] = {TRUE};
45 #endif
46 #ifndef NO_SENTENCE
47 char o_paragraphs[30] = "PPppPApa";
48 #endif
49 #if MSDOS
50 char o_pcbios[1] = {TRUE};
51 #endif
52 char o_readonly[1] = {FALSE};
53 char o_redraw[1] = {TRUE};
54 char o_report[3] = {5, 1, 127};
55 char o_scroll[3] = {12, 1, 127};
56 #ifndef NO_SENTENCE
57 char o_sections[30] = "SEseSHsh";
58 #endif
59 char o_shell[60] = "/bin/sh";
60 char o_shiftwidth[3] = {8, 1, 255};
61 #ifndef NO_SHOWMODE
62 char o_showmode[1] = {FALSE};
63 #endif
64 char o_sidescroll[3] = {8, 1, 40};
65 char o_sync[1] = {FALSE};
66 char o_tabstop[3] = {8, 1, 40};
67 char o_term[30] = "?";
68 char o_vbell[1] = {TRUE};
69 char o_warn[1] = {TRUE};
70 char o_wrapmargin[3] = {0, 0, 255};
71 char o_wrapscan[1] = {TRUE};
72
73
74 /* The following describes the names & types of all options */
75 #define BOOL 0
76 #define NUM 1
77 #define STR 2
78 #define SET 0x01 /* this option has had its value altered */
79 #define CANSET 0x02 /* this option can be set at any time */
80 #define RCSET 0x06 /* this option can be set in a .exrc file only */
81 #define MR 0x40 /* does this option affect the way text is displayed? */
82 struct
83 {
84 char *name; /* name of an option */
85 char *nm; /* short name of an option */
86 char type; /* type of an option */
87 char flags; /* boolean: has this option been set? */
88 char *value; /* value */
89 }
90 opts[] =
91 {
92 /* name type flags redraw value */
93 { "autoindent", "ai", BOOL, CANSET , o_autoindent },
94 { "autowrite", "aw", BOOL, CANSET , o_autowrite },
95 #ifndef NO_CHARATTR
96 { "charattr", "ca", BOOL, CANSET | MR, o_charattr },
97 #endif
98 { "columns", "co", NUM, SET , o_columns },
99 { "directory", "dir", STR, RCSET , o_directory },
100 { "errorbells", "eb", BOOL, CANSET , o_errorbells },
101 { "exrefresh", "er", BOOL, CANSET , o_exrefresh },
102 #ifndef NO_SENTENCE
103 { "hideformat", "hf", BOOL, CANSET | MR, o_hideformat },
104 #endif
105 { "ignorecase", "ic", BOOL, CANSET , o_ignorecase },
106 #ifndef NO_EXTENSIONS
107 { "inputmode", "im", BOOL, CANSET , o_inputmode },
108 #endif
109 { "keytime", "kt", NUM, CANSET , o_keytime },
110 { "keywordprg", "kp", STR, CANSET , o_keywordprg },
111 { "lines", "ls", NUM, SET , o_lines },
112 { "list", "li", BOOL, CANSET | MR, o_list },
113 #ifndef NO_MAGIC
114 { "magic", "ma", BOOL, CANSET , o_magic },
115 #endif
116 #ifndef NO_SENTENCE
117 { "paragraphs", "pa", STR, CANSET , o_paragraphs },
118 #endif
119 #if MSDOS
120 { "pcbios", "pc", BOOL, SET , o_pcbios },
121 #endif
122 { "readonly", "ro", BOOL, CANSET , o_readonly },
123 { "redraw", "rd", BOOL, CANSET , o_redraw },
124 { "report", "re", NUM, CANSET , o_report },
125 { "scroll", "sc", NUM, CANSET , o_scroll },
126 #ifndef NO_SENTENCE
127 { "sections", "se", STR, CANSET , o_sections },
128 #endif
129 { "shell", "sh", STR, CANSET , o_shell },
130 #ifndef NO_SHOWMODE
131 { "showmode", "sho", BOOL, CANSET , o_showmode },
132 #endif
133 { "shiftwidth", "sw", NUM, CANSET , o_shiftwidth },
134 { "sidescroll", "ss", NUM, CANSET , o_sidescroll },
135 { "sync", "sy", BOOL, CANSET , o_sync },
136 { "tabstop", "ts", NUM, CANSET | MR, o_tabstop },
137 { "term", "te", STR, SET , o_term },
138 { "vbell", "vb", BOOL, CANSET , o_vbell },
139 { "warn", "wa", BOOL, CANSET , o_warn },
140 { "wrapmargin", "wm", NUM, CANSET , o_wrapmargin },
141 { "wrapscan", "ws", BOOL, CANSET , o_wrapscan },
142 { NULL, NULL, 0, CANSET, NULL }
143 };
144
145
146 /* This function initializes certain options from environment variables, etc. */
initopts()147 initopts()
148 {
149 char *val;
150 int i;
151
152 /* set some stuff from environment variables */
153 #if ANY_UNIX || TOS
154 if (val = getenv("SHELL")) /* yes, ASSIGNMENT! */
155 {
156 strcpy(o_shell, val);
157 }
158 if (val = getenv("TERM")) /* yes, ASSIGNMENT! */
159 {
160 strcpy(o_term, val);
161 }
162 #endif
163 #if MSDOS
164 if (val = getenv("COMSPEC")) /* yes, ASSIGNMENT! */
165 {
166 strcpy(o_shell, val);
167 }
168 if ((val = getenv("TERM")) /* yes, ASSIGNMENT! */
169 && strcmp(val, "pcbios"))
170 {
171 strcpy(o_term, val);
172 o_pcbios[0] = 0;
173 }
174 else
175 {
176 strcpy(o_term, "pcbios");
177 o_pcbios[0] = 1;
178 }
179 #endif
180 #if MSDOS || TOS
181 if ((val = getenv("TMP")) /* yes, ASSIGNMENT! */
182 || (val = getenv("TEMP")))
183 strcpy(o_directory, val);
184 #endif
185
186 *o_scroll = LINES / 2 - 1;
187
188 /* disable the vbell option if we don't know how to do a vbell */
189 if (!has_VB)
190 {
191 for (i = 0; opts[i].value != o_vbell; i++)
192 {
193 }
194 opts[i].flags &= ~CANSET;
195 *o_vbell = FALSE;
196 }
197 }
198
199 /* This function lists the current values of all options */
dumpopts(all)200 dumpopts(all)
201 int all; /* boolean: dump all options, or just set ones? */
202 {
203 int i;
204 int col;
205 char nbuf[4];
206
207 for (i = col = 0; opts[i].name; i++)
208 {
209 /* if not set and not all, ignore this option */
210 if (!all && !(opts[i].flags & SET))
211 {
212 continue;
213 }
214
215 /* align this option in one of the columns */
216 if (col > 52)
217 {
218 addch('\n');
219 col = 0;
220 }
221 else if (col > 26)
222 {
223 while (col < 52)
224 {
225 qaddch(' ');
226 col++;
227 }
228 }
229 else if (col > 0)
230 {
231 while (col < 26)
232 {
233 qaddch(' ');
234 col++;
235 }
236 }
237
238 switch (opts[i].type)
239 {
240 case BOOL:
241 if (!*opts[i].value)
242 {
243 qaddch('n');
244 qaddch('o');
245 col += 2;
246 }
247 qaddstr(opts[i].name);
248 col += strlen(opts[i].name);
249 break;
250
251 case NUM:
252 sprintf(nbuf, "%-3d", UCHAR(*opts[i].value));
253 qaddstr(opts[i].name);
254 qaddch('=');
255 qaddstr(nbuf);
256 col += 4 + strlen(opts[i].name);
257 break;
258
259 case STR:
260 qaddstr(opts[i].name);
261 qaddch('=');
262 qaddch('"');
263 qaddstr(opts[i].value);
264 qaddch('"');
265 col += 3 + strlen(opts[i].name) + strlen(opts[i].value);
266 break;
267 }
268 exrefresh();
269 }
270 if (col > 0)
271 {
272 addch('\n');
273 exrefresh();
274 }
275 }
276
277 /* This function saves the current configuarion of options to a file */
saveopts(fd)278 saveopts(fd)
279 int fd; /* file descriptor to write to */
280 {
281 int i;
282 char buf[256], *pos;
283
284 /* write each set options */
285 for (i = 0; opts[i].name; i++)
286 {
287 /* if unset or unsettable, ignore this option */
288 if (!(opts[i].flags & SET) || !(opts[i].flags & CANSET))
289 {
290 continue;
291 }
292
293 strcpy(buf, "set ");
294 pos = &buf[4];
295 switch (opts[i].type)
296 {
297 case BOOL:
298 if (!*opts[i].value)
299 {
300 *pos++='n';
301 *pos++='o';
302 }
303 strcpy(pos, opts[i].name);
304 strcat(pos, "\n");
305 break;
306
307 case NUM:
308 sprintf(pos, "%s=%-3d\n", opts[i].name, *opts[i].value & 0xff);
309 break;
310
311 case STR:
312 sprintf(pos, "%s=\"%s\"\n", opts[i].name, opts[i].value);
313 break;
314 }
315 twrite(fd, buf, strlen(buf));
316 }
317 }
318
319
320 /* This function changes the values of one or more options. */
setopts(assignments)321 setopts(assignments)
322 char *assignments; /* a string containing option assignments */
323 {
324 char *name; /* name of variable in assignments */
325 char *value; /* value of the variable */
326 char *scan; /* used for moving through strings */
327 int i, j;
328
329 /* for each assignment... */
330 for (name = assignments; *name; )
331 {
332 /* skip whitespace */
333 if (*name == ' ' || *name == '\t')
334 {
335 name++;
336 continue;
337 }
338
339 /* find the value, if any */
340 for (scan = name; *scan >= 'a' && *scan <= 'z'; scan++)
341 {
342 }
343 if (*scan == '=')
344 {
345 *scan++ = '\0';
346 if (*scan == '"')
347 {
348 value = ++scan;
349 while (*scan && *scan != '"')
350 {
351 scan++;
352 }
353 if (*scan)
354 {
355 *scan++ = '\0';
356 }
357 }
358 else
359 {
360 value = scan;
361 while (*scan && *scan != ' ' && *scan != '\t')
362 {
363 scan++;
364 }
365 if (*scan)
366 {
367 *scan++ = '\0';
368 }
369 }
370 }
371 else
372 {
373 if (*scan)
374 {
375 *scan++ = '\0';
376 }
377 value = NULL;
378 if (name[0] == 'n' && name[1] == 'o')
379 {
380 name += 2;
381 }
382 }
383
384 /* find the variable */
385 for (i = 0;
386 opts[i].name && strcmp(opts[i].name, name) && strcmp(opts[i].nm, name);
387 i++)
388 {
389 }
390
391 /* change the variable */
392 if (!opts[i].name)
393 {
394 msg("invalid option name \"%s\"", name);
395 }
396 else if ((opts[i].flags & CANSET) != CANSET)
397 {
398 msg("option \"%s\" can't be altered", name);
399 }
400 else if ((opts[i].flags & RCSET) != CANSET && nlines >= 1L)
401 {
402 msg("option \"%s\" can only be set in a %s file", name, EXRC);
403 }
404 else if (value)
405 {
406 switch (opts[i].type)
407 {
408 case BOOL:
409 msg("option \"[no]%s\" is boolean", name);
410 break;
411
412 case NUM:
413 j = atoi(value);
414 if (j == 0 && *value != '0')
415 {
416 msg("option \"%s\" must have a numeric value", name);
417 }
418 else if (j < opts[i].value[1] || j > (opts[i].value[2] & 0xff))
419 {
420 msg("option \"%s\" must have a value between %d and %d",
421 name, opts[i].value[1], opts[i].value[2] & 0xff);
422 }
423 else
424 {
425 *opts[i].value = atoi(value);
426 opts[i].flags |= SET;
427 }
428 break;
429
430 case STR:
431 strcpy(opts[i].value, value);
432 opts[i].flags |= SET;
433 break;
434 }
435 if (opts[i].flags & MR)
436 {
437 mustredraw = TRUE;
438 }
439 }
440 else /* valid option, no value */
441 {
442 if (opts[i].type == BOOL)
443 {
444 *opts[i].value = (name[-1] != 'o');
445 opts[i].flags |= SET;
446 if (opts[i].flags & MR)
447 {
448 mustredraw = TRUE;
449 }
450 }
451 else
452 {
453 msg("option \"%s\" must be given a value", name);
454 }
455 }
456
457 /* move on to the next option */
458 name = scan;
459 }
460 }
461