mirror of
https://github.com/openbsd/src.git
synced 2026-04-30 17:16:30 +00:00
233 lines
5.1 KiB
C
233 lines
5.1 KiB
C
/* $OpenBSD: help.c,v 1.37 2023/03/08 04:43:11 guenther 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.
|
|
*/
|
|
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 its own wall chart.
|
|
*/
|
|
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));
|
|
}
|
|
|
|
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);
|
|
}
|