|
|
1.1 ! root 1: /* opts.c */ ! 2: ! 3: /* Author: ! 4: * Steve Kirkendall ! 5: * 16820 SW Tallac Way ! 6: * Beaverton, OR 97006 ! 7: * [email protected], 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: /* maximum width to permit for strings, including ="" */ ! 23: #define MAXWIDTH 20 ! 24: ! 25: /* These are the default values of all options */ ! 26: char o_autoindent[1] = {FALSE}; ! 27: char o_autoprint[1] = {TRUE}; ! 28: char o_autowrite[1] = {FALSE}; ! 29: #ifndef NO_ERRLIST ! 30: char o_cc[30] = {CC_COMMAND}; ! 31: #endif ! 32: #ifndef NO_CHARATTR ! 33: char o_charattr[1] = {FALSE}; ! 34: #endif ! 35: char o_columns[3] = {80, 32, 255}; ! 36: #ifndef NO_DIGRAPH ! 37: char o_digraph[1] = {FALSE}; ! 38: #endif ! 39: char o_directory[30] = TMPDIR; ! 40: char o_edcompatible[1] = {FALSE}; ! 41: char o_errorbells[1] = {TRUE}; ! 42: char o_exrefresh[1] = {TRUE}; ! 43: #ifndef NO_DIGRAPH ! 44: char o_flipcase[80] ! 45: # if CS_IBMPC ! 46: = {"\207\200\201\232\202\220\204\216\206\217\221\222\224\231\244\245"} ! 47: # endif ! 48: # if CS_LATIN1 ! 49: /* initialized by initopts() */ ! 50: # endif ! 51: ; ! 52: #endif ! 53: #ifndef NO_SENTENCE ! 54: char o_hideformat[1] = {FALSE}; ! 55: #endif ! 56: char o_ignorecase[1] = {FALSE}; ! 57: #ifndef NO_EXTENSIONS ! 58: char o_inputmode[1] = {FALSE}; ! 59: #endif ! 60: char o_keytime[3] = {2, 0, 5}; ! 61: char o_keywordprg[80] = {KEYWORDPRG}; ! 62: char o_lines[3] = {25, 2, 50}; /* More lines? Enlarge kbuf */ ! 63: char o_list[1] = {FALSE}; ! 64: #ifndef NO_MAGIC ! 65: char o_magic[1] = {TRUE}; ! 66: #endif ! 67: #ifndef NO_ERRLIST ! 68: char o_make[30] = {MAKE_COMMAND}; ! 69: #endif ! 70: #ifndef NO_MODELINE ! 71: char o_modeline[1] = {FALSE}; ! 72: #endif ! 73: #ifndef NO_SENTENCE ! 74: char o_paragraphs[30] = "PPppIPLPQP"; ! 75: #endif ! 76: #if MSDOS ! 77: char o_pcbios[1] = {TRUE}; ! 78: #endif ! 79: char o_readonly[1] = {FALSE}; ! 80: char o_report[3] = {5, 1, 127}; ! 81: char o_scroll[3] = {12, 1, 127}; ! 82: #ifndef NO_SENTENCE ! 83: char o_sections[30] = "NHSHSSSEse"; ! 84: #endif ! 85: char o_shell[60] = SHELL; ! 86: char o_shiftwidth[3] = {8, 1, 255}; ! 87: #ifndef NO_SHOWMATCH ! 88: char o_showmatch[1] = {FALSE}; ! 89: #endif ! 90: #ifndef NO_SHOWMODE ! 91: char o_smd[1] = {FALSE}; ! 92: #endif ! 93: char o_sidescroll[3] = {8, 1, 40}; ! 94: char o_sync[1] = {NEEDSYNC}; ! 95: char o_tabstop[3] = {8, 1, 40}; ! 96: char o_term[30] = "?"; ! 97: char o_vbell[1] = {TRUE}; ! 98: char o_warn[1] = {TRUE}; ! 99: char o_wrapmargin[3] = {0, 0, 255}; ! 100: char o_wrapscan[1] = {TRUE}; ! 101: ! 102: ! 103: /* The following describes the names & types of all options */ ! 104: #define BOOL 0 ! 105: #define NUM 1 ! 106: #define STR 2 ! 107: #define SET 0x01 /* this option has had its value altered */ ! 108: #define CANSET 0x02 /* this option can be set at any time */ ! 109: #define RCSET 0x06 /* this option can be set in a .exrc file only */ ! 110: #define MR 0x40 /* does this option affect the way text is displayed? */ ! 111: struct ! 112: { ! 113: char *name; /* name of an option */ ! 114: char *nm; /* short name of an option */ ! 115: char type; /* type of an option */ ! 116: char flags; /* boolean: has this option been set? */ ! 117: char *value; /* value */ ! 118: } ! 119: opts[] = ! 120: { ! 121: /* name type flags redraw value */ ! 122: { "autoindent", "ai", BOOL, CANSET , o_autoindent }, ! 123: { "autoprint", "ap", BOOL, CANSET , o_autoprint }, ! 124: { "autowrite", "aw", BOOL, CANSET , o_autowrite }, ! 125: #ifndef NO_ERRLIST ! 126: { "cc", "cc", STR, CANSET , o_cc }, ! 127: #endif ! 128: #ifndef NO_CHARATTR ! 129: { "charattr", "ca", BOOL, CANSET | MR, o_charattr }, ! 130: #endif ! 131: { "columns", "co", NUM, SET , o_columns }, ! 132: #ifndef NO_DIGRAPH ! 133: { "digraph", "dig", BOOL, CANSET , o_digraph }, ! 134: #endif ! 135: { "directory", "dir", STR, RCSET , o_directory }, ! 136: { "edcompatible","ed", BOOL, CANSET , o_edcompatible }, ! 137: { "errorbells", "eb", BOOL, CANSET , o_errorbells }, ! 138: { "exrefresh", "er", BOOL, CANSET , o_exrefresh }, ! 139: #ifndef NO_DIGRAPH ! 140: { "flipcase", "fc", STR, CANSET , o_flipcase }, ! 141: #endif ! 142: #ifndef NO_SENTENCE ! 143: { "hideformat", "hf", BOOL, CANSET | MR, o_hideformat }, ! 144: #endif ! 145: { "ignorecase", "ic", BOOL, CANSET , o_ignorecase }, ! 146: #ifndef NO_EXTENSIONS ! 147: { "inputmode", "im", BOOL, CANSET , o_inputmode }, ! 148: #endif ! 149: { "keytime", "kt", NUM, CANSET , o_keytime }, ! 150: { "keywordprg", "kp", STR, CANSET , o_keywordprg }, ! 151: { "lines", "ls", NUM, SET , o_lines }, ! 152: { "list", "li", BOOL, CANSET | MR, o_list }, ! 153: #ifndef NO_MAGIC ! 154: { "magic", "ma", BOOL, CANSET , o_magic }, ! 155: #endif ! 156: #ifndef NO_ERRLIST ! 157: { "make", "mk", STR, CANSET , o_make }, ! 158: #endif ! 159: #ifndef NO_MODELINE ! 160: { "modeline", "ml", BOOL, CANSET , o_modeline }, ! 161: #endif ! 162: #ifndef NO_SENTENCE ! 163: { "paragraphs", "pa", STR, CANSET , o_paragraphs }, ! 164: #endif ! 165: #if MSDOS ! 166: { "pcbios", "pc", BOOL, SET , o_pcbios }, ! 167: #endif ! 168: { "readonly", "ro", BOOL, CANSET , o_readonly }, ! 169: { "report", "re", NUM, CANSET , o_report }, ! 170: { "scroll", "sc", NUM, CANSET , o_scroll }, ! 171: #ifndef NO_SENTENCE ! 172: { "sections", "se", STR, CANSET , o_sections }, ! 173: #endif ! 174: { "shell", "sh", STR, CANSET , o_shell }, ! 175: #ifndef NO_SHOWMATCH ! 176: { "showmatch", "sm", BOOL, CANSET , o_showmatch }, ! 177: #endif ! 178: #ifndef NO_SHOWMODE ! 179: { "showmode", "smd", BOOL, CANSET , o_smd }, ! 180: #endif ! 181: { "shiftwidth", "sw", NUM, CANSET , o_shiftwidth }, ! 182: { "sidescroll", "ss", NUM, CANSET , o_sidescroll }, ! 183: { "sync", "sy", BOOL, CANSET , o_sync }, ! 184: { "tabstop", "ts", NUM, CANSET | MR, o_tabstop }, ! 185: { "term", "te", STR, SET , o_term }, ! 186: { "vbell", "vb", BOOL, CANSET , o_vbell }, ! 187: { "warn", "wa", BOOL, CANSET , o_warn }, ! 188: { "wrapmargin", "wm", NUM, CANSET , o_wrapmargin }, ! 189: { "wrapscan", "ws", BOOL, CANSET , o_wrapscan }, ! 190: { NULL, NULL, 0, CANSET, NULL } ! 191: }; ! 192: ! 193: ! 194: /* This function initializes certain options from environment variables, etc. */ ! 195: void initopts() ! 196: { ! 197: char *val; ! 198: int i; ! 199: ! 200: /* set some stuff from environment variables */ ! 201: #if MSDOS ! 202: if (val = getenv("COMSPEC")) /* yes, ASSIGNMENT! */ ! 203: #else ! 204: if (val = getenv("SHELL")) /* yes, ASSIGNMENT! */ ! 205: #endif ! 206: { ! 207: strcpy(o_shell, val); ! 208: } ! 209: ! 210: #if ANY_UNIX ! 211: if (val = getenv("TERM")) /* yes, ASSIGNMENT! */ ! 212: { ! 213: strcpy(o_term, val); ! 214: } ! 215: #endif ! 216: #if TOS ! 217: val = "vt52"; ! 218: strcpy(o_term, val); ! 219: #endif ! 220: #if MSDOS ! 221: if ((val = getenv("TERM")) /* yes, ASSIGNMENT! */ ! 222: && strcmp(val, "pcbios")) ! 223: { ! 224: strcpy(o_term, val); ! 225: o_pcbios[0] = 0; ! 226: } ! 227: else ! 228: { ! 229: strcpy(o_term, "pcbios"); ! 230: o_pcbios[0] = 1; ! 231: } ! 232: #endif ! 233: #if MSDOS || TOS ! 234: if ((val = getenv("TMP")) /* yes, ASSIGNMENT! */ ! 235: || (val = getenv("TEMP"))) ! 236: strcpy(o_directory, val); ! 237: #endif ! 238: ! 239: *o_scroll = LINES / 2 - 1; ! 240: ! 241: /* disable the vbell option if we don't know how to do a vbell */ ! 242: if (!has_VB) ! 243: { ! 244: for (i = 0; opts[i].value != o_vbell; i++) ! 245: { ! 246: } ! 247: opts[i].flags &= ~CANSET; ! 248: *o_vbell = FALSE; ! 249: } ! 250: ! 251: #ifndef NO_DIGRAPH ! 252: # ifdef CS_LATIN1 ! 253: for (i = 0, val = o_flipcase; i < 32; i++) ! 254: { ! 255: /* leave out the multiply/divide symbols */ ! 256: if (i == 23) ! 257: continue; ! 258: ! 259: /* add upper/lowercase pair */ ! 260: *val++ = i + 0xc0; ! 261: *val++ = i + 0xe0; ! 262: } ! 263: *val = '\0'; ! 264: # endif /* CS_LATIN1 */ ! 265: #endif /* not NO_DIGRAPH */ ! 266: } ! 267: ! 268: /* This function lists the current values of all options */ ! 269: void dumpopts(all) ! 270: int all; /* boolean: dump all options, or just set ones? */ ! 271: { ! 272: #ifndef NO_OPTCOLS ! 273: int i, j, k; ! 274: char nbuf[4]; /* used for converting numbers to ASCII */ ! 275: int widths[5]; /* width of each column, including gap */ ! 276: int ncols; /* number of columns */ ! 277: int nrows; /* number of options per column */ ! 278: int nset; /* number of options to be output */ ! 279: int width; /* width of a particular option */ ! 280: int todump[50]; /* indicies of options to be dumped */ ! 281: ! 282: /* step 1: count the number of set options */ ! 283: for (nset = i = 0; opts[i].name; i++) ! 284: { ! 285: if (all || (opts[i].flags & SET)) ! 286: { ! 287: todump[nset++] = i; ! 288: } ! 289: } ! 290: ! 291: /* step two: try to use as many columns as possible */ ! 292: for (ncols = (nset > 5 ? 5 : nset); ncols > 1; ncols--) ! 293: { ! 294: /* how many would go in this column? */ ! 295: nrows = (nset + ncols - 1) / ncols; ! 296: ! 297: /* figure out the width of each column */ ! 298: for (i = 0; i < ncols; i++) ! 299: { ! 300: widths[i] = 0; ! 301: for (j = 0, k = nrows * i; j < nrows && k < nset; j++, k++) ! 302: { ! 303: /* figure out the width of a particular option */ ! 304: switch (opts[todump[k]].type) ! 305: { ! 306: case BOOL: ! 307: if (!*opts[todump[k]].value) ! 308: width = 2; ! 309: else ! 310: width = 0; ! 311: break; ! 312: ! 313: case STR: ! 314: width = 3 + strlen(opts[todump[k]].value); ! 315: if (width > MAXWIDTH) ! 316: width = MAXWIDTH; ! 317: break; ! 318: ! 319: case NUM: ! 320: width = 4; ! 321: break; ! 322: } ! 323: width += strlen(opts[todump[k]].name); ! 324: ! 325: /* if this is the widest so far, widen col */ ! 326: if (width > widths[i]) ! 327: { ! 328: widths[i] = width; ! 329: } ! 330: } ! 331: ! 332: } ! 333: ! 334: /* if the total width is narrow enough, then use it */ ! 335: for (width = -2, i = 0; i < ncols; i++) ! 336: { ! 337: width += widths[i] + 2; ! 338: } ! 339: if (width < COLS - 1) ! 340: { ! 341: break; ! 342: } ! 343: } ! 344: ! 345: /* step 3: output the columns */ ! 346: nrows = (nset + ncols - 1) / ncols; ! 347: for (i = 0; i < nrows; i++) ! 348: { ! 349: for (j = 0; j < ncols; j++) ! 350: { ! 351: /* if we hit the end of the options, quit */ ! 352: k = i + j * nrows; ! 353: if (k >= nset) ! 354: { ! 355: break; ! 356: } ! 357: ! 358: /* output this option's value */ ! 359: width = 0; ! 360: switch (opts[todump[k]].type) ! 361: { ! 362: case BOOL: ! 363: if (!*opts[todump[k]].value) ! 364: { ! 365: qaddch('n'); ! 366: qaddch('o'); ! 367: width = 2; ! 368: } ! 369: qaddstr(opts[todump[k]].name); ! 370: width += strlen(opts[todump[k]].name); ! 371: break; ! 372: ! 373: case NUM: ! 374: sprintf(nbuf, "%-3d", UCHAR(*opts[todump[k]].value)); ! 375: qaddstr(opts[todump[k]].name); ! 376: qaddch('='); ! 377: qaddstr(nbuf); ! 378: width = 4 + strlen(opts[todump[k]].name); ! 379: break; ! 380: ! 381: case STR: ! 382: qaddstr(opts[todump[k]].name); ! 383: qaddch('='); ! 384: qaddch('"'); ! 385: strcpy(tmpblk.c, opts[todump[k]].value); ! 386: width = 3 + strlen(tmpblk.c); ! 387: if (width > MAXWIDTH) ! 388: { ! 389: width = MAXWIDTH; ! 390: strcpy(tmpblk.c + MAXWIDTH - 6, "..."); ! 391: } ! 392: qaddstr(tmpblk.c); ! 393: qaddch('"'); ! 394: width += strlen(opts[todump[k]].name); ! 395: break; ! 396: } ! 397: ! 398: /* pad the field to the correct size */ ! 399: if (k + nrows <= nset) ! 400: { ! 401: while (width < widths[j] + 2) ! 402: { ! 403: qaddch(' '); ! 404: width++; ! 405: } ! 406: } ! 407: } ! 408: addch('\n'); ! 409: exrefresh(); ! 410: } ! 411: #else ! 412: int i; ! 413: int col; ! 414: char nbuf[4]; ! 415: ! 416: for (i = col = 0; opts[i].name; i++) ! 417: { ! 418: /* if not set and not all, ignore this option */ ! 419: if (!all && !(opts[i].flags & SET)) ! 420: { ! 421: continue; ! 422: } ! 423: ! 424: /* align this option in one of the columns */ ! 425: if (col > 52) ! 426: { ! 427: addch('\n'); ! 428: col = 0; ! 429: } ! 430: else if (col > 26) ! 431: { ! 432: while (col < 52) ! 433: { ! 434: qaddch(' '); ! 435: col++; ! 436: } ! 437: } ! 438: else if (col > 0) ! 439: { ! 440: while (col < 26) ! 441: { ! 442: qaddch(' '); ! 443: col++; ! 444: } ! 445: } ! 446: ! 447: switch (opts[i].type) ! 448: { ! 449: case BOOL: ! 450: if (!*opts[i].value) ! 451: { ! 452: qaddch('n'); ! 453: qaddch('o'); ! 454: col += 2; ! 455: } ! 456: qaddstr(opts[i].name); ! 457: col += strlen(opts[i].name); ! 458: break; ! 459: ! 460: case NUM: ! 461: sprintf(nbuf, "%-3d", UCHAR(*opts[i].value)); ! 462: qaddstr(opts[i].name); ! 463: qaddch('='); ! 464: qaddstr(nbuf); ! 465: col += 4 + strlen(opts[i].name); ! 466: break; ! 467: ! 468: case STR: ! 469: qaddstr(opts[i].name); ! 470: qaddch('='); ! 471: qaddch('"'); ! 472: qaddstr(opts[i].value); ! 473: qaddch('"'); ! 474: col += 3 + strlen(opts[i].name) + strlen(opts[i].value); ! 475: break; ! 476: } ! 477: exrefresh(); ! 478: } ! 479: if (col > 0) ! 480: { ! 481: addch('\n'); ! 482: exrefresh(); ! 483: } ! 484: #endif ! 485: } ! 486: ! 487: #ifndef NO_MKEXRC ! 488: /* This function saves the current configuarion of options to a file */ ! 489: void saveopts(fd) ! 490: int fd; /* file descriptor to write to */ ! 491: { ! 492: int i; ! 493: char buf[256], *pos; ! 494: ! 495: /* write each set options */ ! 496: for (i = 0; opts[i].name; i++) ! 497: { ! 498: /* if unset or unsettable, ignore this option */ ! 499: if (!(opts[i].flags & SET) || !(opts[i].flags & CANSET)) ! 500: { ! 501: continue; ! 502: } ! 503: ! 504: strcpy(buf, "set "); ! 505: pos = &buf[4]; ! 506: switch (opts[i].type) ! 507: { ! 508: case BOOL: ! 509: if (!*opts[i].value) ! 510: { ! 511: *pos++='n'; ! 512: *pos++='o'; ! 513: } ! 514: strcpy(pos, opts[i].name); ! 515: strcat(pos, "\n"); ! 516: break; ! 517: ! 518: case NUM: ! 519: sprintf(pos, "%s=%-3d\n", opts[i].name, *opts[i].value & 0xff); ! 520: break; ! 521: ! 522: case STR: ! 523: sprintf(pos, "%s=\"%s\"\n", opts[i].name, opts[i].value); ! 524: break; ! 525: } ! 526: twrite(fd, buf, strlen(buf)); ! 527: } ! 528: } ! 529: #endif ! 530: ! 531: ! 532: /* This function changes the values of one or more options. */ ! 533: void setopts(assignments) ! 534: char *assignments; /* a string containing option assignments */ ! 535: { ! 536: char *name; /* name of variable in assignments */ ! 537: char *value; /* value of the variable */ ! 538: char *scan; /* used for moving through strings */ ! 539: int i, j; ! 540: ! 541: /* for each assignment... */ ! 542: for (name = assignments; *name; ) ! 543: { ! 544: /* skip whitespace */ ! 545: if (*name == ' ' || *name == '\t') ! 546: { ! 547: name++; ! 548: continue; ! 549: } ! 550: ! 551: /* find the value, if any */ ! 552: for (scan = name; *scan >= 'a' && *scan <= 'z'; scan++) ! 553: { ! 554: } ! 555: if (*scan == '=') ! 556: { ! 557: *scan++ = '\0'; ! 558: if (*scan == '"') ! 559: { ! 560: value = ++scan; ! 561: while (*scan && *scan != '"') ! 562: { ! 563: scan++; ! 564: } ! 565: if (*scan) ! 566: { ! 567: *scan++ = '\0'; ! 568: } ! 569: } ! 570: else ! 571: { ! 572: value = scan; ! 573: while (*scan && *scan != ' ' && *scan != '\t') ! 574: { ! 575: scan++; ! 576: } ! 577: if (*scan) ! 578: { ! 579: *scan++ = '\0'; ! 580: } ! 581: } ! 582: } ! 583: else ! 584: { ! 585: if (*scan) ! 586: { ! 587: *scan++ = '\0'; ! 588: } ! 589: value = NULL; ! 590: if (name[0] == 'n' && name[1] == 'o') ! 591: { ! 592: name += 2; ! 593: } ! 594: } ! 595: ! 596: /* find the variable */ ! 597: for (i = 0; ! 598: opts[i].name && strcmp(opts[i].name, name) && strcmp(opts[i].nm, name); ! 599: i++) ! 600: { ! 601: } ! 602: ! 603: /* change the variable */ ! 604: if (!opts[i].name) ! 605: { ! 606: msg("invalid option name \"%s\"", name); ! 607: } ! 608: else if ((opts[i].flags & CANSET) != CANSET) ! 609: { ! 610: msg("option \"%s\" can't be altered", name); ! 611: } ! 612: else if ((opts[i].flags & RCSET) != CANSET && nlines >= 1L) ! 613: { ! 614: msg("option \"%s\" can only be set in a %s file", name, EXRC); ! 615: } ! 616: else if (value) ! 617: { ! 618: switch (opts[i].type) ! 619: { ! 620: case BOOL: ! 621: msg("option \"[no]%s\" is boolean", name); ! 622: break; ! 623: ! 624: case NUM: ! 625: j = atoi(value); ! 626: if (j == 0 && *value != '0') ! 627: { ! 628: msg("option \"%s\" must have a numeric value", name); ! 629: } ! 630: else if (j < opts[i].value[1] || j > (opts[i].value[2] & 0xff)) ! 631: { ! 632: msg("option \"%s\" must have a value between %d and %d", ! 633: name, opts[i].value[1], opts[i].value[2] & 0xff); ! 634: } ! 635: else ! 636: { ! 637: *opts[i].value = atoi(value); ! 638: opts[i].flags |= SET; ! 639: } ! 640: break; ! 641: ! 642: case STR: ! 643: strcpy(opts[i].value, value); ! 644: opts[i].flags |= SET; ! 645: break; ! 646: } ! 647: if (opts[i].flags & MR) ! 648: { ! 649: mustredraw = TRUE; ! 650: } ! 651: } ! 652: else /* valid option, no value */ ! 653: { ! 654: if (opts[i].type == BOOL) ! 655: { ! 656: *opts[i].value = (name[-1] != 'o'); ! 657: opts[i].flags |= SET; ! 658: if (opts[i].flags & MR) ! 659: { ! 660: mustredraw = TRUE; ! 661: } ! 662: } ! 663: else ! 664: { ! 665: msg("option \"%s\" must be given a value", name); ! 666: } ! 667: } ! 668: ! 669: /* move on to the next option */ ! 670: name = scan; ! 671: } ! 672: ! 673: /* special processing ... */ ! 674: ! 675: /* if "readonly" then set the READONLY flag for this file */ ! 676: if (*o_readonly) ! 677: { ! 678: setflag(file, READONLY); ! 679: } ! 680: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.