summaryrefslogtreecommitdiffstats
path: root/contrib/texinfo/info/infodoc.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/texinfo/info/infodoc.c')
-rw-r--r--contrib/texinfo/info/infodoc.c615
1 files changed, 477 insertions, 138 deletions
diff --git a/contrib/texinfo/info/infodoc.c b/contrib/texinfo/info/infodoc.c
index 2b70918..731cb48 100644
--- a/contrib/texinfo/info/infodoc.c
+++ b/contrib/texinfo/info/infodoc.c
@@ -1,7 +1,7 @@
/* infodoc.c -- Functions which build documentation nodes.
- $Id: infodoc.c,v 1.23 1999/09/25 16:10:04 karl Exp $
+ $Id: infodoc.c,v 1.28 2002/02/27 13:37:33 karl Exp $
- Copyright (C) 1993, 97, 98, 99 Free Software Foundation, Inc.
+ Copyright (C) 1993, 97, 98, 99, 2001, 02 Free Software Foundation, Inc.
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
@@ -20,17 +20,12 @@
Written by Brian Fox (bfox@ai.mit.edu). */
#include "info.h"
+#include "funs.h"
/* 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
-/* **************************************************************** */
-/* */
-/* Info Help Windows */
-/* */
-/* **************************************************************** */
-
/* The name of the node used in the help window. */
static char *info_help_nodename = "*Info Help*";
@@ -40,26 +35,71 @@ 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;
-/* The static text which appears in the internal info help node. */
+/* The (more or less) static text which appears in the internal info
+ help node. The actual key bindings are inserted. Keep the
+ 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[scroll-forward] Scroll forward a page.\n"),
+ N_("\\%-10[scroll-backward] Scroll backward a page.\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"),
+ N_("\\%-10[scroll-forward] Scroll forward 1 line.\n"),
+ N_("\\%-10[scroll-backward] Scroll backward 1 line.\n"),
+ "\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 */
+
static char *info_internal_help_text[] = {
- N_("Basic Commands in Info Windows\n"),
- N_("******************************\n"),
+ N_("Basic Commands in Info Windows\n\
+******************************\n"),
"\n",
N_(" %-10s Quit this help.\n"),
N_(" %-10s Quit Info altogether.\n"),
N_(" %-10s Invoke the Info tutorial.\n"),
"\n",
- N_("Moving within a node:\n"),
- 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_("Selecting other nodes:\n"),
- N_("----------------------\n"),
+ N_("Selecting other nodes:\n\
+----------------------\n",
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"),
@@ -72,17 +112,26 @@ static char *info_internal_help_text[] = {
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",
- N_("Other commands:\n"),
- N_("---------------\n"),
+ 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"),
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"),
- N_(" %-10s Search forward through this Info file for a specified string,\n"),
+ N_(" %-10s Search forward for a specified string,\n"),
N_(" and select the node in which the next occurrence is found.\n"),
- N_(" %-10s Search backward in this Info file for a specified string,\n"),
+ N_(" %-10s Search backward for a specified string\n"),
N_(" and select the node in which the next occurrence is found.\n"),
NULL
};
@@ -133,7 +182,9 @@ static char *info_help_keys_text[][2] = {
NULL
};
-static char *where_is (), *where_is_internal ();
+#endif /* !INFOKEY */
+
+static char *where_is_internal ();
void
dump_map_to_message_buffer (prefix, map)
@@ -141,20 +192,18 @@ dump_map_to_message_buffer (prefix, map)
Keymap map;
{
register int i;
+ 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';
for (i = 0; i < 256; i++)
{
+ new_prefix[prefix_len] = i;
if (map[i].type == ISKMAP)
{
- char *new_prefix, *keyname;
-
- keyname = pretty_keyname (i);
- new_prefix = (char *)
- xmalloc (3 + strlen (prefix) + strlen (keyname));
- sprintf (new_prefix, "%s%s%s ", prefix, *prefix ? " " : "", keyname);
-
dump_map_to_message_buffer (new_prefix, (Keymap)map[i].function);
- free (new_prefix);
}
else if (map[i].function)
{
@@ -176,14 +225,13 @@ dump_map_to_message_buffer (prefix, map)
if (last - 1 != i)
{
- printf_to_message_buffer
- ("%s%s .. ", prefix, pretty_keyname (i));
- printf_to_message_buffer
- ("%s%s\t", prefix, pretty_keyname (last - 1));
+ printf_to_message_buffer ("%s .. ", pretty_keyseq (new_prefix));
+ new_prefix[prefix_len] = last - 1;
+ printf_to_message_buffer ("%s\t", pretty_keyseq (new_prefix));
i = last - 1;
}
else
- printf_to_message_buffer ("%s%s\t", prefix, pretty_keyname (i));
+ printf_to_message_buffer ("%s\t", pretty_keyseq (new_prefix));
#if defined (NAMED_FUNCTIONS)
/* Print the name of the function, and some padding before the
@@ -210,6 +258,7 @@ dump_map_to_message_buffer (prefix, map)
printf_to_message_buffer ("%s\n", doc);
}
}
+ free (new_prefix);
}
/* How to create internal_info_help_node. HELP_IS_ONLY_WINDOW_P says
@@ -225,6 +274,7 @@ create_internal_info_help_node (help_is_only_window_p)
register int i;
NODE *node;
char *contents = NULL;
+ char *exec_keys;
#ifndef HELP_NODE_GETS_REGENERATED
if (internal_info_help_node_contents)
@@ -239,6 +289,10 @@ create_internal_info_help_node (help_is_only_window_p)
for (i = 0; info_internal_help_text[i]; i++)
{
+#ifdef INFOKEY
+ printf_to_message_buffer (replace_in_documentation (
+ _(info_internal_help_text[i]), help_is_only_window_p));
+#else
/* 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])
@@ -252,6 +306,7 @@ create_internal_info_help_node (help_is_only_window_p)
key = "l";
printf_to_message_buffer (msg, key);
+#endif /* !INFOKEY */
}
printf_to_message_buffer ("---------------------\n\n");
@@ -265,35 +320,46 @@ create_internal_info_help_node (help_is_only_window_p)
dump_map_to_message_buffer ("", echo_area_keymap);
#if defined (NAMED_FUNCTIONS)
- /* Get a list of the M-x commands which have no keystroke equivs. */
+ /* 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);
for (i = 0; function_doc_array[i].func; i++)
{
- VFunction *func = function_doc_array[i].func;
+ InfoCommand *cmd = DocInfoCmd(&function_doc_array[i]);
- if ((!where_is_internal (info_keymap, func)) &&
- (!where_is_internal (echo_area_keymap, func)))
+ if (InfoFunction(cmd) != info_do_lowercase_version
+ && !where_is_internal (info_keymap, cmd)
+ && !where_is_internal (echo_area_keymap, cmd))
{
if (!printed_one_mx)
{
printf_to_message_buffer ("---------------------\n\n");
- printf_to_message_buffer
- (_("The following commands can only be invoked via M-x:\n\n"));
+ if (exec_keys && exec_keys[0])
+ printf_to_message_buffer
+ (_("The following commands can only be invoked via %s:\n\n"), exec_keys);
+ else
+ printf_to_message_buffer
+ (_("The following commands cannot be invoked at all:\n\n"));
printed_one_mx = 1;
}
printf_to_message_buffer
- ("M-x %s\n %s\n",
+ ("%s %s\n %s\n",
+ exec_keys,
function_doc_array[i].func_name,
replace_in_documentation (strlen (function_doc_array[i].doc)
- == 0
- ? function_doc_array[i].doc
- : _(function_doc_array[i].doc)));
+ ? _(function_doc_array[i].doc)
+ : "")
+ );
}
}
if (printed_one_mx)
printf_to_message_buffer ("\n");
+
+ maybe_free (exec_keys);
#endif /* NAMED_FUNCTIONS */
printf_to_message_buffer
@@ -492,39 +558,56 @@ DECLARE_INFO_COMMAND (info_get_info_help_node, _("Visit Info node `(info)Help'")
/* Return the documentation associated with the Info command FUNCTION. */
char *
-function_documentation (function)
- VFunction *function;
+function_documentation (cmd)
+ InfoCommand *cmd;
{
+ char *doc;
+
+#if defined (INFOKEY)
+
+ doc = cmd->doc;
+
+#else /* !INFOKEY */
+
register int i;
for (i = 0; function_doc_array[i].func; i++)
- if (function == function_doc_array[i].func)
+ if (InfoFunction(cmd) == function_doc_array[i].func)
break;
- return replace_in_documentation ((strlen (function_doc_array[i].doc) == 0)
- ? function_doc_array[i].doc
- : _(function_doc_array[i].doc));
+ doc = function_doc_array[i].func ? function_doc_array[i].doc : "";
+
+#endif /* !INFOKEY */
+
+ return replace_in_documentation ((strlen (doc) == 0) ? doc : _(doc));
}
#if defined (NAMED_FUNCTIONS)
/* Return the user-visible name of the function associated with the
Info command FUNCTION. */
char *
-function_name (function)
-
- VFunction *function;
+function_name (cmd)
+ InfoCommand *cmd;
{
+#if defined (INFOKEY)
+
+ return cmd->func_name;
+
+#else /* !INFOKEY */
+
register int i;
for (i = 0; function_doc_array[i].func; i++)
- if (function == function_doc_array[i].func)
+ if (InfoFunction(cmd) == function_doc_array[i].func)
break;
return (function_doc_array[i].func_name);
+
+#endif /* !INFOKEY */
}
-/* Return a pointer to the function named NAME. */
-VFunction *
+/* Return a pointer to the info command for function NAME. */
+InfoCommand *
named_function (name)
char *name;
{
@@ -534,7 +617,7 @@ named_function (name)
if (strcmp (function_doc_array[i].func_name, name) == 0)
break;
- return (function_doc_array[i].func);
+ return (DocInfoCmd(&function_doc_array[i]));
}
#endif /* NAMED_FUNCTIONS */
@@ -544,7 +627,7 @@ key_documentation (key, map)
char key;
Keymap map;
{
- VFunction *function = map[key].function;
+ InfoCommand *function = map[key].function;
if (function)
return (function_documentation (function));
@@ -554,21 +637,21 @@ key_documentation (key, map)
DECLARE_INFO_COMMAND (describe_key, _("Print documentation for KEY"))
{
- char keyname[50];
- int keyname_index = 0;
+ char keys[50];
unsigned char keystroke;
- char *rep;
+ char *k = keys;
Keymap map;
- keyname[0] = 0;
+ *k = '\0';
map = window->keymap;
for (;;)
{
- message_in_echo_area (_("Describe key: %s"), keyname);
+ message_in_echo_area (_("Describe key: %s"), pretty_keyseq (keys));
keystroke = info_get_input_char ();
unmessage_in_echo_area ();
+#if !defined (INFOKEY)
if (Meta_p (keystroke))
{
if (map[ESC].type != ISKMAP)
@@ -578,32 +661,53 @@ DECLARE_INFO_COMMAND (describe_key, _("Print documentation for KEY"))
return;
}
- strcpy (keyname + keyname_index, "ESC ");
- keyname_index = strlen (keyname);
+ *k++ = '\e';
keystroke = UnMeta (keystroke);
map = (Keymap)map[ESC].function;
}
+#endif /* !INFOKEY */
- /* Add the printed representation of KEYSTROKE to our keyname. */
- rep = pretty_keyname (keystroke);
- strcpy (keyname + keyname_index, rep);
- keyname_index = strlen (keyname);
+ /* Add the KEYSTROKE to our list. */
+ *k++ = keystroke;
+ *k = '\0';
- if (map[keystroke].function == (VFunction *)NULL)
+ if (map[keystroke].function == (InfoCommand *)NULL)
{
- message_in_echo_area (_("%s is undefined."), keyname);
+ message_in_echo_area (_("%s is undefined."), pretty_keyseq (keys));
return;
}
else if (map[keystroke].type == ISKMAP)
{
map = (Keymap)map[keystroke].function;
- strcat (keyname, " ");
- keyname_index = strlen (keyname);
continue;
}
else
{
- char *message, *fundoc, *funname = "";
+ char *keyname, *message, *fundoc, *funname = "";
+
+#if defined (INFOKEY)
+ /* 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. */
+ if (InfoFunction(map[keystroke].function) == info_do_lowercase_version)
+ {
+ unsigned char lowerkey = Meta_p(keystroke)
+ ? Meta (tolower (UnMeta (keystroke)))
+ : tolower (keystroke);
+
+ if (map[lowerkey].function == (InfoCommand *)NULL)
+ {
+ message_in_echo_area (_("%s is undefined."),
+ pretty_keyseq (keys));
+ return;
+ }
+ }
+#endif
+
+ keyname = pretty_keyseq (keys);
#if defined (NAMED_FUNCTIONS)
funname = function_name (map[keystroke].function);
@@ -627,13 +731,12 @@ DECLARE_INFO_COMMAND (describe_key, _("Print documentation for KEY"))
}
}
-/* How to get the pretty printable name of a character. */
-static char rep_buffer[30];
-
+/* Return the pretty printable name of a single character. */
char *
pretty_keyname (key)
unsigned char key;
{
+ static char rep_buffer[30];
char *rep;
if (Meta_p (key))
@@ -642,7 +745,11 @@ pretty_keyname (key)
rep = pretty_keyname (UnMeta (key));
+#if defined (INFOKEY)
+ sprintf (temp, "M-%s", rep);
+#else /* !INFOKEY */
sprintf (temp, "ESC %s", rep);
+#endif /* !INFOKEY */
strcpy (rep_buffer, temp);
rep = rep_buffer;
}
@@ -675,57 +782,269 @@ pretty_keyname (key)
return (rep);
}
+/* Return the pretty printable string which represents KEYSEQ. */
+
+static void pretty_keyseq_internal ();
+
+char *
+pretty_keyseq (keyseq)
+ char *keyseq;
+{
+ static char keyseq_rep[200];
+
+ keyseq_rep[0] = '\0';
+ if (*keyseq)
+ pretty_keyseq_internal (keyseq, keyseq_rep);
+ return (keyseq_rep);
+}
+
+static void
+pretty_keyseq_internal (keyseq, rep)
+ char *keyseq, *rep;
+{
+ 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 *
+strrpbrk (s, f)
+ const char *s, *f;
+{
+ register const char *e = s + strlen(s);
+ register const char *t;
+
+ while (e-- != s)
+ {
+ for (t = f; *t; t++)
+ if (*e == *t)
+ return (char *)e;
+ }
+ return NULL;
+}
+
/* Replace the names of functions with the key that invokes them. */
char *
-replace_in_documentation (string)
+replace_in_documentation (string, help_is_only_window_p)
char *string;
+ int help_is_only_window_p;
{
+ unsigned reslen = strlen (string);
register int i, start, next;
static char *result = (char *)NULL;
maybe_free (result);
- result = (char *)xmalloc (1 + strlen (string));
+ result = (char *)xmalloc (1 + reslen);
i = next = start = 0;
/* Skip to the beginning of a replaceable function. */
for (i = start; string[i]; i++)
{
- /* Is this the start of a replaceable function name? */
- if (string[i] == '\\' && string[i + 1] == '[')
- {
- char *fun_name, *rep;
- VFunction *function;
-
- /* Copy in the old text. */
- strncpy (result + next, string + start, i - start);
- next += (i - start);
- start = i + 2;
-
- /* Move to the end of the function name. */
- for (i = start; string[i] && (string[i] != ']'); i++);
-
- fun_name = (char *)xmalloc (1 + i - start);
- strncpy (fun_name, string + start, i - start);
- fun_name[i - start] = '\0';
-
- /* Find a key which invokes this function in the info_keymap. */
- function = named_function (fun_name);
+ int j = i + 1;
- /* 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 (!function)
- abort ();
-
- rep = where_is (info_keymap, function);
- strcpy (result + next, rep);
- next = strlen (result);
-
- start = i;
- if (string[i])
- start++;
- }
+ /* Is this the start of a replaceable function name? */
+ if (string[i] == '\\')
+ {
+ 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) + 1 : 0) + strlen (rep);
+ 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);
+ }
}
strcpy (result + next, string + start);
return (result);
@@ -737,10 +1056,10 @@ static char *where_is_rep = (char *)NULL;
static int where_is_rep_index = 0;
static int where_is_rep_size = 0;
-static char *
-where_is (map, function)
+char *
+where_is (map, cmd)
Keymap map;
- VFunction *function;
+ InfoCommand *cmd;
{
char *rep;
@@ -748,35 +1067,53 @@ where_is (map, function)
where_is_rep = (char *)xmalloc (where_is_rep_size = 100);
where_is_rep_index = 0;
- rep = where_is_internal (map, function);
+ rep = where_is_internal (map, cmd);
- /* If it couldn't be found, return "M-x Foo". */
+ /* If it couldn't be found, return "M-x Foo" (or equivalent). */
if (!rep)
{
char *name;
- name = function_name (function);
+ name = function_name (cmd);
+ if (!name)
+ return NULL; /* no such function */
+
+ rep = where_is_internal (map, InfoCmd(info_execute_command));
+ if (!rep)
+ return ""; /* function exists but can't be got to by user */
- if (name)
- sprintf (where_is_rep, "M-x %s", name);
+ sprintf (where_is_rep, "%s %s", rep, name);
rep = where_is_rep;
}
return (rep);
}
-/* Return the printed rep of FUNCTION as found in MAP, or NULL. */
+/* Return the printed rep of the keystrokes that invoke FUNCTION,
+ as found in MAP, or NULL. */
static char *
-where_is_internal (map, function)
+where_is_internal (map, cmd)
Keymap map;
- VFunction *function;
+ InfoCommand *cmd;
{
+#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 */
+
register int i;
/* If the function is directly invokable in MAP, return the representation
of that keystroke. */
for (i = 0; i < 256; i++)
- if ((map[i].type == ISFUNC) && map[i].function == function)
+ if ((map[i].type == ISFUNC) && map[i].function == cmd)
{
sprintf (where_is_rep + where_is_rep_index, "%s", pretty_keyname (i));
return (where_is_rep);
@@ -794,7 +1131,7 @@ where_is_internal (map, function)
pretty_keyname (i));
where_is_rep_index = strlen (where_is_rep);
- rep = where_is_internal ((Keymap)map[i].function, function);
+ rep = where_is_internal ((Keymap)map[i].function, cmd);
if (rep)
return (where_is_rep);
@@ -804,6 +1141,8 @@ where_is_internal (map, function)
}
return NULL;
+
+#endif /* INFOKEY */
}
extern char *read_function_name ();
@@ -823,23 +1162,23 @@ DECLARE_INFO_COMMAND (info_where_is,
if (*command_name)
{
- VFunction *function;
+ InfoCommand *command;
- function = named_function (command_name);
+ command = named_function (command_name);
- if (function)
+ if (command)
{
char *location;
- location = where_is (active_window->keymap, function);
+ location = where_is (active_window->keymap, command);
- if (!location)
+ if (!location || !location[0])
{
info_error (_("`%s' is not on any keys"), command_name);
}
else
{
- if (strncmp (location, "M-x ", 4) == 0)
+ if (strstr (location, function_name (command)))
window_message_in_echo_area
(_("%s can only be invoked via %s."), command_name, location);
else
OpenPOWER on IntegriCloud