/* * Extended (M-X) commands. */ #include #include "def.h" extern char MSG_not_now[]; extern char MSG_func[]; extern char MSG_unk_func[]; extern char MSG_cmd_t_ex[]; extern char MSG_unk_ext[]; extern char MSG_d_b[]; extern char MSG_unbd[]; extern char MSG_bnd_to[]; extern char MSG_ins_self[]; extern char MSG_bnd_file[]; extern char MSG_bld_wall[]; extern char MSG_wall_head[]; extern char MSG_beavrc[]; extern char MSG_null[]; extern char MSG_extended_command[]; extern char MSG_unk_rc[]; #ifdef CUSTOMIZE char *flook (); //static char *bindnm = //{ // 0 //}; /* file name for customized key bindings */ #endif /* * This function modifies the keyboard * binding table, by adjusting the entries in the * big "bindings" array. Most of the grief deals with the * prompting for additional arguments. This code does not * work right if there is a keyboard macro floating around. * Should be fixed. */ bool bindtokey () { register int s; register SYMBOL *sp; register int c; char xname[NXNAME]; #ifdef CUSTOMIZE char xname2[NXNAME]; #endif if (kbdmip != NULL || kbdmop != NULL) { writ_echo (MSG_not_now); return (FALSE); } if ((s = eread (MSG_func, xname, NXNAME, EFAUTO, NULL)) != TRUE) return (s); if ((sp = symlookup (xname)) == NULL) { writ_echo (MSG_unk_func); return (FALSE); } #ifdef CUSTOMIZE strcpy (xname2, xname); #endif eputc (' '); eputc ('K'); eputc ('e'); eputc ('y'); eputc (':'); eputc (' '); ttflush (); c = getkey (); /* Read key. */ keyname (xname, c); /* Display keyname. */ eputs (xname); ttflush (); if (binding[c] != NULL) /* Unbind old, and */ --binding[c]->s_nkey; binding[c] = sp; /* rebind new. */ ++sp->s_nkey; sp->s_modify |= SBOUND; /* flag as altered key binding */ return (TRUE); } /* * Extended command. Call the message line * routine to read in the command name and apply autocompletion * to it. When it comes back, look the name up in the symbol table * and run the command if it is found and has the right type. * Print an error if there is anything wrong. */ char extend (f, n, k) int f, n, k; { register SYMBOL *sp; register char s; char xname[NXNAME]; if ((s = eread (MSG_cmd_t_ex, xname, NXNAME, EFNEW | EFAUTO, NULL)) != TRUE) return (s); if ((sp = symlookup (xname)) != NULL) return ((*sp->s_funcp) (f, n, KRANDOM)); writ_echo (MSG_unk_ext); return (ABORT); } /* * Read a key from the keyboard, and look it * up in the binding table. Display the name of the function * currently bound to the key. Say that the key is not bound * if it is indeed not bound, or if the type is not a * "builtin". This is a bit of overkill, because this is the * only kind of function there is. */ bool help () { register SYMBOL *sp; register int c; char b[20]; char buf[80]; writ_echo (MSG_d_b); c = getkey (); keyname (b, c); if ((sp = binding[c]) == NULL) { sprintf (buf, MSG_unbd, b); writ_echo (buf); } else { sprintf (buf, MSG_bnd_to, b, sp->s_name); writ_echo (buf); } return (TRUE); } /* * Sort the lines in the buffer. */ void sort_buf (b_ptr, cnt) BUFFER *b_ptr; int cnt; { LINE *lp1, *lp2; bool no_swap; int loop1, loop2; for (loop1 = cnt; loop1 > 0; loop1--) { no_swap = TRUE; lp1 = b_ptr->b_linep->l_fp; /* point to first line */ lp2 = lp1->l_fp; /* point to next line */ for (loop2 = 0; loop2 <= loop1; loop2++) { /* compare strings and swap if necessary */ if (0 < strcmp (&lp1->l_text[HFUNCCOL], &lp2->l_text[HFUNCCOL])) { lp1->l_bp->l_fp = lp2; /* get pointer to first string */ lp2->l_fp->l_bp = lp1; /* make it point to second string */ lp1->l_fp = lp2->l_fp; lp2->l_bp = lp1->l_bp; lp1->l_bp = lp2; lp2->l_fp = lp1; lp2->l_file_offset = lp1->l_file_offset; lp1->l_file_offset = lp2->l_file_offset + lp2->l_used; no_swap = FALSE; } else { /* if no swap then advance both pointers */ lp1 = lp2; } lp2 = lp1->l_fp; } /* quick exit if sort is finished sooner than expected */ if (no_swap) { return; } } } /* * This function creates a table, listing all * of the command keys and their current bindings, and stores * the table in the standard pop-op buffer (the one used by the * directory list command, the buffer list command, etc.). This * lets the editor produce it's own wall chart. The bindings to * "ins-self" are only displayed if there is an argument. */ char wallchart (f, n, k) int f, n, k; { register char s; register int key, i, j; register SYMBOL *sp; register char *cp1; register char *cp2; char buf[64]; WINDOW *wp; if ((s = bclear (blistp)) != TRUE) /* Clear it out. */ return (s); i = 0; (void) strcpy (blistp->b_fname, MSG_null); blistp->b_flag = BFVIEW; blistp->b_type = BTHELP; writ_echo (MSG_bld_wall); sprintf (buf, MSG_wall_head); if (addline (buf) == FALSE) return (FALSE); for (key = 0; key < NKEYS; ++key) { /* For all keys. */ sp = binding[key]; if (sp != NULL && (f != FALSE || strcmp (sp->s_name, MSG_ins_self) != 0)) { cp1 = &buf[0]; while (cp1 < &buf[HFUNCCOL]) /* Goto column 3. */ *cp1++ = ' '; if ((sp->s_modify & SBOUND) == 0) /* comment out default binding */ buf[0] = '#'; cp2 = sp->s_name; /* Add function name. */ while ((*cp1++ = *cp2++)) ; cp1--; while (cp1 < &buf[HKEY]) /* Goto column 32. */ *cp1++ = ' '; keyname (&buf[HKEY], key); cp1 = &buf[strlen (buf)]; while (cp1 < &buf[HKEYCODE]) /* Goto column 50. */ *cp1++ = ' '; sprintf (&buf[HKEYCODE], "%4X", key); if (addline (buf) == FALSE) break; /* lets go with what we have */ i++; } } /* list unbound functions lest they get lost */ for (j = 0; j < NSHASH; j++) { sp = symbol[j]; while (sp != NULL) { if (sp->s_nkey == 0) { cp1 = &buf[0]; while (cp1 < &buf[HFUNCCOL]) /* Goto column 3. */ *cp1++ = ' '; buf[0] = '#'; cp2 = sp->s_name; /* Add function name. */ while ((*cp1++ = *cp2++)) ; cp1--; while (cp1 < &buf[HENDCOL]) *cp1++ = ' '; *cp1 = 0; i++; if (addline (buf) == FALSE) break; /* lets go with what we have */ } sp = sp->s_symp; } } sort_buf (blistp, i); /* sort buffer lines */ popblist (); writ_echo (MSG_null); /* make new window the current window */ wp = wheadp; while (wp != NULL) { if (wp->w_bufp == blistp) { curwp = wp; curbp = wp->w_bufp; return (TRUE); } wp = wp->w_wndp; } return (TRUE); } /* check for RC file and read it in if found * - also, set local file variable for bindtokey for saving new defs * (this is some what of a hack as it only handles 'bindtokey' changes at * this time - also local file io !!!) */ void check_extend (sfname) char *sfname; /* name of startup file (null if default) */ { char *fname; /* resulting file name to execute */ char rc_name[NFILEN]; /* fixed up name of rc file */ char *term; char *getenv (); register SYMBOL *sp; char funcname[NXNAME + 1]; char keybind[NXNAME + 1]; int keyval; FILE *bindf; /* look up the startup file */ if ((sfname != NULL) && (*sfname != 0)) fname = flook (sfname, TRUE); else { #ifdef UNIX /* hidden file under unix */ strcpy (&rc_name[0], "."); strcpy (&rc_name[1], MSG_beavrc); if ((term = getenv ("TERM")) != 0) { strcpy (&rc_name[strlen (rc_name)], "."); strcpy (&rc_name[strlen (rc_name)], term); } fname = flook (rc_name, TRUE); /* if fixed up name is not there then check original */ if (fname == NULL) { /* hidden file under unix */ strcpy (&rc_name[0], "."); strcpy (&rc_name[1], MSG_beavrc); fname = flook (rc_name, TRUE); } #else strcpy (rc_name, MSG_beavrc); fname = flook (rc_name, TRUE); #ifdef AMIGA /* look for .beavrc in the current directory */ if (!fname) { rc_name[0] = '.'; strcpy (&rc_name[1], MSG_beavrc); fname = flook (rc_name, TRUE); } /* look for .beavrc in S: */ if (!fname) { /* Have a look in startup directory */ rc_name[0] = 'S'; rc_name[1] = ':'; rc_name[2] = '.'; strcpy (&rc_name[3], MSG_beavrc); fname = flook (rc_name, TRUE); } #endif /* AMIGA */ #endif } /* if it isn't around, don't sweat it */ if (fname == NULL) return; if ((bindf = fopen (fname, "r"))) { char buffr[80]; char *buffp; buffp = buffr; while (fread (buffp++, sizeof (char), 1, bindf) == 1) { /* scanf is unhappy with commas */ if (buffp[-1] == ',') buffp[-1] = '-'; /* did we get a whole line */ if (buffp[-1] == '\n') { *buffp = 0; /* terminate line */ buffp = buffr; sscanf (buffr, "%s %s %x", funcname, keybind, &keyval); if ((buffr[0] == '#') || (keyval == 0)) continue; /* check if this is a command to execute */ if ((strcmp (funcname, MSG_extended_command) == 0) && (keybind[0] > 'Z')) { if ((sp = symlookup (keybind)) != NULL) (*sp->s_funcp) (TRUE, keyval, KRANDOM); else { char temp_b[40]; sprintf (temp_b, "%s %s", MSG_unk_rc, keybind); writ_echo (temp_b); } } else { if ((sp = symlookup (funcname))) { if (binding[keyval] != NULL) /* Unbind old, and */ --binding[keyval]->s_nkey; binding[keyval] = sp; /* rebind new. */ ++sp->s_nkey; sp->s_modify |= SBOUND; /* flag as altered key binding */ } } } } fclose (bindf); } } /* Look up the existance of a file along the normal or PATH environment variable. Look first in the HOME directory if asked and possible */ char * flook (fname, hflag) char *fname; /* base file name to search for */ int hflag; /* Look in the HOME environment variable first? */ { register char *home; /* path to home directory */ register char *path; /* environmental PATH variable */ register char *sp; /* pointer into path spec */ //register int i; /* index */ static char fspec[NFILEN * 2]; /* full path spec to search */ char *getenv (); FILE *bindf; if (hflag) { home = getenv ("HOME"); if (home != NULL) { /* build home dir file spec */ strcpy (fspec, home); if (fspec[strlen (fspec) - 1] != '/') strcat (fspec, "/"); strcat (fspec, fname); /* and try it out */ if ((bindf = fopen (fspec, "r"))) { fclose (bindf); return (fspec); } } } /* always try the current directory first */ if ((bindf = fopen (fname, "r"))) { fclose (bindf); return (fname); } /* get the PATH variable */ path = getenv ("PATH"); if (path != NULL) while (*path) { /* build next possible file spec */ sp = fspec; while (*path && (*path != PATHCHR)) *sp++ = *path++; /* add a terminating dir separator if we need it */ if (sp[-1] != SEPCHAR) *sp++ = SEPCHAR; *sp = 0; strcat (fspec, fname); /* and try it out */ if ((bindf = fopen (fspec, "r"))) { fclose (bindf); return (fspec); } if (*path == PATHCHR) ++path; } return (NULL); /* no such luck */ } /* interactive method for loading binding file * (uses above routine, obviously) */ char load_extend () { #ifdef CUSTOMIZE register char s; char fname[NFILEN]; if ((s = ereply (MSG_bnd_file, fname, NFILEN, NULL)) != TRUE) return (s); check_extend (fname); writ_echo (okmsg); #endif return (TRUE); } int find_keyval (name) char *name; { SYMBOL *sp; int key; for (key = 0; key < NKEYS; ++key) { /* For all keys. */ sp = binding[key]; if (sp != NULL && (strcmp (sp->s_name, name) == 0)) return (key); } return (0); }