Back to index

tetex-bin  3.0
Functions | Variables
toc.c File Reference
#include "system.h"
#include "makeinfo.h"
#include "cmds.h"
#include "files.h"
#include "macro.h"
#include "node.h"
#include "html.h"
#include "lang.h"
#include "sectioning.h"
#include "toc.h"
#include "xml.h"

Go to the source code of this file.

Functions

int toc_add_entry (char *tocname, int level, char *node_name, char *anchor)
char * toc_find_section_of_node (char *node)
void toc_free (void)
static void contents_update_html (void)
static void contents_update_info (void)
static void shortcontents_update_html (char *contents_filename)
static void shortcontents_update_info (void)
void cm_contents (int arg)

Variables

static TOC_ENTRY_ELT ** toc_entry_alist = NULL
static int toc_counter = 0

Function Documentation

void cm_contents ( int  arg)

Definition at line 355 of file toc.c.

{
  /* the file where we found the @contents directive */
  static char *contents_filename;

  /* No need to mess with delayed stuff for XML and Docbook.  */
  if (xml)
    {
      if (arg == START)
        {
          int elt = STREQ (command, "contents") ? CONTENTS : SHORTCONTENTS;
          xml_insert_element (elt, START);
          xml_insert_element (elt, END);
        }
    }
  else if (!handling_delayed_writes)
    {
      register_delayed_write (STREQ (command, "contents")
          ? "@contents" : "@shortcontents");

      if (html && STREQ (command, "contents"))
        {
          if (contents_filename)
            free (contents_filename);
          contents_filename = xstrdup (current_output_filename);
        }
    }
  else if (html)
    STREQ (command, "contents")
      ? contents_update_html () : shortcontents_update_html (contents_filename);
  else if (no_headers)
    STREQ (command, "contents")
      ? contents_update_info () : shortcontents_update_info ();
}

Here is the call graph for this function:

static void contents_update_html ( void  ) [static]

Definition at line 186 of file toc.c.

{
  int i;
  int k;
  int last_level;

  /* does exist any toc? */
  if (!toc_counter)
      /* no, so return to sender ;-) */
      return;

  add_html_block_elt_args ("\n<div class=\"contents\">\n<h2>%s</h2>\n<ul>\n", _("Table of Contents"));

  last_level = toc_entry_alist[0]->level;

  for (i = 0; i < toc_counter; i++)
    {
      if (toc_entry_alist[i]->level > last_level)
        {
          /* unusual, but it is possible
             @chapter ...
             @subsubsection ...      ? */
          for (k = 0; k < (toc_entry_alist[i]->level-last_level); k++)
            add_html_block_elt ("<ul>\n");
        }
      else if (toc_entry_alist[i]->level < last_level)
        {
          /* @subsubsection ...
             @chapter ... this IS usual.*/
          for (k = 0; k < (last_level-toc_entry_alist[i]->level); k++)
            add_word ("</li></ul>\n");
        }

      /* No double entries in TOC.  */
      if (!(i && strcmp (toc_entry_alist[i]->name,
                      toc_entry_alist[i-1]->name) == 0))
        {
          /* each toc entry is a list item.  */
          add_word ("<li>");

          /* Insert link -- to an external file if splitting, or
             within the current document if not splitting.  */
         add_word ("<a ");
          /* For chapters (only), insert an anchor that the short contents
             will link to.  */
          if (toc_entry_alist[i]->level == 0)
           {
             char *p = toc_entry_alist[i]->name;

             /* toc_entry_alist[i]->name has the form `foo">bar',
               that is, it includes both the node name and anchor
               text.  We need to find where `foo', the node name,
               ends, and use that in toc_FOO.  */
             while (*p && *p != '"')
              p++;
             add_word_args ("name=\"toc_%.*s\" ",
                     p - toc_entry_alist[i]->name, toc_entry_alist[i]->name);
           }
         add_word_args ("href=\"%s#%s</a>\n",
                 splitting ? toc_entry_alist[i]->html_file : "",
                 toc_entry_alist[i]->name);
        }

      last_level = toc_entry_alist[i]->level;
    }

  /* Go back to start level. */
  if (toc_entry_alist[0]->level < last_level)
    for (k = 0; k < (last_level-toc_entry_alist[0]->level); k++)
      add_word ("</li></ul>\n");

  add_word ("</li></ul>\n</div>\n\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void contents_update_info ( void  ) [static]

Definition at line 263 of file toc.c.

{
  int i;
  int k;

  if (!toc_counter)
      return;

  insert_string ((char *) _("Table of Contents"));
  insert ('\n');
  for (i = 0; i < strlen (_("Table of Contents")); i++)
    insert ('*');
  insert_string ("\n\n");

  for (i = 0; i < toc_counter; i++)
    {
      if (toc_entry_alist[i]->level == 0)
        add_char ('\n');

      /* indention with two spaces per level, should this
         changed? */
      for (k = 0; k < toc_entry_alist[i]->level; k++)
        insert_string ("  ");

      insert_string (toc_entry_alist[i]->name);
      insert ('\n');
    }
  insert_string ("\n\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void shortcontents_update_html ( char *  contents_filename) [static]

Definition at line 295 of file toc.c.

{
  int i;
  char *toc_file = NULL;

  /* does exist any toc? */
  if (!toc_counter)
    return;

  add_html_block_elt_args ("\n<div class=\"shortcontents\">\n<h2>%s</h2>\n<ul>\n", _("Short Contents"));

  if (contents_filename)
    toc_file = filename_part (contents_filename);

  for (i = 0; i < toc_counter; i++)
    {
      char *name = toc_entry_alist[i]->name;

      if (toc_entry_alist[i]->level == 0)
       {
         if (contents_filename)
           add_word_args ("<li><a href=\"%s#toc_%s</a></li>\n",
                   splitting ? toc_file : "", name);
         else
           add_word_args ("<a href=\"%s#%s</a>\n",
                   splitting ? toc_entry_alist[i]->html_file : "", name);
       }
    }
  add_word ("</ul>\n</div>\n\n");
  if (contents_filename)
    free (toc_file);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void shortcontents_update_info ( void  ) [static]

Definition at line 330 of file toc.c.

{
  int i;

  if (!toc_counter)
      return;

  insert_string ((char *) _("Short Contents"));
  insert ('\n');
  for (i = 0; i < strlen (_("Short Contents")); i++)
    insert ('*');
  insert_string ("\n\n");

  for (i = 0; i < toc_counter; i++)
    {
      if (toc_entry_alist[i]->level == 0)
        {
          insert_string (toc_entry_alist[i]->name);
          insert ('\n');
        }
    }
  insert_string ("\n\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

int toc_add_entry ( char *  tocname,
int  level,
char *  node_name,
char *  anchor 
)

Definition at line 43 of file toc.c.

{
  char *tocname_and_node, *expanded_node, *d;
  char *s = NULL;
  char *filename = NULL;

  if (!node_name)
    node_name = "";

  /* I assume that xrealloc behaves like xmalloc if toc_entry_alist is
     NULL */
  toc_entry_alist = xrealloc (toc_entry_alist,
                              (toc_counter + 1) * sizeof (TOC_ENTRY_ELT *));

  toc_entry_alist[toc_counter] = xmalloc (sizeof (TOC_ENTRY_ELT));

  if (html)
    {
      /* We need to insert the expanded node name into the toc, so
         that when we eventually output the toc, its <a ref= link will
         point to the <a name= tag created by cm_node in the navigation
         bar.  We cannot expand the containing_node member, for the
         reasons explained in the WARNING below.  We also cannot wait
         with the node name expansion until the toc is actually output,
         since by that time the macro definitions may have been changed.
         So instead we store in the tocname member the expanded node
         name and the toc name concatenated together (with the necessary
         html markup), since that's how they are output.  */
      if (!anchor)
        s = expanded_node = expand_node_name (node_name);
      else
        expanded_node = anchor;
      if (splitting)
       {
         if (!anchor)
           filename = nodename_to_filename (expanded_node);
         else
           filename = filename_part (current_output_filename);
       }
      /* Sigh...  Need to HTML-escape the expanded node name like
         add_anchor_name does, except that we are not writing this to
         the output, so can't use add_anchor_name...  */
      /* The factor 5 in the next allocation is because the maximum
         expansion of HTML-escaping is for the & character, which is
         output as "&amp;".  2 is for "> that separates node from tocname.  */
      d = tocname_and_node = (char *)xmalloc (2 + 5 * strlen (expanded_node)
                                              + strlen (tocname) + 1);
      if (!anchor)
        {
          for (; *s; s++)
            {
              if (cr_or_whitespace (*s))
                *d++ = '-';
              else if (! URL_SAFE_CHAR (*s))
                {
                  sprintf (d, "_00%x", (unsigned char) *s);
                  /* do this manually since sprintf returns char * on
                     SunOS 4 and other old systems.  */
                  while (*d)
                    d++;
                }
              else
                *d++ = *s;
            }
          strcpy (d, "\">");
        }
      else
        /* Section outside any node, they provided explicit anchor.  */
        strcpy (d, anchor);
      strcat (d, tocname);
      free (tocname);       /* it was malloc'ed by substring() */
      free (expanded_node);
      toc_entry_alist[toc_counter]->name = tocname_and_node;
    }
  else
    toc_entry_alist[toc_counter]->name = tocname;
  /* WARNING!  The node name saved in containing_node member must
     be the node name with _only_ macros expanded (the macros in
     the node name are expanded by cm_node when it grabs the name
     from the @node directive).  Non-macros, like @value, @@ and
     other @-commands must NOT be expanded in containing_node,
     because toc_find_section_of_node looks up the node name where
     they are also unexpanded.  You *have* been warned!  */
  toc_entry_alist[toc_counter]->containing_node = xstrdup (node_name);
  toc_entry_alist[toc_counter]->level = level;
  toc_entry_alist[toc_counter]->number = toc_counter;
  toc_entry_alist[toc_counter]->html_file = filename;

  /* have to be done at least */
  return toc_counter++;
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* toc_find_section_of_node ( char *  node)

Definition at line 149 of file toc.c.

{
  int i;

  if (!node)
    node = "";
  for (i = 0; i < toc_counter; i++)
    if (STREQ (node, toc_entry_alist[i]->containing_node))
      return toc_entry_alist[i]->name;

  return NULL;
}

Here is the caller graph for this function:

Definition at line 164 of file toc.c.

{
  int i;

  if (toc_counter)
    {
      for (i = 0; i < toc_counter; i++)
        {
          free (toc_entry_alist[i]->name);
          free (toc_entry_alist[i]->containing_node);
          free (toc_entry_alist[i]);
        }

      free (toc_entry_alist);
      toc_entry_alist = NULL; /* to be sure ;-) */
      toc_counter = 0; /* to be absolutley sure ;-) */
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

int toc_counter = 0 [static]

Definition at line 39 of file toc.c.

Definition at line 36 of file toc.c.