help.c revision 1.12
1/*	$OpenBSD: help.c,v 1.12 2001/05/24 03:05:23 mickey Exp $	*/
2
3/*
4 * Help functions for Mg 2
5 */
6
7#include "def.h"
8
9#ifndef NO_HELP
10#include "kbd.h"
11#include "key.h"
12#ifndef NO_MACRO
13#include "macro.h"
14#endif /* !NO_MACRO */
15
16static int	showall(BUFFER *, KEYMAP *, char *);
17static int	findbind(KEYMAP *, PF, char *, size_t);
18
19/*
20 * Read a key from the keyboard, and look it up in the keymap.
21 * Display the name of the function currently bound to the key.
22 */
23/* ARGSUSED */
24int
25desckey(f, n)
26	int f, n;
27{
28	KEYMAP	*curmap;
29	PF	 funct;
30	int	 c, m, i;
31	char	*pep;
32	char	 prompt[80];
33
34#ifndef NO_MACRO
35	if (inmacro)
36		return TRUE;	/* ignore inside keyboard macro */
37#endif /* !NO_MACRO */
38	pep = prompt + strlcpy(prompt, "Describe key briefly: ", sizeof(prompt));
39	key.k_count = 0;
40	m = curbp->b_nmodes;
41	curmap = curbp->b_modes[m]->p_map;
42	for (;;) {
43		for (;;) {
44			ewprintf("%s", prompt);
45			pep[-1] = ' ';
46			pep = keyname(pep, sizeof(prompt) - (pep - prompt),
47			    key.k_chars[key.k_count++] = c = getkey(FALSE));
48			if ((funct = doscan(curmap, c, &curmap)) != NULL)
49				break;
50			*pep++ = '-';
51			*pep = '\0';
52		}
53		if (funct != rescan)
54			break;
55		if (ISUPPER(key.k_chars[key.k_count - 1])) {
56			funct = doscan(curmap,
57			    TOLOWER(key.k_chars[key.k_count - 1]), &curmap);
58			if (funct == NULL) {
59				*pep++ = '-';
60				*pep = '\0';
61				continue;
62			}
63			if (funct != rescan)
64				break;
65		}
66nextmode:
67		if (--m < 0)
68			break;
69		curmap = curbp->b_modes[m]->p_map;
70		for (i = 0; i < key.k_count; i++) {
71			funct = doscan(curmap, key.k_chars[i], &curmap);
72			if (funct != NULL) {
73				if (i == key.k_count - 1 && funct != rescan)
74					goto found;
75				funct = rescan;
76				goto nextmode;
77			}
78		}
79		*pep++ = '-';
80		*pep = '\0';
81	}
82found:
83	if (funct == rescan || funct == selfinsert)
84		ewprintf("%k is not bound to any function");
85	else if ((pep = function_name(funct)) != NULL)
86		ewprintf("%k runs the command %s", pep);
87	else
88		ewprintf("%k is bound to an unnamed function");
89	return TRUE;
90}
91
92/*
93 * This function creates a table, listing all of the command
94 * keys and their current bindings, and stores the table in the
95 * *help* pop-up buffer.  This lets Mg produce it's own wall chart.
96 */
97/* ARGSUSED */
98int
99wallchart(f, n)
100	int f, n;
101{
102	int		 m;
103	BUFFER		*bp;
104
105	bp = bfind("*help*", TRUE);
106	if (bclear(bp) != TRUE)
107		/* clear it out */
108		return FALSE;
109	for (m = curbp->b_nmodes; m > 0; m--) {
110		if ((addlinef(bp, "Local keybindings for mode %s:",
111				curbp->b_modes[m]->p_name) == FALSE) ||
112		    (showall(bp, curbp->b_modes[m]->p_map, "") == FALSE) ||
113		    (addline(bp, "") == FALSE))
114			return FALSE;
115	}
116	if ((addline(bp, "Global bindings:") == FALSE) ||
117	    (showall(bp, fundamental_map, "") == FALSE))
118		return FALSE;
119	return popbuftop(bp);
120}
121
122static int
123showall(BUFFER *bp, KEYMAP *map, char *prefix)
124{
125	KEYMAP *newmap;
126	char buf[80], key[16];
127	PF fun;
128	int c;
129
130	if (addline(bp, "") == FALSE)
131		return FALSE;
132
133	/* XXX - 256 ? */
134	for (c = 0; c < 256; c++) {
135		fun = doscan(map, c, &newmap);
136		if (fun == rescan || fun == selfinsert)
137			continue;
138		keyname(buf, c, sizeof(buf));
139		sprintf(key, "%s%s ", prefix, buf);
140		if (fun == NULL) {
141			if (showall(bp, newmap, key) == FALSE)
142				return FALSE;
143		} else {
144			if (addlinef(bp, "%-16s%s", key,
145				    function_name(fun)) == FALSE)
146				return FALSE;
147		}
148	}
149
150	return TRUE;
151}
152
153int
154help_help(f, n)
155	int f, n;
156{
157	KEYMAP	*kp;
158	PF	 funct;
159
160	if ((kp = name_map("help")) == NULL)
161		return FALSE;
162	ewprintf("a b c: ");
163	do {
164		funct = doscan(kp, getkey(FALSE), NULL);
165	} while (funct == NULL || funct == help_help);
166#ifndef NO_MACRO
167	if (macrodef && macrocount < MAXMACRO)
168		macro[macrocount - 1].m_funct = funct;
169#endif /* !NO_MACRO */
170	return (*funct)(f, n);
171}
172
173/* ARGSUSED */
174int
175apropos_command(f, n)
176	int f, n;
177{
178	BUFFER		*bp;
179	LIST		*fnames, *el;
180	char		 string[32];
181
182	if (eread("apropos: ", string, sizeof(string), EFNEW) == ABORT)
183		return ABORT;
184	/* FALSE means we got a 0 character string, which is fine */
185	bp = bfind("*help*", TRUE);
186	if (bclear(bp) == FALSE)
187		return FALSE;
188
189	fnames = complete_function_list("", NULL);
190	for (el = fnames; el != NULL; el = el->l_next) {
191		char buf[32];
192
193		if (strstr(el->l_name, string) == NULL)
194			continue;
195
196		buf[0] = '\0';
197		findbind(fundamental_map, name_function(el->l_name),
198		    buf, sizeof(buf));
199
200		if (addlinef(bp, "%-32s%s", el->l_name,  buf) == FALSE) {
201			free_file_list(fnames);
202			return FALSE;
203		}
204	}
205	free_file_list(fnames);
206	return popbuftop(bp);
207}
208
209static int
210findbind(KEYMAP *map, PF fun, char *buf, size_t len)
211{
212	KEYMAP *newmap;
213	PF nfun;
214	char buf2[16], key[16];
215	int c;
216
217	/* XXX - 256 ? */
218	for (c = 0; c < 256; c++) {
219		nfun = doscan(map, c, &newmap);
220		if (nfun == fun) {
221			keyname(buf, c, len);
222			return TRUE;
223		}
224		if (nfun == NULL) {
225			if (findbind(newmap, fun, buf2, sizeof(buf2)) == TRUE) {
226				keyname(key, c, sizeof(key));
227				snprintf(buf, len, "%s %s", key, buf2);
228				return TRUE;
229			}
230		}
231	}
232
233	return FALSE;
234}
235#endif /* !NO_HELP */
236