Changeset View
Changeset View
Standalone View
Standalone View
contrib/mg/help.c
- This file was added.
/* $OpenBSD: help.c,v 1.35 2015/03/19 21:22:15 bcallah Exp $ */ | |||||
/* This file is in the public domain. */ | |||||
/* | |||||
* Help functions for Mg 2 | |||||
*/ | |||||
#include <sys/queue.h> | |||||
#include <signal.h> | |||||
#include <stdio.h> | |||||
#include <string.h> | |||||
#include "def.h" | |||||
#include "funmap.h" | |||||
#include "kbd.h" | |||||
#include "key.h" | |||||
#include "macro.h" | |||||
static int showall(struct buffer *, KEYMAP *, char *); | |||||
static int findbind(KEYMAP *, PF, char *, size_t); | |||||
/* | |||||
* Read a key from the keyboard, and look it up in the keymap. | |||||
* Display the name of the function currently bound to the key. | |||||
*/ | |||||
/* ARGSUSED */ | |||||
int | |||||
desckey(int f, int n) | |||||
{ | |||||
KEYMAP *curmap; | |||||
PF funct; | |||||
int c, m, i, num; | |||||
char *pep; | |||||
char dprompt[80]; | |||||
if (inmacro) | |||||
return (TRUE); /* ignore inside keyboard macro */ | |||||
num = strlcpy(dprompt, "Describe key briefly: ", sizeof(dprompt)); | |||||
if (num >= sizeof(dprompt)) | |||||
num = sizeof(dprompt) - 1; | |||||
pep = dprompt + num; | |||||
key.k_count = 0; | |||||
m = curbp->b_nmodes; | |||||
curmap = curbp->b_modes[m]->p_map; | |||||
for (;;) { | |||||
for (;;) { | |||||
ewprintf("%s", dprompt); | |||||
pep[-1] = ' '; | |||||
pep = getkeyname(pep, sizeof(dprompt) - (pep - dprompt), | |||||
key.k_chars[key.k_count++] = c = getkey(FALSE)); | |||||
if ((funct = doscan(curmap, c, &curmap)) != NULL) | |||||
break; | |||||
*pep++ = '-'; | |||||
*pep = '\0'; | |||||
} | |||||
if (funct != rescan) | |||||
break; | |||||
if (ISUPPER(key.k_chars[key.k_count - 1])) { | |||||
funct = doscan(curmap, | |||||
TOLOWER(key.k_chars[key.k_count - 1]), &curmap); | |||||
if (funct == NULL) { | |||||
*pep++ = '-'; | |||||
*pep = '\0'; | |||||
continue; | |||||
} | |||||
if (funct != rescan) | |||||
break; | |||||
} | |||||
nextmode: | |||||
if (--m < 0) | |||||
break; | |||||
curmap = curbp->b_modes[m]->p_map; | |||||
for (i = 0; i < key.k_count; i++) { | |||||
funct = doscan(curmap, key.k_chars[i], &curmap); | |||||
if (funct != NULL) { | |||||
if (i == key.k_count - 1 && funct != rescan) | |||||
goto found; | |||||
funct = rescan; | |||||
goto nextmode; | |||||
} | |||||
} | |||||
*pep++ = '-'; | |||||
*pep = '\0'; | |||||
} | |||||
found: | |||||
if (funct == rescan || funct == selfinsert) | |||||
ewprintf("%k is not bound to any function"); | |||||
else if ((pep = (char *)function_name(funct)) != NULL) | |||||
ewprintf("%k runs the command %s", pep); | |||||
else | |||||
ewprintf("%k is bound to an unnamed function"); | |||||
return (TRUE); | |||||
} | |||||
/* | |||||
* This function creates a table, listing all of the command | |||||
* keys and their current bindings, and stores the table in the | |||||
* *help* pop-up buffer. This lets Mg produce it's own wall chart. | |||||
*/ | |||||
/* ARGSUSED */ | |||||
int | |||||
wallchart(int f, int n) | |||||
{ | |||||
int m; | |||||
struct buffer *bp; | |||||
bp = bfind("*help*", TRUE); | |||||
if (bclear(bp) != TRUE) | |||||
/* clear it out */ | |||||
return (FALSE); | |||||
bp->b_flag |= BFREADONLY; | |||||
for (m = curbp->b_nmodes; m > 0; m--) { | |||||
if ((addlinef(bp, "Local keybindings for mode %s:", | |||||
curbp->b_modes[m]->p_name) == FALSE) || | |||||
(showall(bp, curbp->b_modes[m]->p_map, "") == FALSE) || | |||||
(addline(bp, "") == FALSE)) | |||||
return (FALSE); | |||||
} | |||||
if ((addline(bp, "Global bindings:") == FALSE) || | |||||
(showall(bp, fundamental_map, "") == FALSE)) | |||||
return (FALSE); | |||||
return (popbuftop(bp, WNONE)); | |||||
} | |||||
static int | |||||
showall(struct buffer *bp, KEYMAP *map, char *prefix) | |||||
{ | |||||
KEYMAP *newmap; | |||||
char buf[80], keybuf[16]; | |||||
PF fun; | |||||
int c; | |||||
if (addline(bp, "") == FALSE) | |||||
return (FALSE); | |||||
/* XXX - 256 ? */ | |||||
for (c = 0; c < 256; c++) { | |||||
fun = doscan(map, c, &newmap); | |||||
if (fun == rescan || fun == selfinsert) | |||||
continue; | |||||
getkeyname(buf, sizeof(buf), c); | |||||
(void)snprintf(keybuf, sizeof(keybuf), "%s%s ", prefix, buf); | |||||
if (fun == NULL) { | |||||
if (showall(bp, newmap, keybuf) == FALSE) | |||||
return (FALSE); | |||||
} else { | |||||
if (addlinef(bp, "%-16s%s", keybuf, | |||||
function_name(fun)) == FALSE) | |||||
return (FALSE); | |||||
} | |||||
} | |||||
return (TRUE); | |||||
} | |||||
int | |||||
help_help(int f, int n) | |||||
{ | |||||
KEYMAP *kp; | |||||
PF funct; | |||||
if ((kp = name_map("help")) == NULL) | |||||
return (FALSE); | |||||
ewprintf("a b c: "); | |||||
do { | |||||
funct = doscan(kp, getkey(FALSE), NULL); | |||||
} while (funct == NULL || funct == help_help); | |||||
if (macrodef && macrocount < MAXMACRO) | |||||
macro[macrocount - 1].m_funct = funct; | |||||
return ((*funct)(f, n)); | |||||
} | |||||
/* ARGSUSED */ | |||||
int | |||||
apropos_command(int f, int n) | |||||
{ | |||||
struct buffer *bp; | |||||
struct list *fnames, *el; | |||||
char string[32]; | |||||
if (eread("apropos: ", string, sizeof(string), EFNUL | EFNEW) == NULL) | |||||
return (ABORT); | |||||
/* FALSE means we got a 0 character string, which is fine */ | |||||
bp = bfind("*help*", TRUE); | |||||
if (bclear(bp) == FALSE) | |||||
return (FALSE); | |||||
fnames = complete_function_list(""); | |||||
for (el = fnames; el != NULL; el = el->l_next) { | |||||
char buf[32]; | |||||
if (strstr(el->l_name, string) == NULL) | |||||
continue; | |||||
buf[0] = '\0'; | |||||
findbind(fundamental_map, name_function(el->l_name), | |||||
buf, sizeof(buf)); | |||||
if (addlinef(bp, "%-32s%s", el->l_name, buf) == FALSE) { | |||||
free_file_list(fnames); | |||||
return (FALSE); | |||||
} | |||||
} | |||||
free_file_list(fnames); | |||||
return (popbuftop(bp, WNONE)); | |||||
} | |||||
static int | |||||
findbind(KEYMAP *map, PF fun, char *buf, size_t len) | |||||
{ | |||||
KEYMAP *newmap; | |||||
PF nfun; | |||||
char buf2[16], keybuf[16]; | |||||
int c; | |||||
/* XXX - 256 ? */ | |||||
for (c = 0; c < 256; c++) { | |||||
nfun = doscan(map, c, &newmap); | |||||
if (nfun == fun) { | |||||
getkeyname(buf, len, c); | |||||
return (TRUE); | |||||
} | |||||
if (nfun == NULL) { | |||||
if (findbind(newmap, fun, buf2, sizeof(buf2)) == TRUE) { | |||||
getkeyname(keybuf, sizeof(keybuf), c); | |||||
(void)snprintf(buf, len, "%s %s", keybuf, buf2); | |||||
return (TRUE); | |||||
} | |||||
} | |||||
} | |||||
return (FALSE); | |||||
} |