[BACK]Return to help.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

File: [local] / src / usr.bin / mg / help.c (download)

Revision 1.25, Tue Aug 9 00:53:48 2005 UTC (18 years, 10 months ago) by kjell
Branch: MAIN
CVS Tags: OPENBSD_3_8_BASE, OPENBSD_3_8
Changes since 1.24: +3 -2 lines

Clean up eread handling in mg. (basically, fallout from the 'enter often
means abort' behaviour added during the hackathon). Eliminates
redundant ereply function, fixes miscellaneous cores when aborting,
and move a number of assumed pathnames into the prompt text, since
they are used there anyway. All changes consistent with emacs behavior

ok beck@ many, many moons ago.

/*	$OpenBSD: help.c,v 1.25 2005/08/09 00:53:48 kjell Exp $	*/

/* This file is in the public domain. */

/*
 * Help functions for Mg 2
 */

#include "def.h"
#include "funmap.h"

#ifndef NO_HELP
#include "kbd.h"
#include "key.h"
#ifndef NO_MACRO
#include "macro.h"
#endif /* !NO_MACRO */

static int	showall(BUFFER *, KEYMAP *, char *);
static int	findbind(KEYMAP *, PF, char *, size_t);

/*
 * Read a key from the keyboard, and look it up in the keymap.
 * Display the name of the function currently bound to the key.
 */
/* ARGSUSED */
int
desckey(int f, int n)
{
	KEYMAP	*curmap;
	PF	 funct;
	int	 c, m, i, num;
	char	*pep;
	char	 prompt[80];

#ifndef NO_MACRO
	if (inmacro)
		return (TRUE);	/* ignore inside keyboard macro */
#endif /* !NO_MACRO */
	num = strlcpy(prompt, "Describe key briefly: ", sizeof(prompt));
	if (num >= sizeof(prompt))
		num = sizeof(prompt) - 1;
	pep = prompt + num;
	key.k_count = 0;
	m = curbp->b_nmodes;
	curmap = curbp->b_modes[m]->p_map;
	for (;;) {
		for (;;) {
			ewprintf("%s", prompt);
			pep[-1] = ' ';
			pep = keyname(pep, sizeof(prompt) - (pep - prompt),
			    key.k_chars[key.k_count++] = c = getkey(FALSE));
			if ((funct = doscan(curmap, c, &curmap)) != NULL)
				break;
			*pep++ = '-';
			*pep = '\0';
		}
		if (funct != rescan)
			break;
		if (ISUPPER(key.k_chars[key.k_count - 1])) {
			funct = doscan(curmap,
			    TOLOWER(key.k_chars[key.k_count - 1]), &curmap);
			if (funct == NULL) {
				*pep++ = '-';
				*pep = '\0';
				continue;
			}
			if (funct != rescan)
				break;
		}
nextmode:
		if (--m < 0)
			break;
		curmap = curbp->b_modes[m]->p_map;
		for (i = 0; i < key.k_count; i++) {
			funct = doscan(curmap, key.k_chars[i], &curmap);
			if (funct != NULL) {
				if (i == key.k_count - 1 && funct != rescan)
					goto found;
				funct = rescan;
				goto nextmode;
			}
		}
		*pep++ = '-';
		*pep = '\0';
	}
found:
	if (funct == rescan || funct == selfinsert)
		ewprintf("%k is not bound to any function");
	else if ((pep = (char *)function_name(funct)) != NULL)
		ewprintf("%k runs the command %s", pep);
	else
		ewprintf("%k is bound to an unnamed function");
	return (TRUE);
}

/*
 * This function creates a table, listing all of the command
 * keys and their current bindings, and stores the table in the
 * *help* pop-up buffer.  This lets Mg produce it's own wall chart.
 */
/* ARGSUSED */
int
wallchart(int f, int n)
{
	int		 m;
	BUFFER		*bp;

	bp = bfind("*help*", TRUE);
	if (bclear(bp) != TRUE)
		/* clear it out */
		return (FALSE);
	bp->b_flag |= BFREADONLY;
	for (m = curbp->b_nmodes; m > 0; m--) {
		if ((addlinef(bp, "Local keybindings for mode %s:",
				curbp->b_modes[m]->p_name) == FALSE) ||
		    (showall(bp, curbp->b_modes[m]->p_map, "") == FALSE) ||
		    (addline(bp, "") == FALSE))
			return (FALSE);
	}
	if ((addline(bp, "Global bindings:") == FALSE) ||
	    (showall(bp, fundamental_map, "") == FALSE))
		return (FALSE);
	return (popbuftop(bp));
}

static int
showall(BUFFER *bp, KEYMAP *map, char *prefix)
{
	KEYMAP	*newmap;
	char	 buf[80], key[16];
	PF	 fun;
	int	 c;

	if (addline(bp, "") == FALSE)
		return (FALSE);

	/* XXX - 256 ? */
	for (c = 0; c < 256; c++) {
		fun = doscan(map, c, &newmap);
		if (fun == rescan || fun == selfinsert)
			continue;
		keyname(buf, sizeof(buf), c);
		(void)snprintf(key, sizeof(key), "%s%s ", prefix, buf);
		if (fun == NULL) {
			if (showall(bp, newmap, key) == FALSE)
				return (FALSE);
		} else {
			if (addlinef(bp, "%-16s%s", key,
				    function_name(fun)) == FALSE)
				return (FALSE);
		}
	}
	return (TRUE);
}

int
help_help(int f, int n)
{
	KEYMAP	*kp;
	PF	 funct;

	if ((kp = name_map("help")) == NULL)
		return (FALSE);
	ewprintf("a b c: ");
	do {
		funct = doscan(kp, getkey(FALSE), NULL);
	} while (funct == NULL || funct == help_help);
#ifndef NO_MACRO
	if (macrodef && macrocount < MAXMACRO)
		macro[macrocount - 1].m_funct = funct;
#endif /* !NO_MACRO */
	return ((*funct)(f, n));
}

/* ARGSUSED */
int
apropos_command(int f, int n)
{
	BUFFER		*bp;
	LIST		*fnames, *el;
	char		 string[32], *bufp;

	if ((bufp = eread("apropos: ", string, sizeof(string),
	   EFNUL | EFNEW)) == NULL)
		return (ABORT);
	/* FALSE means we got a 0 character string, which is fine */
	bp = bfind("*help*", TRUE);
	if (bclear(bp) == FALSE)
		return (FALSE);

	fnames = complete_function_list("");
	for (el = fnames; el != NULL; el = el->l_next) {
		char buf[32];

		if (strstr(el->l_name, string) == NULL)
			continue;

		buf[0] = '\0';
		findbind(fundamental_map, name_function(el->l_name),
		    buf, sizeof(buf));

		if (addlinef(bp, "%-32s%s", el->l_name,  buf) == FALSE) {
			free_file_list(fnames);
			return (FALSE);
		}
	}
	free_file_list(fnames);
	return (popbuftop(bp));
}

static int
findbind(KEYMAP *map, PF fun, char *buf, size_t len)
{
	KEYMAP	*newmap;
	PF	 nfun;
	char	 buf2[16], key[16];
	int	 c;

	/* XXX - 256 ? */
	for (c = 0; c < 256; c++) {
		nfun = doscan(map, c, &newmap);
		if (nfun == fun) {
			keyname(buf, len, c);
			return (TRUE);
		}
		if (nfun == NULL) {
			if (findbind(newmap, fun, buf2, sizeof(buf2)) == TRUE) {
				keyname(key, sizeof(key), c);
				(void)snprintf(buf, len, "%s %s", key, buf2);
				return (TRUE);
			}
		}
	}
	return (FALSE);
}
#endif /* !NO_HELP */