home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / v / vim_src.zip / PARAM.C < prev    next >
C/C++ Source or Header  |  1993-01-12  |  15KB  |  525 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  * VIM - Vi IMitation
  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.  
  39. /*
  40.  * The param structure is initialized here.
  41.  * The order of the parameters should be alfabetic
  42.  */
  43. struct param params[] =
  44. {
  45.         {"autoindent",    "ai",    P_BOOL,        (char *)&p_ai},
  46. /*        {"autoprint",    "ap",    P_BOOL,        (char *)&p_ap}, */
  47.         {"autowrite",    "aw",    P_BOOL,        (char *)&p_aw},
  48.         {"backspace",    "bs",    P_NUM,        (char *)&p_bs},
  49.         {"backup",        "bk",    P_BOOL,        (char *)&p_bk},
  50. #ifdef UNIX
  51.          {"backupdir",    "bdir",    P_STRING,    (char *)&p_bdir},
  52. #endif
  53. /*        {"beautify",    "bf",    P_BOOL,        (char *)&p_bf}, */
  54.         {"columns",        "co",    P_NUM,        (char *)&Columns},
  55. #ifdef DIGRAPHS
  56.         {"digraph",        "dg",    P_BOOL,        (char *)&p_dg},
  57. #endif /* DIGRAPHS */
  58.          {"directory",    "dir",    P_STRING,    (char *)&p_dir},
  59.         {"equalprg",    "ep",      P_STRING,    (char *)&p_ep},
  60.         {"errorbells",    "eb",    P_BOOL,        (char *)&p_eb},
  61.         {"errorfile",    "ef",      P_STRING,    (char *)&p_ef},
  62.         {"expandtab",    "et",    P_BOOL,        (char *)&p_et},
  63.         {"graphic",        "gr",    P_BOOL,        (char *)&p_gr},
  64. /*        {"hardtabs",    "ht",    P_NUM,        (char *)&p_ht}, */
  65.         {"helpfile",    "hf",      P_STRING,    (char *)&p_hf},
  66.         {"history",     "hi",     P_NUM,        (char *)&p_hi},
  67.         {"ignorecase",    "ic",    P_BOOL,        (char *)&p_ic},
  68.         {"insertmode",    "im",    P_BOOL,        (char *)&p_im},
  69.         {"joinspaces",     "js",    P_BOOL,        (char *)&p_js},
  70.         {"keywordprg",    "kp",      P_STRING,    (char *)&p_kp},
  71.         {"lines",        NULL,     P_NUM,        (char *)&Rows},
  72. /*        {"lisp",        NULL,    P_BOOL        (char *)&p_lisp}, */
  73.         {"list",        NULL,    P_BOOL,        (char *)&p_list},
  74.         {"magic",        NULL,    P_BOOL,        (char *)&p_magic},
  75.         {"modelines",    "ml",    P_NUM,        (char *)&p_ml},
  76.         {"number",        "nu",    P_BOOL,        (char *)&p_nu},
  77. /*        {"open",        NULL,    P_BOOL,        (char *)&p_open}, */
  78. /*        {"optimize",    "opt",    P_BOOL,        (char *)&p_opt}, */
  79.         {"paragraphs",    "para",    P_STRING,    (char *)&p_para},
  80. /*        {"prompt",        NULL,    P_BOOL,        (char *)&p_prompt}, */
  81.         {"readonly",    "ro",    P_BOOL,        (char *)&p_ro},
  82. /*        {"redraw",        NULL,    P_BOOL,        (char *)&p_redraw}, */
  83.         {"remap",        NULL,    P_BOOL,        (char *)&p_remap},
  84.         {"repdel",        "rd",    P_BOOL,        (char *)&p_rd},
  85.         {"report",        NULL,    P_NUM,        (char *)&p_report},
  86.         {"ruler",        "ru",    P_BOOL,        (char *)&p_ru},
  87.         {"scroll",        NULL,     P_NUM,        (char *)&p_scroll},
  88.         {"scrolljump",    "sj",     P_NUM,        (char *)&p_sj},
  89.         {"sections",    NULL,    P_STRING,    (char *)&p_sections},
  90.         {"shell",        "sh",    P_STRING,    (char *)&p_sh},
  91.         {"shelltype",    "st",    P_NUM,        (char *)&p_st},
  92.         {"shiftround",    "sr",    P_BOOL,        (char *)&p_sr},
  93.         {"shiftwidth",    "sw",    P_NUM,        (char *)&p_sw},
  94.         {"showcmd",        "sc",    P_BOOL,        (char *)&p_sc},
  95.         {"showmatch",    "sm",    P_BOOL,        (char *)&p_sm},
  96.         {"showmode",    "mo",    P_BOOL,        (char *)&p_mo},
  97. /*        {"slowopen",    "slow",    P_BOOL,        (char *)&p_slow}, */
  98.         {"smartindent", "si",    P_BOOL,        (char *)&p_si},
  99.         {"suffixes",    "su",    P_STRING,    (char *)&p_su},
  100.         {"tabstop",     "ts",    P_NUM,        (char *)&p_ts},
  101.         {"taglength",    "tl",    P_NUM,        (char *)&p_tl},
  102.         {"tags",        NULL,    P_STRING,    (char *)&p_tags},
  103.         {"term",        NULL,    P_STRING,    (char *)&term_strings.t_name},
  104.         {"terse",        NULL,    P_BOOL,        (char *)&p_terse},
  105. #ifdef MSDOS
  106.         {"textmode",    "tx",    P_BOOL,        (char *)&p_tx},
  107. #endif
  108.         {"textwidth",    "tw",    P_NUM,        (char *)&p_tw},
  109.         {"tildeop",     "to",    P_BOOL,        (char *)&p_to},
  110.         {"timeout",     NULL,    P_BOOL,        (char *)&p_timeout},
  111.         {"undolevels",    "ul",    P_NUM,        (char *)&p_ul},
  112.         {"updatecount",    "uc",    P_NUM,        (char *)&p_uc},
  113.         {"updatetime",    "ut",    P_NUM,        (char *)&p_ut},
  114.         {"visualbell",    "vb",    P_BOOL,        (char *)&p_vb},
  115.         {"warn",        NULL,    P_BOOL,        (char *)&p_warn},
  116. /*        {"window",        NULL,     P_NUM,        (char *)&p_window}, */
  117. /*        {"w300",        NULL,     P_NUM,        (char *)&p_w300}, */
  118. /*        {"w1200",        NULL,     P_NUM,        (char *)&p_w1200}, */
  119. /*        {"w9600",        NULL,     P_NUM,        (char *)&p_w9600}, */
  120.         {"wrapscan",    "ws",    P_BOOL,        (char *)&p_ws},
  121.         {"wrapmargin",    "wm",    P_NUM,        (char *)&p_wm},
  122.         {"writeany",    "wa",    P_BOOL,        (char *)&p_wa},
  123.         {"writebackup",    "wb",    P_BOOL,        (char *)&p_wb},
  124.         {"yankendofline", "ye",    P_BOOL,        (char *)&p_ye},
  125.  
  126. /* terminal output codes */
  127.         {"t_el",        NULL,    P_STRING,    (char *)&term_strings.t_el},
  128.         {"t_il",        NULL,    P_STRING,    (char *)&term_strings.t_il},
  129.         {"t_cil",        NULL,    P_STRING,    (char *)&term_strings.t_cil},
  130.         {"t_dl",        NULL,    P_STRING,    (char *)&term_strings.t_dl},
  131.         {"t_cdl",        NULL,    P_STRING,    (char *)&term_strings.t_cdl},
  132.         {"t_ed",        NULL,    P_STRING,    (char *)&term_strings.t_ed},
  133.         {"t_ci",        NULL,    P_STRING,    (char *)&term_strings.t_ci},
  134.         {"t_cv",        NULL,    P_STRING,    (char *)&term_strings.t_cv},
  135.         {"t_tp",        NULL,    P_STRING,    (char *)&term_strings.t_tp},
  136.         {"t_ti",        NULL,    P_STRING,    (char *)&term_strings.t_ti},
  137.         {"t_cm",        NULL,    P_STRING,    (char *)&term_strings.t_cm},
  138.         {"t_sr",        NULL,    P_STRING,    (char *)&term_strings.t_sr},
  139.         {"t_cri",        NULL,    P_STRING,    (char *)&term_strings.t_cri},
  140.         {"t_vb",        NULL,    P_STRING,    (char *)&term_strings.t_vb},
  141.         {"t_ks",        NULL,    P_STRING,    (char *)&term_strings.t_ks},
  142.         {"t_ke",        NULL,    P_STRING,    (char *)&term_strings.t_ke},
  143.  
  144. /* terminal key codes */
  145.         {"t_ku",        NULL,    P_STRING,    (char *)&term_strings.t_ku},
  146.         {"t_kd",        NULL,    P_STRING,    (char *)&term_strings.t_kd},
  147.         {"t_kr",        NULL,    P_STRING,    (char *)&term_strings.t_kr},
  148.         {"t_kl",        NULL,    P_STRING,    (char *)&term_strings.t_kl},
  149.         {"t_sku",        NULL,    P_STRING,    (char *)&term_strings.t_sku},
  150.         {"t_skd",        NULL,    P_STRING,    (char *)&term_strings.t_skd},
  151.         {"t_skr",        NULL,    P_STRING,    (char *)&term_strings.t_skr},
  152.         {"t_skl",        NULL,    P_STRING,    (char *)&term_strings.t_skl},
  153.         {"t_f1",        NULL,    P_STRING,    (char *)&term_strings.t_f1},
  154.         {"t_f2",        NULL,    P_STRING,    (char *)&term_strings.t_f2},
  155.         {"t_f3",        NULL,    P_STRING,    (char *)&term_strings.t_f3},
  156.         {"t_f4",        NULL,    P_STRING,    (char *)&term_strings.t_f4},
  157.         {"t_f5",        NULL,    P_STRING,    (char *)&term_strings.t_f5},
  158.         {"t_f6",        NULL,    P_STRING,    (char *)&term_strings.t_f6},
  159.         {"t_f7",        NULL,    P_STRING,    (char *)&term_strings.t_f7},
  160.         {"t_f8",        NULL,    P_STRING,    (char *)&term_strings.t_f8},
  161.         {"t_f9",        NULL,    P_STRING,    (char *)&term_strings.t_f9},
  162.         {"t_f10",        NULL,    P_STRING,    (char *)&term_strings.t_f10},
  163.         {"t_sf1",        NULL,    P_STRING,    (char *)&term_strings.t_sf1},
  164.         {"t_sf2",        NULL,    P_STRING,    (char *)&term_strings.t_sf2},
  165.         {"t_sf3",        NULL,    P_STRING,    (char *)&term_strings.t_sf3},
  166.         {"t_sf4",        NULL,    P_STRING,    (char *)&term_strings.t_sf4},
  167.         {"t_sf5",        NULL,    P_STRING,    (char *)&term_strings.t_sf5},
  168.         {"t_sf6",        NULL,    P_STRING,    (char *)&term_strings.t_sf6},
  169.         {"t_sf7",        NULL,    P_STRING,    (char *)&term_strings.t_sf7},
  170.         {"t_sf8",        NULL,    P_STRING,    (char *)&term_strings.t_sf8},
  171.         {"t_sf9",        NULL,    P_STRING,    (char *)&term_strings.t_sf9},
  172.         {"t_sf10",        NULL,    P_STRING,    (char *)&term_strings.t_sf10},
  173.         {"t_help",        NULL,    P_STRING,    (char *)&term_strings.t_help},
  174.         {"t_undo",        NULL,    P_STRING,    (char *)&term_strings.t_undo},
  175.         {NULL, NULL, 0, NULL}            /* end marker */
  176. };
  177.  
  178. static void    showparams __ARGS((int));
  179. static void showonep __ARGS((struct param *));
  180. static int  istermparam __ARGS((struct param *));
  181.  
  182. /*
  183.  * Initialize the shell parameter and scroll size.
  184.  */
  185.     void
  186. set_init()
  187. {
  188.         char *p;
  189.  
  190.         if ((p = getenv("SHELL")) != NULL)
  191.             p_sh = strsave(p);
  192.         p_scroll = (Rows >> 1);
  193. }
  194.  
  195.     void
  196. doset(arg)
  197.     char        *arg;    /* parameter string */
  198. {
  199.     register int i;
  200.     char        *s;
  201.     int            prefix;    /* 0: nothing, 1: "no", 2: "inv" in front of name */
  202.     int         nextchar;
  203.     int         len = 0;
  204.     int         flags;
  205.     int            olduc = p_uc;    /* remember old update count */
  206.  
  207.     if (*arg == NUL)
  208.     {
  209.         showparams(0);
  210.         return;
  211.     }
  212.  
  213.     while (*arg)        /* loop to process all parameters */
  214.     {
  215.         if (strncmp(arg, "all", (size_t)3) == 0)
  216.                 showparams(1);
  217.         else if (strncmp(arg, "termcap", (size_t)7) == 0)
  218.                 showparams(2);
  219.         else
  220.         {
  221.             prefix = 1;
  222.             if (strncmp(arg, "no", (size_t)2) == 0)
  223.             {
  224.                 prefix = 0;
  225.                 arg += 2;
  226.             }
  227.             else if (strncmp(arg, "inv", (size_t)3) == 0)
  228.             {
  229.                 prefix = 2;
  230.                 arg += 3;
  231.             }
  232.             for (i = 0; (s = params[i].fullname) != NULL; i++)
  233.             {
  234.                 if (strncmp(arg, s, (size_t)(len = strlen(s))) == 0) /* match full name */
  235.                     break;
  236.             }
  237.             if (s == NULL)
  238.             {
  239.                 for (i = 0; params[i].fullname != NULL; i++)
  240.                 {
  241.                         s = params[i].shortname;
  242.                         if (s != NULL && strncmp(arg, s, (size_t)(len = strlen(s))) == 0) /* match short name */
  243.                             break;
  244.                         s = NULL;
  245.                 }
  246.             }
  247.  
  248.             if (s == NULL)        /* found a mismatch: skip the rest */
  249.             {
  250.                 emsg(e_unrset);
  251.                 break;
  252.             }
  253.  
  254.             flags = params[i].flags;
  255.             nextchar = arg[len];
  256.             /*
  257.              * allow '=' and ':' as MSDOS command.com allows only one
  258.              * '=' character per "set" command line. grrr. (jw)
  259.              */
  260.             if (nextchar == '?' || 
  261.                 ((nextchar != '=' && nextchar != ':') &&
  262.                 !(flags & P_BOOL)))
  263.             {                                        /* print value */
  264.                 gotocmdline(TRUE, NUL);
  265.                 showonep(¶ms[i]);
  266.             }
  267.             else if (nextchar != NUL && strchr("=: \t", nextchar) == NULL)
  268.             {
  269.                 emsg(e_setparam);
  270.                 break;
  271.             }
  272.             else if (flags & P_BOOL)                    /* boolean */
  273.             {
  274.                     if (nextchar == '=' || nextchar == ':')
  275.                     {
  276.                         emsg(e_setparam);
  277.                         break;
  278.                     }
  279.                     if (prefix == 2)
  280.                         *(int *)(params[i].var) ^= 1;    /* invert it */
  281.                     else
  282.                         *(int *)(params[i].var) = prefix;
  283.             }
  284.             else                                /* numeric or string */
  285.             {
  286.                 if ((nextchar != '=' && nextchar != ':') || prefix != 1)
  287.                 {
  288.                     emsg(e_setparam);
  289.                     break;
  290.                 }
  291.                 if (flags & P_NUM)                /* numeric */
  292.                 {
  293.                     len = atoi(arg + len + 1);
  294.                     if ((long *)params[i].var == &p_wm)    /* wrapmargin is translated into textlength */
  295.                     {
  296.                         if (len >= Columns)
  297.                             len = Columns - 1;
  298.                         p_tw = Columns - len;
  299.                     }
  300.                     *(long *)(params[i].var) = len;
  301.                 }
  302.                 else                            /* string */
  303.                 {
  304.                     arg += len + 1;
  305.                     s = alloc((unsigned)(strlen(arg) + 1)); /* get a bit too much */
  306.                     if (s == NULL)
  307.                         break;
  308.                     if (flags & P_CHANGED)
  309.                         free(*(char **)(params[i].var));
  310.                     *(char **)(params[i].var) = s;
  311.                                 /* copy the string */
  312.                     while (*arg && *arg != ' ' && *arg != '\t')
  313.                     {
  314.                         if (*arg == '\\' && *(arg + 1)) /* skip over escaped chars */
  315.                                 ++arg;
  316.                         *s++ = *arg++;
  317.                     }
  318.                     *s = NUL;
  319.                     /*
  320.                      * options that need some action
  321.                      * to perform when changed (jw)
  322.                      */
  323.                     if (params[i].var == (char *)&term_strings.t_name)
  324.                         set_term(term_strings.t_name);
  325.                     else if (istermparam(¶ms[i]))
  326.                         ttest(FALSE);
  327.                 }
  328.             }
  329.             params[i].flags |= P_CHANGED;
  330.         }
  331.  
  332.         skiptospace(&arg);                /* skip to next white space */
  333.         skipspace(&arg);                /* skip spaces */
  334.     }
  335.  
  336.     /*
  337.      * Check the bounds for numeric parameters here
  338.      */
  339.     if (p_ts <= 0 || p_ts > 16)
  340.     {
  341.         emsg(e_tabsize);
  342.         p_ts = 8;
  343.     }
  344.     if (p_scroll <= 0 || p_scroll > Rows)
  345.     {
  346.         emsg(e_scroll);
  347.         p_scroll = Rows >> 1;
  348.     }
  349.     if (p_sj < 0 || p_sj >= Rows)
  350.     {
  351.         emsg(e_scroll);
  352.         p_sj = 1;
  353.     }
  354.     if (p_ul < 0)
  355.     {
  356.         emsg(e_positive);
  357.         p_ul = 100;
  358.     }
  359.     if (p_uc < 0)
  360.     {
  361.         emsg(e_positive);
  362.         p_uc = 100;
  363.     }
  364.     if (p_uc == 0 && olduc != 0)        /* p_uc changed from on to off */
  365.         stopscript();
  366.     if (p_uc > 0 && olduc == 0)        /* p_uc changed from off to on */
  367.         startscript();
  368. #ifdef MSDOS
  369.     textfile(p_tx);
  370. #endif
  371.     if (p_ut < 0)
  372.     {
  373.         emsg(e_positive);
  374.         p_ut = 2000;
  375.     }
  376.  
  377.     /*
  378.      * Update the screen in case we changed something like "tabstop" or
  379.      * "lines" or "list" that will change its appearance.
  380.      */
  381.     updateScreen(NOT_VALID);
  382. }
  383.  
  384. /*
  385.  * if 'all' == 0: show changed parameters
  386.  * if 'all' == 1: show all normal parameters
  387.  * if 'all' == 2: show all terminal parameters
  388.  */
  389.     static void
  390. showparams(all)
  391.     int            all;
  392. {
  393.     struct param   *p;
  394.     int                col = 0;
  395.     int                inc;
  396.     int                isterm;
  397.  
  398.     gotocmdline(TRUE, NUL);
  399.     outstrn("Parameters:\n");
  400.  
  401.     settmode(0);                /* set cooked mode so output can be halted */
  402.     for (p = ¶ms[0]; p->fullname != NULL; p++)
  403.     {
  404.         isterm = istermparam(p);
  405.         if ((all == 2 && isterm) ||
  406.             (all == 1 && !isterm) ||
  407.             (all == 0 && (p->flags & P_CHANGED)))
  408.         {
  409.             if ((p->flags & P_STRING) && *(char **)(p->var) != NULL)
  410.                 inc = strlen(p->fullname) + strsize(*(char **)(p->var)) + 1;
  411.             else
  412.                 inc = 1;
  413.             if (col + inc >= Columns)
  414.             {
  415.                 outchar('\n');
  416.                 col = 0;
  417.             }
  418.  
  419.             showonep(p);
  420.             col += inc;
  421.             col += 19 - col % 19;
  422.             if (col < Columns - 19)
  423.                 windgoto((int)Rows - 1, col); /* make columns */
  424.             else
  425.             {
  426.                 col = 0;
  427.                 outchar('\n');
  428.             }
  429.             flushbuf();
  430.         }
  431.     }
  432.  
  433.     if (col)
  434.         outchar('\n');
  435.     settmode(1);
  436.     wait_return(TRUE);
  437. }
  438.  
  439.     static void
  440. showonep(p)
  441.         struct param *p;
  442. {
  443.     char            buf[64];
  444.  
  445.     if ((p->flags & P_BOOL) && !*(int *)(p->var))
  446.         outstrn("no");
  447.     outstrn(p->fullname);
  448.     if (!(p->flags & P_BOOL))
  449.     {
  450.         outchar('=');
  451.         if (p->flags & P_NUM)
  452.         {
  453.             sprintf(buf, "%ld", *(long *)(p->var));
  454.             outstrn(buf);
  455.         }
  456.         else if (*(char **)(p->var) != NULL)
  457.             outtrans(*(char **)(p->var), -1);
  458.     }
  459. }
  460.  
  461. /*
  462.  * Write modified parameters as set command to a file.
  463.  * Return 1 on error.
  464.  */
  465.     int
  466. makeset(fd)
  467.     FILE *fd;
  468. {
  469.     struct param    *p;
  470.     char            *s;
  471.     int                e;
  472.  
  473.     for (p = ¶ms[0]; p->fullname != NULL; p++)
  474.         if (p->flags & P_CHANGED)
  475.         {
  476.             if (p->flags & P_BOOL)
  477.                 e = fprintf(fd, "set %s%s\n", *(int *)(p->var) ? "" : "no", p->fullname);
  478.             else if (p->flags & P_NUM)
  479.                 e = fprintf(fd, "set %s=%ld\n", p->fullname, *(long *)(p->var));
  480.             else
  481.             {
  482.                 fprintf(fd, "set %s=", p->fullname);
  483.                 s = *(char **)(p->var);
  484.                 if (s != NULL)
  485.                     for ( ; *s; ++s)
  486.                     {
  487.                         if (*s < ' ' || *s > '~')
  488.                             putc(CTRL('V'), fd);
  489.                         putc(*s, fd);
  490.                     }
  491.                 e = putc('\n', fd);
  492.             }
  493.             if (e < 0)
  494.                 return 1;
  495.         }
  496.     return 0;
  497. }
  498.  
  499. /*
  500.  * Clear all the terminal parameters.
  501.  * If the parameter has been changed, free the allocated memory.
  502.  * Reset the "changed" flag, so the new value will not be freed.
  503.  */
  504.     void
  505. clear_termparam()
  506. {
  507.     struct param   *p;
  508.  
  509.     for (p = ¶ms[0]; p->fullname != NULL; p++)
  510.         if (istermparam(p))
  511.         {
  512.             if (p->flags & P_CHANGED)
  513.                 free(*(char **)(p->var));
  514.             *(char **)(p->var) = NULL;
  515.             p->flags &= ~P_CHANGED;
  516.         }
  517. }
  518.  
  519.     static int
  520. istermparam(p)
  521.     struct param *p;
  522. {
  523.     return (p->fullname[0] == 't' && p->fullname[1] == '_');
  524. }
  525.