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