help.c revision 1.7
1/* $OpenBSD: help.c,v 1.7 2001/05/23 21:01:16 art 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 __P((char *ind, KEYMAP *map)); 17static VOID findbind __P((PF, char *, KEYMAP *)); 18static VOID bindfound __P((void)); 19 20static BUFFER *bp; 21static char buf[80]; /* used by showall and findbind */ 22static char buf2[128]; 23static char *buf2p; 24 25/* 26 * Read a key from the keyboard, and look it up in the keymap. 27 * Display the name of the function currently bound to the key. 28 */ 29/* ARGSUSED */ 30int 31desckey(f, n) 32 int f, n; 33{ 34 KEYMAP *curmap; 35 PF funct; 36 int c, m, i; 37 char *pep; 38 char prompt[80]; 39 40#ifndef NO_MACRO 41 if (inmacro) 42 return TRUE; /* ignore inside keyboard macro */ 43#endif /* !NO_MACRO */ 44 (VOID)strcpy(prompt, "Describe key briefly: "); 45 pep = prompt + strlen(prompt); 46 key.k_count = 0; 47 m = curbp->b_nmodes; 48 curmap = curbp->b_modes[m]->p_map; 49 for (;;) { 50 for (;;) { 51 ewprintf("%s", prompt); 52 pep[-1] = ' '; 53 pep = keyname(pep, key.k_chars[key.k_count++] = 54 c = getkey(FALSE)); 55 if ((funct = doscan(curmap, c, &curmap)) != NULL) 56 break; 57 *pep++ = '-'; 58 *pep = '\0'; 59 } 60 if (funct != rescan) 61 break; 62 if (ISUPPER(key.k_chars[key.k_count - 1])) { 63 funct = doscan(curmap, 64 TOLOWER(key.k_chars[key.k_count - 1]), &curmap); 65 if (funct == NULL) { 66 *pep++ = '-'; 67 *pep = '\0'; 68 continue; 69 } 70 if (funct != rescan) 71 break; 72 } 73nextmode: 74 if (--m < 0) 75 break; 76 curmap = curbp->b_modes[m]->p_map; 77 for (i = 0; i < key.k_count; i++) { 78 funct = doscan(curmap, key.k_chars[i], &curmap); 79 if (funct != NULL) { 80 if (i == key.k_count - 1 && funct != rescan) 81 goto found; 82 funct = rescan; 83 goto nextmode; 84 } 85 } 86 *pep++ = '-'; 87 *pep = '\0'; 88 } 89found: 90 if (funct == rescan || funct == selfinsert) 91 ewprintf("%k is not bound to any function"); 92 else if ((pep = function_name(funct)) != NULL) 93 ewprintf("%k runs the command %s", pep); 94 else 95 ewprintf("%k is bound to an unnamed function"); 96 return TRUE; 97} 98 99/* 100 * This function creates a table, listing all of the command 101 * keys and their current bindings, and stores the table in the 102 * *help* pop-up buffer. This lets Mg produce it's own wall chart. 103 */ 104/* ARGSUSED */ 105int 106wallchart(f, n) 107 int f, n; 108{ 109 int m; 110 static char locbind[80] = "Local keybindings for mode "; 111 112 bp = bfind("*help*", TRUE); 113 if (bclear(bp) != TRUE) 114 /* clear it out */ 115 return FALSE; 116 for (m = curbp->b_nmodes; m > 0; m--) { 117 (VOID)strcpy(&locbind[27], curbp->b_modes[m]->p_name); 118 (VOID)strcat(&locbind[27], ":"); 119 if ((addline(bp, locbind) == FALSE) || 120 (showall(buf, curbp->b_modes[m]->p_map) == FALSE) || 121 (addline(bp, "") == FALSE)) 122 return FALSE; 123 } 124 if ((addline(bp, "Global bindings:") == FALSE) || 125 (showall(buf, map_table[0].p_map) == FALSE)) 126 return FALSE; 127 return popbuftop(bp); 128} 129 130static int 131showall(ind, map) 132 char *ind; 133 KEYMAP *map; 134{ 135 MAP_ELEMENT *ele; 136 PF functp; 137 int i, last; 138 char *cp, *cp2; 139 140 if (addline(bp, "") == FALSE) 141 return FALSE; 142 last = -1; 143 for (ele = &map->map_element[0]; 144 ele < &map->map_element[map->map_num]; ele++) { 145 if (map->map_default != rescan && ++last < ele->k_base) { 146 cp = keyname(ind, last); 147 if (last < ele->k_base - 1) { 148 (VOID)strcpy(cp, " .. "); 149 cp = keyname(cp + 4, ele->k_base - 1); 150 } 151 do { 152 *cp++ = ' '; 153 } while (cp < &buf[16]); 154 (VOID)strcpy(cp, function_name(map->map_default)); 155 if (addline(bp, buf) == FALSE) 156 return FALSE; 157 } 158 last = ele->k_num; 159 for (i = ele->k_base; i <= last; i++) { 160 functp = ele->k_funcp[i - ele->k_base]; 161 if (functp != rescan) { 162 if (functp != NULL) 163 cp2 = function_name(functp); 164 else 165 cp2 = map_name(ele->k_prefmap); 166 if (cp2 != NULL) { 167 cp = keyname(ind, i); 168 do { 169 *cp++ = ' '; 170 } while (cp < &buf[16]); 171 (VOID)strcpy(cp, cp2); 172 if (addline(bp, buf) == FALSE) 173 return FALSE; 174 } 175 } 176 } 177 } 178 for (ele = &map->map_element[0]; 179 ele < &map->map_element[map->map_num]; ele++) { 180 if (ele->k_prefmap != NULL) { 181 for (i = ele->k_base; 182 ele->k_funcp[i - ele->k_base] != NULL; i++) { 183 if (i >= ele->k_num) 184 /* damaged map */ 185 return FALSE; 186 } 187 cp = keyname(ind, i); 188 *cp++ = ' '; 189 if (showall(cp, ele->k_prefmap) == FALSE) 190 return FALSE; 191 } 192 } 193 return TRUE; 194} 195 196int 197help_help(f, n) 198 int f, n; 199{ 200 KEYMAP *kp; 201 PF funct; 202 203 if ((kp = name_map("help")) == NULL) 204 return FALSE; 205 ewprintf("a b c: "); 206 do { 207 funct = doscan(kp, getkey(FALSE), NULL); 208 } while (funct == NULL || funct == help_help); 209#ifndef NO_MACRO 210 if (macrodef && macrocount < MAXMACRO) 211 macro[macrocount - 1].m_funct = funct; 212#endif /* !NO_MACRO */ 213 return (*funct)(f, n); 214} 215 216/* ARGSUSED */ 217int 218apropos_command(f, n) 219 int f, n; 220{ 221 BUFFER *bp; 222 FUNCTNAMES *fnp; 223 char *cp1, *cp2; 224 char string[32]; 225 226 if (eread("apropos: ", string, sizeof(string), EFNEW) == ABORT) 227 return ABORT; 228 /* FALSE means we got a 0 character string, which is fine */ 229 bp = bfind("*help*", TRUE); 230 if (bclear(bp) == FALSE) 231 return FALSE; 232 for (fnp = &functnames[0]; fnp < &functnames[nfunct]; fnp++) { 233 for (cp1 = fnp->n_name; *cp1; cp1++) { 234 cp2 = string; 235 while (*cp2 && *cp1 == *cp2) 236 cp1++, cp2++; 237 if (!*cp2) { 238 (VOID)strcpy(buf2, fnp->n_name); 239 buf2p = &buf2[strlen(buf2)]; 240 findbind(fnp->n_funct, buf, map_table[0].p_map); 241 if (addline(bp, buf2) == FALSE) 242 return FALSE; 243 break; 244 } else 245 cp1 -= cp2 - string; 246 } 247 } 248 return popbuftop(bp); 249} 250 251static VOID 252findbind(funct, ind, map) 253 KEYMAP *map; 254 PF funct; 255 char *ind; 256{ 257 MAP_ELEMENT *ele; 258 int i, last; 259 char *cp; 260 261 last = -1; 262 for (ele = &map->map_element[0]; 263 ele < &map->map_element[map->map_num]; ele++) { 264 if (map->map_default == funct && ++last < ele->k_base) { 265 cp = keyname(ind, last); 266 if (last < ele->k_base - 1) { 267 (VOID)strcpy(cp, " .. "); 268 (VOID)keyname(cp + 4, ele->k_base - 1); 269 } 270 bindfound(); 271 } 272 last = ele->k_num; 273 for (i = ele->k_base; i <= last; i++) { 274 if (funct == ele->k_funcp[i - ele->k_base]) { 275 if (funct == NULL) { 276 cp = map_name(ele->k_prefmap); 277 if (!cp || 278 strncmp(cp, buf2, strlen(cp)) != 0) 279 continue; 280 } 281 (VOID)keyname(ind, i); 282 bindfound(); 283 } 284 } 285 } 286 for (ele = &map->map_element[0]; 287 ele < &map->map_element[map->map_num]; ele++) { 288 if (ele->k_prefmap != NULL) { 289 for (i = ele->k_base; 290 ele->k_funcp[i - ele->k_base] != NULL; i++) { 291 if (i >= ele->k_num) 292 /* damaged */ 293 return; 294 } 295 cp = keyname(ind, i); 296 *cp++ = ' '; 297 findbind(funct, cp, ele->k_prefmap); 298 } 299 } 300} 301 302static VOID 303bindfound() 304{ 305 if (buf2p < &buf2[32]) { 306 do { 307 *buf2p++ = ' '; 308 } while (buf2p < &buf2[32]); 309 } else { 310 *buf2p++ = ','; 311 *buf2p++ = ' '; 312 } 313 (VOID)strcpy(buf2p, buf); 314 buf2p += strlen(buf); 315} 316#endif /* !NO_HELP */ 317