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