2003-05-02 00:48:41 +00:00
|
|
|
|
/* infodoc.c -- functions which build documentation nodes.
|
2005-05-23 10:46:22 +00:00
|
|
|
|
$Id: infodoc.c,v 1.8 2004/04/11 17:56:45 karl Exp $
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
2005-05-23 10:46:22 +00:00
|
|
|
|
Copyright (C) 1993, 1997, 1998, 1999, 2001, 2002, 2003, 2004 Free Software
|
2003-05-02 00:48:41 +00:00
|
|
|
|
Foundation, Inc.
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
|
any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
|
|
Written by Brian Fox (bfox@ai.mit.edu). */
|
|
|
|
|
|
|
|
|
|
#include "info.h"
|
2002-03-25 13:08:32 +00:00
|
|
|
|
#include "funs.h"
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
2000-01-17 10:39:58 +00:00
|
|
|
|
/* HELP_NODE_GETS_REGENERATED is always defined now that keys may get
|
|
|
|
|
rebound, or other changes in the help text may occur. */
|
|
|
|
|
#define HELP_NODE_GETS_REGENERATED 1
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
/* The name of the node used in the help window. */
|
|
|
|
|
static char *info_help_nodename = "*Info Help*";
|
|
|
|
|
|
|
|
|
|
/* A node containing printed key bindings and their documentation. */
|
|
|
|
|
static NODE *internal_info_help_node = (NODE *)NULL;
|
|
|
|
|
|
|
|
|
|
/* A pointer to the contents of the help node. */
|
|
|
|
|
static char *internal_info_help_node_contents = (char *)NULL;
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
/* The (more or less) static text which appears in the internal info
|
2003-06-18 12:57:43 +00:00
|
|
|
|
help node. The actual key bindings are inserted. Keep the
|
2002-03-25 13:08:32 +00:00
|
|
|
|
underlines (****, etc.) in the same N_ call as the text lines they
|
|
|
|
|
refer to, so translations can make the number of *'s or -'s match. */
|
|
|
|
|
#if defined(INFOKEY)
|
|
|
|
|
|
|
|
|
|
static char *info_internal_help_text[] = {
|
|
|
|
|
N_("Basic Commands in Info Windows\n\
|
|
|
|
|
******************************\n"),
|
|
|
|
|
"\n",
|
|
|
|
|
N_("\\%-10[quit-help] Quit this help.\n"),
|
|
|
|
|
N_("\\%-10[quit] Quit Info altogether.\n"),
|
|
|
|
|
N_("\\%-10[get-info-help-node] Invoke the Info tutorial.\n"),
|
|
|
|
|
"\n",
|
|
|
|
|
N_("Selecting other nodes:\n\
|
|
|
|
|
----------------------\n"),
|
|
|
|
|
N_("\\%-10[next-node] Move to the \"next\" node of this node.\n"),
|
|
|
|
|
N_("\\%-10[prev-node] Move to the \"previous\" node of this node.\n"),
|
|
|
|
|
N_("\\%-10[up-node] Move \"up\" from this node.\n"),
|
|
|
|
|
N_("\\%-10[menu-item] Pick menu item specified by name.\n\
|
|
|
|
|
Picking a menu item causes another node to be selected.\n"),
|
|
|
|
|
N_("\\%-10[xref-item] Follow a cross reference. Reads name of reference.\n"),
|
|
|
|
|
N_("\\%-10[history-node] Move to the last node seen in this window.\n"),
|
|
|
|
|
N_("\\%-10[move-to-next-xref] Skip to next hypertext link within this node.\n"),
|
|
|
|
|
N_("\\%-10[move-to-prev-xref] Skip to previous hypertext link within this node.\n"),
|
|
|
|
|
N_("\\%-10[select-reference-this-line] Follow the hypertext link under cursor.\n"),
|
|
|
|
|
N_("\\%-10[dir-node] Move to the `directory' node. Equivalent to `\\[goto-node] (DIR)'.\n"),
|
|
|
|
|
N_("\\%-10[top-node] Move to the Top node. Equivalent to `\\[goto-node] Top'.\n"),
|
|
|
|
|
"\n",
|
|
|
|
|
N_("Moving within a node:\n\
|
|
|
|
|
---------------------\n"),
|
|
|
|
|
N_("\\%-10[beginning-of-node] Go to the beginning of this node.\n"),
|
|
|
|
|
N_("\\%-10[end-of-node] Go to the end of this node.\n"),
|
2003-05-02 00:48:41 +00:00
|
|
|
|
N_("\\%-10[next-line] Scroll forward 1 line.\n"),
|
|
|
|
|
N_("\\%-10[prev-line] Scroll backward 1 line.\n"),
|
|
|
|
|
N_("\\%-10[scroll-forward] Scroll forward a page.\n"),
|
|
|
|
|
N_("\\%-10[scroll-backward] Scroll backward a page.\n"),
|
2002-03-25 13:08:32 +00:00
|
|
|
|
"\n",
|
|
|
|
|
N_("Other commands:\n\
|
|
|
|
|
---------------\n"),
|
|
|
|
|
N_("\\%-10[menu-digit] Pick first ... ninth item in node's menu.\n"),
|
|
|
|
|
N_("\\%-10[last-menu-item] Pick last item in node's menu.\n"),
|
|
|
|
|
N_("\\%-10[index-search] Search for a specified string in the index entries of this Info\n\
|
|
|
|
|
file, and select the node referenced by the first entry found.\n"),
|
|
|
|
|
N_("\\%-10[goto-node] Move to node specified by name.\n\
|
|
|
|
|
You may include a filename as well, as in (FILENAME)NODENAME.\n"),
|
|
|
|
|
N_("\\%-10[search] Search forward for a specified string\n\
|
|
|
|
|
and select the node in which the next occurrence is found.\n"),
|
|
|
|
|
N_("\\%-10[search-backward] Search backward for a specified string\n\
|
|
|
|
|
and select the node in which the previous occurrence is found.\n"),
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#else /* !INFOKEY */
|
|
|
|
|
|
1997-01-11 02:12:38 +00:00
|
|
|
|
static char *info_internal_help_text[] = {
|
2002-03-25 13:08:32 +00:00
|
|
|
|
N_("Basic Commands in Info Windows\n\
|
|
|
|
|
******************************\n"),
|
2000-01-17 10:39:58 +00:00
|
|
|
|
"\n",
|
|
|
|
|
N_(" %-10s Quit this help.\n"),
|
|
|
|
|
N_(" %-10s Quit Info altogether.\n"),
|
|
|
|
|
N_(" %-10s Invoke the Info tutorial.\n"),
|
|
|
|
|
"\n",
|
2002-03-25 13:08:32 +00:00
|
|
|
|
N_("Selecting other nodes:\n\
|
|
|
|
|
----------------------\n",
|
2000-01-17 10:39:58 +00:00
|
|
|
|
N_(" %-10s Move to the `next' node of this node.\n"),
|
|
|
|
|
N_(" %-10s Move to the `previous' node of this node.\n"),
|
|
|
|
|
N_(" %-10s Move `up' from this node.\n"),
|
|
|
|
|
N_(" %-10s Pick menu item specified by name.\n"),
|
|
|
|
|
N_(" Picking a menu item causes another node to be selected.\n"),
|
|
|
|
|
N_(" %-10s Follow a cross reference. Reads name of reference.\n"),
|
|
|
|
|
N_(" %-10s Move to the last node seen in this window.\n"),
|
|
|
|
|
N_(" %-10s Skip to next hypertext link within this node.\n"),
|
|
|
|
|
N_(" %-10s Follow the hypertext link under cursor.\n"),
|
|
|
|
|
N_(" %-10s Move to the `directory' node. Equivalent to `g (DIR)'.\n"),
|
|
|
|
|
N_(" %-10s Move to the Top node. Equivalent to `g Top'.\n"),
|
|
|
|
|
"\n",
|
2002-03-25 13:08:32 +00:00
|
|
|
|
N_("Moving within a node:\n\
|
|
|
|
|
---------------------\n"),
|
|
|
|
|
N_(" %-10s Scroll forward a page.\n"),
|
|
|
|
|
N_(" %-10s Scroll backward a page.\n"),
|
|
|
|
|
N_(" %-10s Go to the beginning of this node.\n"),
|
|
|
|
|
N_(" %-10s Go to the end of this node.\n"),
|
|
|
|
|
N_(" %-10s Scroll forward 1 line.\n"),
|
|
|
|
|
N_(" %-10s Scroll backward 1 line.\n"),
|
|
|
|
|
"\n",
|
|
|
|
|
N_("Other commands:\n\
|
|
|
|
|
---------------\n"),
|
2000-01-17 10:39:58 +00:00
|
|
|
|
N_(" %-10s Pick first ... ninth item in node's menu.\n"),
|
|
|
|
|
N_(" %-10s Pick last item in node's menu.\n"),
|
|
|
|
|
N_(" %-10s Search for a specified string in the index entries of this Info\n"),
|
|
|
|
|
N_(" file, and select the node referenced by the first entry found.\n"),
|
|
|
|
|
N_(" %-10s Move to node specified by name.\n"),
|
|
|
|
|
N_(" You may include a filename as well, as in (FILENAME)NODENAME.\n"),
|
2002-03-25 13:08:32 +00:00
|
|
|
|
N_(" %-10s Search forward for a specified string,\n"),
|
2000-01-17 10:39:58 +00:00
|
|
|
|
N_(" and select the node in which the next occurrence is found.\n"),
|
2002-03-25 13:08:32 +00:00
|
|
|
|
N_(" %-10s Search backward for a specified string\n"),
|
2000-01-17 10:39:58 +00:00
|
|
|
|
N_(" and select the node in which the next occurrence is found.\n"),
|
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static char *info_help_keys_text[][2] = {
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "CTRL-x 0", "CTRL-x 0" },
|
|
|
|
|
{ "q", "q" },
|
|
|
|
|
{ "h", "ESC h" },
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "SPC", "SPC" },
|
|
|
|
|
{ "DEL", "b" },
|
|
|
|
|
{ "b", "ESC b" },
|
|
|
|
|
{ "e", "ESC e" },
|
|
|
|
|
{ "ESC 1 SPC", "RET" },
|
|
|
|
|
{ "ESC 1 DEL", "y" },
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "n", "CTRL-x n" },
|
|
|
|
|
{ "p", "CTRL-x p" },
|
|
|
|
|
{ "u", "CTRL-x u" },
|
|
|
|
|
{ "m", "ESC m" },
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "f", "ESC f" },
|
|
|
|
|
{ "l", "l" },
|
|
|
|
|
{ "TAB", "TAB" },
|
|
|
|
|
{ "RET", "CTRL-x RET" },
|
|
|
|
|
{ "d", "ESC d" },
|
|
|
|
|
{ "t", "ESC t" },
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "1-9", "ESC 1-9" },
|
|
|
|
|
{ "0", "ESC 0" },
|
|
|
|
|
{ "i", "CTRL-x i" },
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "g", "CTRL-x g" },
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "s", "/" },
|
|
|
|
|
{ "", "" },
|
|
|
|
|
{ "ESC - s", "?" },
|
|
|
|
|
{ "", "" },
|
1999-01-14 19:35:19 +00:00
|
|
|
|
NULL
|
1997-01-11 02:12:38 +00:00
|
|
|
|
};
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
#endif /* !INFOKEY */
|
|
|
|
|
|
2005-05-23 10:46:22 +00:00
|
|
|
|
static char *where_is_internal (Keymap map, InfoCommand *cmd);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
void
|
2005-05-23 10:46:22 +00:00
|
|
|
|
dump_map_to_message_buffer (char *prefix, Keymap map)
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
|
|
|
|
register int i;
|
2002-03-25 13:08:32 +00:00
|
|
|
|
unsigned prefix_len = strlen (prefix);
|
|
|
|
|
char *new_prefix = (char *)xmalloc (prefix_len + 2);
|
|
|
|
|
|
|
|
|
|
strncpy (new_prefix, prefix, prefix_len);
|
|
|
|
|
new_prefix[prefix_len + 1] = '\0';
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
for (i = 0; i < 256; i++)
|
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
new_prefix[prefix_len] = i;
|
1997-01-11 02:12:38 +00:00
|
|
|
|
if (map[i].type == ISKMAP)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
|
|
|
|
dump_map_to_message_buffer (new_prefix, (Keymap)map[i].function);
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
else if (map[i].function)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
|
|
|
|
register int last;
|
|
|
|
|
char *doc, *name;
|
|
|
|
|
|
|
|
|
|
doc = function_documentation (map[i].function);
|
|
|
|
|
name = function_name (map[i].function);
|
|
|
|
|
|
|
|
|
|
if (!*doc)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* Find out if there is a series of identical functions, as in
|
|
|
|
|
ea_insert (). */
|
|
|
|
|
for (last = i + 1; last < 256; last++)
|
|
|
|
|
if ((map[last].type != ISFUNC) ||
|
|
|
|
|
(map[last].function != map[i].function))
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (last - 1 != i)
|
|
|
|
|
{
|
2005-05-23 10:46:22 +00:00
|
|
|
|
printf_to_message_buffer ("%s .. ", pretty_keyseq (new_prefix),
|
|
|
|
|
NULL, NULL);
|
2003-05-02 00:48:41 +00:00
|
|
|
|
new_prefix[prefix_len] = last - 1;
|
2005-05-23 10:46:22 +00:00
|
|
|
|
printf_to_message_buffer ("%s\t", pretty_keyseq (new_prefix),
|
|
|
|
|
NULL, NULL);
|
1999-01-14 19:35:19 +00:00
|
|
|
|
i = last - 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
2005-05-23 10:46:22 +00:00
|
|
|
|
printf_to_message_buffer ("%s\t", pretty_keyseq (new_prefix),
|
|
|
|
|
NULL, NULL);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
#if defined (NAMED_FUNCTIONS)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
/* Print the name of the function, and some padding before the
|
|
|
|
|
documentation string is printed. */
|
|
|
|
|
{
|
|
|
|
|
int length_so_far;
|
|
|
|
|
int desired_doc_start = 40; /* Must be multiple of 8. */
|
|
|
|
|
|
2005-05-23 10:46:22 +00:00
|
|
|
|
printf_to_message_buffer ("(%s)", name, NULL, NULL);
|
1999-01-14 19:35:19 +00:00
|
|
|
|
length_so_far = message_buffer_length_this_line ();
|
|
|
|
|
|
2005-05-23 10:46:22 +00:00
|
|
|
|
if ((desired_doc_start + strlen (doc))
|
|
|
|
|
>= (unsigned int) the_screen->width)
|
|
|
|
|
printf_to_message_buffer ("\n ", NULL, NULL, NULL);
|
1999-01-14 19:35:19 +00:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
while (length_so_far < desired_doc_start)
|
|
|
|
|
{
|
2005-05-23 10:46:22 +00:00
|
|
|
|
printf_to_message_buffer ("\t", NULL, NULL, NULL);
|
1999-01-14 19:35:19 +00:00
|
|
|
|
length_so_far += character_width ('\t', length_so_far);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
#endif /* NAMED_FUNCTIONS */
|
2005-05-23 10:46:22 +00:00
|
|
|
|
printf_to_message_buffer ("%s\n", doc, NULL, NULL);
|
1999-01-14 19:35:19 +00:00
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
2002-03-25 13:08:32 +00:00
|
|
|
|
free (new_prefix);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-01-17 10:39:58 +00:00
|
|
|
|
/* How to create internal_info_help_node. HELP_IS_ONLY_WINDOW_P says
|
|
|
|
|
whether we're going to end up in a second (or more) window of our
|
|
|
|
|
own, or whether there's only one window and we're going to usurp it.
|
|
|
|
|
This determines how to quit the help window. Maybe we should just
|
|
|
|
|
make q do the right thing in both cases. */
|
|
|
|
|
|
1997-01-11 02:12:38 +00:00
|
|
|
|
static void
|
2005-05-23 10:46:22 +00:00
|
|
|
|
create_internal_info_help_node (int help_is_only_window_p)
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
|
|
|
|
register int i;
|
|
|
|
|
NODE *node;
|
2000-01-17 10:39:58 +00:00
|
|
|
|
char *contents = NULL;
|
2002-03-25 13:08:32 +00:00
|
|
|
|
char *exec_keys;
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
2000-01-17 10:39:58 +00:00
|
|
|
|
#ifndef HELP_NODE_GETS_REGENERATED
|
1997-01-11 02:12:38 +00:00
|
|
|
|
if (internal_info_help_node_contents)
|
|
|
|
|
contents = internal_info_help_node_contents;
|
|
|
|
|
#endif /* !HELP_NODE_GETS_REGENERATED */
|
|
|
|
|
|
|
|
|
|
if (!contents)
|
|
|
|
|
{
|
|
|
|
|
int printed_one_mx = 0;
|
|
|
|
|
|
|
|
|
|
initialize_message_buffer ();
|
|
|
|
|
|
|
|
|
|
for (i = 0; info_internal_help_text[i]; i++)
|
2000-01-17 10:39:58 +00:00
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
#ifdef INFOKEY
|
2005-05-23 10:46:22 +00:00
|
|
|
|
printf_to_message_buffer (replace_in_documentation
|
|
|
|
|
((char *) _(info_internal_help_text[i]), help_is_only_window_p),
|
|
|
|
|
NULL, NULL, NULL);
|
2002-03-25 13:08:32 +00:00
|
|
|
|
#else
|
2000-01-17 10:39:58 +00:00
|
|
|
|
/* Don't translate blank lines, gettext outputs the po file
|
|
|
|
|
header in that case. We want a blank line. */
|
|
|
|
|
char *msg = *(info_internal_help_text[i])
|
|
|
|
|
? _(info_internal_help_text[i])
|
|
|
|
|
: info_internal_help_text[i];
|
|
|
|
|
char *key = info_help_keys_text[i][vi_keys_p];
|
2003-06-18 12:57:43 +00:00
|
|
|
|
|
2000-01-17 10:39:58 +00:00
|
|
|
|
/* If we have only one window (because the window size was too
|
|
|
|
|
small to split it), CTRL-x 0 doesn't work to `quit' help. */
|
|
|
|
|
if (STREQ (key, "CTRL-x 0") && help_is_only_window_p)
|
|
|
|
|
key = "l";
|
|
|
|
|
|
2005-05-23 10:46:22 +00:00
|
|
|
|
printf_to_message_buffer (msg, key, NULL, NULL);
|
2002-03-25 13:08:32 +00:00
|
|
|
|
#endif /* !INFOKEY */
|
2000-01-17 10:39:58 +00:00
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
2005-05-23 10:46:22 +00:00
|
|
|
|
printf_to_message_buffer ("---------------------\n\n", NULL, NULL, NULL);
|
|
|
|
|
printf_to_message_buffer ((char *) _("The current search path is:\n"),
|
|
|
|
|
NULL, NULL, NULL);
|
|
|
|
|
printf_to_message_buffer (" %s\n", infopath, NULL, NULL);
|
|
|
|
|
printf_to_message_buffer ("---------------------\n\n", NULL, NULL, NULL);
|
|
|
|
|
printf_to_message_buffer ((char *) _("Commands available in Info windows:\n\n"),
|
|
|
|
|
NULL, NULL, NULL);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
dump_map_to_message_buffer ("", info_keymap);
|
2005-05-23 10:46:22 +00:00
|
|
|
|
printf_to_message_buffer ("---------------------\n\n", NULL, NULL, NULL);
|
|
|
|
|
printf_to_message_buffer ((char *) _("Commands available in the echo area:\n\n"),
|
|
|
|
|
NULL, NULL, NULL);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
dump_map_to_message_buffer ("", echo_area_keymap);
|
|
|
|
|
|
|
|
|
|
#if defined (NAMED_FUNCTIONS)
|
2002-03-25 13:08:32 +00:00
|
|
|
|
/* Get a list of commands which have no keystroke equivs. */
|
|
|
|
|
exec_keys = where_is (info_keymap, InfoCmd(info_execute_command));
|
|
|
|
|
if (exec_keys)
|
|
|
|
|
exec_keys = xstrdup (exec_keys);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
for (i = 0; function_doc_array[i].func; i++)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
InfoCommand *cmd = DocInfoCmd(&function_doc_array[i]);
|
1999-01-14 19:35:19 +00:00
|
|
|
|
|
2005-05-23 10:46:22 +00:00
|
|
|
|
if (InfoFunction(cmd) != (VFunction *) info_do_lowercase_version
|
2003-05-02 00:48:41 +00:00
|
|
|
|
&& !where_is_internal (info_keymap, cmd)
|
2002-03-25 13:08:32 +00:00
|
|
|
|
&& !where_is_internal (echo_area_keymap, cmd))
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
|
|
|
|
if (!printed_one_mx)
|
|
|
|
|
{
|
2005-05-23 10:46:22 +00:00
|
|
|
|
printf_to_message_buffer ("---------------------\n\n",
|
|
|
|
|
NULL, NULL, NULL);
|
2003-05-02 00:48:41 +00:00
|
|
|
|
if (exec_keys && exec_keys[0])
|
|
|
|
|
printf_to_message_buffer
|
2005-05-23 10:46:22 +00:00
|
|
|
|
((char *) _("The following commands can only be invoked via %s:\n\n"),
|
|
|
|
|
exec_keys, NULL, NULL);
|
2003-05-02 00:48:41 +00:00
|
|
|
|
else
|
|
|
|
|
printf_to_message_buffer
|
2005-05-23 10:46:22 +00:00
|
|
|
|
((char *) _("The following commands cannot be invoked at all:\n\n"),
|
|
|
|
|
NULL, NULL, NULL);
|
1999-01-14 19:35:19 +00:00
|
|
|
|
printed_one_mx = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf_to_message_buffer
|
2002-03-25 13:08:32 +00:00
|
|
|
|
("%s %s\n %s\n",
|
2003-05-02 00:48:41 +00:00
|
|
|
|
exec_keys,
|
1999-01-14 19:35:19 +00:00
|
|
|
|
function_doc_array[i].func_name,
|
2000-01-17 10:39:58 +00:00
|
|
|
|
replace_in_documentation (strlen (function_doc_array[i].doc)
|
2005-05-23 10:46:22 +00:00
|
|
|
|
? (char *) _(function_doc_array[i].doc) : "", 0)
|
2003-05-02 00:48:41 +00:00
|
|
|
|
);
|
2000-01-17 10:39:58 +00:00
|
|
|
|
|
1999-01-14 19:35:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
if (printed_one_mx)
|
2005-05-23 10:46:22 +00:00
|
|
|
|
printf_to_message_buffer ("\n", NULL, NULL, NULL);
|
2002-03-25 13:08:32 +00:00
|
|
|
|
|
|
|
|
|
maybe_free (exec_keys);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
#endif /* NAMED_FUNCTIONS */
|
|
|
|
|
|
|
|
|
|
printf_to_message_buffer
|
1999-01-14 19:35:19 +00:00
|
|
|
|
("%s", replace_in_documentation
|
2005-05-23 10:46:22 +00:00
|
|
|
|
((char *) _("--- Use `\\[history-node]' or `\\[kill-node]' to exit ---\n"), 0),
|
|
|
|
|
NULL, NULL);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
node = message_buffer_to_node ();
|
|
|
|
|
internal_info_help_node_contents = node->contents;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* We already had the right contents, so simply use them. */
|
|
|
|
|
node = build_message_node ("", 0, 0);
|
|
|
|
|
free (node->contents);
|
|
|
|
|
node->contents = contents;
|
|
|
|
|
node->nodelen = 1 + strlen (contents);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal_info_help_node = node;
|
|
|
|
|
|
|
|
|
|
/* Do not GC this node's contents. It never changes, and we never need
|
|
|
|
|
to delete it once it is made. If you change some things (such as
|
|
|
|
|
placing information about dynamic variables in the help text) then
|
|
|
|
|
you will need to allow the contents to be gc'd, and you will have to
|
|
|
|
|
arrange to always regenerate the help node. */
|
|
|
|
|
#if defined (HELP_NODE_GETS_REGENERATED)
|
|
|
|
|
add_gcable_pointer (internal_info_help_node->contents);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
name_internal_node (internal_info_help_node, info_help_nodename);
|
|
|
|
|
|
|
|
|
|
/* Even though this is an internal node, we don't want the window
|
|
|
|
|
system to treat it specially. So we turn off the internalness
|
|
|
|
|
of it here. */
|
|
|
|
|
internal_info_help_node->flags &= ~N_IsInternal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return a window which is the window showing help in this Info. */
|
2000-01-17 10:39:58 +00:00
|
|
|
|
|
|
|
|
|
/* If the eligible window's height is >= this, split it to make the help
|
|
|
|
|
window. Otherwise display the help window in the current window. */
|
|
|
|
|
#define HELP_SPLIT_SIZE 24
|
|
|
|
|
|
1997-01-11 02:12:38 +00:00
|
|
|
|
static WINDOW *
|
2005-05-23 10:46:22 +00:00
|
|
|
|
info_find_or_create_help_window (void)
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
2000-01-17 10:39:58 +00:00
|
|
|
|
int help_is_only_window_p;
|
|
|
|
|
WINDOW *eligible = NULL;
|
|
|
|
|
WINDOW *help_window = get_window_of_node (internal_info_help_node);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
/* If we couldn't find the help window, then make it. */
|
|
|
|
|
if (!help_window)
|
|
|
|
|
{
|
2000-01-17 10:39:58 +00:00
|
|
|
|
WINDOW *window;
|
1997-01-11 02:12:38 +00:00
|
|
|
|
int max = 0;
|
|
|
|
|
|
|
|
|
|
for (window = windows; window; window = window->next)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
|
|
|
|
if (window->height > max)
|
|
|
|
|
{
|
|
|
|
|
max = window->height;
|
|
|
|
|
eligible = window;
|
|
|
|
|
}
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
if (!eligible)
|
2000-01-17 10:39:58 +00:00
|
|
|
|
return NULL;
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
2000-01-17 10:39:58 +00:00
|
|
|
|
#ifndef HELP_NODE_GETS_REGENERATED
|
1997-01-11 02:12:38 +00:00
|
|
|
|
else
|
2000-01-17 10:39:58 +00:00
|
|
|
|
/* help window is static, just return it. */
|
|
|
|
|
return help_window;
|
|
|
|
|
#endif /* not HELP_NODE_GETS_REGENERATED */
|
|
|
|
|
|
|
|
|
|
/* Make sure that we have a node containing the help text. The
|
|
|
|
|
argument is false if help will be the only window (so l must be used
|
|
|
|
|
to quit help), true if help will be one of several visible windows
|
|
|
|
|
(so CTRL-x 0 must be used to quit help). */
|
2005-05-23 10:46:22 +00:00
|
|
|
|
help_is_only_window_p = ((help_window && !windows->next)
|
|
|
|
|
|| (!help_window && eligible->height < HELP_SPLIT_SIZE));
|
2000-01-17 10:39:58 +00:00
|
|
|
|
create_internal_info_help_node (help_is_only_window_p);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
/* Either use the existing window to display the help node, or create
|
|
|
|
|
a new window if there was no existing help window. */
|
|
|
|
|
if (!help_window)
|
2000-01-17 10:39:58 +00:00
|
|
|
|
{ /* Split the largest window into 2 windows, and show the help text
|
1999-01-14 19:35:19 +00:00
|
|
|
|
in that window. */
|
2000-01-17 10:39:58 +00:00
|
|
|
|
if (eligible->height >= HELP_SPLIT_SIZE)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
|
|
|
|
active_window = eligible;
|
|
|
|
|
help_window = window_make_window (internal_info_help_node);
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
else
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
|
|
|
|
set_remembered_pagetop_and_point (active_window);
|
|
|
|
|
window_set_node_of_window (active_window, internal_info_help_node);
|
|
|
|
|
help_window = active_window;
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
2000-01-17 10:39:58 +00:00
|
|
|
|
{ /* Case where help node always gets regenerated, and we have an
|
1999-01-14 19:35:19 +00:00
|
|
|
|
existing window in which to place the node. */
|
1997-01-11 02:12:38 +00:00
|
|
|
|
if (active_window != help_window)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
|
|
|
|
set_remembered_pagetop_and_point (active_window);
|
|
|
|
|
active_window = help_window;
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
window_set_node_of_window (active_window, internal_info_help_node);
|
|
|
|
|
}
|
|
|
|
|
remember_window_and_node (help_window, help_window->node);
|
2000-01-17 10:39:58 +00:00
|
|
|
|
return help_window;
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Create or move to the help window. */
|
1999-01-14 19:35:19 +00:00
|
|
|
|
DECLARE_INFO_COMMAND (info_get_help_window, _("Display help message"))
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
|
|
|
|
WINDOW *help_window;
|
|
|
|
|
|
|
|
|
|
help_window = info_find_or_create_help_window ();
|
|
|
|
|
if (help_window)
|
|
|
|
|
{
|
|
|
|
|
active_window = help_window;
|
|
|
|
|
active_window->flags |= W_UpdateWindow;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2005-05-23 10:46:22 +00:00
|
|
|
|
info_error ((char *) msg_cant_make_help, NULL, NULL);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Show the Info help node. This means that the "info" file is installed
|
|
|
|
|
where it can easily be found on your system. */
|
1999-01-14 19:35:19 +00:00
|
|
|
|
DECLARE_INFO_COMMAND (info_get_info_help_node, _("Visit Info node `(info)Help'"))
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
|
|
|
|
NODE *node;
|
|
|
|
|
char *nodename;
|
|
|
|
|
|
|
|
|
|
/* If there is a window on the screen showing the node "(info)Help" or
|
|
|
|
|
the node "(info)Help-Small-Screen", simply select that window. */
|
|
|
|
|
{
|
|
|
|
|
WINDOW *win;
|
|
|
|
|
|
|
|
|
|
for (win = windows; win; win = win->next)
|
|
|
|
|
{
|
1999-01-14 19:35:19 +00:00
|
|
|
|
if (win->node && win->node->filename &&
|
|
|
|
|
(strcasecmp
|
|
|
|
|
(filename_non_directory (win->node->filename), "info") == 0) &&
|
|
|
|
|
((strcmp (win->node->nodename, "Help") == 0) ||
|
|
|
|
|
(strcmp (win->node->nodename, "Help-Small-Screen") == 0)))
|
|
|
|
|
{
|
|
|
|
|
active_window = win;
|
|
|
|
|
return;
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If the current window is small, show the small screen help. */
|
|
|
|
|
if (active_window->height < 24)
|
|
|
|
|
nodename = "Help-Small-Screen";
|
|
|
|
|
else
|
|
|
|
|
nodename = "Help";
|
|
|
|
|
|
|
|
|
|
/* Try to get the info file for Info. */
|
|
|
|
|
node = info_get_node ("Info", nodename);
|
|
|
|
|
|
|
|
|
|
if (!node)
|
|
|
|
|
{
|
|
|
|
|
if (info_recent_file_error)
|
2005-05-23 10:46:22 +00:00
|
|
|
|
info_error (info_recent_file_error, NULL, NULL);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
else
|
2005-05-23 10:46:22 +00:00
|
|
|
|
info_error ((char *) msg_cant_file_node, "Info", nodename);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* If the current window is very large (greater than 45 lines),
|
1999-01-14 19:35:19 +00:00
|
|
|
|
then split it and show the help node in another window.
|
|
|
|
|
Otherwise, use the current window. */
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
if (active_window->height > 45)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
active_window = window_make_window (node);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
else
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
|
|
|
|
set_remembered_pagetop_and_point (active_window);
|
|
|
|
|
window_set_node_of_window (active_window, node);
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
remember_window_and_node (active_window, node);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* **************************************************************** */
|
1999-01-14 19:35:19 +00:00
|
|
|
|
/* */
|
|
|
|
|
/* Groveling Info Keymaps and Docs */
|
|
|
|
|
/* */
|
1997-01-11 02:12:38 +00:00
|
|
|
|
/* **************************************************************** */
|
|
|
|
|
|
|
|
|
|
/* Return the documentation associated with the Info command FUNCTION. */
|
|
|
|
|
char *
|
2005-05-23 10:46:22 +00:00
|
|
|
|
function_documentation (InfoCommand *cmd)
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
char *doc;
|
|
|
|
|
|
|
|
|
|
#if defined (INFOKEY)
|
|
|
|
|
|
|
|
|
|
doc = cmd->doc;
|
|
|
|
|
|
|
|
|
|
#else /* !INFOKEY */
|
|
|
|
|
|
1997-01-11 02:12:38 +00:00
|
|
|
|
register int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; function_doc_array[i].func; i++)
|
2002-03-25 13:08:32 +00:00
|
|
|
|
if (InfoFunction(cmd) == function_doc_array[i].func)
|
1997-01-11 02:12:38 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
doc = function_doc_array[i].func ? function_doc_array[i].doc : "";
|
|
|
|
|
|
|
|
|
|
#endif /* !INFOKEY */
|
|
|
|
|
|
2005-05-23 10:46:22 +00:00
|
|
|
|
return replace_in_documentation ((strlen (doc) == 0) ? doc : (char *) _(doc), 0);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined (NAMED_FUNCTIONS)
|
|
|
|
|
/* Return the user-visible name of the function associated with the
|
|
|
|
|
Info command FUNCTION. */
|
|
|
|
|
char *
|
2005-05-23 10:46:22 +00:00
|
|
|
|
function_name (InfoCommand *cmd)
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
#if defined (INFOKEY)
|
|
|
|
|
|
|
|
|
|
return cmd->func_name;
|
|
|
|
|
|
|
|
|
|
#else /* !INFOKEY */
|
|
|
|
|
|
1997-01-11 02:12:38 +00:00
|
|
|
|
register int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; function_doc_array[i].func; i++)
|
2002-03-25 13:08:32 +00:00
|
|
|
|
if (InfoFunction(cmd) == function_doc_array[i].func)
|
1997-01-11 02:12:38 +00:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
return (function_doc_array[i].func_name);
|
2002-03-25 13:08:32 +00:00
|
|
|
|
|
|
|
|
|
#endif /* !INFOKEY */
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
/* Return a pointer to the info command for function NAME. */
|
|
|
|
|
InfoCommand *
|
2005-05-23 10:46:22 +00:00
|
|
|
|
named_function (char *name)
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
|
|
|
|
register int i;
|
|
|
|
|
|
|
|
|
|
for (i = 0; function_doc_array[i].func; i++)
|
|
|
|
|
if (strcmp (function_doc_array[i].func_name, name) == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
return (DocInfoCmd(&function_doc_array[i]));
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
#endif /* NAMED_FUNCTIONS */
|
|
|
|
|
|
|
|
|
|
/* Return the documentation associated with KEY in MAP. */
|
|
|
|
|
char *
|
2005-05-23 10:46:22 +00:00
|
|
|
|
key_documentation (char key, Keymap map)
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
InfoCommand *function = map[key].function;
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
if (function)
|
|
|
|
|
return (function_documentation (function));
|
|
|
|
|
else
|
|
|
|
|
return ((char *)NULL);
|
|
|
|
|
}
|
|
|
|
|
|
1999-01-14 19:35:19 +00:00
|
|
|
|
DECLARE_INFO_COMMAND (describe_key, _("Print documentation for KEY"))
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
char keys[50];
|
1997-01-11 02:12:38 +00:00
|
|
|
|
unsigned char keystroke;
|
2002-03-25 13:08:32 +00:00
|
|
|
|
char *k = keys;
|
1997-01-11 02:12:38 +00:00
|
|
|
|
Keymap map;
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
*k = '\0';
|
1997-01-11 02:12:38 +00:00
|
|
|
|
map = window->keymap;
|
|
|
|
|
|
2000-01-17 10:39:58 +00:00
|
|
|
|
for (;;)
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
2005-05-23 10:46:22 +00:00
|
|
|
|
message_in_echo_area ((char *) _("Describe key: %s"),
|
|
|
|
|
pretty_keyseq (keys), NULL);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
keystroke = info_get_input_char ();
|
|
|
|
|
unmessage_in_echo_area ();
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
#if !defined (INFOKEY)
|
2000-01-17 10:39:58 +00:00
|
|
|
|
if (Meta_p (keystroke))
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
|
|
|
|
if (map[ESC].type != ISKMAP)
|
|
|
|
|
{
|
|
|
|
|
window_message_in_echo_area
|
2000-01-17 10:39:58 +00:00
|
|
|
|
(_("ESC %s is undefined."), pretty_keyname (UnMeta (keystroke)));
|
1999-01-14 19:35:19 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2003-05-02 00:48:41 +00:00
|
|
|
|
*k++ = '\e';
|
1999-01-14 19:35:19 +00:00
|
|
|
|
keystroke = UnMeta (keystroke);
|
|
|
|
|
map = (Keymap)map[ESC].function;
|
|
|
|
|
}
|
2002-03-25 13:08:32 +00:00
|
|
|
|
#endif /* !INFOKEY */
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
/* Add the KEYSTROKE to our list. */
|
|
|
|
|
*k++ = keystroke;
|
|
|
|
|
*k = '\0';
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
if (map[keystroke].function == (InfoCommand *)NULL)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
2005-05-23 10:46:22 +00:00
|
|
|
|
message_in_echo_area ((char *) _("%s is undefined."),
|
|
|
|
|
pretty_keyseq (keys), NULL);
|
1999-01-14 19:35:19 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
else if (map[keystroke].type == ISKMAP)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
|
|
|
|
map = (Keymap)map[keystroke].function;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
else
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
char *keyname, *message, *fundoc, *funname = "";
|
|
|
|
|
|
|
|
|
|
#if defined (INFOKEY)
|
2003-05-02 00:48:41 +00:00
|
|
|
|
/* If the key is bound to do-lowercase-version, but its
|
|
|
|
|
lower-case variant is undefined, say that this key is
|
|
|
|
|
also undefined. This is especially important for unbound
|
|
|
|
|
edit keys that emit an escape sequence: it's terribly
|
|
|
|
|
confusing to see a message "Home (do-lowercase-version)"
|
|
|
|
|
or some such when Home is unbound. */
|
2005-05-23 10:46:22 +00:00
|
|
|
|
if (InfoFunction(map[keystroke].function)
|
|
|
|
|
== (VFunction *) info_do_lowercase_version)
|
2003-05-02 00:48:41 +00:00
|
|
|
|
{
|
|
|
|
|
unsigned char lowerkey = Meta_p(keystroke)
|
|
|
|
|
? Meta (tolower (UnMeta (keystroke)))
|
|
|
|
|
: tolower (keystroke);
|
|
|
|
|
|
|
|
|
|
if (map[lowerkey].function == (InfoCommand *)NULL)
|
|
|
|
|
{
|
2005-05-23 10:46:22 +00:00
|
|
|
|
message_in_echo_area ((char *) _("%s is undefined."),
|
|
|
|
|
pretty_keyseq (keys), NULL);
|
2003-05-02 00:48:41 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2002-03-25 13:08:32 +00:00
|
|
|
|
#endif
|
|
|
|
|
|
2003-05-02 00:48:41 +00:00
|
|
|
|
keyname = pretty_keyseq (keys);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
#if defined (NAMED_FUNCTIONS)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
funname = function_name (map[keystroke].function);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
#endif /* NAMED_FUNCTIONS */
|
|
|
|
|
|
1999-01-14 19:35:19 +00:00
|
|
|
|
fundoc = function_documentation (map[keystroke].function);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
1999-01-14 19:35:19 +00:00
|
|
|
|
message = (char *)xmalloc
|
|
|
|
|
(10 + strlen (keyname) + strlen (fundoc) + strlen (funname));
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
#if defined (NAMED_FUNCTIONS)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
sprintf (message, "%s (%s): %s.", keyname, funname, fundoc);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
#else
|
1999-01-14 19:35:19 +00:00
|
|
|
|
sprintf (message, _("%s is defined to %s."), keyname, fundoc);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
#endif /* !NAMED_FUNCTIONS */
|
|
|
|
|
|
2005-05-23 10:46:22 +00:00
|
|
|
|
window_message_in_echo_area ("%s", message, NULL);
|
1999-01-14 19:35:19 +00:00
|
|
|
|
free (message);
|
|
|
|
|
break;
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
/* Return the pretty printable name of a single character. */
|
1997-01-11 02:12:38 +00:00
|
|
|
|
char *
|
2005-05-23 10:46:22 +00:00
|
|
|
|
pretty_keyname (unsigned char key)
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
static char rep_buffer[30];
|
1997-01-11 02:12:38 +00:00
|
|
|
|
char *rep;
|
|
|
|
|
|
|
|
|
|
if (Meta_p (key))
|
|
|
|
|
{
|
|
|
|
|
char temp[20];
|
|
|
|
|
|
|
|
|
|
rep = pretty_keyname (UnMeta (key));
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
#if defined (INFOKEY)
|
|
|
|
|
sprintf (temp, "M-%s", rep);
|
|
|
|
|
#else /* !INFOKEY */
|
1997-01-11 02:12:38 +00:00
|
|
|
|
sprintf (temp, "ESC %s", rep);
|
2002-03-25 13:08:32 +00:00
|
|
|
|
#endif /* !INFOKEY */
|
1997-01-11 02:12:38 +00:00
|
|
|
|
strcpy (rep_buffer, temp);
|
|
|
|
|
rep = rep_buffer;
|
|
|
|
|
}
|
|
|
|
|
else if (Control_p (key))
|
|
|
|
|
{
|
|
|
|
|
switch (key)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
|
|
|
|
case '\n': rep = "LFD"; break;
|
|
|
|
|
case '\t': rep = "TAB"; break;
|
|
|
|
|
case '\r': rep = "RET"; break;
|
|
|
|
|
case ESC: rep = "ESC"; break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
sprintf (rep_buffer, "C-%c", UnControl (key));
|
|
|
|
|
rep = rep_buffer;
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
switch (key)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
|
|
|
|
case ' ': rep = "SPC"; break;
|
|
|
|
|
case DEL: rep = "DEL"; break;
|
|
|
|
|
default:
|
|
|
|
|
rep_buffer[0] = key;
|
|
|
|
|
rep_buffer[1] = '\0';
|
|
|
|
|
rep = rep_buffer;
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
return (rep);
|
|
|
|
|
}
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
/* Return the pretty printable string which represents KEYSEQ. */
|
|
|
|
|
|
2005-05-23 10:46:22 +00:00
|
|
|
|
static void pretty_keyseq_internal (char *keyseq, char *rep);
|
2002-03-25 13:08:32 +00:00
|
|
|
|
|
|
|
|
|
char *
|
2005-05-23 10:46:22 +00:00
|
|
|
|
pretty_keyseq (char *keyseq)
|
2002-03-25 13:08:32 +00:00
|
|
|
|
{
|
|
|
|
|
static char keyseq_rep[200];
|
|
|
|
|
|
|
|
|
|
keyseq_rep[0] = '\0';
|
|
|
|
|
if (*keyseq)
|
|
|
|
|
pretty_keyseq_internal (keyseq, keyseq_rep);
|
|
|
|
|
return (keyseq_rep);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2005-05-23 10:46:22 +00:00
|
|
|
|
pretty_keyseq_internal (char *keyseq, char *rep)
|
2002-03-25 13:08:32 +00:00
|
|
|
|
{
|
|
|
|
|
if (term_kP && strncmp(keyseq, term_kP, strlen(term_kP)) == 0)
|
|
|
|
|
{
|
|
|
|
|
strcpy(rep, "PgUp");
|
|
|
|
|
keyseq += strlen(term_kP);
|
|
|
|
|
}
|
|
|
|
|
else if (term_kN && strncmp(keyseq, term_kN, strlen(term_kN)) == 0)
|
|
|
|
|
{
|
|
|
|
|
strcpy(rep, "PgDn");
|
|
|
|
|
keyseq += strlen(term_kN);
|
|
|
|
|
}
|
|
|
|
|
#if defined(INFOKEY)
|
|
|
|
|
else if (term_kh && strncmp(keyseq, term_kh, strlen(term_kh)) == 0)
|
|
|
|
|
{
|
|
|
|
|
strcpy(rep, "Home");
|
|
|
|
|
keyseq += strlen(term_kh);
|
|
|
|
|
}
|
|
|
|
|
else if (term_ke && strncmp(keyseq, term_ke, strlen(term_ke)) == 0)
|
|
|
|
|
{
|
|
|
|
|
strcpy(rep, "End");
|
|
|
|
|
keyseq += strlen(term_ke);
|
|
|
|
|
}
|
|
|
|
|
else if (term_ki && strncmp(keyseq, term_ki, strlen(term_ki)) == 0)
|
|
|
|
|
{
|
|
|
|
|
strcpy(rep, "INS");
|
|
|
|
|
keyseq += strlen(term_ki);
|
|
|
|
|
}
|
|
|
|
|
else if (term_kx && strncmp(keyseq, term_kx, strlen(term_kx)) == 0)
|
|
|
|
|
{
|
|
|
|
|
strcpy(rep, "DEL");
|
|
|
|
|
keyseq += strlen(term_kx);
|
|
|
|
|
}
|
|
|
|
|
#endif /* INFOKEY */
|
|
|
|
|
else if (term_ku && strncmp(keyseq, term_ku, strlen(term_ku)) == 0)
|
|
|
|
|
{
|
|
|
|
|
strcpy(rep, "Up");
|
|
|
|
|
keyseq += strlen(term_ku);
|
|
|
|
|
}
|
|
|
|
|
else if (term_kd && strncmp(keyseq, term_kd, strlen(term_kd)) == 0)
|
|
|
|
|
{
|
|
|
|
|
strcpy(rep, "Down");
|
|
|
|
|
keyseq += strlen(term_kd);
|
|
|
|
|
}
|
|
|
|
|
else if (term_kl && strncmp(keyseq, term_kl, strlen(term_kl)) == 0)
|
|
|
|
|
{
|
|
|
|
|
strcpy(rep, "Left");
|
|
|
|
|
keyseq += strlen(term_kl);
|
|
|
|
|
}
|
|
|
|
|
else if (term_kr && strncmp(keyseq, term_kr, strlen(term_kr)) == 0)
|
|
|
|
|
{
|
|
|
|
|
strcpy(rep, "Right");
|
|
|
|
|
keyseq += strlen(term_kr);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
strcpy (rep, pretty_keyname (keyseq[0]));
|
|
|
|
|
keyseq++;
|
|
|
|
|
}
|
|
|
|
|
if (*keyseq)
|
|
|
|
|
{
|
|
|
|
|
strcat (rep, " ");
|
|
|
|
|
pretty_keyseq_internal (keyseq, rep + strlen(rep));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return a pointer to the last character in s that is found in f. */
|
|
|
|
|
static char *
|
2005-05-23 10:46:22 +00:00
|
|
|
|
strrpbrk (const char *s, const char *f)
|
2002-03-25 13:08:32 +00:00
|
|
|
|
{
|
|
|
|
|
register const char *e = s + strlen(s);
|
|
|
|
|
register const char *t;
|
|
|
|
|
|
|
|
|
|
while (e-- != s)
|
|
|
|
|
{
|
|
|
|
|
for (t = f; *t; t++)
|
|
|
|
|
if (*e == *t)
|
2003-05-02 00:48:41 +00:00
|
|
|
|
return (char *)e;
|
2002-03-25 13:08:32 +00:00
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
1997-01-11 02:12:38 +00:00
|
|
|
|
/* Replace the names of functions with the key that invokes them. */
|
|
|
|
|
char *
|
2005-05-23 10:46:22 +00:00
|
|
|
|
replace_in_documentation (char *string, int help_is_only_window_p)
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
unsigned reslen = strlen (string);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
register int i, start, next;
|
|
|
|
|
static char *result = (char *)NULL;
|
|
|
|
|
|
|
|
|
|
maybe_free (result);
|
2002-03-25 13:08:32 +00:00
|
|
|
|
result = (char *)xmalloc (1 + reslen);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
i = next = start = 0;
|
|
|
|
|
|
|
|
|
|
/* Skip to the beginning of a replaceable function. */
|
|
|
|
|
for (i = start; string[i]; i++)
|
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
int j = i + 1;
|
1999-01-14 19:35:19 +00:00
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
/* Is this the start of a replaceable function name? */
|
|
|
|
|
if (string[i] == '\\')
|
2003-05-02 00:48:41 +00:00
|
|
|
|
{
|
|
|
|
|
char *fmt = NULL;
|
|
|
|
|
unsigned min = 0;
|
|
|
|
|
unsigned max = 0;
|
|
|
|
|
|
|
|
|
|
if(string[j] == '%')
|
|
|
|
|
{
|
|
|
|
|
if (string[++j] == '-')
|
|
|
|
|
j++;
|
|
|
|
|
if (isdigit(string[j]))
|
|
|
|
|
{
|
|
|
|
|
min = atoi(string + j);
|
|
|
|
|
while (isdigit(string[j]))
|
|
|
|
|
j++;
|
|
|
|
|
if (string[j] == '.' && isdigit(string[j + 1]))
|
|
|
|
|
{
|
|
|
|
|
j += 1;
|
|
|
|
|
max = atoi(string + j);
|
|
|
|
|
while (isdigit(string[j]))
|
|
|
|
|
j++;
|
|
|
|
|
}
|
|
|
|
|
fmt = (char *)xmalloc (j - i + 2);
|
|
|
|
|
strncpy (fmt, string + i + 1, j - i);
|
|
|
|
|
fmt[j - i - 1] = 's';
|
|
|
|
|
fmt[j - i] = '\0';
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
j = i + 1;
|
|
|
|
|
}
|
|
|
|
|
if (string[j] == '[')
|
|
|
|
|
{
|
|
|
|
|
unsigned arg = 0;
|
|
|
|
|
char *argstr = NULL;
|
|
|
|
|
char *rep_name, *fun_name, *rep;
|
|
|
|
|
InfoCommand *command;
|
|
|
|
|
char *repstr = NULL;
|
|
|
|
|
unsigned replen;
|
|
|
|
|
|
|
|
|
|
/* Copy in the old text. */
|
|
|
|
|
strncpy (result + next, string + start, i - start);
|
|
|
|
|
next += (i - start);
|
|
|
|
|
start = j + 1;
|
|
|
|
|
|
|
|
|
|
/* Look for an optional numeric arg. */
|
|
|
|
|
i = start;
|
|
|
|
|
if (isdigit(string[i])
|
|
|
|
|
|| (string[i] == '-' && isdigit(string[i + 1])) )
|
|
|
|
|
{
|
|
|
|
|
arg = atoi(string + i);
|
|
|
|
|
if (string[i] == '-')
|
|
|
|
|
i++;
|
|
|
|
|
while (isdigit(string[i]))
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
start = i;
|
|
|
|
|
|
|
|
|
|
/* Move to the end of the function name. */
|
|
|
|
|
for (i = start; string[i] && (string[i] != ']'); i++);
|
|
|
|
|
|
|
|
|
|
rep_name = (char *)xmalloc (1 + i - start);
|
|
|
|
|
strncpy (rep_name, string + start, i - start);
|
|
|
|
|
rep_name[i - start] = '\0';
|
|
|
|
|
|
|
|
|
|
/* If we have only one window (because the window size was too
|
|
|
|
|
small to split it), we have to quit help by going back one
|
|
|
|
|
noew in the history list, not deleting the window. */
|
|
|
|
|
if (strcmp (rep_name, "quit-help") == 0)
|
|
|
|
|
fun_name = help_is_only_window_p ? "history-node"
|
|
|
|
|
: "delete-window";
|
|
|
|
|
else
|
|
|
|
|
fun_name = rep_name;
|
|
|
|
|
|
|
|
|
|
/* Find a key which invokes this function in the info_keymap. */
|
|
|
|
|
command = named_function (fun_name);
|
|
|
|
|
|
|
|
|
|
free (rep_name);
|
|
|
|
|
|
|
|
|
|
/* If the internal documentation string fails, there is a
|
|
|
|
|
serious problem with the associated command's documentation.
|
|
|
|
|
We croak so that it can be fixed immediately. */
|
|
|
|
|
if (!command)
|
|
|
|
|
abort ();
|
|
|
|
|
|
|
|
|
|
if (arg)
|
|
|
|
|
{
|
|
|
|
|
char *argrep, *p;
|
|
|
|
|
|
|
|
|
|
argrep = where_is (info_keymap, InfoCmd(info_add_digit_to_numeric_arg));
|
|
|
|
|
p = argrep ? strrpbrk (argrep, "0123456789-") : NULL;
|
|
|
|
|
if (p)
|
|
|
|
|
{
|
|
|
|
|
argstr = (char *)xmalloc (p - argrep + 21);
|
|
|
|
|
strncpy (argstr, argrep, p - argrep);
|
|
|
|
|
sprintf (argstr + (p - argrep), "%d", arg);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
command = NULL;
|
|
|
|
|
}
|
|
|
|
|
rep = command ? where_is (info_keymap, command) : NULL;
|
|
|
|
|
if (!rep)
|
|
|
|
|
rep = "N/A";
|
|
|
|
|
replen = (argstr ? strlen (argstr) : 0) + strlen (rep) + 1;
|
|
|
|
|
repstr = (char *)xmalloc (replen);
|
|
|
|
|
repstr[0] = '\0';
|
|
|
|
|
if (argstr)
|
|
|
|
|
{
|
|
|
|
|
strcat(repstr, argstr);
|
|
|
|
|
strcat(repstr, " ");
|
|
|
|
|
free (argstr);
|
|
|
|
|
}
|
|
|
|
|
strcat(repstr, rep);
|
|
|
|
|
|
|
|
|
|
if (fmt)
|
|
|
|
|
{
|
|
|
|
|
if (replen > max)
|
|
|
|
|
replen = max;
|
|
|
|
|
if (replen < min)
|
|
|
|
|
replen = min;
|
|
|
|
|
}
|
|
|
|
|
if (next + replen > reslen)
|
|
|
|
|
{
|
|
|
|
|
reslen = next + replen + 1;
|
|
|
|
|
result = (char *)xrealloc (result, reslen + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fmt)
|
|
|
|
|
sprintf (result + next, fmt, repstr);
|
|
|
|
|
else
|
|
|
|
|
strcpy (result + next, repstr);
|
|
|
|
|
|
|
|
|
|
next = strlen (result);
|
|
|
|
|
free (repstr);
|
|
|
|
|
|
|
|
|
|
start = i;
|
|
|
|
|
if (string[i])
|
|
|
|
|
start++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
maybe_free (fmt);
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
strcpy (result + next, string + start);
|
|
|
|
|
return (result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Return a string of characters which could be typed from the keymap
|
|
|
|
|
MAP to invoke FUNCTION. */
|
|
|
|
|
static char *where_is_rep = (char *)NULL;
|
|
|
|
|
static int where_is_rep_index = 0;
|
|
|
|
|
static int where_is_rep_size = 0;
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
char *
|
2005-05-23 10:46:22 +00:00
|
|
|
|
where_is (Keymap map, InfoCommand *cmd)
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
|
|
|
|
char *rep;
|
|
|
|
|
|
|
|
|
|
if (!where_is_rep_size)
|
|
|
|
|
where_is_rep = (char *)xmalloc (where_is_rep_size = 100);
|
|
|
|
|
where_is_rep_index = 0;
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
rep = where_is_internal (map, cmd);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
/* If it couldn't be found, return "M-x Foo" (or equivalent). */
|
1997-01-11 02:12:38 +00:00
|
|
|
|
if (!rep)
|
|
|
|
|
{
|
|
|
|
|
char *name;
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
name = function_name (cmd);
|
|
|
|
|
if (!name)
|
2003-05-02 00:48:41 +00:00
|
|
|
|
return NULL; /* no such function */
|
2002-03-25 13:08:32 +00:00
|
|
|
|
|
|
|
|
|
rep = where_is_internal (map, InfoCmd(info_execute_command));
|
|
|
|
|
if (!rep)
|
|
|
|
|
return ""; /* function exists but can't be got to by user */
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
sprintf (where_is_rep, "%s %s", rep, name);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
rep = where_is_rep;
|
|
|
|
|
}
|
|
|
|
|
return (rep);
|
|
|
|
|
}
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
/* Return the printed rep of the keystrokes that invoke FUNCTION,
|
|
|
|
|
as found in MAP, or NULL. */
|
1997-01-11 02:12:38 +00:00
|
|
|
|
static char *
|
2005-05-23 10:46:22 +00:00
|
|
|
|
where_is_internal (Keymap map, InfoCommand *cmd)
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
#if defined(INFOKEY)
|
|
|
|
|
|
|
|
|
|
register FUNCTION_KEYSEQ *k;
|
|
|
|
|
|
|
|
|
|
for (k = cmd->keys; k; k = k->next)
|
|
|
|
|
if (k->map == map)
|
|
|
|
|
return pretty_keyseq (k->keyseq);
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
#else /* !INFOKEY */
|
2003-05-02 00:48:41 +00:00
|
|
|
|
/* There is a bug in that create_internal_info_help_node calls
|
|
|
|
|
where_is_internal without setting where_is_rep_index to zero. This
|
|
|
|
|
was found by Mandrake and reported by Thierry Vignaud
|
|
|
|
|
<tvignaud@mandrakesoft.com> around April 24, 2002.
|
2003-06-18 12:57:43 +00:00
|
|
|
|
|
2003-05-02 00:48:41 +00:00
|
|
|
|
I think the best fix is to make where_is_rep_index another
|
|
|
|
|
parameter to this recursively-called function, instead of a static
|
|
|
|
|
variable. But this [!INFOKEY] branch of the code is not enabled
|
|
|
|
|
any more, so let's just skip the whole thing. --karl, 28sep02. */
|
1997-01-11 02:12:38 +00:00
|
|
|
|
register int i;
|
2000-01-17 10:39:58 +00:00
|
|
|
|
|
1997-01-11 02:12:38 +00:00
|
|
|
|
/* If the function is directly invokable in MAP, return the representation
|
|
|
|
|
of that keystroke. */
|
|
|
|
|
for (i = 0; i < 256; i++)
|
2002-03-25 13:08:32 +00:00
|
|
|
|
if ((map[i].type == ISFUNC) && map[i].function == cmd)
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
1999-01-14 19:35:19 +00:00
|
|
|
|
sprintf (where_is_rep + where_is_rep_index, "%s", pretty_keyname (i));
|
|
|
|
|
return (where_is_rep);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Okay, search subsequent maps for this function. */
|
|
|
|
|
for (i = 0; i < 256; i++)
|
|
|
|
|
{
|
|
|
|
|
if (map[i].type == ISKMAP)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
|
|
|
|
int saved_index = where_is_rep_index;
|
|
|
|
|
char *rep;
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
1999-01-14 19:35:19 +00:00
|
|
|
|
sprintf (where_is_rep + where_is_rep_index, "%s ",
|
|
|
|
|
pretty_keyname (i));
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
1999-01-14 19:35:19 +00:00
|
|
|
|
where_is_rep_index = strlen (where_is_rep);
|
2002-03-25 13:08:32 +00:00
|
|
|
|
rep = where_is_internal ((Keymap)map[i].function, cmd);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
1999-01-14 19:35:19 +00:00
|
|
|
|
if (rep)
|
|
|
|
|
return (where_is_rep);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
1999-01-14 19:35:19 +00:00
|
|
|
|
where_is_rep_index = saved_index;
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-01-17 10:39:58 +00:00
|
|
|
|
return NULL;
|
2002-03-25 13:08:32 +00:00
|
|
|
|
|
|
|
|
|
#endif /* INFOKEY */
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DECLARE_INFO_COMMAND (info_where_is,
|
2000-01-17 10:39:58 +00:00
|
|
|
|
_("Show what to type to execute a given command"))
|
1997-01-11 02:12:38 +00:00
|
|
|
|
{
|
|
|
|
|
char *command_name;
|
|
|
|
|
|
2005-05-23 10:46:22 +00:00
|
|
|
|
command_name = read_function_name ((char *) _("Where is command: "), window);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
|
|
|
|
if (!command_name)
|
|
|
|
|
{
|
|
|
|
|
info_abort_key (active_window, count, key);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*command_name)
|
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
InfoCommand *command;
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
command = named_function (command_name);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
if (command)
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
|
|
|
|
char *location;
|
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
location = where_is (active_window->keymap, command);
|
1999-01-14 19:35:19 +00:00
|
|
|
|
|
2002-03-25 13:08:32 +00:00
|
|
|
|
if (!location || !location[0])
|
1999-01-14 19:35:19 +00:00
|
|
|
|
{
|
2005-05-23 10:46:22 +00:00
|
|
|
|
info_error ((char *) _("`%s' is not on any keys"),
|
|
|
|
|
command_name, NULL);
|
1999-01-14 19:35:19 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2002-03-25 13:08:32 +00:00
|
|
|
|
if (strstr (location, function_name (command)))
|
1999-01-14 19:35:19 +00:00
|
|
|
|
window_message_in_echo_area
|
2005-05-23 10:46:22 +00:00
|
|
|
|
((char *) _("%s can only be invoked via %s."),
|
|
|
|
|
command_name, location);
|
1999-01-14 19:35:19 +00:00
|
|
|
|
else
|
|
|
|
|
window_message_in_echo_area
|
2005-05-23 10:46:22 +00:00
|
|
|
|
((char *) _("%s can be invoked via %s."),
|
|
|
|
|
command_name, location);
|
1999-01-14 19:35:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
1997-01-11 02:12:38 +00:00
|
|
|
|
else
|
2005-05-23 10:46:22 +00:00
|
|
|
|
info_error ((char *) _("There is no function named `%s'"),
|
|
|
|
|
command_name, NULL);
|
1997-01-11 02:12:38 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free (command_name);
|
|
|
|
|
}
|