123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923 |
- /* indices.c -- deal with an Info file index.
- $Id$
- Copyright 1993, 1997, 1998, 1999, 2002, 2003, 2004, 2007, 2008, 2011,
- 2013, 2014, 2015, 2016, 2017 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
- the Free Software Foundation, either version 3 of the License, 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, see <http://www.gnu.org/licenses/>.
- Originally written by Brian Fox. */
- #include "info.h"
- #include "info-utils.h"
- #include "session.h"
- #include "echo-area.h"
- #include "indices.h"
- #include "variables.h"
- /* User-visible variable controls the output of info-index-next. */
- int show_index_match = 1;
- /* The combined indices of the last file processed by
- info_indices_of_file_buffer. */
- static REFERENCE **index_index = NULL;
- /* The offset of the most recently selected index element. */
- static int index_offset = 0;
- /* Whether we are doing initial index search. */
- static int index_initial = 0;
- /* Whether we are doing partial index search */
- static int index_partial = 0;
- /* Variable which holds the last string searched for. */
- static char *index_search = NULL;
- /* A couple of "globals" describing where the initial index was found. */
- static char *initial_index_filename = NULL;
- static char *initial_index_nodename = NULL;
- /* A structure associating index names with index offset ranges. */
- typedef struct {
- char *name; /* The nodename of this index. */
- int first; /* The index in our list of the first entry. */
- int last; /* The index in our list of the last entry. */
- } INDEX_NAME_ASSOC;
- /* An array associating index nodenames with index offset ranges. Used
- for reporting to the user which index node an index entry was found
- in. */
- static INDEX_NAME_ASSOC **index_nodenames = NULL;
- static size_t index_nodenames_index = 0;
- static size_t index_nodenames_slots = 0;
- /* Add the name of NODE, and the range of the associated index elements
- (passed in ARRAY) to index_nodenames. ARRAY must have at least one
- element. */
- static void
- add_index_to_index_nodenames (REFERENCE **array, NODE *node)
- {
- register int i, last;
- INDEX_NAME_ASSOC *assoc;
- for (last = 0; array[last + 1]; last++);
- assoc = xmalloc (sizeof (INDEX_NAME_ASSOC));
- assoc->name = xstrdup (node->nodename);
- if (!index_nodenames_index)
- {
- assoc->first = 0;
- assoc->last = last;
- }
- else
- {
- for (i = 0; index_nodenames[i + 1]; i++);
- assoc->first = 1 + index_nodenames[i]->last;
- assoc->last = assoc->first + last;
- }
- add_pointer_to_array (assoc, index_nodenames_index, index_nodenames,
- index_nodenames_slots, 10);
- }
- /* Find and concatenate the indices of FILE_BUFFER, saving the result in
- INDEX_INDEX. The indices are defined as the first node in the file
- containing the word "Index" and any immediately following nodes whose names
- also contain "Index". All such indices are concatenated and the result
- returned. */
- static void
- info_indices_of_file_buffer (FILE_BUFFER *file_buffer)
- {
- register int i;
- REFERENCE **result = NULL;
- /* No file buffer, no indices. */
- if (!file_buffer)
- {
- free (index_index);
- index_index = 0;
- return;
- }
- /* If the file is the same as the one that we last built an
- index for, don't do anything. */
- if (initial_index_filename
- && FILENAME_CMP (initial_index_filename, file_buffer->filename) == 0)
- {
- return;
- }
- /* Display a message because finding the index entries might take a while. */
- if (info_windows_initialized_p)
- window_message_in_echo_area (_("Finding index entries..."));
- /* Reset globals describing where the index was found. */
- free (initial_index_filename);
- free (initial_index_nodename);
- initial_index_filename = NULL;
- initial_index_nodename = NULL;
- if (index_nodenames)
- {
- for (i = 0; index_nodenames[i]; i++)
- {
- free (index_nodenames[i]->name);
- free (index_nodenames[i]);
- }
- index_nodenames_index = 0;
- index_nodenames[0] = NULL;
- }
- /* Grovel the names of the nodes found in this file. */
- if (file_buffer->tags)
- {
- TAG *tag;
- for (i = 0; (tag = file_buffer->tags[i]); i++)
- {
- if (strcasestr (tag->nodename, "Index")
- && tag->cache.nodelen != 0) /* Not an anchor. */
- {
- NODE *node;
- REFERENCE **menu;
- node = info_node_of_tag (file_buffer, &file_buffer->tags[i]);
- if (!node)
- continue;
- if (!initial_index_filename)
- {
- /* Remember the filename and nodename of this index. */
- initial_index_filename = xstrdup (file_buffer->filename);
- initial_index_nodename = xstrdup (tag->nodename);
- }
- menu = node->references;
- /* If we have a non-empty menu, add this index's nodename
- and range to our list of index_nodenames. */
- if (menu && menu[0])
- {
- add_index_to_index_nodenames (menu, node);
- /* Concatenate the references found so far. */
- {
- REFERENCE **old_result = result;
- result = info_concatenate_references (result, menu);
- free (old_result);
- }
- }
- free_history_node (node);
- }
- }
- }
- /* If there is a result, clean it up so that every entry has a filename. */
- for (i = 0; result && result[i]; i++)
- if (!result[i]->filename)
- result[i]->filename = xstrdup (file_buffer->filename);
- free (index_index);
- index_index = result;
- if (info_windows_initialized_p)
- window_clear_echo_area ();
- }
- void info_next_index_match (WINDOW *window, int count);
- DECLARE_INFO_COMMAND (info_index_search,
- _("Look up a string in the index for this file"))
- {
- FILE_BUFFER *fb;
- char *line;
- int old_offset;
- fb = file_buffer_of_window (window);
- if (fb)
- info_indices_of_file_buffer (fb); /* Sets index_index. */
- if (!fb || !index_index)
- {
- info_error (_("No indices found."));
- return;
- }
- line = info_read_maybe_completing (_("Index entry: "), index_index);
- /* User aborted? */
- if (!line)
- {
- info_abort_key (window, 1);
- return;
- }
- /* Empty line means move to the Index node. */
- if (!*line)
- {
- free (line);
- if (initial_index_filename && initial_index_nodename)
- {
- NODE *node;
- node = info_get_node (initial_index_filename,
- initial_index_nodename);
- info_set_node_of_window (window, node);
- }
- return;
- }
- /* Start the search either at the first or last index entry. */
- if (count < 0)
- {
- register int i;
- for (i = 0; index_index[i]; i++);
- index_offset = i;
- }
- else
- {
- index_offset = -1;
- index_initial = 0;
- index_partial = 0;
- }
-
- old_offset = index_offset;
- /* The "last" string searched for is this one. */
- free (index_search);
- index_search = line;
- info_next_index_match (window, count);
- /* If the search failed, return the index offset to where it belongs. */
- if (index_offset == old_offset)
- index_offset = 0;
- }
- /* Return true if ENT->label matches "S( <[0-9]+>)?", where S stands
- for the first LEN characters from STR. */
- static int
- index_entry_matches (REFERENCE *ent, const char *str, size_t len)
- {
- char *p;
-
- if (strncmp (ent->label, str, len))
- return 0;
- p = ent->label + len;
- if (!*p)
- return 1;
- if (p[0] == ' ' && p[1] == '<')
- {
- for (p += 2; *p; p++)
- {
- if (p[0] == '>' && p[1] == 0)
- return 1;
- else if (!isdigit (*p))
- return 0;
- }
- }
- return 0;
- }
- /* Search for the next occurence of STRING in FB's indices starting at OFFSET
- in direction DIR.
-
- Try to get an exact match, If no match found, progress onto looking for
- initial matches, then non-initial substrings, updating the values of
- INDEX_INITIAL and INDEX_PARTIAL.
- If a match is found, return a pointer to the matching index entry, and
- set *FOUND_OFFSET to its offset in INDEX_INDEX. Otherwise, return null.
- If we found a partial match, set *MATCH_OFFSET to the end of the match
- within the index entry text, else to 0. */
- REFERENCE *
- next_index_match (FILE_BUFFER *fb, char *string, int offset, int dir,
- int *found_offset, int *match_offset)
- {
- int i;
- int partial_match;
- size_t search_len;
- REFERENCE *result;
- partial_match = 0;
- search_len = strlen (string);
- info_indices_of_file_buffer (fb); /* Sets index_index. */
- if (!index_index)
- {
- info_error (_("No indices found."));
- return 0;
- }
- if (index_search != string)
- {
- free (index_search); index_search = string;
- }
- if (!index_initial && !index_partial)
- {
- /* First try to find an exact match. */
- for (i = offset + dir; i > -1 && index_index[i]; i += dir)
- if (index_entry_matches (index_index[i], string, search_len))
- {
- *match_offset = 0;
- break;
- }
- if (i < 0 || !index_index[i])
- {
- offset = 0;
- index_initial = 1;
- }
- }
- if (index_initial)
- {
- for (i = offset + dir; i > -1 && index_index[i]; i += dir)
- if (!index_entry_matches (index_index[i], string, search_len)
- && !strncmp (index_index[i]->label, string, search_len))
- {
- *match_offset = search_len;
- break;
- }
- if (i < 0 || !index_index[i])
- {
- offset = 0;
- index_initial = 0;
- index_partial = 1;
- }
- }
- if (index_partial)
- {
- /* Look for substrings, excluding case-matching inital matches. */
- for (i = offset + dir; i > -1 && index_index[i]; i += dir)
- {
- if (strncmp (index_index[i]->label, string, search_len) != 0)
- {
- partial_match = string_in_line (string, index_index[i]->label);
- if (partial_match != -1)
- {
- *match_offset = partial_match;
- break;
- }
- }
- }
- if (partial_match <= 0)
- index_partial = 0;
- }
- if (i < 0 || !index_index[i])
- result = 0;
- else
- {
- index_offset = i;
- result = index_index[i];
- }
- *found_offset = i;
- return result;
- }
- /* Display a message saying where the index match was found. */
- void
- report_index_match (int i, int match_offset)
- {
- register int j;
- const char *name = "CAN'T SEE THIS";
- char *match;
- for (j = 0; index_nodenames[j]; j++)
- {
- if ((i >= index_nodenames[j]->first) &&
- (i <= index_nodenames[j]->last))
- {
- name = index_nodenames[j]->name;
- break;
- }
- }
- /* If we had a partial match, indicate to the user which part of the
- string matched. */
- match = xstrdup (index_index[i]->label);
- if (match_offset > 0 && show_index_match)
- {
- int k, ls, start, upper;
- ls = strlen (index_search);
- start = match_offset - ls;
- upper = isupper (match[start]) ? 1 : 0;
- for (k = 0; k < ls; k++)
- if (upper)
- match[k + start] = tolower (match[k + start]);
- else
- match[k + start] = toupper (match[k + start]);
- }
- {
- char *format;
- format = replace_in_documentation
- (_("Found '%s' in %s. ('\\[next-index-match]' tries to find next.)"),
- 0);
- window_message_in_echo_area (format, match, (char *) name);
- }
- free (match);
- }
- DECLARE_INFO_COMMAND (info_next_index_match,
- _("Go to the next matching index item from the last '\\[index-search]' command"))
- {
- int i;
- int match_offset;
- int dir;
- REFERENCE *result;
-
- /* If there is no previous search string, the user hasn't built an index
- yet. */
- if (!index_search)
- {
- info_error (_("No previous index search string."));
- return;
- }
- /* The direction of this search is controlled by the value of the
- numeric argument. */
- if (count < 0)
- dir = -1;
- else
- dir = 1;
- result = next_index_match (file_buffer_of_window (window), index_search,
- index_offset, dir, &i, &match_offset);
- /* If that failed, print an error. */
- if (!result)
- {
- info_error (index_offset > 0 ?
- _("No more index entries containing '%s'.") :
- _("No index entries containing '%s'."),
- index_search);
- index_offset = 0;
- return;
- }
- /* Report to the user on what we have found. */
- report_index_match (i, match_offset);
- info_select_reference (window, result);
- }
- /* Look for the best match of STRING in the indices of FB. If SLOPPY, allow
- case-insensitive initial substrings to match. Return null if no match is
- found. Return value should not be freed or modified. This differs from the
- behaviour of next_index_match in that only _initial_ substrings are
- considered. */
- REFERENCE *
- look_in_indices (FILE_BUFFER *fb, char *string, int sloppy)
- {
- REFERENCE **index_ptr;
- REFERENCE *nearest = 0;
- /* Remember the search string so we can use it as the default for
- 'virtual-index' or 'next-index-match'. */
- free (index_search);
- index_search = xstrdup (string);
- info_indices_of_file_buffer (fb); /* Sets index_index. */
- if (!index_index)
- return 0;
- for (index_ptr = index_index; *index_ptr; index_ptr++)
- {
- if (!strcmp (string, (*index_ptr)->label))
- {
- nearest = *index_ptr;
- break;
- }
- /* Case-insensitive initial substring. */
- if (sloppy && !nearest && !mbsncasecmp (string, (*index_ptr)->label,
- mbslen (string)))
- {
- nearest = *index_ptr;
- }
- }
- return nearest;
- }
- /* **************************************************************** */
- /* */
- /* Info APROPOS: Search every known index. */
- /* */
- /* **************************************************************** */
- /* For every menu item in DIR, search the indices of that file for
- SEARCH_STRING. */
- REFERENCE **
- apropos_in_all_indices (char *search_string, int inform)
- {
- size_t i, dir_index;
- REFERENCE **all_indices = NULL;
- REFERENCE **dir_menu = NULL;
- NODE *dir_node;
- dir_node = get_dir_node ();
- /* It should be safe to assume that dir nodes do not contain any
- cross-references, i.e., its references list only contains
- menu items. */
- if (dir_node)
- dir_menu = dir_node->references;
- if (!dir_menu)
- {
- free (dir_node);
- return NULL;
- }
- /* For every menu item in DIR, get the associated file buffer and
- read the indices of that file buffer. Gather all of the indices into
- one large one. */
- for (dir_index = 0; dir_menu[dir_index]; dir_index++)
- {
- REFERENCE **this_index, *this_item;
- FILE_BUFFER *this_fb, *loaded_file = 0;
- this_item = dir_menu[dir_index];
- if (!this_item->filename)
- continue;
- /* If we already scanned this file, don't do that again.
- In addition to being faster, this also avoids having
- multiple identical entries in the *Apropos* menu. */
- for (i = 0; i < dir_index; i++)
- if (dir_menu[i]->filename
- && FILENAME_CMP (this_item->filename, dir_menu[i]->filename) == 0)
- break;
- if (i < dir_index)
- continue;
- this_fb = check_loaded_file (this_item->filename);
- if (!this_fb)
- this_fb = loaded_file = info_find_file (this_item->filename);
- if (!this_fb)
- continue; /* Couldn't load file. */
- if (this_fb && inform)
- message_in_echo_area (_("Scanning indices of '%s'..."), this_item->filename);
- info_indices_of_file_buffer (this_fb);
- this_index = index_index;
- if (this_fb && inform)
- unmessage_in_echo_area ();
- if (this_index)
- {
- /* Remember the filename which contains this set of references. */
- for (i = 0; this_index && this_index[i]; i++)
- if (!this_index[i]->filename)
- this_index[i]->filename = xstrdup (this_fb->filename);
- /* Concatenate with the other indices. */
- {
- REFERENCE **old_indices = all_indices;
- all_indices = info_concatenate_references (all_indices, this_index);
- free (old_indices);
- }
- }
- /* Try to avoid running out of memory by not loading all of the
- Info files on the system into memory. This is risky because we
- may have a pointer into the file buffer, so only free the contents
- if we have just loaded the file. */
- if (loaded_file)
- {
- free (loaded_file->contents);
- loaded_file->contents = NULL;
- }
- }
- /* Build a list of the references which contain SEARCH_STRING. */
- if (all_indices)
- {
- REFERENCE *entry, **apropos_list = NULL;
- size_t apropos_list_index = 0;
- size_t apropos_list_slots = 0;
- for (i = 0; (entry = all_indices[i]); i++)
- {
- if (string_in_line (search_string, entry->label) != -1)
- {
- add_pointer_to_array (entry, apropos_list_index, apropos_list,
- apropos_list_slots, 100);
- }
- }
- free (all_indices);
- all_indices = apropos_list;
- }
- free (dir_node);
- return all_indices;
- }
- static char *apropos_list_nodename = "*Apropos*";
- DECLARE_INFO_COMMAND (info_index_apropos,
- _("Grovel all known info file's indices for a string and build a menu"))
- {
- char *line, *prompt;
- REFERENCE **apropos_list;
- NODE *apropos_node;
- struct text_buffer message;
- if (index_search)
- asprintf (&prompt, "%s [%s]: ", _("Index apropos"), index_search);
- else
- asprintf (&prompt, "%s: ", _("Index apropos"));
- line = info_read_in_echo_area (prompt);
- free (prompt);
- window = active_window;
- /* User aborted? */
- if (!line)
- {
- info_abort_key (window, 1);
- return;
- }
- /* User typed something? */
- if (*line)
- {
- free (index_search);
- index_search = line;
- }
- else
- free (line); /* Try to use the last search string. */
- if (index_search && *index_search)
- {
- apropos_list = apropos_in_all_indices (index_search, 1);
- if (!apropos_list)
- {
- info_error (_(APROPOS_NONE), index_search);
- return;
- }
- else
- {
- /* Create the node. FIXME: Labels and node names taken from the
- indices of Info files may be in a different character encoding to
- the one currently being used.
- This problem is reduced by makeinfo not putting quotation marks
- from @samp, etc., into node names and index entries. */
- register int i;
- text_buffer_init (&message);
- text_buffer_add_char (&message, '\n');
- text_buffer_printf (&message, _("Index entries containing "
- "'%s':\n"), index_search);
- text_buffer_printf (&message, "\n* Menu:");
- text_buffer_add_string (&message, "\0\b[index\0\b]", 11);
- text_buffer_add_char (&message, '\n');
- for (i = 0; apropos_list[i]; i++)
- {
- int line_start = text_buffer_off (&message);
- char *filename;
- /* Remove file extension. */
- filename = program_name_from_file_name
- (apropos_list[i]->filename);
- /* The label might be identical to that of another index
- entry in another Info file. Therefore, we make the file
- name part of the menu entry, to make them all distinct. */
- text_buffer_printf (&message, "* %s [%s]: ",
- apropos_list[i]->label, filename);
- while (text_buffer_off (&message) - line_start < 40)
- text_buffer_add_char (&message, ' ');
- text_buffer_printf (&message, "(%s)%s.",
- filename, apropos_list[i]->nodename);
- text_buffer_printf (&message, " (line %ld)\n",
- apropos_list[i]->line_number);
- free (filename);
- }
- }
- apropos_node = text_buffer_to_node (&message);
- {
- char *old_contents = apropos_node->contents;
- scan_node_contents (apropos_node, 0, 0);
- if (old_contents != apropos_node->contents)
- free (old_contents);
- }
- name_internal_node (apropos_node, xstrdup (apropos_list_nodename));
- /* Find/Create a window to contain this node. */
- {
- WINDOW *new;
- NODE *node;
- /* If a window is visible and showing an apropos list already,
- re-use it. */
- for (new = windows; new; new = new->next)
- {
- node = new->node;
- if (internal_info_node_p (node) &&
- (strcmp (node->nodename, apropos_list_nodename) == 0))
- break;
- }
- /* If we couldn't find an existing window, try to use the next window
- in the chain. */
- if (!new && window->next)
- new = window->next;
- /* If we still don't have a window, make a new one to contain
- the list. */
- if (!new)
- new = window_make_window ();
- /* If we couldn't make a new window, use this one. */
- if (!new)
- new = window;
- /* Lines do not wrap in this window. */
- new->flags |= W_NoWrap;
- info_set_node_of_window (new, apropos_node);
- active_window = new;
- }
- free (apropos_list);
- }
- }
- #define NODECOL 41
- #define LINECOL 62
- static void
- format_reference (REFERENCE *ref, const char *filename, struct text_buffer *buf)
- {
- size_t n;
-
- n = text_buffer_printf (buf, "* %s: ", ref->label);
- if (n < NODECOL)
- n += text_buffer_fill (buf, ' ', NODECOL - n);
-
- if (ref->filename && strcmp (ref->filename, filename))
- n += text_buffer_printf (buf, "(%s)", ref->filename);
- n += text_buffer_printf (buf, "%s. ", ref->nodename);
- if (n < LINECOL)
- n += text_buffer_fill (buf, ' ', LINECOL - n);
- else
- {
- text_buffer_add_char (buf, '\n');
- text_buffer_fill (buf, ' ', LINECOL);
- }
-
- text_buffer_printf (buf, "(line %4d)\n", ref->line_number);
- }
- NODE *
- create_virtual_index (FILE_BUFFER *file_buffer, char *index_search)
- {
- struct text_buffer text;
- int i;
- size_t cnt;
- NODE *node;
- text_buffer_init (&text);
- text_buffer_printf (&text,
- "File: %s, Node: Index for '%s'\n\n",
- file_buffer->filename, index_search);
- text_buffer_printf (&text, _("Virtual Index\n"
- "*************\n\n"
- "Index entries that match '%s':\n"),
- index_search);
- text_buffer_add_string (&text, "\0\b[index\0\b]", 11);
- text_buffer_printf (&text, "\n* Menu:\n\n");
- cnt = 0;
- index_offset = 0;
- index_initial = 0;
- index_partial = 0;
- while (1)
- {
- REFERENCE *result;
- int match_offset;
- result = next_index_match (file_buffer, index_search, index_offset, 1,
- &i, &match_offset);
- if (!result)
- break;
- format_reference (index_index[i],
- file_buffer->filename, &text);
- cnt++;
- }
- text_buffer_add_char (&text, '\0');
- if (cnt == 0)
- {
- text_buffer_free (&text);
- return 0;
- }
- node = info_create_node ();
- asprintf (&node->nodename, "Index for '%s'", index_search);
- node->fullpath = file_buffer->filename;
- node->contents = text_buffer_base (&text);
- node->nodelen = text_buffer_off (&text) - 1;
- node->body_start = strcspn (node->contents, "\n");
- node->flags |= N_IsInternal | N_WasRewritten;
- scan_node_contents (node, 0, 0);
- return node;
- }
- DECLARE_INFO_COMMAND (info_virtual_index,
- _("List all matches of a string in the index"))
- {
- char *prompt, *line;
- FILE_BUFFER *fb;
- NODE *node;
-
- fb = file_buffer_of_window (window);
- if (!initial_index_filename ||
- !fb ||
- (FILENAME_CMP (initial_index_filename, fb->filename) != 0))
- {
- window_message_in_echo_area (_("Finding index entries..."));
- info_indices_of_file_buffer (fb);
- }
- if (!index_index)
- {
- info_error (_("No indices found."));
- return;
- }
-
- /* Default to last search if there is one. */
- if (index_search)
- asprintf (&prompt, "%s [%s]: ", _("Index topic"), index_search);
- else
- asprintf (&prompt, "%s: ", _("Index topic"));
- line = info_read_maybe_completing (prompt, index_index);
- free (prompt);
- /* User aborted? */
- if (!line)
- {
- info_abort_key (window, 1);
- return;
- }
- if (*line)
- {
- free (index_search);
- index_search = line;
- }
- else if (!index_search)
- {
- free (line);
- return; /* No previous search string, and no string given. */
- }
-
- node = create_virtual_index (fb, index_search);
- if (!node)
- {
- info_error (_("No index entries containing '%s'."), index_search);
- return;
- }
- info_set_node_of_window (window, node);
- }
|