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