add O_SHOWDIRTY option
[nvi.git] / common / options.c
blobd911e2ac6caa092495ff8c85c15d62d9aced21f4
1 /*-
2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
6 */
8 #ifndef lint
9 static char sccsid[] = "$Id: options.c,v 8.25 1993/11/15 08:42:12 bostic Exp $ (Berkeley) $Date: 1993/11/15 08:42:12 $";
10 #endif /* not lint */
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <sys/ioctl.h>
16 #include <ctype.h>
17 #include <curses.h>
18 #include <errno.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
23 #include "vi.h"
24 #include "excmd.h"
25 #include "pathnames.h"
27 static int opts_abbcmp __P((const void *, const void *));
28 static int opts_cmp __P((const void *, const void *));
29 static OPTLIST const *opts_prefix __P((char *));
30 static int opts_print __P((SCR *, OPTLIST const *, OPTION *));
32 static OPTLIST const optlist[] = {
33 /* O_ALTWERASE */
34 {"altwerase", f_altwerase, OPT_0BOOL, 0},
35 /* O_AUTOINDENT */
36 {"autoindent", NULL, OPT_0BOOL, 0},
37 /* O_AUTOPRINT */
38 {"autoprint", NULL, OPT_1BOOL, 0},
39 /* O_AUTOWRITE */
40 {"autowrite", NULL, OPT_0BOOL, 0},
41 /* O_BEAUTIFY */
42 {"beautify", NULL, OPT_0BOOL, 0},
43 /* O_COLUMNS */
44 {"columns", f_columns, OPT_NUM, OPT_NOSAVE},
45 /* O_COMMENT */
46 {"comment", NULL, OPT_0BOOL, 0},
47 /* O_DIGRAPH */
48 {"digraph", NULL, OPT_0BOOL, 0},
49 /* O_DIRECTORY */
50 {"directory", NULL, OPT_STR, OPT_NOSAVE},
51 /* O_EDCOMPATIBLE */
52 {"edcompatible",NULL, OPT_0BOOL, 0},
53 /* O_ERRORBELLS */
54 {"errorbells", NULL, OPT_0BOOL, 0},
55 /* O_EXRC */
56 {"exrc", NULL, OPT_0BOOL, 0},
57 /* O_EXTENDED */
58 {"extended", NULL, OPT_0BOOL, 0},
59 /* O_FLASH */
60 {"flash", NULL, OPT_1BOOL, 0},
61 /* O_IGNORECASE */
62 {"ignorecase", NULL, OPT_0BOOL, 0},
63 /* O_KEYTIME */
64 {"keytime", f_keytime, OPT_NUM, 0},
65 /* O_LEFTRIGHT */
66 {"leftright", f_leftright, OPT_0BOOL, 0},
67 /* O_LINES */
68 {"lines", f_lines, OPT_NUM, OPT_NOSAVE},
69 /* O_LISP */
70 {"lisp", f_lisp, OPT_0BOOL, 0},
71 /* O_LIST */
72 {"list", f_list, OPT_0BOOL, 0},
73 /* O_MAGIC */
74 {"magic", NULL, OPT_1BOOL, 0},
75 /* O_MATCHTIME */
76 {"matchtime", f_matchtime, OPT_NUM, 0},
77 /* O_MESG */
78 {"mesg", f_mesg, OPT_1BOOL, 0},
79 /* O_MODELINE */
80 {"modeline", f_modelines, OPT_0BOOL, 0},
81 /* O_MODELINES */
82 {"modelines", f_modelines, OPT_0BOOL, 0},
83 /* O_NUMBER */
84 {"number", f_number, OPT_0BOOL, 0},
85 /* O_NUNDO */
86 {"nundo", NULL, OPT_0BOOL, 0},
87 /* O_OPEN */
88 {"open", NULL, OPT_1BOOL, 0},
89 /* O_OPTIMIZE */
90 {"optimize", f_optimize, OPT_1BOOL, 0},
91 /* O_PARAGRAPHS */
92 {"paragraphs", f_paragraph, OPT_STR, 0},
93 /* O_PROMPT */
94 {"prompt", NULL, OPT_1BOOL, 0},
95 /* O_READONLY */
96 {"readonly", f_readonly, OPT_0BOOL, 0},
97 /* O_REDRAW */
98 {"redraw", NULL, OPT_0BOOL, 0},
99 /* O_REMAP */
100 {"remap", NULL, OPT_1BOOL, 0},
101 /* O_REPORT */
102 {"report", NULL, OPT_NUM, OPT_NOSTR},
103 /* O_RULER */
104 {"ruler", f_ruler, OPT_0BOOL, 0},
105 /* O_SCROLL */
106 {"scroll", NULL, OPT_NUM, 0},
107 /* O_SECTIONS */
108 {"sections", f_section, OPT_STR, 0},
109 /* O_SHELL */
110 {"shell", NULL, OPT_STR, 0},
111 /* O_SHIFTWIDTH */
112 {"shiftwidth", f_shiftwidth, OPT_NUM, 0},
113 /* O_SHOWDIRTY */
114 {"showdirty", NULL, OPT_0BOOL, 0},
115 /* O_SHOWMATCH */
116 {"showmatch", NULL, OPT_0BOOL, 0},
117 /* O_SHOWMODE */
118 {"showmode", NULL, OPT_0BOOL, 0},
119 /* O_SIDESCROLL */
120 {"sidescroll", f_sidescroll, OPT_NUM, 0},
121 /* O_TABSTOP */
122 {"tabstop", f_tabstop, OPT_NUM, 0},
123 /* O_TAGLENGTH */
124 {"taglength", NULL, OPT_NUM, OPT_NOSTR},
125 /* O_TAGS */
126 {"tags", f_tags, OPT_STR, 0},
127 /* O_TERM */
128 {"term", f_term, OPT_STR, OPT_NOSAVE},
129 /* O_TERSE */
130 {"terse", NULL, OPT_0BOOL, 0},
131 /* O_TIMEOUT */
132 {"timeout", NULL, OPT_0BOOL, 0},
133 /* O_TTYWERASE */
134 {"ttywerase", f_ttywerase, OPT_0BOOL, 0},
135 /* O_VERBOSE */
136 {"verbose", NULL, OPT_0BOOL, 0},
137 /* O_W300 */
138 {"w300", f_w300, OPT_NUM, OPT_NEVER},
139 /* O_W1200 */
140 {"w1200", f_w1200, OPT_NUM, OPT_NEVER},
141 /* O_W9600 */
142 {"w9600", f_w9600, OPT_NUM, OPT_NEVER},
143 /* O_WARN */
144 {"warn", NULL, OPT_1BOOL, 0},
145 /* O_WINDOW */
146 {"window", f_window, OPT_NUM, 0},
147 /* O_WRAPMARGIN */
148 {"wrapmargin", f_wrapmargin, OPT_NUM, OPT_NOSTR},
149 /* O_WRAPSCAN */
150 {"wrapscan", NULL, OPT_1BOOL, 0},
151 /* O_WRITEANY */
152 {"writeany", NULL, OPT_0BOOL, 0},
153 {NULL},
156 typedef struct abbrev {
157 char *name;
158 int offset;
159 } OABBREV;
161 static OABBREV const abbrev[] = {
162 {"ai", O_AUTOINDENT},
163 {"ap", O_AUTOPRINT},
164 {"aw", O_AUTOWRITE},
165 {"bf", O_BEAUTIFY},
166 {"co", O_COLUMNS},
167 {"dir", O_DIRECTORY},
168 {"eb", O_ERRORBELLS},
169 {"ed", O_EDCOMPATIBLE},
170 {"fl", O_FLASH},
171 {"ic", O_IGNORECASE},
172 {"kt", O_KEYTIME},
173 {"li", O_LIST},
174 {"ls", O_LINES},
175 {"ma", O_MAGIC},
176 {"me", O_MESG},
177 {"modeline", O_MODELINES},
178 {"nu", O_NUMBER},
179 {"opt", O_OPTIMIZE},
180 {"pa", O_PARAGRAPHS},
181 {"pr", O_PROMPT},
182 {"re", O_REPORT},
183 {"ro", O_READONLY},
184 {"ru", O_RULER},
185 {"sc", O_SCROLL},
186 {"se", O_SECTIONS},
187 {"sh", O_SHELL},
188 {"sm", O_SHOWMATCH},
189 {"ss", O_SIDESCROLL},
190 {"sw", O_SHIFTWIDTH},
191 {"te", O_TERM},
192 {"tr", O_TERSE},
193 {"ts", O_TABSTOP},
194 {"ve", O_VERBOSE},
195 {"wa", O_WARN},
196 {"wm", O_WRAPMARGIN},
197 {"wr", O_WRITEANY},
198 {"ws", O_WRAPSCAN},
199 {NULL},
203 * opts_init --
204 * Initialize some of the options. Since the user isn't really
205 * "setting" these variables, don't set their OPT_SET bits.
208 opts_init(sp)
209 SCR *sp;
211 OPTLIST const *op;
212 u_long v;
213 int cnt;
214 char *s, *argv[2], b1[1024];
216 argv[0] = b1;
217 argv[1] = NULL;
219 #define SET_DEF(opt, str) { \
220 if (str != b1) /* GCC puts strings in text-space. */ \
221 (void)strcpy(b1, str); \
222 if (opts_set(sp, argv)) { \
223 msgq(sp, M_ERR, \
224 "Unable to set default %s option", optlist[opt]); \
225 return (1); \
227 F_CLR(&sp->opts[opt], OPT_SET); \
229 /* Set default values. */
230 for (op = optlist, cnt = 0; op->name != NULL; ++op, ++cnt)
231 if (op->type == OPT_0BOOL)
232 O_CLR(sp, cnt);
233 else if (op->type == OPT_1BOOL)
234 O_SET(sp, cnt);
236 (void)snprintf(b1, sizeof(b1), "directory=%s",
237 (s = getenv("TMPDIR")) == NULL ? _PATH_PRESERVE : s);
238 SET_DEF(O_DIRECTORY, b1);
239 SET_DEF(O_KEYTIME, "keytime=6");
240 SET_DEF(O_MATCHTIME, "matchtime=7");
241 SET_DEF(O_REPORT, "report=5");
242 SET_DEF(O_PARAGRAPHS, "paragraphs=IPLPPPQPP LIpplpipbp");
243 (void)snprintf(b1, sizeof(b1), "scroll=%ld", O_VAL(sp, O_LINES) / 2);
244 SET_DEF(O_SCROLL, b1);
245 SET_DEF(O_SECTIONS, "sections=NHSHH HUnhsh");
246 (void)snprintf(b1, sizeof(b1),
247 "shell=%s", (s = getenv("SHELL")) == NULL ? _PATH_BSHELL : s);
248 SET_DEF(O_SHELL, b1);
249 SET_DEF(O_SHIFTWIDTH, "shiftwidth=8");
250 SET_DEF(O_SIDESCROLL, "sidescroll=16");
251 SET_DEF(O_TABSTOP, "tabstop=8");
252 (void)snprintf(b1, sizeof(b1), "tags=%s", _PATH_TAGS);
253 SET_DEF(O_TAGS, b1);
254 (void)snprintf(b1, sizeof(b1),
255 "term=%s", (s = getenv("TERM")) == NULL ? "unknown" : s);
256 SET_DEF(O_TERM, b1);
259 * The default window option values are:
260 * 8 if baud rate <= 600
261 * 16 if baud rate <= 1200
262 * LINES - 1 if baud rate > 1200
264 v = baud_from_bval(sp);
265 if (v <= 600)
266 v = 8;
267 else if (v <= 1200)
268 v = 16;
269 else
270 v = O_VAL(sp, O_LINES) - 1;
271 (void)snprintf(b1, sizeof(b1), "window=%lu", v);
272 SET_DEF(O_WINDOW, b1);
274 SET_DEF(O_WRAPMARGIN, "wrapmargin=0");
277 * By default, the historic vi always displayed information
278 * about two options, redraw and term. Term seems sufficient.
280 F_SET(&sp->opts[O_TERM], OPT_SET);
281 return (0);
285 * opts_set --
286 * Change the values of one or more options.
289 opts_set(sp, argv)
290 SCR *sp;
291 char **argv;
293 enum optdisp disp;
294 OABBREV atmp, *ap;
295 OPTLIST const *op;
296 OPTLIST otmp;
297 OPTION *spo;
298 u_long value, turnoff;
299 int ch, offset, rval;
300 char *endp, *equals, *name, *p;
302 disp = NO_DISPLAY;
303 for (rval = 0; *argv; ++argv) {
305 * The historic vi dumped the options for each occurrence of
306 * "all" in the set list. Puhleeze.
308 if (!strcmp(*argv, "all")) {
309 disp = ALL_DISPLAY;
310 continue;
313 /* Find equals sign or end of set, skipping backquoted chars. */
314 for (p = name = *argv, equals = NULL; ch = *p; ++p)
315 switch(ch) {
316 case '=':
317 equals = p;
318 break;
319 case '\\':
320 /* Historic vi just used the backslash. */
321 if (p[1] == '\0')
322 break;
323 ++p;
324 break;
327 turnoff = 0;
328 op = NULL;
329 if (equals)
330 *equals++ = '\0';
332 /* Check list of abbreviations. */
333 atmp.name = name;
334 if ((ap = bsearch(&atmp, abbrev,
335 sizeof(abbrev) / sizeof(OABBREV) - 1,
336 sizeof(OABBREV), opts_abbcmp)) != NULL) {
337 op = optlist + ap->offset;
338 goto found;
341 /* Check list of options. */
342 otmp.name = name;
343 if ((op = bsearch(&otmp, optlist,
344 sizeof(optlist) / sizeof(OPTLIST) - 1,
345 sizeof(OPTLIST), opts_cmp)) != NULL)
346 goto found;
348 /* Try the name without any leading "no". */
349 if (name[0] == 'n' && name[1] == 'o') {
350 turnoff = 1;
351 name += 2;
352 } else
353 goto prefix;
355 /* Check list of abbreviations. */
356 atmp.name = name;
357 if ((ap = bsearch(&atmp, abbrev,
358 sizeof(abbrev) / sizeof(OABBREV) - 1,
359 sizeof(OABBREV), opts_abbcmp)) != NULL) {
360 op = optlist + ap->offset;
361 goto found;
364 /* Check list of options. */
365 otmp.name = name;
366 if ((op = bsearch(&otmp, optlist,
367 sizeof(optlist) / sizeof(OPTLIST) - 1,
368 sizeof(OPTLIST), opts_cmp)) != NULL)
369 goto found;
371 /* Check for prefix match. */
372 prefix: op = opts_prefix(name);
374 found: if (op == NULL) {
375 msgq(sp, M_ERR,
376 "no %s option: 'set all' gives all option values",
377 name);
378 continue;
381 /* Find current option values. */
382 offset = op - optlist;
383 spo = sp->opts + offset;
385 /* Set name, value. */
386 switch (op->type) {
387 case OPT_0BOOL:
388 case OPT_1BOOL:
389 if (equals) {
390 msgq(sp, M_ERR,
391 "set: [no]%s option doesn't take a value",
392 name);
393 break;
395 if (op->func != NULL) {
396 if (op->func(sp, spo, NULL, turnoff)) {
397 rval = 1;
398 break;
400 } else if (turnoff)
401 O_CLR(sp, offset);
402 else
403 O_SET(sp, offset);
404 goto change;
405 case OPT_NUM:
407 * !!!
408 * Extension to historic vi. If the OPT_NOSTR flag is
409 * set, a numeric option may be turned off by using a
410 * "no" prefix, e.g. "nowrapmargin". (We assume that
411 * setting the value to 0 turns a numeric option off.)
413 if (turnoff) {
414 if (F_ISSET(op, OPT_NOSTR)) {
415 value = 0;
416 goto nostr;
418 msgq(sp, M_ERR,
419 "set: %s option isn't a boolean", name);
420 break;
422 if (!equals) {
423 if (!disp)
424 disp = SELECT_DISPLAY;
425 F_SET(spo, OPT_SELECTED);
426 break;
428 value = strtol(equals, &endp, 10);
429 if (*endp && !isblank(*endp)) {
430 msgq(sp, M_ERR,
431 "set %s: illegal number %s", name, equals);
432 break;
434 nostr: if (op->func != NULL) {
435 if (op->func(sp, spo, equals, value)) {
436 rval = 1;
437 break;
439 } else
440 O_VAL(sp, offset) = value;
441 goto change;
442 case OPT_STR:
443 if (turnoff) {
444 msgq(sp, M_ERR,
445 "set: %s option isn't a boolean", name);
446 break;
448 if (!equals) {
449 if (!disp)
450 disp = SELECT_DISPLAY;
451 F_SET(spo, OPT_SELECTED);
452 break;
454 if (op->func != NULL) {
455 if (op->func(sp, spo, equals, (u_long)0)) {
456 rval = 1;
457 break;
459 } else {
460 if (F_ISSET(&sp->opts[offset], OPT_ALLOCATED))
461 free(O_STR(sp, offset));
462 if ((O_STR(sp, offset) =
463 strdup(equals)) == NULL) {
464 msgq(sp, M_SYSERR, NULL);
465 rval = 1;
466 break;
467 } else
468 F_SET(&sp->opts[offset], OPT_ALLOCATED);
470 change: if (sp->s_optchange != NULL)
471 (void)sp->s_optchange(sp, offset);
472 F_SET(&sp->opts[offset], OPT_SET);
473 break;
474 default:
475 abort();
478 if (disp)
479 opts_dump(sp, disp);
480 return (rval);
484 * opts_dump --
485 * List the current values of selected options.
487 void
488 opts_dump(sp, type)
489 SCR *sp;
490 enum optdisp type;
492 OPTLIST const *op;
493 int base, b_num, chcnt, cnt, col, colwidth, curlen, endcol, s_num;
494 int numcols, numrows, row, tablen, termwidth;
495 int b_op[O_OPTIONCOUNT], s_op[O_OPTIONCOUNT];
496 char nbuf[20];
499 * Options are output in two groups -- those that fit at least two to
500 * a line and those that don't. We do output on tab boundaries for no
501 * particular reason. First get the set of options to list, keeping
502 * track of the length of each. No error checking, because we know
503 * that O_TERM was set so at least one option has the OPT_SET bit on.
504 * Termwidth is the tab stop before half of the line in the first loop,
505 * and the full line length later on.
507 colwidth = -1;
508 tablen = O_VAL(sp, O_TABSTOP);
509 termwidth = (sp->cols - 1) / 2 & ~(tablen - 1);
510 for (b_num = s_num = 0, op = optlist; op->name; ++op) {
511 cnt = op - optlist;
513 /* If OPT_NEVER set, it's never displayed. */
514 if (F_ISSET(op, OPT_NEVER))
515 continue;
517 switch (type) {
518 case ALL_DISPLAY: /* Display all. */
519 break;
520 case CHANGED_DISPLAY: /* Display changed. */
521 if (!F_ISSET(&sp->opts[cnt], OPT_SET))
522 continue;
523 break;
524 case SELECT_DISPLAY: /* Display selected. */
525 if (!F_ISSET(&sp->opts[cnt], OPT_SELECTED))
526 continue;
527 break;
528 default:
529 case NO_DISPLAY:
530 abort();
531 /* NOTREACHED */
533 F_CLR(&sp->opts[cnt], OPT_SELECTED);
535 curlen = strlen(op->name);
536 switch (op->type) {
537 case OPT_0BOOL:
538 case OPT_1BOOL:
539 if (!O_ISSET(sp, cnt))
540 curlen += 2;
541 break;
542 case OPT_NUM:
543 (void)snprintf(nbuf,
544 sizeof(nbuf), "%ld", O_VAL(sp, cnt));
545 curlen += strlen(nbuf);
546 break;
547 case OPT_STR:
548 curlen += strlen(O_STR(sp, cnt)) + 3;
549 break;
551 if (curlen < termwidth) {
552 if (colwidth < curlen)
553 colwidth = curlen;
554 s_op[s_num++] = cnt;
555 } else
556 b_op[b_num++] = cnt;
559 colwidth = (colwidth + tablen) & ~(tablen - 1);
560 termwidth = sp->cols - 1;
561 numcols = termwidth / colwidth;
562 if (s_num > numcols) {
563 numrows = s_num / numcols;
564 if (s_num % numcols)
565 ++numrows;
566 } else
567 numrows = 1;
569 for (row = 0; row < numrows;) {
570 endcol = colwidth;
571 for (base = row, chcnt = col = 0; col < numcols; ++col) {
572 chcnt += opts_print(sp,
573 &optlist[s_op[base]], &sp->opts[s_op[base]]);
574 if ((base += numrows) >= s_num)
575 break;
576 while ((cnt =
577 (chcnt + tablen & ~(tablen - 1))) <= endcol) {
578 (void)ex_printf(EXCOOKIE, "\t");
579 chcnt = cnt;
581 endcol += colwidth;
583 if (++row < numrows || b_num)
584 (void)ex_printf(EXCOOKIE, "\n");
587 for (row = 0; row < b_num;) {
588 (void)opts_print(sp, &optlist[b_op[row]], &sp->opts[b_op[row]]);
589 if (++row < b_num)
590 (void)ex_printf(EXCOOKIE, "\n");
592 (void)ex_printf(EXCOOKIE, "\n");
596 * opts_print --
597 * Print out an option.
599 static int
600 opts_print(sp, op, spo)
601 SCR *sp;
602 OPTLIST const *op;
603 OPTION *spo;
605 int curlen, offset;
607 curlen = 0;
608 offset = op - optlist;
609 switch (op->type) {
610 case OPT_0BOOL:
611 case OPT_1BOOL:
612 curlen += ex_printf(EXCOOKIE,
613 "%s%s", O_ISSET(sp, offset) ? "" : "no", op->name);
614 break;
615 case OPT_NUM:
616 curlen += ex_printf(EXCOOKIE,
617 "%s=%ld", op->name, O_VAL(sp, offset));
618 break;
619 case OPT_STR:
620 curlen += ex_printf(EXCOOKIE,
621 "%s=\"%s\"", op->name, O_STR(sp, offset));
622 break;
624 return (curlen);
628 * opts_save --
629 * Write the current configuration to a file.
632 opts_save(sp, fp)
633 SCR *sp;
634 FILE *fp;
636 OPTION *spo;
637 OPTLIST const *op;
638 int ch, cnt;
639 char *p;
641 for (spo = sp->opts, op = optlist; op->name; ++op) {
642 if (F_ISSET(op, OPT_NOSAVE))
643 continue;
644 cnt = op - optlist;
645 switch (op->type) {
646 case OPT_0BOOL:
647 case OPT_1BOOL:
648 if (O_ISSET(sp, cnt))
649 (void)fprintf(fp, "set %s\n", op->name);
650 else
651 (void)fprintf(fp, "set no%s\n", op->name);
652 break;
653 case OPT_NUM:
654 (void)fprintf(fp,
655 "set %s=%-3d\n", op->name, O_VAL(sp, cnt));
656 break;
657 case OPT_STR:
658 for (p = op->name; (ch = *p) != '\0'; ++p) {
659 if (isblank(ch))
660 (void)putc('\\', fp);
661 (void)putc(ch, fp);
663 (void)putc('=', fp);
664 for (p = O_STR(sp, cnt); (ch = *p) != '\0'; ++p) {
665 if (isblank(ch))
666 (void)putc('\\', fp);
667 (void)putc(ch, fp);
669 (void)putc('\n', fp);
670 break;
672 if (ferror(fp)) {
673 msgq(sp, M_ERR, "I/O error: %s", strerror(errno));
674 return (1);
677 return (0);
681 * opts_prefix --
682 * Check to see if the name is the prefix of one (and only one)
683 * option. If so, return the option.
685 static OPTLIST const *
686 opts_prefix(name)
687 char *name;
689 OPTLIST const *op, *save_op;
690 size_t len;
692 save_op = NULL;
693 len = strlen(name);
694 for (op = optlist; op->name != NULL; ++op) {
695 if (op->name[0] < name[0])
696 continue;
697 if (op->name[0] > name[0])
698 break;
699 if (!memcmp(op->name, name, len)) {
700 if (save_op != NULL)
701 return (NULL);
702 save_op = op;
705 return (save_op);
708 static int
709 opts_abbcmp(a, b)
710 const void *a, *b;
712 return(strcmp(((OABBREV *)a)->name, ((OABBREV *)b)->name));
715 static int
716 opts_cmp(a, b)
717 const void *a, *b;
719 return(strcmp(((OPTLIST *)a)->name, ((OPTLIST *)b)->name));
723 * opts_free --
724 * Free all option strings
726 void
727 opts_free(sp)
728 SCR *sp;
730 int cnt;
731 char *p;
733 for (cnt = 0; cnt < O_OPTIONCOUNT; ++cnt)
734 if (F_ISSET(&sp->opts[cnt], OPT_ALLOCATED)) {
735 p = O_STR(sp, cnt);
736 FREE(p, strlen(p) + 1);
741 * opts_copy --
742 * Copy a screen's OPTION array.
745 opts_copy(orig, sp)
746 SCR *orig, *sp;
748 OPTION *op;
749 int cnt;
751 /* Copy most everything without change. */
752 memmove(sp->opts, orig->opts, sizeof(orig->opts));
755 * Allocate copies of the strings -- keep trying to reallocate
756 * after ENOMEM failure, otherwise end up with more than one
757 * screen referencing the original memory.
759 for (op = sp->opts, cnt = 0; cnt < O_OPTIONCOUNT; ++cnt, ++op)
760 if (F_ISSET(&sp->opts[cnt], OPT_ALLOCATED) &&
761 (O_STR(sp, cnt) = strdup(O_STR(sp, cnt))) == NULL) {
762 msgq(orig, M_SYSERR, NULL);
763 return (1);
765 return (0);