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