home *** CD-ROM | disk | FTP | other *** search
/ Shareware 1 2 the Maxx / sw_1.zip / sw_1 / OS2 / BEAV132X.ZIP / EXTEND.C < prev    next >
C/C++ Source or Header  |  1992-01-06  |  12KB  |  511 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.  
  22. #ifdef CUSTOMIZE
  23.  
  24. char *flook();
  25.  
  26. static char *bindnm =
  27. {
  28.     0
  29. };                              /* file name for customized key bindings */
  30. #endif
  31.  
  32. /*
  33. * This function modifies the keyboard
  34. * binding table, by adjusting the entries in the
  35. * big "bindings" array. Most of the grief deals with the
  36. * prompting for additional arguments. This code does not
  37. * work right if there is a keyboard macro floating around.
  38. * Should be fixed.
  39. */
  40. bool bindtokey ()
  41. {
  42.  
  43.     register int    s;
  44.     register    SYMBOL * sp;
  45.     register int    c;
  46.     char    xname[NXNAME];
  47. #ifdef CUSTOMIZE
  48.     char    xname2[NXNAME];
  49. #endif
  50.  
  51.     if (kbdmip != NULL || kbdmop != NULL)
  52.     {
  53.         writ_echo (MSG_not_now);
  54.         return (FALSE);
  55.     }
  56.  
  57.     if ((s = eread (MSG_func, xname, NXNAME, EFAUTO, NULL)) != TRUE)
  58.         return (s);
  59.     if ((sp = symlookup (xname)) == NULL)
  60.     {
  61.         writ_echo (MSG_unk_func);
  62.         return (FALSE);
  63.     }
  64.  
  65. #ifdef CUSTOMIZE
  66.     strcpy (xname2, xname);
  67. #endif
  68.     eputc (' ');
  69.     eputc ('K');
  70.     eputc ('e');
  71.     eputc ('y');
  72.     eputc (':');
  73.     eputc (' ');
  74.     ttflush ();
  75.     c = getkey ();              /* Read key.        */
  76.     keyname (xname, c);         /* Display keyname. */
  77.     eputs (xname);
  78.     ttflush ();
  79.     if (binding[c] != NULL)     /* Unbind old, and  */
  80.         --binding[c] -> s_nkey;
  81.     binding[c] = sp;            /* rebind new.      */
  82.     ++sp -> s_nkey;
  83.     sp -> s_modify |= SBOUND;    /* flag as altered key binding */
  84.  
  85.     return (TRUE);
  86. }
  87.  
  88.  
  89. /*
  90. * Extended command. Call the message line
  91. * routine to read in the command name and apply autocompletion
  92. * to it. When it comes back, look the name up in the symbol table
  93. * and run the command if it is found and has the right type.
  94. * Print an error if there is anything wrong.
  95. */
  96. char    extend (f, n, k)
  97. int 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. int f, n, k;
  205. {
  206.  
  207.     register char   s;
  208.     register int    key, i, j;
  209.     register    SYMBOL * sp;
  210.     register char  *cp1;
  211.     register char  *cp2;
  212.     char    buf[64];
  213.     WINDOW  *wp;
  214.  
  215.     if ((s = bclear (blistp)) != TRUE)/* Clear it out.    */
  216.         return (s);
  217.     i = 0;
  218.     (void) strcpy (blistp -> b_fname, MSG_null);
  219.     blistp -> b_flag = BFVIEW;
  220.     blistp -> b_type = BTHELP;
  221.     writ_echo (MSG_bld_wall);
  222.     sprintf (buf, MSG_wall_head);
  223.     if (addline (buf) == FALSE)
  224.         return(FALSE);
  225.     for (key = 0; key < NKEYS; ++key)
  226.     {
  227.         /* For all keys.    */
  228.         sp = binding[key];
  229.         if (sp != NULL &&
  230.             (f != FALSE || strcmp (sp -> s_name, MSG_ins_self) != 0))
  231.         {
  232.             cp1 = &buf[0];
  233.             while (cp1 < &buf[HFUNCCOL])/* Goto column 3.  */
  234.                 *cp1++ = ' ';
  235.             if ((sp -> s_modify & SBOUND) == 0)    /* comment out default binding */
  236.                 buf[0] = '#';
  237.             cp2 = sp -> s_name; /* Add function name.   */
  238.             while (*cp1++ = *cp2++)
  239.                 ;
  240.             cp1--;
  241.             while (cp1 < &buf[HKEY])/* Goto column 32.  */
  242.                 *cp1++ = ' ';
  243.             keyname (&buf[HKEY], key);
  244.             cp1 = &buf[strlen(buf)];
  245.             while (cp1 < &buf[HKEYCODE])/* Goto column 50.  */
  246.                 *cp1++ = ' ';
  247.             sprintf (&buf[HKEYCODE], "%4X", key);
  248.             if (addline (buf) == FALSE)
  249.                 break; /* lets go with what we have */
  250.             i++;
  251.         }
  252.     }
  253.  
  254.     /* list unbound functions lest they get lost */
  255.     for (j = 0; j < NSHASH; j++)
  256.     {
  257.         sp = symbol[j];
  258.         while (sp != NULL)
  259.         {
  260.             if (sp -> s_nkey == 0)
  261.             {
  262.                 cp1 = &buf[0];
  263.                 while (cp1 < &buf[HFUNCCOL])/* Goto column 3.  */
  264.                     *cp1++ = ' ';
  265.                 buf[0] = '#';
  266.                 cp2 = sp -> s_name; /* Add function name.   */
  267.                 while (*cp1++ = *cp2++)
  268.                     ;
  269.                 cp1--;
  270.                 while (cp1 < &buf[HENDCOL])
  271.                     *cp1++ = ' ';
  272.                 *cp1 = 0;
  273.                 i++;
  274.                 if (addline (buf) == FALSE)
  275.                     break; /* lets go with what we have */
  276.             }
  277.             sp = sp -> s_symp;
  278.         }
  279.     }
  280.     sort_buf (blistp, i);      /* sort buffer lines */
  281.     popblist ();
  282.     writ_echo (MSG_null);
  283.     /* make new window the current window */
  284.     wp = wheadp;
  285.     while (wp != NULL)
  286.     {
  287.         if (wp -> w_bufp == blistp)
  288.         {
  289.             curwp = wp;
  290.             curbp = wp -> w_bufp;
  291.             return (TRUE);
  292.         }
  293.         wp = wp -> w_wndp;
  294.     }
  295.     return (TRUE);
  296. }
  297.  
  298. /* check for BEAVFIL and read it in if found
  299. * - also, set local file variable for bindtokey for saving new defs
  300. * (this is some what of a hack as it only handles 'bindtokey' changes at
  301. * this time - also local file io !!!)
  302. */
  303. void check_extend (sfname)
  304.  
  305. char *sfname;    /* name of startup file (null if default) */
  306.  
  307. {
  308.     char *fname;    /* resulting file name to execute */
  309.     char    rc_name[NFILEN];    /* fixed up name of rc file */
  310.     char    *term;
  311.     char *getenv();
  312.     register    SYMBOL * sp;
  313.     char    funcname[NXNAME + 1];
  314.     char    keybind[NXNAME + 1];
  315.     int     keyval;
  316.     FILE * bindf;
  317.  
  318.     /* look up the startup file */
  319.     if ((sfname != NULL) && (*sfname != 0))
  320.         fname = flook(sfname, TRUE);
  321.     else
  322.     {
  323. #ifdef UNIX
  324.         /* hidden file under unix */
  325.         strcpy (&rc_name[0], ".");
  326.         strcpy (&rc_name[1], MSG_beavrc);
  327.  
  328.         if ((term = getenv("TERM")) != 0)
  329.         {
  330.             strcpy (&rc_name[strlen(rc_name)], ".");
  331.             strcpy (&rc_name[strlen(rc_name)], term);
  332.         }
  333.         fname = flook(rc_name, TRUE);
  334.         /* if fixed up name is not there then check original */
  335.         if (fname == NULL)
  336.         {
  337.             /* hidden file under unix */
  338.             strcpy (&rc_name[0], ".");
  339.             strcpy (&rc_name[1], MSG_beavrc);
  340.             fname = flook(rc_name, TRUE);
  341.         }
  342. #else
  343.         strcpy (rc_name, MSG_beavrc);
  344.         fname = flook(rc_name, TRUE);
  345. #ifdef AMIGA
  346.         /* look for .beavrc in the current directory */
  347.         if(!fname) {
  348.             rc_name[0] = '.';
  349.             strcpy (&rc_name[1], MSG_beavrc);
  350.             fname = flook(rc_name, TRUE);
  351.         }
  352.         /* look for .beavrc in S: */
  353.         if(!fname) {
  354.             /* Have a look in startup directory */
  355.             rc_name[0] = 'S';
  356.             rc_name[1] = ':';
  357.             rc_name[2] = '.';
  358.             strcpy (&rc_name[3], MSG_beavrc);
  359.             fname = flook(rc_name, TRUE);
  360.         }
  361. #endif /* AMIGA */
  362. #endif
  363.     }
  364.     /* if it isn't around, don't sweat it */
  365.     if (fname == NULL)
  366.         return;
  367.  
  368.     if (bindf = fopen(fname, "r"))
  369.     {
  370.         char    buffr[80];
  371.         char    *buffp;
  372.  
  373.         buffp = buffr;
  374.         while (fread (buffp++, sizeof(char), 1, bindf) == 1)
  375.         {
  376.             /* scanf is unhappy with commas */
  377.             if (buffp[-1] == ',')
  378.                 buffp[-1] = '-';
  379.  
  380.             /* did we get a whole line */
  381.             if (buffp[-1] == '\n')
  382.             {
  383.                 *buffp = 0;    /* terminate line */
  384.                 buffp = buffr;
  385.                 sscanf (buffr, "%s %s %x", funcname, keybind, &keyval);
  386.                 if ((buffr[0] == '#') || (keyval == 0))
  387.                     continue;
  388.                 if (sp = symlookup (funcname))
  389.                 {
  390.                     if (binding[keyval] != NULL)/* Unbind old, and  */
  391.                         --binding[keyval] -> s_nkey;
  392.                     binding[keyval] = sp;/* rebind new.      */
  393.                     ++sp -> s_nkey;
  394.                     sp -> s_modify |= SBOUND;    /* flag as altered key binding */
  395.                 }
  396.             }
  397.         }
  398.         fclose (bindf);
  399.     }
  400. }
  401.  
  402. /*    Look up the existance of a file along the normal or PATH
  403.     environment variable. Look first in the HOME directory if
  404.     asked and possible
  405. */
  406.  
  407. char *flook(fname, hflag)
  408.  
  409. char *fname;    /* base file name to search for */
  410. int hflag;    /* Look in the HOME environment variable first? */
  411.  
  412. {
  413.     register char *home;    /* path to home directory */
  414.     register char *path;    /* environmental PATH variable */
  415.     register char *sp;    /* pointer into path spec */
  416.     register int i;        /* index */
  417.     static char fspec[NFILEN * 2];    /* full path spec to search */
  418.     char *getenv();
  419.     FILE * bindf;
  420.  
  421.     if (hflag) {
  422.         home = getenv("HOME");
  423.         if (home != NULL) {
  424.             /* build home dir file spec */
  425.             strcpy(fspec, home);
  426.             if (fspec[strlen(fspec) - 1] != '/')
  427.                 strcat(fspec, "/");
  428.             strcat(fspec, fname);
  429.  
  430.             /* and try it out */
  431.             if (bindf = fopen(fspec, "r"))
  432.             {
  433.                 fclose(bindf);
  434.                 return(fspec);
  435.             }
  436.         }
  437.     }
  438.  
  439.     /* always try the current directory first */
  440.     if (bindf = fopen(fname, "r"))
  441.     {
  442.         fclose(bindf);
  443.         return(fname);
  444.     }
  445.  
  446.     /* get the PATH variable */
  447.     path = getenv("PATH");
  448.     if (path != NULL)
  449.         while (*path) {
  450.  
  451.             /* build next possible file spec */
  452.             sp = fspec;
  453.             while (*path && (*path != PATHCHR))
  454.                 *sp++ = *path++;
  455.  
  456.             /* add a terminating dir separator if we need it */
  457.             if (sp[-1] != SEPCHAR)
  458.                 *sp++ = SEPCHAR;
  459.  
  460.             *sp = 0;
  461.             strcat(fspec, fname);
  462.  
  463.             /* and try it out */
  464.             if (bindf = fopen(fspec, "r"))
  465.             {
  466.                 fclose(bindf);
  467.                 return(fspec);
  468.             }
  469.  
  470.             if (*path == PATHCHR)
  471.                 ++path;
  472.         }
  473.  
  474.     return(NULL);    /* no such luck */
  475. }
  476.  
  477.  
  478. /* interactive method for loading binding file
  479. * (uses above routine, obviously)
  480. */
  481. char    load_extend ()
  482. {
  483.  
  484. #ifdef CUSTOMIZE
  485.     register char   s;
  486.     char    fname[NFILEN];
  487.  
  488.     if ((s = ereply (MSG_bnd_file, fname, NFILEN, NULL)) != TRUE)
  489.         return (s);
  490.     check_extend (fname);
  491.     writ_echo (okmsg);
  492. #endif
  493.     return (TRUE);
  494. }
  495.  
  496. int     find_keyval (name)
  497. char   *name;
  498. {
  499.     SYMBOL * sp;
  500.     int     key;
  501.  
  502.     for (key = 0; key < NKEYS; ++key)
  503.     {
  504.         /* For all keys.    */
  505.         sp = binding[key];
  506.         if (sp != NULL && (strcmp (sp -> s_name, name) == 0))
  507.             return (key);
  508.     }
  509.     return (0);
  510. }
  511.