home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 5 / FreshFish_July-August1994.bin / bbs / util / vim-2.0.lha / Vim-2.0 / src / param.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-15  |  22.9 KB  |  849 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  * VIM - Vi IMproved
  4.  *
  5.  * Code Contributions By:    Bram Moolenaar            mool@oce.nl
  6.  *                            Tim Thompson            twitch!tjt
  7.  *                            Tony Andrews            onecom!wldrdg!tony 
  8.  *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  9.  */
  10.  
  11. /*
  12.  * Code to handle user-settable parameters. This is all pretty much table-
  13.  * driven. To add a new parameter, put it in the params array, and add a
  14.  * variable for it in param.h. If it's a numeric parameter, add any necessary
  15.  * bounds checks to doset().
  16.  */
  17.  
  18. #include "vim.h"
  19. #include "globals.h"
  20. #include "proto.h"
  21. #include "param.h"
  22.  
  23. struct param
  24. {
  25.     char        *fullname;        /* full parameter name */
  26.     char        *shortname;     /* permissible abbreviation */
  27.     int         flags;            /* see below */
  28.     char        *var;            /* pointer to variable */
  29. };
  30.  
  31. /*
  32.  * Flags
  33.  */
  34. #define P_BOOL            0x01    /* the parameter is boolean */
  35. #define P_NUM            0x02    /* the parameter is numeric */
  36. #define P_STRING        0x04    /* the parameter is a string */
  37. #define P_CHANGED        0x08    /* the parameter has been changed */
  38. #define P_EXPAND        0x10    /* environment expansion */
  39.  
  40. /*
  41.  * The param structure is initialized here.
  42.  * The order of the parameters should be alfabetic
  43.  * The parameters with a NULL variable are 'hidden': a set command for
  44.  * them is ignored and they are not printed.
  45.  */
  46. struct param params[] =
  47. {
  48.         {"autoindent",    "ai",    P_BOOL,        (char *)&p_ai},
  49.         {"autoprint",    "ap",    P_BOOL,        (char *)NULL},
  50.         {"autowrite",    "aw",    P_BOOL,        (char *)&p_aw},
  51.         {"backspace",    "bs",    P_NUM,        (char *)&p_bs},
  52.         {"backup",        "bk",    P_BOOL,        (char *)&p_bk},
  53. #ifdef UNIX
  54.          {"backupdir",    "bdir",    P_STRING|P_EXPAND,    (char *)&p_bdir},
  55. #endif
  56.         {"beautify",    "bf",    P_BOOL,        (char *)NULL},
  57.         {"binary",        "bin",    P_BOOL,        (char *)&p_bin},
  58. #ifdef MSDOS
  59.         {"bioskey",        "biosk",P_BOOL,        (char *)&p_biosk},
  60. #endif
  61.         {"columns",        "co",    P_NUM,        (char *)&Columns},
  62.         {"compatible",    "cp",    P_BOOL,        (char *)&p_cp},
  63. #ifdef DIGRAPHS
  64.         {"digraph",        "dg",    P_BOOL,        (char *)&p_dg},
  65. #endif /* DIGRAPHS */
  66.          {"directory",    "dir",    P_STRING|P_EXPAND,    (char *)&p_dir},
  67.         {"edcompatible",NULL,    P_BOOL,        (char *)&p_ed},
  68.         {"equalprg",    "ep",      P_STRING|P_EXPAND,    (char *)&p_ep},
  69.         {"errorbells",    "eb",    P_BOOL,        (char *)&p_eb},
  70.         {"errorfile",    "ef",      P_STRING|P_EXPAND,    (char *)&p_ef},
  71.         {"errorformat",    "efm",     P_STRING,    (char *)&p_efm},
  72.         {"esckeys",        "ek",    P_BOOL,        (char *)&p_ek},
  73.         {"expandtab",    "et",    P_BOOL,        (char *)&p_et},
  74.         {"exrc",        NULL,    P_BOOL,        (char *)&p_exrc},
  75.         {"formatprg",    "fp",      P_STRING|P_EXPAND,    (char *)&p_fp},
  76.         {"graphic",        "gr",    P_BOOL,        (char *)&p_gr},
  77.         {"hardtabs",    "ht",    P_NUM,        (char *)NULL},
  78.         {"helpfile",    "hf",      P_STRING|P_EXPAND,    (char *)&p_hf},
  79.         {"history",     "hi",     P_NUM,        (char *)&p_hi},
  80.         {"ignorecase",    "ic",    P_BOOL,        (char *)&p_ic},
  81.         {"insertmode",    "im",    P_BOOL,        (char *)&p_im},
  82.         {"joinspaces",     "js",    P_BOOL,        (char *)&p_js},
  83.         {"keywordprg",    "kp",      P_STRING|P_EXPAND,    (char *)&p_kp},
  84.         {"lines",        NULL,     P_NUM,        (char *)&Rows},
  85.         {"lisp",        NULL,    P_BOOL,        (char *)NULL},
  86.         {"list",        NULL,    P_BOOL,        (char *)&p_list},
  87.         {"magic",        NULL,    P_BOOL,        (char *)&p_magic},
  88.         {"makeprg",        "mp",      P_STRING|P_EXPAND,    (char *)&p_mp},
  89.         {"mesg",        NULL,    P_BOOL,        (char *)NULL},
  90.         {"modeline",    "ml",    P_BOOL,        (char *)&p_ml},
  91.         {"modelines",    "mls",    P_NUM,        (char *)&p_mls},
  92.         {"number",        "nu",    P_BOOL,        (char *)&p_nu},
  93.         {"open",        NULL,    P_BOOL,        (char *)NULL},
  94.         {"optimize",    "opt",    P_BOOL,        (char *)NULL},
  95.         {"paragraphs",    "para",    P_STRING,    (char *)&p_para},
  96.         {"paste",        NULL,    P_BOOL,        (char *)&p_paste},
  97.         {"prompt",        NULL,    P_BOOL,        (char *)NULL},
  98.         {"readonly",    "ro",    P_BOOL,        (char *)&p_ro},
  99.         {"redraw",        NULL,    P_BOOL,        (char *)NULL},
  100.         {"remap",        NULL,    P_BOOL,        (char *)&p_remap},
  101.         {"report",        NULL,    P_NUM,        (char *)&p_report},
  102.         {"revins",        "ri",    P_BOOL,        (char *)&p_ri},
  103.         {"ruler",        "ru",    P_BOOL,        (char *)&p_ru},
  104.         {"secure",        NULL,    P_BOOL,        (char *)&p_secure},
  105.         {"scroll",        NULL,     P_NUM,        (char *)&p_scroll},
  106.         {"scrolljump",    "sj",     P_NUM,        (char *)&p_sj},
  107.         {"sections",    "sect",    P_STRING,    (char *)&p_sections},
  108.         {"shell",        "sh",    P_STRING|P_EXPAND,    (char *)&p_sh},
  109.         {"shelltype",    "st",    P_NUM,        (char *)&p_st},
  110.         {"shiftround",    "sr",    P_BOOL,        (char *)&p_sr},
  111.         {"shiftwidth",    "sw",    P_NUM,        (char *)&p_sw},
  112. #ifndef MSDOS
  113.         {"shortname",    "sn",    P_BOOL,        (char *)&p_sn},
  114. #endif
  115.         {"showcmd",        "sc",    P_BOOL,        (char *)&p_sc},
  116.         {"showmatch",    "sm",    P_BOOL,        (char *)&p_sm},
  117.         {"showmode",    "smd",    P_BOOL,        (char *)&p_smd},
  118.         {"sidescroll",    "ss",    P_NUM,        (char *)&p_ss},
  119.         {"slowopen",    "slow",    P_BOOL,        (char *)NULL},
  120.         {"smartindent", "si",    P_BOOL,        (char *)&p_si},
  121.         {"sourceany", NULL,    P_BOOL,        (char *)NULL},
  122.         {"suffixes",    "su",    P_STRING,    (char *)&p_su},
  123.         {"tabstop",     "ts",    P_NUM,        (char *)&p_ts},
  124.         {"taglength",    "tl",    P_NUM,        (char *)&p_tl},
  125.         {"tags",        NULL,    P_STRING|P_EXPAND,    (char *)&p_tags},
  126.         {"term",        NULL,    P_STRING|P_EXPAND,    (char *)&term_strings.t_name},
  127.         {"terse",        NULL,    P_BOOL,        (char *)NULL},
  128.         {"textauto",    "ta",    P_BOOL,        (char *)&p_ta},
  129.         {"textmode",    "tx",    P_BOOL,        (char *)&p_tx},
  130.         {"textwidth",    "tw",    P_NUM,        (char *)&p_tw},
  131.         {"tildeop",     "to",    P_BOOL,        (char *)&p_to},
  132.         {"timeout",     NULL,    P_BOOL,        (char *)&p_timeout},
  133.         {"timeoutlen",    "tm",    P_NUM,        (char *)&p_tm},
  134.         {"ttimeout",     NULL,    P_BOOL,        (char *)&p_ttimeout},
  135.         {"ttytype",        NULL,    P_STRING,    (char *)NULL},
  136.         {"undolevels",    "ul",    P_NUM,        (char *)&p_ul},
  137.         {"updatecount",    "uc",    P_NUM,        (char *)&p_uc},
  138.         {"updatetime",    "ut",    P_NUM,        (char *)&p_ut},
  139.         {"visualbell",    "vb",    P_BOOL,        (char *)&p_vb},
  140.         {"warn",        NULL,    P_BOOL,        (char *)&p_warn},
  141.         {"wildchar",    "wc",     P_NUM,        (char *)&p_wc},
  142.         {"window",        NULL,     P_NUM,        (char *)NULL},
  143.         {"w300",        NULL,     P_NUM,        (char *)NULL},
  144.         {"w1200",        NULL,     P_NUM,        (char *)NULL},
  145.         {"w9600",        NULL,     P_NUM,        (char *)NULL},
  146.         {"wrap",        NULL,    P_BOOL,        (char *)&p_wrap},
  147.         {"wrapscan",    "ws",    P_BOOL,        (char *)&p_ws},
  148.         {"wrapmargin",    "wm",    P_NUM,        (char *)&p_wm},
  149.         {"writeany",    "wa",    P_BOOL,        (char *)&p_wa},
  150.         {"writebackup",    "wb",    P_BOOL,        (char *)&p_wb},
  151.         {"yankendofline", "ye",    P_BOOL,        (char *)&p_ye},
  152.  
  153. /* terminal output codes */
  154.         {"t_el",        NULL,    P_STRING,    (char *)&term_strings.t_el},
  155.         {"t_il",        NULL,    P_STRING,    (char *)&term_strings.t_il},
  156.         {"t_cil",        NULL,    P_STRING,    (char *)&term_strings.t_cil},
  157.         {"t_dl",        NULL,    P_STRING,    (char *)&term_strings.t_dl},
  158.         {"t_cdl",        NULL,    P_STRING,    (char *)&term_strings.t_cdl},
  159.         {"t_ed",        NULL,    P_STRING,    (char *)&term_strings.t_ed},
  160.         {"t_ci",        NULL,    P_STRING,    (char *)&term_strings.t_ci},
  161.         {"t_cv",        NULL,    P_STRING,    (char *)&term_strings.t_cv},
  162.         {"t_tp",        NULL,    P_STRING,    (char *)&term_strings.t_tp},
  163.         {"t_ti",        NULL,    P_STRING,    (char *)&term_strings.t_ti},
  164.         {"t_cm",        NULL,    P_STRING,    (char *)&term_strings.t_cm},
  165.         {"t_sr",        NULL,    P_STRING,    (char *)&term_strings.t_sr},
  166.         {"t_cri",        NULL,    P_STRING,    (char *)&term_strings.t_cri},
  167.         {"t_vb",        NULL,    P_STRING,    (char *)&term_strings.t_vb},
  168.         {"t_ks",        NULL,    P_STRING,    (char *)&term_strings.t_ks},
  169.         {"t_ke",        NULL,    P_STRING,    (char *)&term_strings.t_ke},
  170.         {"t_ts",        NULL,    P_STRING,    (char *)&term_strings.t_ts},
  171.         {"t_te",        NULL,    P_STRING,    (char *)&term_strings.t_te},
  172.  
  173. /* terminal key codes */
  174.         {"t_ku",        NULL,    P_STRING,    (char *)&term_strings.t_ku},
  175.         {"t_kd",        NULL,    P_STRING,    (char *)&term_strings.t_kd},
  176.         {"t_kr",        NULL,    P_STRING,    (char *)&term_strings.t_kr},
  177.         {"t_kl",        NULL,    P_STRING,    (char *)&term_strings.t_kl},
  178.         {"t_sku",        NULL,    P_STRING,    (char *)&term_strings.t_sku},
  179.         {"t_skd",        NULL,    P_STRING,    (char *)&term_strings.t_skd},
  180.         {"t_skr",        NULL,    P_STRING,    (char *)&term_strings.t_skr},
  181.         {"t_skl",        NULL,    P_STRING,    (char *)&term_strings.t_skl},
  182.         {"t_f1",        NULL,    P_STRING,    (char *)&term_strings.t_f1},
  183.         {"t_f2",        NULL,    P_STRING,    (char *)&term_strings.t_f2},
  184.         {"t_f3",        NULL,    P_STRING,    (char *)&term_strings.t_f3},
  185.         {"t_f4",        NULL,    P_STRING,    (char *)&term_strings.t_f4},
  186.         {"t_f5",        NULL,    P_STRING,    (char *)&term_strings.t_f5},
  187.         {"t_f6",        NULL,    P_STRING,    (char *)&term_strings.t_f6},
  188.         {"t_f7",        NULL,    P_STRING,    (char *)&term_strings.t_f7},
  189.         {"t_f8",        NULL,    P_STRING,    (char *)&term_strings.t_f8},
  190.         {"t_f9",        NULL,    P_STRING,    (char *)&term_strings.t_f9},
  191.         {"t_f10",        NULL,    P_STRING,    (char *)&term_strings.t_f10},
  192.         {"t_sf1",        NULL,    P_STRING,    (char *)&term_strings.t_sf1},
  193.         {"t_sf2",        NULL,    P_STRING,    (char *)&term_strings.t_sf2},
  194.         {"t_sf3",        NULL,    P_STRING,    (char *)&term_strings.t_sf3},
  195.         {"t_sf4",        NULL,    P_STRING,    (char *)&term_strings.t_sf4},
  196.         {"t_sf5",        NULL,    P_STRING,    (char *)&term_strings.t_sf5},
  197.         {"t_sf6",        NULL,    P_STRING,    (char *)&term_strings.t_sf6},
  198.         {"t_sf7",        NULL,    P_STRING,    (char *)&term_strings.t_sf7},
  199.         {"t_sf8",        NULL,    P_STRING,    (char *)&term_strings.t_sf8},
  200.         {"t_sf9",        NULL,    P_STRING,    (char *)&term_strings.t_sf9},
  201.         {"t_sf10",        NULL,    P_STRING,    (char *)&term_strings.t_sf10},
  202.         {"t_help",        NULL,    P_STRING,    (char *)&term_strings.t_help},
  203.         {"t_undo",        NULL,    P_STRING,    (char *)&term_strings.t_undo},
  204.         {NULL, NULL, 0, NULL}            /* end marker */
  205. };
  206.  
  207. static void param_expand __ARGS((int, int));
  208. static int findparam __ARGS((char *));
  209. static void    showparams __ARGS((int));
  210. static void showonep __ARGS((struct param *));
  211. static int  istermparam __ARGS((struct param *));
  212.  
  213. /*
  214.  * Initialize the shell parameter and scroll size.
  215.  */
  216.     void
  217. set_init()
  218. {
  219.     char    *p;
  220.     int        i;
  221.  
  222.     if ((p = (char *)vimgetenv("SHELL")) != NULL
  223. #ifdef MSDOS
  224.             || (p = (char *)vimgetenv("COMSPEC")) != NULL
  225. #endif
  226.                                                             )
  227.     {
  228.         p = strsave(p);
  229.         if (p != NULL)        /* we don't want a NULL */
  230.             p_sh = p;
  231.     }
  232.  
  233.     p_scroll = (Rows >> 1);
  234.     comp_col();
  235.  
  236.     /*
  237.      * expand environment variables in some string options
  238.      */
  239.     for (i = 0; params[i].fullname != NULL; i++)
  240.         param_expand(i, FALSE);
  241. }
  242.  
  243. /*
  244.  * parse 'arg' for option settings
  245.  * 'arg' may be IObuff, but only when no errors can be present.
  246.  */
  247.     int
  248. doset(arg)
  249.     char        *arg;    /* parameter string (may be written to!) */
  250. {
  251.     register int i;
  252.     char        *s;
  253.     char        *errmsg;
  254.     char        *startarg;
  255.     int            prefix;    /* 0: nothing, 1: "no", 2: "inv" in front of name */
  256.     int         nextchar;
  257.     int         len;
  258.     int         flags;
  259.     long        value;
  260.     long        olduc = p_uc;        /* remember old update count */
  261.     long        oldRows = Rows;        /* remember old Rows */
  262.     int            errcnt = 0;            /* number of errornous entries */
  263.     static long    save_tw = 0;        /* saved options for 'paste' */
  264.     static int    save_ai = 0;
  265.     static int    save_si = 0;
  266.     static int    save_sm = 0;
  267.     static int    save_ru = 0;
  268.     static int    save_ri = 0;
  269.     static int    did_paste = FALSE;    /* when TRUE saved values have been set */
  270.     int            do_wait = FALSE;    /* call wait_return() at the end */
  271.     int            did_show = FALSE;    /* already showed one value */
  272.  
  273.     if (*arg == NUL)
  274.     {
  275.         showparams(0);
  276.         return 0;
  277.     }
  278.  
  279.     while (*arg)        /* loop to process all parameters */
  280.     {
  281.         errmsg = NULL;
  282.         startarg = arg;        /* remember for error message */
  283.         if (strncmp(arg, "all", (size_t)3) == 0)
  284.             showparams(1);
  285.         else if (strncmp(arg, "termcap", (size_t)7) == 0)
  286.             showparams(2);
  287.         else
  288.         {
  289.             prefix = 1;
  290.             if (strncmp(arg, "no", (size_t)2) == 0)
  291.             {
  292.                 prefix = 0;
  293.                 arg += 2;
  294.             }
  295.             else if (strncmp(arg, "inv", (size_t)3) == 0)
  296.             {
  297.                 prefix = 2;
  298.                 arg += 3;
  299.             }
  300.                 /* find end of name */
  301.             for (len = 0; isalnum(arg[len]) || arg[len] == '_'; ++len)
  302.                 ;
  303.             nextchar = arg[len];
  304.             arg[len] = 0;                                /* name ends with 0 */
  305.             i = findparam(arg);
  306.             arg[len] = nextchar;                        /* restore nextchar */
  307.  
  308.             if (i == -1)        /* found a mismatch: skip the rest */
  309.             {
  310.                 errmsg = "Unknown option";
  311.                 goto skip;
  312.             }
  313.  
  314.             if (!params[i].var)            /* hidden option */
  315.                 goto skip;
  316.  
  317.             flags = params[i].flags;
  318.             /*
  319.              * allow '=' and ':' as MSDOS command.com allows only one
  320.              * '=' character per "set" command line. grrr. (jw)
  321.              */
  322.             if (nextchar == '?' || 
  323.                 (prefix == 1 && nextchar != '=' &&
  324.                  nextchar != ':' && !(flags & P_BOOL)))
  325.             {                                        /* print value */
  326.                 if (did_show)
  327.                 {
  328.                     outchar('\n');            /* cursor below last one */
  329.                     do_wait = TRUE;            /* have to call wait_return() */
  330.                 }
  331.                 else
  332.                 {
  333.                     gotocmdline(TRUE, NUL);    /* cursor at status line */
  334.                     did_show = TRUE;        /* remember that we did a line */
  335.                 }
  336.                 showonep(¶ms[i]);
  337.  
  338.                     /* check if the message is too long to fit in one line */
  339.                 if ((flags & P_STRING) && strlen(params[i].fullname) +
  340.                             (*(char **)(params[i].var) == NULL ? 0 :
  341.                             strsize(*(char **)(params[i].var))) + 1 >= (unsigned)sc_col)
  342.                     do_wait = TRUE;
  343.             }
  344.             else
  345.             {
  346.                 if (nextchar != NUL && strchr("=: \t", nextchar) == NULL)
  347.                 {
  348.                     errmsg = e_invarg;
  349.                     goto skip;
  350.                 }
  351.                 else if (flags & P_BOOL)                    /* boolean */
  352.                 {
  353.                         if (nextchar == '=' || nextchar == ':')
  354.                         {
  355.                             errmsg = e_invarg;
  356.                             goto skip;
  357.                         }
  358.                         /*
  359.                          * in secure mode, setting of the secure option is not allowed
  360.                          */
  361.                         if (secure && (int *)params[i].var == &p_secure)
  362.                         {
  363.                             errmsg = "not allowed here";
  364.                             goto skip;
  365.                         }
  366.                         if (prefix == 2)
  367.                             *(int *)(params[i].var) ^= 1;    /* invert it */
  368.                         else
  369.                             *(int *)(params[i].var) = prefix;
  370.                             /* handle compatbile option here */
  371.                         if ((int *)params[i].var == &p_cp && p_cp)
  372.                         {
  373.                             p_bs = 0;        /* normal backspace */
  374.                             p_bk = 0;        /* no backup file */
  375. #ifdef DIGRAPHS
  376.                             p_dg = 0;        /* no digraphs */
  377. #endif /* DIGRAPHS */
  378.                             p_ek = 0;        /* no ESC keys in insert mode */
  379.                             p_et = 0;        /* no expansion of tabs */
  380.                             p_hi = 0;        /* no history */
  381.                             p_im = 0;        /* do not start in insert mode */
  382.                             p_js = 1;        /* insert 2 spaces after period */
  383.                             p_ml = 0;        /* no modelines */
  384.                             p_ru = 0;        /* no ruler */
  385.                             p_ri = 0;        /* no reverse insert */
  386.                             p_sj = 1;        /* no scrolljump */
  387.                             p_sr = 0;        /* do not round indent to shiftwidth */
  388.                             p_sc = 0;        /* no showcommand */
  389.                             p_smd = 0;        /* no showmode */
  390.                             p_si = 0;        /* no smartindent */
  391.                             p_ta = 0;        /* no automatic textmode detection */
  392.                             p_tw = 0;        /* no automatic line wrap */
  393.                             p_to = 0;        /* no tilde operator */
  394.                             p_ttimeout = 0;    /* no terminal timeout */
  395.                             p_ul = 0;        /* no multilevel undo */
  396.                             p_uc = 0;        /* no autoscript file */
  397.                             p_wb = 0;        /* no backup file */
  398.                             if (p_wc == TAB)
  399.                                 p_wc = Ctrl('E');    /* normal use for TAB */
  400.                             p_ye = 0;        /* no yank to end of line */
  401.                         }
  402.                         if ((int *)params[i].var == &p_bin && p_bin)    /* handle bin */
  403.                         {
  404.                             p_tw = 0;        /* no automatic line wrap */
  405.                             p_tx = 0;        /* no text mode */
  406.                             p_ta = 0;        /* no text auto */
  407.                             p_ml = 0;        /* no modelines */
  408.                             p_et = 0;        /* no expandtab */
  409.                         }
  410.                         if ((int *)params[i].var == &p_paste)    /* handle paste here */
  411.                         {
  412.                             if (p_paste)
  413.                             {
  414.                                 save_tw = p_tw;        /* save current values */
  415.                                 save_ai = p_ai;
  416.                                 save_si = p_si;
  417.                                 save_sm = p_sm;
  418.                                 save_ru = p_ru;
  419.                                 save_ri = p_ri;
  420.                                 p_tw = 0;            /* textwidth is 0 */
  421.                                 p_ai = 0;            /* no auto-indent */
  422.                                 p_si = 0;            /* no smart-indent */
  423.                                 p_sm = 0;            /* no showmatch */
  424.                                 p_ru = 0;            /* no ruler */
  425.                                 p_ri = 0;            /* no reverse insert */
  426.                                 did_paste = TRUE;
  427.                             }
  428.                             else if (did_paste)        /* restore old values */
  429.                             {
  430.                                 p_tw = save_tw;
  431.                                 p_ai = save_ai;
  432.                                 p_si = save_si;
  433.                                 p_sm = save_sm;
  434.                                 p_ru = save_ru;
  435.                                 p_ri = save_ri;
  436.                             }
  437.                         }
  438.                 }
  439.                 else                                /* numeric or string */
  440.                 {
  441.                     if ((nextchar != '=' && nextchar != ':') || prefix != 1)
  442.                     {
  443.                         errmsg = e_invarg;
  444.                         goto skip;
  445.                     }
  446.                     if (flags & P_NUM)                /* numeric */
  447.                     {
  448.                         value = atol(arg + len + 1);
  449.                             /* wrapmargin is translated into textwidth */
  450.                         if ((long *)params[i].var == &p_wm)
  451.                         {
  452.                             if (value == 0)        /* switch it off */
  453.                                 p_tw = 0;
  454.                             else
  455.                             {
  456.                                 if (value >= (int)Columns)
  457.                                     value = (int)Columns - 1;
  458.                                 p_tw = Columns - value;
  459.                             }
  460.                         }
  461.                         *(long *)(params[i].var) = value;
  462.                     }
  463.                     else                            /* string */
  464.                     {
  465.                         arg += len + 1;        /* jump to after the '=' */
  466.                         prefix = *arg;        /* remember first char of arg */
  467.                         s = alloc((unsigned)(strlen(arg) + 1)); /* get a bit too much */
  468.                         if (s == NULL)
  469.                             break;
  470.                         if (flags & P_CHANGED)
  471.                             free(*(char **)(params[i].var));
  472.                         *(char **)(params[i].var) = s;
  473.                                     /* copy the string */
  474.                         while (*arg && *arg != ' ')
  475.                         {
  476.                             if (*arg == '\\' && *(arg + 1)) /* skip over escaped chars */
  477.                                     ++arg;
  478.                             *s++ = *arg++;
  479.                         }
  480.                         *s = NUL;
  481.                         if (prefix == '$')
  482.                             param_expand(i, TRUE);    /* expand environment variables */
  483.                         /*
  484.                          * options that need some action
  485.                          * to perform when changed (jw)
  486.                          */
  487.                         if (params[i].var == (char *)&term_strings.t_name)
  488.                             set_term(term_strings.t_name);
  489.                         else if (istermparam(¶ms[i]))
  490.                         {
  491.                             ttest(FALSE);
  492.                             if (params[i].var == (char *)&term_strings.t_tp)
  493.                             {
  494.                                 outstr(T_TP);
  495.                                 updateScreen(CLEAR);
  496.                             }
  497.                         }
  498.                     }
  499.                 }
  500.                 params[i].flags |= P_CHANGED;
  501.             }
  502.         }
  503.  
  504. skip:
  505.         /*
  506.          * Check the bounds for numeric parameters here
  507.          */
  508.         if (Rows < 2)
  509.         {
  510.             Rows = 2;
  511.             errmsg = "Need at least 2 lines";
  512.         }
  513.         /*
  514.          * If the screenheight has been changed, assume it is the physical
  515.          * screenheight, set Rows_max.
  516.          */
  517.         if (oldRows != Rows)
  518.         {
  519.             Rows_max = Rows;
  520. #ifdef MSDOS
  521.             set_window();        /* active window may have changed */
  522. #endif
  523.         }
  524.  
  525.         if (p_ts <= 0)
  526.         {
  527.             errmsg = e_positive;
  528.             p_ts = 8;
  529.         }
  530.         if (p_tm < 0)
  531.         {
  532.             errmsg = e_positive;
  533.             p_tm = 0;
  534.         }
  535.         if (p_scroll <= 0 || p_scroll > Rows)
  536.         {
  537.             if (p_scroll != 0)
  538.                 errmsg = e_scroll;
  539.             p_scroll = Rows >> 1;
  540.         }
  541.         if (p_report < 0)
  542.         {
  543.             errmsg = e_positive;
  544.             p_report = 1;
  545.         }
  546.         if (p_sj < 0 || p_sj >= Rows)
  547.         {
  548.             errmsg = e_scroll;
  549.             p_sj = 1;
  550.         }
  551.         if (p_uc < 0)
  552.         {
  553.             errmsg = e_positive;
  554.             p_uc = 100;
  555.         }
  556.         if (p_ut < 0)
  557.         {
  558.             errmsg = e_positive;
  559.             p_ut = 2000;
  560.         }
  561.         if (p_ss < 0)
  562.         {
  563.             errmsg = e_positive;
  564.             p_ss = 0;
  565.         }
  566.         if (errmsg)
  567.         {
  568.             strcpy(IObuff, errmsg);
  569.             strcat(IObuff, ": ");
  570.             s = IObuff + strlen(IObuff);
  571.             while (*startarg && !isspace(*startarg))
  572.                 *s++ = *startarg++;
  573.             *s = NUL;
  574.             emsg(IObuff);
  575.             arg = startarg;        /* skip to next argument */
  576.             ++errcnt;            /* count number of errors */
  577.         }
  578.         skiptospace(&arg);                /* skip to next white space */
  579.         skipspace(&arg);                /* skip spaces */
  580.     }
  581.  
  582.     if (p_uc == 0 && olduc != 0)        /* p_uc changed from on to off */
  583.         stopscript();
  584.     if (p_uc > 0 && olduc == 0)            /* p_uc changed from off to on */
  585.         startscript();
  586.     comp_col();
  587.  
  588.     /*
  589.      * Update the screen in case we changed something like "tabstop" or
  590.      * "lines" or "list" that will change its appearance.
  591.      * If we messed up the screen by showing more than one line of param
  592.      * values call wait_return(), which will also update the screen..
  593.      */
  594.     if (do_wait)
  595.     {
  596.         outchar('\n');
  597.         wait_return(TRUE);
  598.     }
  599.     else
  600.         updateScreen(NOT_VALID);
  601.     return errcnt;
  602. }
  603.  
  604. /*
  605.  * expand environment variable at the start of some string options
  606.  */
  607.     static void
  608. param_expand(i, dofree)
  609.     int        i;
  610.     int        dofree;
  611. {
  612.     char *p;
  613.  
  614.     if ((params[i].flags & P_EXPAND) && (p = *(char **)(params[i].var)) != NULL && *p == '$')
  615.     {
  616.         expand_env(*(char **)(params[i].var), IObuff, IOSIZE);
  617.         p = strsave(IObuff);
  618.         if (p)
  619.         {
  620.             if (dofree)
  621.                 free(*(char **)(params[i].var));
  622.             *(char **)(params[i].var) = p;
  623.         }
  624.     }
  625. }
  626.  
  627. /*
  628.  * find index for option 'arg'
  629.  * return -1 if not found
  630.  */
  631.     static int
  632. findparam(arg)
  633.     char *arg;
  634. {
  635.     int        i;
  636.     char    *s;
  637.  
  638.     for (i = 0; (s = params[i].fullname) != NULL; i++)
  639.     {
  640.         if (strcmp(arg, s) == 0) /* match full name */
  641.             break;
  642.     }
  643.     if (s == NULL)
  644.     {
  645.         for (i = 0; params[i].fullname != NULL; i++)
  646.         {
  647.             s = params[i].shortname;
  648.             if (s != NULL && strcmp(arg, s) == 0) /* match short name */
  649.                 break;
  650.             s = NULL;
  651.         }
  652.     }
  653.     if (s == NULL)
  654.         i = -1;
  655.     return i;
  656. }
  657.  
  658. /*
  659.  * mark option 'arg' changed
  660.  */
  661.     void
  662. paramchanged(arg)
  663.     char *arg;
  664. {
  665.     int i;
  666.  
  667.     i = findparam(arg);
  668.     if (i >= 0)
  669.         params[i].flags |= P_CHANGED;
  670. }
  671.  
  672. /*
  673.  * if 'all' == 0: show changed parameters
  674.  * if 'all' == 1: show all normal parameters
  675.  * if 'all' == 2: show all terminal parameters
  676.  */
  677.     static void
  678. showparams(all)
  679.     int            all;
  680. {
  681.     struct param   *p;
  682.     int                col = 0;
  683.     int                inc;
  684.     int                isterm;
  685.  
  686.     gotocmdline(TRUE, NUL);
  687.     outstrn("Parameters:\n");
  688.  
  689. #ifdef AMIGA
  690.     settmode(0);                /* set cooked mode so output can be halted */
  691. #endif
  692.     for (p = ¶ms[0]; p->fullname != NULL; p++)
  693.     {
  694.         isterm = istermparam(p);
  695.         if (p->var && (
  696.             (all == 2 && isterm) ||
  697.             (all == 1 && !isterm) ||
  698.             (all == 0 && (p->flags & P_CHANGED))))
  699.         {
  700.             if ((p->flags & P_STRING) && *(char **)(p->var) != NULL)
  701.             {
  702.                 inc = strlen(p->fullname) + strsize(*(char **)(p->var)) + 1;
  703.                 if (inc < 18)
  704.                     inc = 18;
  705.             }
  706.             else
  707.                 inc = 18;
  708.             if (col + inc >= Columns)
  709.             {
  710.                 col = 0;
  711.                 if (Rows != Rows_max)
  712.                     windgoto((int)Rows_max - 1, 0);
  713.                 outchar('\n');                /* scroll screen one line up */
  714.             }
  715.             windgoto((int)Rows - 1, col); /* make columns */
  716.             showonep(p);
  717.             col += inc;
  718.             col += 19 - col % 19;
  719.             flushbuf();
  720.         }
  721.     }
  722.  
  723.     if (col)
  724.         outchar('\n');
  725. #ifdef AMIGA
  726.     settmode(1);
  727. #endif
  728.     wait_return(TRUE);
  729. }
  730.  
  731. /*
  732.  * showonep: show the value of one option
  733.  * must not be called with a hidden option!
  734.  */
  735.     static void
  736. showonep(p)
  737.         struct param *p;
  738. {
  739.     char            buf[64];
  740.  
  741.     if ((p->flags & P_BOOL) && !*(int *)(p->var))
  742.         outstrn("no");
  743.     outstrn(p->fullname);
  744.     if (!(p->flags & P_BOOL))
  745.     {
  746.         outchar('=');
  747.         if (p->flags & P_NUM)
  748.         {
  749.             sprintf(buf, "%ld", *(long *)(p->var));
  750.             outstrn(buf);
  751.         }
  752.         else if (*(char **)(p->var) != NULL)
  753.             outtrans(*(char **)(p->var), -1);
  754.     }
  755. }
  756.  
  757. /*
  758.  * Write modified parameters as set command to a file.
  759.  * Return 1 on error.
  760.  */
  761.     int
  762. makeset(fd)
  763.     FILE *fd;
  764. {
  765.     struct param    *p;
  766.     char            *s;
  767.     int                e;
  768.  
  769.     for (p = ¶ms[0]; p->fullname != NULL; p++)
  770.         if ((p->flags & P_CHANGED) && p->var)
  771.         {
  772.             if (p->flags & P_BOOL)
  773.                 fprintf(fd, "set %s%s", *(int *)(p->var) ? "" : "no", p->fullname);
  774.             else if (p->flags & P_NUM)
  775.                 fprintf(fd, "set %s=%ld", p->fullname, *(long *)(p->var));
  776.             else
  777.             {
  778.                 fprintf(fd, "set %s=", p->fullname);
  779.                 s = *(char **)(p->var);
  780.                     /* some characters hav to be escaped with CTRL-V or backslash */
  781.                 if (s != NULL && putescstr(fd, s, TRUE) < 0)
  782.                     return 1;
  783.             }
  784. #ifdef MSDOS
  785.             putc('\r', fd);
  786. #endif
  787.                 /*
  788.                  * Only check error for this putc, should catch at least
  789.                  * the "disk full" situation.
  790.                  */
  791.             e = putc('\n', fd);
  792.             if (e < 0)
  793.                 return 1;
  794.         }
  795.     return 0;
  796. }
  797.  
  798. /*
  799.  * Clear all the terminal parameters.
  800.  * If the parameter has been changed, free the allocated memory.
  801.  * Reset the "changed" flag, so the new value will not be freed.
  802.  */
  803.     void
  804. clear_termparam()
  805. {
  806.     struct param   *p;
  807.  
  808.     for (p = ¶ms[0]; p->fullname != NULL; p++)
  809.         if (istermparam(p))            /* terminal parameters must never be hidden */
  810.         {
  811.             if (p->flags & P_CHANGED)
  812.                 free(*(char **)(p->var));
  813.             *(char **)(p->var) = NULL;
  814.             p->flags &= ~P_CHANGED;
  815.         }
  816. }
  817.  
  818.     static int
  819. istermparam(p)
  820.     struct param *p;
  821. {
  822.     return (p->fullname[0] == 't' && p->fullname[1] == '_');
  823. }
  824.  
  825. /*
  826.  * Compute columns for ruler and shown command. 'sc_col' is also used to
  827.  * decide what the maximum length of a message on the status line can be.
  828.  */
  829.  
  830. #define COL_SHOWCMD 10        /* columns needed by shown command */
  831. #define COL_RULER 17        /* columns needed by ruler */
  832.  
  833.     void
  834. comp_col()
  835. {
  836.     sc_col = 0;
  837.     ru_col = 0;
  838.     if (p_ru)
  839.         ru_col = sc_col = COL_RULER + 1;
  840.     if (p_sc)
  841.     {
  842.         sc_col += COL_SHOWCMD;
  843.         if (!p_ru)
  844.             ++sc_col;
  845.     }
  846.     sc_col = Columns - sc_col;
  847.     ru_col = Columns - ru_col;
  848. }
  849.