[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.4, Mon Jan 29 01:58:07 2001 UTC (23 years, 3 months ago) by niklas
Branch: MAIN
CVS Tags: OPENBSD_2_9_BASE, OPENBSD_2_9
Changes since 1.3: +2 -0 lines

$OpenBSD$

/*	$OpenBSD: help.c,v 1.4 2001/01/29 01:58:07 niklas Exp $	*/

/*
 * Help functions for Mg 2 
 */

#include "def.h"

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

static int	showall		__P((char *ind, KEYMAP *map));
static VOID	findbind	__P((PF, char *, KEYMAP *));
static VOID	bindfound	__P((void));

static BUFFER  *bp;
static char     buf[80];	/* used by showall and findbind */
static char     buf2[128];
static char    *buf2p;

/*
 * 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(f, n)
	int f, n;
{
	KEYMAP	*curmap;
	PF	 funct;
	int	 c, m, i;
	char	*pep;
	char	 prompt[80];

#ifndef NO_MACRO
	if (inmacro)
		return TRUE;	/* ignore inside keyboard macro */
#endif /* !NO_MACRO */
	(VOID)strcpy(prompt, "Describe key briefly: ");
	pep = prompt + strlen(prompt);
	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, key.k_chars[key.k_count++] =
			    c = getkey(FALSE));
			if ((funct = doscan(curmap, c)) != prefix)
				break;
			*pep++ = '-';
			*pep = '\0';
			curmap = ele->k_prefmap;
		}
		if (funct != rescan)
			break;
		if (ISUPPER(key.k_chars[key.k_count - 1])) {
			funct = doscan(curmap,
			    TOLOWER(key.k_chars[key.k_count - 1]));
			if (funct == prefix) {
				*pep++ = '-';
				*pep = '\0';
				curmap = ele->k_prefmap;
				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]);
			if (funct != prefix) {
				if (i == key.k_count - 1 && funct != rescan)
					goto found;
				funct = rescan;
				goto nextmode;
			}
			curmap = ele->k_prefmap;
		}
		*pep++ = '-';
		*pep = '\0';
	}
found:
	if (funct == rescan)
		ewprintf("%k is not bound to any function");
	else if ((pep = 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(f, n)
	int f, n;
{
	int		 m;
	static char	 locbind[80] = "Local keybindings for mode ";

	bp = bfind("*help*", TRUE);
	if (bclear(bp) != TRUE)
		/* clear it out */
		return FALSE;
	for (m = curbp->b_nmodes; m > 0; m--) {
		(VOID)strcpy(&locbind[27], curbp->b_modes[m]->p_name);
		(VOID)strcat(&locbind[27], ":");
		if ((addline(bp, locbind) == FALSE) ||
		    (showall(buf, curbp->b_modes[m]->p_map) == FALSE) ||
		    (addline(bp, "") == FALSE))
			return FALSE;
	}
	if ((addline(bp, "Global bindings:") == FALSE) ||
	    (showall(buf, map_table[0].p_map) == FALSE))
		return FALSE;
	return popbuftop(bp);
}

static int
showall(ind, map)
	char   *ind;
	KEYMAP *map;
{
	MAP_ELEMENT	*ele;
	PF		 functp;
	int		 i, last;
	char		*cp, *cp2;

	if (addline(bp, "") == FALSE)
		return FALSE;
	last = -1;
	for (ele = &map->map_element[0]; 
	    ele < &map->map_element[map->map_num]; ele++) {
		if (map->map_default != rescan && ++last < ele->k_base) {
			cp = keyname(ind, last);
			if (last < ele->k_base - 1) {
				(VOID)strcpy(cp, " .. ");
				cp = keyname(cp + 4, ele->k_base - 1);
			}
			do {
				*cp++ = ' ';
			} while (cp < &buf[16]);
			(VOID)strcpy(cp, function_name(map->map_default));
			if (addline(bp, buf) == FALSE)
				return FALSE;
		}
		last = ele->k_num;
		for (i = ele->k_base; i <= last; i++) {
			functp = ele->k_funcp[i - ele->k_base];
			if (functp != rescan) {
				if (functp != prefix)
					cp2 = function_name(functp);
				else
					cp2 = map_name(ele->k_prefmap);
				if (cp2 != NULL) {
					cp = keyname(ind, i);
					do {
						*cp++ = ' ';
					} while (cp < &buf[16]);
					(VOID)strcpy(cp, cp2);
					if (addline(bp, buf) == FALSE)
						return FALSE;
				}
			}
		}
	}
	for (ele = &map->map_element[0]; 
	    ele < &map->map_element[map->map_num]; ele++) {
		if (ele->k_prefmap != NULL) {
			for (i = ele->k_base;
			    ele->k_funcp[i - ele->k_base] != prefix; i++) {
				if (i >= ele->k_num)
					/* damaged map */
					return FALSE;
			}
			cp = keyname(ind, i);
			*cp++ = ' ';
			if (showall(cp, ele->k_prefmap) == FALSE)
				return FALSE;
		}
	}
	return TRUE;
}

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

	if ((kp = name_map("help")) == NULL)
		return FALSE;
	ewprintf("a b c: ");
	do {
		funct = doscan(kp, getkey(FALSE));
	} 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(f, n)
	int f, n;
{
	BUFFER		*bp;
	FUNCTNAMES	*fnp;
	char		*cp1, *cp2;
	char		 string[32];

	if (eread("apropos: ", string, sizeof(string), EFNEW) == ABORT)
		return ABORT;
	/* FALSE means we got a 0 character string, which is fine */
	bp = bfind("*help*", TRUE);
	if (bclear(bp) == FALSE)
		return FALSE;
	for (fnp = &functnames[0]; fnp < &functnames[nfunct]; fnp++) {
		for (cp1 = fnp->n_name; *cp1; cp1++) {
			cp2 = string;
			while (*cp2 && *cp1 == *cp2)
				cp1++, cp2++;
			if (!*cp2) {
				(VOID)strcpy(buf2, fnp->n_name);
				buf2p = &buf2[strlen(buf2)];
				findbind(fnp->n_funct, buf, map_table[0].p_map);
				if (addline(bp, buf2) == FALSE)
					return FALSE;
				break;
			} else
				cp1 -= cp2 - string;
		}
	}
	return popbuftop(bp);
}

static VOID
findbind(funct, ind, map)
	KEYMAP *map;
	PF      funct;
	char   *ind;
{
	MAP_ELEMENT	*ele;
	int		 i, last;
	char		*cp;

	last = -1;
	for (ele = &map->map_element[0]; 
	    ele < &map->map_element[map->map_num]; ele++) {
		if (map->map_default == funct && ++last < ele->k_base) {
			cp = keyname(ind, last);
			if (last < ele->k_base - 1) {
				(VOID)strcpy(cp, " .. ");
				(VOID)keyname(cp + 4, ele->k_base - 1);
			}
			bindfound();
		}
		last = ele->k_num;
		for (i = ele->k_base; i <= last; i++) {
			if (funct == ele->k_funcp[i - ele->k_base]) {
				if (funct == prefix) {
					cp = map_name(ele->k_prefmap);
					if (!cp ||
					    strncmp(cp, buf2, strlen(cp)) != 0)
						continue;
				}
				(VOID)keyname(ind, i);
				bindfound();
			}
		}
	}
	for (ele = &map->map_element[0]; 
	    ele < &map->map_element[map->map_num]; ele++) {
		if (ele->k_prefmap != NULL) {
			for (i = ele->k_base;
			    ele->k_funcp[i - ele->k_base] != prefix; i++) {
				if (i >= ele->k_num)
					/* damaged */
					return;
			}
			cp = keyname(ind, i);
			*cp++ = ' ';
			findbind(funct, cp, ele->k_prefmap);
		}
	}
}

static VOID
bindfound()
{
	if (buf2p < &buf2[32]) {
		do {
			*buf2p++ = ' ';
		} while (buf2p < &buf2[32]);
	} else {
		*buf2p++ = ',';
		*buf2p++ = ' ';
	}
	(VOID)strcpy(buf2p, buf);
	buf2p += strlen(buf);
}
#endif /* !NO_HELP */