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