#include "info.h"
#include "indices.h"
int show_index_match = 1;
static REFERENCE **index_index = (REFERENCE **)NULL;
static int index_offset = 0;
static char *index_search = (char *)NULL;
static char *initial_index_filename = (char *)NULL;
static char *initial_index_nodename = (char *)NULL;
typedef struct {
char *name;
int first;
int last;
} INDEX_NAME_ASSOC;
static INDEX_NAME_ASSOC **index_nodenames = (INDEX_NAME_ASSOC **)NULL;
static int index_nodenames_index = 0;
static int index_nodenames_slots = 0;
static void
add_index_to_index_nodenames (array, node)
REFERENCE **array;
NODE *node;
{
register int i, last;
INDEX_NAME_ASSOC *assoc;
for (last = 0; array[last + 1]; last++);
assoc = (INDEX_NAME_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, INDEX_NAME_ASSOC *);
}
REFERENCE **
info_indices_of_window (window)
WINDOW *window;
{
FILE_BUFFER *fb;
fb = file_buffer_of_window (window);
return (info_indices_of_file_buffer (fb));
}
REFERENCE **
info_indices_of_file_buffer (file_buffer)
FILE_BUFFER *file_buffer;
{
register int i;
REFERENCE **result = (REFERENCE **)NULL;
if (!file_buffer)
return ((REFERENCE **)NULL);
maybe_free (initial_index_filename);
maybe_free (initial_index_nodename);
initial_index_filename = (char *)NULL;
initial_index_nodename = (char *)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] = (INDEX_NAME_ASSOC *)NULL;
}
if (file_buffer->tags)
{
TAG *tag;
for (i = 0; (tag = file_buffer->tags[i]); i++)
{
if (string_in_line ("Index", tag->nodename) != -1)
{
NODE *node;
REFERENCE **menu;
node = info_get_node (tag->filename, tag->nodename);
if (!node)
continue;
initial_index_filename = xstrdup (file_buffer->filename);
initial_index_nodename = xstrdup (tag->nodename);
menu = info_menu_of_node (node);
if (menu)
{
add_index_to_index_nodenames (menu, node);
result = info_concatenate_references (result, menu);
}
free (node);
}
}
}
for (i = 0; result && result[i]; i++)
if (!result[i]->filename)
result[i]->filename = xstrdup (file_buffer->filename);
return (result);
}
DECLARE_INFO_COMMAND (info_index_search,
_("Look up a string in the index for this file"))
{
do_info_index_search (window, count, 0);
}
void
do_info_index_search (window, count, search_string)
WINDOW *window;
int count;
char *search_string;
{
FILE_BUFFER *fb;
char *line;
index_offset = 0;
maybe_free (index_search);
index_search = (char *)NULL;
fb = file_buffer_of_window (window);
if (!initial_index_filename ||
(FILENAME_CMP (initial_index_filename, fb->filename) != 0))
{
info_free_references (index_index);
window_message_in_echo_area (_("Finding index entries..."));
index_index = info_indices_of_file_buffer (fb);
}
if (!index_index)
{
info_error (_("No indices found."));
return;
}
if (search_string && *search_string)
line = xstrdup (search_string);
else
{
line = info_read_maybe_completing (window, _("Index entry: "),
index_index);
window = active_window;
if (!line)
{
info_abort_key (active_window, 1, 0);
return;
}
if (!*line)
{
free (line);
if (initial_index_filename && initial_index_nodename)
{
NODE *node;
node = info_get_node (initial_index_filename,
initial_index_nodename);
set_remembered_pagetop_and_point (window);
window_set_node_of_window (window, node);
remember_window_and_node (window, node);
window_clear_echo_area ();
return;
}
}
}
{
int old_offset;
if (count < 0)
{
register int i;
for (i = 0; index_index[i]; i++);
index_offset = i;
}
else
index_offset = -1;
old_offset = index_offset;
index_search = line;
info_next_index_match (window, count, 0);
if (index_offset == old_offset)
index_offset = 0;
}
}
int
index_entry_exists (window, string)
WINDOW *window;
char *string;
{
register int i;
FILE_BUFFER *fb;
if (!string)
return 0;
fb = file_buffer_of_window (window);
if (!initial_index_filename
|| (FILENAME_CMP (initial_index_filename, fb->filename) != 0))
{
info_free_references (index_index);
index_index = info_indices_of_file_buffer (fb);
}
if (!index_index)
return 0;
for (i = 0; (i > -1) && (index_index[i]); i++)
if (strcmp (string, index_index[i]->label) == 0)
break;
if ((i < 0) || (!index_index[i]))
{
for (i = 0; (i > -1) && (index_index[i]); i++)
if (string_in_line (string, index_index[i]->label) != -1)
break;
if ((i > -1) && (index_index[i]))
string_in_line (string, index_index[i]->label);
}
if ((i < 0) || (!index_index[i]))
return 0;
return 1;
}
DECLARE_INFO_COMMAND (info_next_index_match,
_("Go to the next matching index item from the last `\\[index-search]' command"))
{
register int i;
int partial, dir;
NODE *node;
if (!index_search)
{
info_error (_("No previous index search string."));
return;
}
if (!index_index)
{
info_error (_("No index entries."));
return;
}
if (count < 0)
dir = -1;
else
dir = 1;
partial = 0;
for (i = index_offset + dir; (i > -1) && (index_index[i]); i += dir)
if (strcmp (index_search, index_index[i]->label) == 0)
break;
if ((i < 0) || (!index_index[i]))
{
for (i = index_offset + dir; (i > -1) && (index_index[i]); i += dir)
if (string_in_line (index_search, index_index[i]->label) != -1)
break;
if ((i > -1) && (index_index[i]))
partial = string_in_line (index_search, index_index[i]->label);
}
if ((i < 0) || (!index_index[i]))
{
info_error (_("No %sindex entries containing \"%s\"."),
index_offset > 0 ? _("more ") : "", index_search);
return;
}
index_offset = i;
{
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;
}
}
match = xstrdup (index_index[i]->label);
if (partial && show_index_match)
{
int j, ls, start, upper;
ls = strlen (index_search);
start = partial - ls;
upper = isupper (match[start]) ? 1 : 0;
for (j = 0; j < ls; j++)
if (upper)
match[j + start] = info_tolower (match[j + start]);
else
match[j + start] = info_toupper (match[j + start]);
}
{
char *format;
format = replace_in_documentation
(_("Found \"%s\" in %s. (`\\[next-index-match]' tries to find next.)"));
window_message_in_echo_area (format, match, name);
}
free (match);
}
node = info_get_node (index_index[i]->filename, index_index[i]->nodename);
if (!node)
{
info_error (msg_cant_file_node,
index_index[i]->filename, index_index[i]->nodename);
return;
}
info_set_node_of_window (1, window, node);
{
long start, loc;
start = window->line_starts[1] - window->node->contents;
loc = info_target_search_node (node, index_index[i]->label, start);
if (loc != -1)
{
window->point = loc;
window_adjust_pagetop (window);
}
}
}
REFERENCE **
apropos_in_all_indices (search_string, inform)
char *search_string;
int inform;
{
register int i, dir_index;
REFERENCE **all_indices = (REFERENCE **)NULL;
REFERENCE **dir_menu = (REFERENCE **)NULL;
NODE *dir_node;
dir_node = info_get_node ("dir", "Top");
if (dir_node)
dir_menu = info_menu_of_node (dir_node);
if (!dir_menu)
return NULL;
for (dir_index = 0; dir_menu[dir_index]; dir_index++)
{
REFERENCE **this_index, *this_item;
NODE *this_node;
FILE_BUFFER *this_fb;
int dir_node_duplicated = 0;
this_item = dir_menu[dir_index];
if (!this_item->filename)
{
dir_node_duplicated = 1;
if (dir_node->parent)
this_item->filename = xstrdup (dir_node->parent);
else
this_item->filename = xstrdup (dir_node->filename);
}
this_node = info_get_node (this_item->filename, this_item->nodename);
if (!this_node && this_item->nodename &&
(strcmp (this_item->label, this_item->nodename) == 0))
this_node = info_get_node (this_item->label, "Top");
if (!this_node)
{
if (dir_node_duplicated)
free (this_item->filename);
continue;
}
{
char *files_name;
files_name = this_node->parent;
if (!files_name)
files_name = this_node->filename;
this_fb = info_find_file (files_name);
for (i = 0; i < dir_index; i++)
if (FILENAME_CMP (this_fb->filename, dir_menu[i]->filename) == 0)
break;
if (i < dir_index)
{
if (dir_node_duplicated)
free (this_item->filename);
continue;
}
if (this_fb && inform)
message_in_echo_area (_("Scanning indices of \"%s\"..."), files_name);
this_index = info_indices_of_file_buffer (this_fb);
free (this_node);
if (this_fb && inform)
unmessage_in_echo_area ();
}
if (this_index)
{
for (i = 0; this_index && this_index[i]; i++)
if (!this_index[i]->filename)
this_index[i]->filename = xstrdup (this_fb->filename);
all_indices = info_concatenate_references (all_indices, this_index);
}
}
info_free_references (dir_menu);
if (all_indices)
{
REFERENCE *entry, **apropos_list = (REFERENCE **)NULL;
int apropos_list_index = 0;
int 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, REFERENCE *);
}
else
{
maybe_free (entry->label);
maybe_free (entry->filename);
maybe_free (entry->nodename);
free (entry);
}
}
free (all_indices);
all_indices = apropos_list;
}
return (all_indices);
}
#define APROPOS_NONE \
N_("No available info files have \"%s\" in their indices.")
void
info_apropos (string)
char *string;
{
REFERENCE **apropos_list;
apropos_list = apropos_in_all_indices (string, 0);
if (!apropos_list)
{
info_error (_(APROPOS_NONE), string);
}
else
{
register int i;
REFERENCE *entry;
for (i = 0; (entry = apropos_list[i]); i++)
fprintf (stdout, "\"(%s)%s\" -- %s\n",
entry->filename, entry->nodename, entry->label);
}
info_free_references (apropos_list);
}
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;
line = info_read_in_echo_area (window, _("Index apropos: "));
window = active_window;
if (!line)
{
info_abort_key (window, 1, 1);
return;
}
if (*line)
{
REFERENCE **apropos_list;
NODE *apropos_node;
apropos_list = apropos_in_all_indices (line, 1);
if (!apropos_list)
{
info_error (_(APROPOS_NONE), line);
}
else
{
register int i;
char *line_buffer;
initialize_message_buffer ();
printf_to_message_buffer
(_("\n* Menu: Nodes whoses indices contain \"%s\":\n"), line);
line_buffer = (char *)xmalloc (500);
for (i = 0; apropos_list[i]; i++)
{
int len;
sprintf (line_buffer, "* %s [%s]: ",
apropos_list[i]->label, apropos_list[i]->filename);
len = pad_to (40, line_buffer);
sprintf (line_buffer + len, "(%s)%s.",
apropos_list[i]->filename, apropos_list[i]->nodename);
printf_to_message_buffer ("%s\n", line_buffer);
}
free (line_buffer);
}
apropos_node = message_buffer_to_node ();
add_gcable_pointer (apropos_node->contents);
name_internal_node (apropos_node, apropos_list_nodename);
apropos_node->flags &= ~N_IsInternal;
{
WINDOW *new;
NODE *node;
set_remembered_pagetop_and_point (window);
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 (!new && window->next)
new = window->next;
if (!new)
{
WINDOW *old_active;
old_active = active_window;
active_window = window;
new = window_make_window ((NODE *)NULL);
active_window = old_active;
}
if (!new)
new = window;
new->flags |= W_NoWrap;
window_set_node_of_window (new, apropos_node);
remember_window_and_node (new, apropos_node);
active_window = new;
}
info_free_references (apropos_list);
}
free (line);
if (!info_error_was_printed)
window_clear_echo_area ();
}