diff options
Diffstat (limited to 'contrib/texinfo/info/infodoc.c')
-rw-r--r-- | contrib/texinfo/info/infodoc.c | 615 |
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 |