home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3445 / extend.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-07  |  11.9 KB  |  492 lines

  1. /*
  2. *   Extended (M-X) commands.
  3. */
  4. #include    "def.h"
  5.  
  6. extern    char    MSG_not_now[];
  7. extern    char    MSG_func[];
  8. extern    char    MSG_unk_func[];
  9. extern    char    MSG_cmd_t_ex[];
  10. extern    char    MSG_unk_ext[];
  11. extern    char    MSG_d_b[];
  12. extern    char    MSG_unbd[];
  13. extern    char    MSG_bnd_to[];
  14. extern    char    MSG_ins_self[];
  15. extern    char    MSG_bnd_file[];
  16. extern    char    MSG_bld_wall[];
  17. extern    char    MSG_wall_head[];
  18. extern    char    MSG_beavrc[];
  19. extern    char    MSG_null[];
  20.  
  21. #include    "lintfunc.dec"
  22. #ifdef CUSTOMIZE 
  23.  
  24. char *flook();
  25.  
  26. static char *bindnm =
  27. {0
  28. };                              /* file name for customized key bindings */
  29. #endif 
  30.  
  31. /*
  32. * This function modifies the keyboard
  33. * binding table, by adjusting the entries in the
  34. * big "bindings" array. Most of the grief deals with the
  35. * prompting for additional arguments. This code does not
  36. * work right if there is a keyboard macro floating around.
  37. * Should be fixed.
  38. */
  39. bool bindtokey ()
  40. {
  41.  
  42.     register int    s;
  43.     register char  *cp;
  44.     register    SYMBOL * sp;
  45.     register int    c;
  46.     char    xname[NXNAME];
  47. #ifdef CUSTOMIZE
  48.     char    xname2[NXNAME];
  49.     FILE * bindf;
  50. #endif 
  51.  
  52.     if (kbdmip != NULL || kbdmop != NULL)
  53.         {
  54.         writ_echo (MSG_not_now);
  55.         return (FALSE);
  56.         }
  57.  
  58.     if ((s = eread (MSG_func, xname, NXNAME, EFAUTO, NULL)) != TRUE)
  59.         return (s);
  60.     if ((sp = symlookup (xname)) == NULL)
  61.         {
  62.         writ_echo (MSG_unk_func);
  63.         return (FALSE);
  64.         }
  65.  
  66. #ifdef CUSTOMIZE
  67.     strcpy (xname2, xname);
  68. #endif 
  69.     eputc (' ');
  70.     eputc ('K');
  71.     eputc ('e');
  72.     eputc ('y');
  73.     eputc (':');
  74.     eputc (' ');
  75.     ttflush ();
  76.     c = getkey ();              /* Read key.        */
  77.     keyname (xname, c);         /* Display keyname. */
  78.     eputs (xname);
  79.     ttflush ();
  80.     if (binding[c] != NULL)     /* Unbind old, and  */
  81.         --binding[c] -> s_nkey;
  82.     binding[c] = sp;            /* rebind new.      */
  83.     ++sp -> s_nkey;
  84.     sp -> s_modify |= SBOUND;    /* flag as altered key binding */
  85.  
  86.     return (TRUE);
  87. }
  88.  
  89.  
  90. /*
  91. * Extended command. Call the message line
  92. * routine to read in the command name and apply autocompletion
  93. * to it. When it comes back, look the name up in the symbol table
  94. * and run the command if it is found and has the right type.
  95. * Print an error if there is anything wrong.
  96. */
  97. char    extend (f, n, k)
  98. {
  99.  
  100.     register    SYMBOL * sp;
  101.     register char   s;
  102.     char    xname[NXNAME];
  103.  
  104.     if ((s = eread (MSG_cmd_t_ex, xname, NXNAME, EFNEW | EFAUTO, NULL)) != TRUE)
  105.         return (s);
  106.     if ((sp = symlookup (xname)) != NULL)
  107.         return ((*sp -> s_funcp) (f, n, KRANDOM));
  108.     writ_echo (MSG_unk_ext);
  109.     return (ABORT);
  110. }
  111.  
  112.  
  113. /*
  114. * Read a key from the keyboard, and look it
  115. * up in the binding table. Display the name of the function
  116. * currently bound to the key. Say that the key is not bound
  117. * if it is indeed not bound, or if the type is not a
  118. * "builtin". This is a bit of overkill, because this is the
  119. * only kind of function there is.
  120. */
  121. bool help ()
  122. {
  123.     register    SYMBOL * sp;
  124.     register int    c;
  125.     char    b[20];
  126.     char    buf[80];
  127.  
  128.     writ_echo (MSG_d_b);
  129.  
  130.     c = getkey ();
  131.     keyname (b, c);
  132.     if ((sp = binding[c]) == NULL)
  133.         {
  134.         sprintf (buf, MSG_unbd, b);
  135.         writ_echo (buf);
  136.         }
  137.     else
  138.         {
  139.         sprintf (buf, MSG_bnd_to, b, sp -> s_name);
  140.         writ_echo (buf);
  141.         }
  142.     return (TRUE);
  143. }
  144.  
  145. /*
  146. *   Sort the lines in the buffer.
  147. */
  148. void    sort_buf (b_ptr, cnt)
  149. BUFFER  *b_ptr;
  150. int     cnt;
  151.     {
  152.     LINE    *lp1, *lp2;
  153.     bool    no_swap;
  154.     int     loop1, loop2;
  155.  
  156.     for (loop1 = cnt; loop1 > 0; loop1--)
  157.         {
  158.         no_swap = TRUE;
  159.         lp1 = b_ptr -> b_linep -> l_fp; /* point to first line */
  160.         lp2 = lp1 -> l_fp;      /* point to next line */
  161.         for (loop2 = 0; loop2 <= loop1; loop2++)
  162.             {
  163.             /* compare strings and swap if necessary */
  164.             if (0 < strcmp (&lp1 -> l_text[HFUNCCOL], &lp2 -> l_text[HFUNCCOL]))
  165.                 {
  166.                 lp1 -> l_bp -> l_fp = lp2;  /* get pointer to first string */
  167.                 lp2 -> l_fp -> l_bp = lp1;  /* make it point to second string */
  168.  
  169.                 lp1 -> l_fp = lp2 -> l_fp;  
  170.                 lp2 -> l_bp = lp1 -> l_bp;  
  171.  
  172.                 lp1 -> l_bp = lp2;  
  173.                 lp2 -> l_fp = lp1;
  174.  
  175.                 lp2 -> l_file_offset = lp1 -> l_file_offset;
  176.                 lp1 -> l_file_offset = lp2 -> l_file_offset + lp2 -> l_used;
  177.  
  178.                 no_swap = FALSE;
  179.                 }
  180.             else
  181.                 {
  182.                 /* if no swap then advance both pointers */
  183.                 lp1 = lp2;
  184.                 }
  185.             lp2 = lp1 -> l_fp;
  186.             }
  187.         /* quick exit if sort is finished sooner than expected */
  188.         if (no_swap)
  189.             {   
  190.             return; 
  191.             }
  192.         }
  193.     }
  194.  
  195. /*
  196. * This function creates a table, listing all
  197. * of the command keys and their current bindings, and stores
  198. * the table in the standard pop-op buffer (the one used by the
  199. * directory list command, the buffer list command, etc.). This
  200. * lets the editor produce it's own wall chart. The bindings to
  201. * "ins-self" are only displayed if there is an argument.
  202. */
  203. char    wallchart (f, n, k)
  204. {
  205.  
  206.     register char   s;
  207.     register int    key, i, j;
  208.     register    SYMBOL * sp;
  209.     register char  *cp1;
  210.     register char  *cp2;
  211.     char    buf[64];
  212.     WINDOW  *wp;
  213.  
  214.     if ((s = bclear (blistp)) != TRUE)/* Clear it out.    */
  215.         return (s);
  216.     i = 0;
  217.     (void) strcpy (blistp -> b_fname, MSG_null);
  218.     blistp -> b_flag = BFVIEW;
  219.     writ_echo (MSG_bld_wall);
  220.     sprintf (buf, MSG_wall_head);
  221.     if (addline (buf) == FALSE)
  222.         return;
  223.     for (key = 0; key < NKEYS; ++key)
  224.         {
  225.     /* For all keys.    */
  226.         sp = binding[key];
  227.         if (sp != NULL &&
  228.                 (f != FALSE || strcmp (sp -> s_name, MSG_ins_self) != 0))
  229.             {
  230.             cp1 = &buf[0];
  231.             while (cp1 < &buf[HFUNCCOL])/* Goto column 3.  */
  232.                 *cp1++ = ' ';
  233.             if ((sp -> s_modify & SBOUND) == 0)    /* comment out default binding */
  234.                 buf[0] = '#';
  235.             cp2 = sp -> s_name; /* Add function name.   */
  236.             while (*cp1++ = *cp2++)
  237.                 ;
  238.             cp1--;
  239.             while (cp1 < &buf[HKEY])/* Goto column 32.  */
  240.                 *cp1++ = ' ';
  241.             keyname (&buf[HKEY], key);
  242.             cp1 = &buf[strlen(buf)];
  243.             while (cp1 < &buf[HKEYCODE])/* Goto column 50.  */
  244.                 *cp1++ = ' ';
  245.             sprintf (&buf[HKEYCODE], "%4X", key);
  246.             if (addline (buf) == FALSE)
  247.                 break; /* lets go with what we have */
  248.             i++;
  249.             }
  250.         }
  251.  
  252.     /* list unbound functions lest they get lost */
  253.     for (j = 0; j < NSHASH; j++)
  254.         {
  255.         sp = symbol[j];
  256.         while (sp != NULL)
  257.             {
  258.             if (sp -> s_nkey == 0)
  259.                 {
  260.                 cp1 = &buf[0];
  261.                 while (cp1 < &buf[HFUNCCOL])/* Goto column 3.  */
  262.                     *cp1++ = ' ';
  263.                 buf[0] = '#';
  264.                 cp2 = sp -> s_name; /* Add function name.   */
  265.                 while (*cp1++ = *cp2++)
  266.                     ;
  267.                 cp1--;
  268.                 while (cp1 < &buf[HENDCOL])
  269.                     *cp1++ = ' ';
  270.                    *cp1 = 0;
  271.                 i++;
  272.                 if (addline (buf) == FALSE)
  273.                     break; /* lets go with what we have */
  274.                 }
  275.             sp = sp -> s_symp;
  276.             }
  277.         }
  278.     sort_buf (blistp, i);      /* sort buffer lines */
  279.     popblist ();
  280.     writ_echo (MSG_null);
  281.     /* make new window the current window */
  282.     wp = wheadp;
  283.     while (wp != NULL)
  284.         {
  285.         if (wp -> w_bufp == blistp)
  286.             {
  287.             curwp = wp;
  288.             curbp = wp -> w_bufp;
  289.             return (TRUE);
  290.             }
  291.         wp = wp -> w_wndp;
  292.         }
  293.     return (TRUE);
  294. }
  295.             
  296. /* check for BEAVFIL and read it in if found
  297. * - also, set local file variable for bindtokey for saving new defs
  298. * (this is some what of a hack as it only handles 'bindtokey' changes at 
  299. * this time - also local file io !!!)
  300. */
  301. void check_extend (sfname)
  302.  
  303. char *sfname;    /* name of startup file (null if default) */
  304.  
  305. {
  306.     char *fname;    /* resulting file name to execute */
  307.     char    rc_name[40];    /* fixed up name of rc file */
  308.     char    *term;
  309.     char *getenv();
  310.     register    SYMBOL * sp;
  311.     char    funcname[NXNAME + 1];
  312.     char    keybind[NXNAME + 1];
  313.     int     keyval;
  314.     FILE * bindf;
  315.  
  316.     /* look up the startup file */
  317.     if ((sfname != NULL) && (*sfname != 0))
  318.         fname = flook(sfname, TRUE);
  319.     else
  320.         {
  321. #ifdef UNIX
  322.         /* hidden file under unix */
  323.         strcpy (&rc_name[0], ".");
  324.         strcpy (&rc_name[1], MSG_beavrc);
  325.  
  326.         if ((term = getenv("TERM")) != 0)
  327.             {
  328.             strcpy (&rc_name[strlen(rc_name)], ".");
  329.             strcpy (&rc_name[strlen(rc_name)], term);
  330.             }
  331.         fname = flook(rc_name, TRUE);
  332.         /* if fixed up name is not there then check original */
  333.         if (fname == NULL)
  334.         {
  335.             /* hidden file under unix */
  336.             strcpy (&rc_name[0], ".");
  337.             strcpy (&rc_name[1], MSG_beavrc);
  338.             fname = flook(rc_name, TRUE);
  339.         }
  340. #else
  341.             strcpy (rc_name, MSG_beavrc);
  342.             fname = flook(rc_name, TRUE);
  343. #endif
  344.     }
  345.     /* if it isn't around, don't sweat it */
  346.     if (fname == NULL)
  347.         return;
  348.  
  349.     if (bindf = fopen(fname, "r"))
  350.     {
  351.     char    buffr[80];
  352.     char    *buffp;
  353.  
  354.         buffp = buffr;
  355.         while (fread (buffp++, sizeof(char), 1, bindf) == 1)
  356.         {
  357.             /* scanf is unhappy with commas */ 
  358.             if (buffp[-1] == ',')
  359.                 buffp[-1] = '-';
  360.  
  361.             /* did we get a whole line */
  362.             if (buffp[-1] == '\n')
  363.             {
  364.                 *buffp = 0;    /* terminate line */
  365.                 buffp = buffr;
  366.                 sscanf (buffr, "%s %s %x", funcname, keybind, &keyval);
  367.                 if ((buffr[0] == '#') || (keyval == 0))
  368.                     continue;
  369.                 if (sp = symlookup (funcname))
  370.                    {
  371.                        if (binding[keyval] != NULL)/* Unbind old, and  */
  372.                        --binding[keyval] -> s_nkey;
  373.                     binding[keyval] = sp;/* rebind new.      */
  374.                        ++sp -> s_nkey;
  375.                     sp -> s_modify |= SBOUND;    /* flag as altered key binding */
  376.                    }
  377.                }
  378.         }
  379.         fclose (bindf);
  380.     }
  381. }
  382.  
  383. /*    Look up the existance of a file along the normal or PATH
  384.     environment variable. Look first in the HOME directory if
  385.     asked and possible
  386. */
  387.  
  388. char *flook(fname, hflag)
  389.  
  390. char *fname;    /* base file name to search for */
  391. int hflag;    /* Look in the HOME environment variable first? */
  392.  
  393. {
  394.     register char *home;    /* path to home directory */
  395.     register char *path;    /* environmental PATH variable */
  396.     register char *sp;    /* pointer into path spec */
  397.     register int i;        /* index */
  398.     static char fspec[128];    /* full path spec to search */
  399.     char *getenv();
  400.     FILE * bindf;
  401.  
  402.     if (hflag) {
  403.         home = getenv("HOME");
  404.         if (home != NULL) {
  405.             /* build home dir file spec */
  406.             strcpy(fspec, home);
  407.             if (fspec[strlen(fspec) - 1] != '/')
  408.                 strcat(fspec, "/");
  409.             strcat(fspec, fname);
  410.  
  411.             /* and try it out */
  412.             if (bindf = fopen(fspec, "r"))
  413.             {
  414.                 fclose(bindf);
  415.                 return(fspec);
  416.             }
  417.         }
  418.     }
  419.  
  420.     /* always try the current directory first */
  421.     if (bindf = fopen(fname, "r"))
  422.     {
  423.         fclose(bindf);
  424.         return(fname);
  425.     }
  426.  
  427.     /* get the PATH variable */
  428.     path = getenv("PATH");
  429.     if (path != NULL)
  430.         while (*path) {
  431.  
  432.             /* build next possible file spec */
  433.             sp = fspec;
  434.             while (*path && (*path != PATHCHR))
  435.                 *sp++ = *path++;
  436.  
  437.             /* add a terminating dir separator if we need it */
  438.             if (sp[-1] != SEPCHAR)
  439.                 *sp++ = SEPCHAR;
  440.  
  441.             *sp = 0;
  442.             strcat(fspec, fname);
  443.  
  444.             /* and try it out */
  445.             if (bindf = fopen(fspec, "r"))
  446.             {
  447.                 fclose(bindf);
  448.                 return(fspec);
  449.             }
  450.  
  451.             if (*path == PATHCHR)
  452.                 ++path;
  453.         }
  454.  
  455.     return(NULL);    /* no such luck */
  456. }
  457.  
  458.  
  459. /* interactive method for loading binding file
  460. * (uses above routine, obviously)
  461. */
  462. char    load_extend ()
  463. {
  464.  
  465. #ifdef CUSTOMIZE
  466.     register char   s;
  467.     char    fname[NFILEN];
  468.  
  469.     if ((s = ereply (MSG_bnd_file, fname, NFILEN, NULL)) != TRUE)
  470.         return (s);
  471.     check_extend (fname);
  472.     writ_echo (okmsg);
  473. #endif
  474.     return (TRUE);
  475. }
  476.  
  477. int     find_keyval (name)
  478. char   *name;
  479. {
  480.     SYMBOL * sp;
  481.     int     key;
  482.  
  483.     for (key = 0; key < NKEYS; ++key)
  484.         {
  485.     /* For all keys.    */
  486.         sp = binding[key];
  487.         if (sp != NULL && (strcmp (sp -> s_name, name) == 0))
  488.             return (key);
  489.         }
  490.     return (0);
  491. }
  492.