Back to index

tetex-bin  3.0
Classes | Defines | Functions | Variables
indices.c File Reference
#include "info.h"
#include "indices.h"

Go to the source code of this file.

Classes

struct  INDEX_NAME_ASSOC

Defines

#define APROPOS_NONE   N_("No available info files have `%s' in their indices.")

Functions

static void add_index_to_index_nodenames (REFERENCE **array, NODE *node)
REFERENCE ** info_indices_of_window (WINDOW *window)
REFERENCE ** info_indices_of_file_buffer (FILE_BUFFER *file_buffer)
 DECLARE_INFO_COMMAND (info_index_search, _("Look up a string in the index for this file"))
void do_info_index_search (WINDOW *window, int count, char *search_string)
int index_entry_exists (WINDOW *window, char *string)
 DECLARE_INFO_COMMAND (info_next_index_match, _("Go to the next matching index item from the last `\\[index-search]' command"))
REFERENCE ** apropos_in_all_indices (char *search_string, int inform)
void info_apropos (char *string)
 DECLARE_INFO_COMMAND (info_index_apropos, _("Grovel all known info file's indices for a string and build a menu"))

Variables

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
static INDEX_NAME_ASSOC ** index_nodenames = (INDEX_NAME_ASSOC **)NULL
static int index_nodenames_index = 0
static int index_nodenames_slots = 0
static char * apropos_list_nodename = "*Apropos*"

Class Documentation

struct INDEX_NAME_ASSOC

Definition at line 44 of file indices.c.

Class Members
int first
int last
char * name

Define Documentation

#define APROPOS_NONE   N_("No available info files have `%s' in their indices.")

Definition at line 595 of file indices.c.


Function Documentation

static void add_index_to_index_nodenames ( REFERENCE **  array,
NODE node 
) [static]

Definition at line 58 of file indices.c.

{
  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 *);
}

Here is the call graph for this function:

Here is the caller graph for this function:

REFERENCE** apropos_in_all_indices ( char *  search_string,
int  inform 
)

Definition at line 467 of file indices.c.

{
  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 every menu item in DIR, get the associated node's 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;
      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);
        }

      /* Find this node.  If we cannot find it, try using the label of the
         entry as a file (i.e., "(LABEL)Top"). */
      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;
       }

      /* Get the file buffer associated with this node. */
      {
        char *files_name;

        files_name = this_node->parent;
        if (!files_name)
          files_name = this_node->filename;

        this_fb = info_find_file (files_name);

       /* 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 (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 ((char *) _("Scanning indices of `%s'..."),
              files_name, NULL);

        this_index = info_indices_of_file_buffer (this_fb);
        free (this_node);

        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.  */
          all_indices = info_concatenate_references (all_indices, this_index);
        }
    }

  info_free_references (dir_menu);

  /* Build a list of the references which contain SEARCH_STRING. */
  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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

DECLARE_INFO_COMMAND ( info_index_search  ,
_("Look up a string in the index for this file")   
)

Definition at line 171 of file indices.c.

{
  do_info_index_search (window, count, 0);
}

Here is the call graph for this function:

DECLARE_INFO_COMMAND ( info_next_index_match  ,
_("Go to the next matching index item from the last `\\[index-search]' command")   
)

Definition at line 324 of file indices.c.

{
  register int i;
  int partial, dir;
  NODE *node;

  /* If there is no previous search string, the user hasn't built an index
     yet. */
  if (!index_search)
    {
      info_error ((char *) _("No previous index search string."), NULL, NULL);
      return;
    }

  /* If there is no index, that is an error. */
  if (!index_index)
    {
      info_error ((char *) _("No index entries."), NULL, NULL);
      return;
    }

  /* The direction of this search is controlled by the value of the
     numeric argument. */
  if (count < 0)
    dir = -1;
  else
    dir = 1;

  /* Search for the next occurence of index_search.  First try to find
     an exact match. */
  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 that failed, look for the next substring match. */
  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 that failed, print an error. */
  if ((i < 0) || (!index_index[i]))
    {
      info_error ((char *) _("No %sindex entries containing `%s'."),
                  index_offset > 0 ? (char *) _("more ") : "", index_search);
      return;
    }

  /* Okay, we found the next one.  Move the offset to the current entry. */
  index_offset = i;

  /* Report to the user on what we have found. */
  {
    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 (partial && show_index_match)
      {
        int k, ls, start, upper;

        ls = strlen (index_search);
        start = partial - ls;
        upper = isupper (match[start]) ? 1 : 0;

        for (k = 0; k < ls; k++)
          if (upper)
            match[k + start] = info_tolower (match[k + start]);
          else
            match[k + start] = info_toupper (match[k + start]);
      }

    {
      char *format;

      format = replace_in_documentation
        ((char *) _("Found `%s' in %s. (`\\[next-index-match]' tries to find next.)"),
         0);

      window_message_in_echo_area (format, match, (char *) name);
    }

    free (match);
  }

  /* Select the node corresponding to this index entry. */
  node = info_get_node (index_index[i]->filename, index_index[i]->nodename);

  if (!node)
    {
      info_error ((char *) msg_cant_file_node,
                  index_index[i]->filename, index_index[i]->nodename);
      return;
    }

  info_set_node_of_window (1, window, node);

  /* Try to find an occurence of LABEL in this 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);
      }
  }
}

Here is the call graph for this function:

DECLARE_INFO_COMMAND ( info_index_apropos  ,
_("Grovel all known info file's indices for a string and build a menu")   
)

Definition at line 621 of file indices.c.

{
  char *line;

  line = info_read_in_echo_area (window, (char *) _("Index apropos: "));

  window = active_window;

  /* User aborted? */
  if (!line)
    {
      info_abort_key (window, 1, 1);
      return;
    }

  /* User typed something? */
  if (*line)
    {
      REFERENCE **apropos_list;
      NODE *apropos_node;

      apropos_list = apropos_in_all_indices (line, 1);

      if (!apropos_list)
        info_error ((char *) _(APROPOS_NONE), line, NULL);
      else
        {
          register int i;
          char *line_buffer;

          initialize_message_buffer ();
          printf_to_message_buffer
            ((char *) _("\n* Menu: Nodes whose indices contain `%s':\n"),
             line, NULL, NULL);
          line_buffer = (char *)xmalloc (500);

          for (i = 0; apropos_list[i]; i++)
            {
              int len;
             /* 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.  */
              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, NULL, NULL);
            }
          free (line_buffer);
        }

      apropos_node = message_buffer_to_node ();
      add_gcable_pointer (apropos_node->contents);
      name_internal_node (apropos_node, apropos_list_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. */
      apropos_node->flags &= ~N_IsInternal;

      /* Find/Create a window to contain this node. */
      {
        WINDOW *new;
        NODE *node;

        set_remembered_pagetop_and_point (window);

        /* 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)
          {
            WINDOW *old_active;

            old_active = active_window;
            active_window = window;
            new = window_make_window ((NODE *)NULL);
            active_window = old_active;
          }

        /* 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;

        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 ();
}

Here is the call graph for this function:

void do_info_index_search ( WINDOW window,
int  count,
char *  search_string 
)

Definition at line 180 of file indices.c.

{
  FILE_BUFFER *fb;
  char *line;

  /* Reset the index offset, since this is not the info-index-next command. */
  index_offset = 0;

  /* The user is selecting a new search string, so flush the old one. */
  maybe_free (index_search);
  index_search = (char *)NULL;

  /* If this window's file is not the same as the one that we last built an
     index for, build and remember an index now. */
  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 ((char *) _("Finding index entries..."),
          NULL, NULL);
      index_index = info_indices_of_file_buffer (fb);
    }

  /* If there is no index, quit now. */
  if (!index_index)
    {
      info_error ((char *) _("No indices found."), NULL, NULL);
      return;
    }

  /* Okay, there is an index.  Look for SEARCH_STRING, or, if it is
     empty, prompt for one.  */
  if (search_string && *search_string)
    line = xstrdup (search_string);
  else
    {
      line = info_read_maybe_completing (window, (char *) _("Index entry: "),
                                         index_index);
      window = active_window;

      /* User aborted? */
      if (!line)
        {
          info_abort_key (active_window, 1, 0);
          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);
              set_remembered_pagetop_and_point (window);
              window_set_node_of_window (window, node);
              remember_window_and_node (window, node);
              window_clear_echo_area ();
              return;
            }
        }
    }

  /* The user typed either a completed index label, or a partial string.
     Find an exact match, or, failing that, the first index entry containing
     the partial string.  So, we just call info_next_index_match () with minor
     manipulation of INDEX_OFFSET. */
  {
    int old_offset;

    /* Start the search right after/before this index. */
    if (count < 0)
      {
        register int i;
        for (i = 0; index_index[i]; i++);
        index_offset = i;
      }
    else
      index_offset = -1;

    old_offset = index_offset;

    /* The "last" string searched for is this one. */
    index_search = line;

    /* Find it, or error. */
    info_next_index_match (window, count, 0);

    /* If the search failed, return the index offset to where it belongs. */
    if (index_offset == old_offset)
      index_offset = 0;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

int index_entry_exists ( WINDOW window,
char *  string 
)

Definition at line 280 of file indices.c.

{
  register int i;
  FILE_BUFFER *fb;

  /* If there is no previous search string, the user hasn't built an index
     yet. */
  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 there is no index, that is an error. */
  if (!index_index)
    return 0;

  for (i = 0; (i > -1) && (index_index[i]); i++)
    if (strcmp (string, index_index[i]->label) == 0)
      break;

  /* If that failed, look for the next substring match. */
  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 that failed, return 0. */
  if ((i < 0) || (!index_index[i]))
    return 0;

  return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void info_apropos ( char *  string)

Definition at line 599 of file indices.c.

{
  REFERENCE **apropos_list;

  apropos_list = apropos_in_all_indices (string, 0);

  if (!apropos_list)
    info_error ((char *) _(APROPOS_NONE), string, NULL);
  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);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 99 of file indices.c.

{
  register int i;
  REFERENCE **result = (REFERENCE **)NULL;

  /* No file buffer, no indices. */
  if (!file_buffer)
    return ((REFERENCE **)NULL);

  /* Reset globals describing where the index was found. */
  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;
    }

  /* 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 (string_in_line ("Index", tag->nodename) != -1)
            {
              NODE *node;
              REFERENCE **menu;

              /* Found one.  Get its menu. */
              node = info_get_node (tag->filename, tag->nodename);
              if (!node)
                continue;

              /* Remember the filename and nodename of this index. */
              initial_index_filename = xstrdup (file_buffer->filename);
              initial_index_nodename = xstrdup (tag->nodename);

              menu = info_menu_of_node (node);

              /* If we have a menu, add this index's nodename and range
                 to our list of index_nodenames. */
              if (menu)
                {
                  add_index_to_index_nodenames (menu, node);

                  /* Concatenate the references found so far. */
                  result = info_concatenate_references (result, menu);
                }
              free (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);

  return (result);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 89 of file indices.c.

{
  FILE_BUFFER *fb;

  fb = file_buffer_of_window (window);

  return (info_indices_of_file_buffer (fb));
}

Here is the call graph for this function:


Variable Documentation

char* apropos_list_nodename = "*Apropos*" [static]

Definition at line 619 of file indices.c.

REFERENCE** index_index = (REFERENCE **)NULL [static]

Definition at line 31 of file indices.c.

Definition at line 51 of file indices.c.

int index_nodenames_index = 0 [static]

Definition at line 52 of file indices.c.

int index_nodenames_slots = 0 [static]

Definition at line 53 of file indices.c.

int index_offset = 0 [static]

Definition at line 34 of file indices.c.

char* index_search = (char *)NULL [static]

Definition at line 37 of file indices.c.

char* initial_index_filename = (char *)NULL [static]

Definition at line 40 of file indices.c.

char* initial_index_nodename = (char *)NULL [static]

Definition at line 41 of file indices.c.

Definition at line 27 of file indices.c.