📄 options.c
字号:
/* Check list of abbreviations. */ atmp.name = name; if ((ap = bsearch(&atmp, abbrev, sizeof(abbrev) / sizeof(OABBREV) - 1, sizeof(OABBREV), opts_abbcmp)) != NULL) { op = optlist + ap->offset; goto found; } /* Check list of options. */ otmp.name = name; if ((op = bsearch(&otmp, optlist, sizeof(optlist) / sizeof(OPTLIST) - 1, sizeof(OPTLIST), opts_cmp)) != NULL) goto found; /* Check for prefix match. */prefix: op = opts_prefix(name);found: if (op == NULL) { msgq(sp, M_ERR, "no %s option: 'set all' gives all option values", name); continue; } /* Find current option values. */ offset = op - optlist; spo = sp->opts + offset; /* Set name, value. */ switch (op->type) { case OPT_0BOOL: case OPT_1BOOL: if (equals) { msgq(sp, M_ERR, "set: [no]%s option doesn't take a value", name); break; } if (op->func != NULL) { if (op->func(sp, spo, NULL, turnoff)) { rval = 1; break; } } else if (turnoff) O_CLR(sp, offset); else O_SET(sp, offset); goto change; case OPT_NUM: /* * !!! * Extension to historic vi. If the OPT_NOSTR flag is * set, a numeric option may be turned off by using a * "no" prefix, e.g. "nowrapmargin". (We assume that * setting the value to 0 turns a numeric option off.) */ if (turnoff) { if (F_ISSET(op, OPT_NOSTR)) { value = 0; goto nostr; } msgq(sp, M_ERR, "set: %s option isn't a boolean", name); break; } if (!equals) { if (!disp) disp = SELECT_DISPLAY; F_SET(spo, OPT_SELECTED); break; } value = strtol(equals, &endp, 10); if (*endp && !isblank(*endp)) { msgq(sp, M_ERR, "set %s: illegal number %s", name, equals); break; }nostr: if (op->func != NULL) { if (op->func(sp, spo, equals, value)) { rval = 1; break; } } else O_VAL(sp, offset) = value; goto change; case OPT_STR: if (turnoff) { msgq(sp, M_ERR, "set: %s option isn't a boolean", name); break; } if (!equals) { if (!disp) disp = SELECT_DISPLAY; F_SET(spo, OPT_SELECTED); break; } if (op->func != NULL) { if (op->func(sp, spo, equals, (u_long)0)) { rval = 1; break; } } else { if (F_ISSET(&sp->opts[offset], OPT_ALLOCATED)) free(O_STR(sp, offset)); if ((O_STR(sp, offset) = strdup(equals)) == NULL) { msgq(sp, M_SYSERR, NULL); rval = 1; break; } else F_SET(&sp->opts[offset], OPT_ALLOCATED); }change: if (sp->s_optchange != NULL) (void)sp->s_optchange(sp, offset); F_SET(&sp->opts[offset], OPT_SET); break; default: abort(); } } if (disp != NO_DISPLAY) opts_dump(sp, disp); return (rval);}/* * opts_dump -- * List the current values of selected options. */voidopts_dump(sp, type) SCR *sp; enum optdisp type;{ OPTLIST const *op; int base, b_num, cnt, col, colwidth, curlen, s_num; int numcols, numrows, row; int b_op[O_OPTIONCOUNT], s_op[O_OPTIONCOUNT]; char nbuf[20]; /* * XXX * It's possible to get here by putting "set option" in the * .exrc file. I can't think of a clean way to layer this, * or a reasonable check to make, so we block it here. */ if (sp->stdfp == NULL) { msgq(sp, M_ERR, "Option display requires that the screen be initialized."); return; } /* * Options are output in two groups -- those that fit in a column and * those that don't. Output is done on 6 character "tab" boundaries * for no particular reason. (Since we don't output tab characters, * we can ignore the terminal's tab settings.) Ignore the user's tab * setting because we have no idea how reasonable it is. * * Find a column width we can live with. */ for (cnt = 6; cnt > 1; --cnt) { colwidth = (sp->cols - 1) / cnt & ~(STANDARD_TAB - 1); if (colwidth >= 10) { colwidth = (colwidth + STANDARD_TAB) & ~(STANDARD_TAB - 1); break; } colwidth = 0; } /* * Get the set of options to list, entering them into * the column list or the overflow list. */ for (b_num = s_num = 0, op = optlist; op->name != NULL; ++op) { cnt = op - optlist; /* If OPT_NEVER set, it's never displayed. */ if (F_ISSET(op, OPT_NEVER)) continue; switch (type) { case ALL_DISPLAY: /* Display all. */ break; case CHANGED_DISPLAY: /* Display changed. */ if (!F_ISSET(&sp->opts[cnt], OPT_SET)) continue; break; case SELECT_DISPLAY: /* Display selected. */ if (!F_ISSET(&sp->opts[cnt], OPT_SELECTED)) continue; break; default: case NO_DISPLAY: abort(); /* NOTREACHED */ } F_CLR(&sp->opts[cnt], OPT_SELECTED); curlen = strlen(op->name); switch (op->type) { case OPT_0BOOL: case OPT_1BOOL: if (!O_ISSET(sp, cnt)) curlen += 2; break; case OPT_NUM: (void)snprintf(nbuf, sizeof(nbuf), "%ld", O_VAL(sp, cnt)); curlen += strlen(nbuf); break; case OPT_STR: curlen += strlen(O_STR(sp, cnt)) + 3; break; } /* Offset by two so there's a gap. */ if (curlen < colwidth - 2) s_op[s_num++] = cnt; else b_op[b_num++] = cnt; } if (s_num > 0) { /* Figure out the number of columns. */ numcols = (sp->cols - 1) / colwidth; if (s_num > numcols) { numrows = s_num / numcols; if (s_num % numcols) ++numrows; } else numrows = 1; /* Display the options in sorted order. */ for (row = 0; row < numrows;) { for (base = row, col = 0; col < numcols; ++col) { cnt = opts_print(sp, &optlist[s_op[base]]); if ((base += numrows) >= s_num) break; (void)ex_printf(EXCOOKIE, "%*s", (int)(colwidth - cnt), ""); } if (++row < numrows || b_num) (void)ex_printf(EXCOOKIE, "\n"); } } for (row = 0; row < b_num;) { (void)opts_print(sp, &optlist[b_op[row]]); if (++row < b_num) (void)ex_printf(EXCOOKIE, "\n"); } (void)ex_printf(EXCOOKIE, "\n");}/* * opts_print -- * Print out an option. */static intopts_print(sp, op) SCR *sp; OPTLIST const *op;{ int curlen, offset; curlen = 0; offset = op - optlist; switch (op->type) { case OPT_0BOOL: case OPT_1BOOL: curlen += ex_printf(EXCOOKIE, "%s%s", O_ISSET(sp, offset) ? "" : "no", op->name); break; case OPT_NUM: curlen += ex_printf(EXCOOKIE, "%s=%ld", op->name, O_VAL(sp, offset)); break; case OPT_STR: curlen += ex_printf(EXCOOKIE, "%s=\"%s\"", op->name, O_STR(sp, offset)); break; } return (curlen);}/* * opts_save -- * Write the current configuration to a file. */intopts_save(sp, fp) SCR *sp; FILE *fp;{ OPTLIST const *op; int ch, cnt; char *p; for (op = optlist; op->name != NULL; ++op) { if (F_ISSET(op, OPT_NOSAVE)) continue; cnt = op - optlist; switch (op->type) { case OPT_0BOOL: case OPT_1BOOL: if (O_ISSET(sp, cnt)) (void)fprintf(fp, "set %s\n", op->name); else (void)fprintf(fp, "set no%s\n", op->name); break; case OPT_NUM: (void)fprintf(fp, "set %s=%-3d\n", op->name, O_VAL(sp, cnt)); break; case OPT_STR: (void)fprintf(fp, "set "); for (p = op->name; (ch = *p) != '\0'; ++p) { if (isblank(ch)) (void)putc('\\', fp); (void)putc(ch, fp); } (void)putc('=', fp); for (p = O_STR(sp, cnt); (ch = *p) != '\0'; ++p) { if (isblank(ch)) (void)putc('\\', fp); (void)putc(ch, fp); } (void)putc('\n', fp); break; } if (ferror(fp)) { msgq(sp, M_ERR, "I/O error: %s", strerror(errno)); return (1); } } return (0);}/* * opts_prefix -- * Check to see if the name is the prefix of one (and only one) * option. If so, return the option. */static OPTLIST const *opts_prefix(name) char *name;{ OPTLIST const *op, *save_op; size_t len; save_op = NULL; len = strlen(name); for (op = optlist; op->name != NULL; ++op) { if (op->name[0] < name[0]) continue; if (op->name[0] > name[0]) break; if (!memcmp(op->name, name, len)) { if (save_op != NULL) return (NULL); save_op = op; } } return (save_op);}static intopts_abbcmp(a, b) const void *a, *b;{ return(strcmp(((OABBREV *)a)->name, ((OABBREV *)b)->name));}static intopts_cmp(a, b) const void *a, *b;{ return(strcmp(((OPTLIST *)a)->name, ((OPTLIST *)b)->name));}/* * opts_free -- * Free all option strings */voidopts_free(sp) SCR *sp;{ int cnt; char *p; for (cnt = 0; cnt < O_OPTIONCOUNT; ++cnt) if (F_ISSET(&sp->opts[cnt], OPT_ALLOCATED)) { p = O_STR(sp, cnt); FREE(p, strlen(p) + 1); }}/* * opts_copy -- * Copy a screen's OPTION array. */intopts_copy(orig, sp) SCR *orig, *sp;{ OPTION *op; int cnt; /* Copy most everything without change. */ memmove(sp->opts, orig->opts, sizeof(orig->opts)); /* * Allocate copies of the strings -- keep trying to reallocate * after ENOMEM failure, otherwise end up with more than one * screen referencing the original memory. */ for (op = sp->opts, cnt = 0; cnt < O_OPTIONCOUNT; ++cnt, ++op) if (F_ISSET(&sp->opts[cnt], OPT_ALLOCATED) && (O_STR(sp, cnt) = strdup(O_STR(sp, cnt))) == NULL) { msgq(orig, M_SYSERR, NULL); return (1); } return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -