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